كيف تخلصت من ألف علامة تبويب ...

... وكان متأخرا 3 سنوات. من الناحية المثالية ، يجب أن يكون الأمر على هذا النحو: يقوم المستخدم بتشغيل المتصفح ، ويعرض المتصفح ما يحتاجه المستخدم. ولكن في حين لم يتم تنفيذ ذلك ، يجب عليك استخدام محركات البحث. من الناحية المثالية ، يجب أن يكون الأمر على هذا النحو: يفتح المستخدم محرك بحث ويدخل استعلام بحث ويعرض ما يحتاجه المستخدم. ولكن في حين أن زر "أشعر أنني محظوظ" لا يعمل بشكل جيد (على الرغم من وجود حركة ملحوظة مؤخرًا في هذا الاتجاه) ، في بعض الأحيان يجب عليك الانتقال إلى عدة عناوين من صفحة نتائج البحث.

على ما يبدو ، تم إصلاح سيناريو استخدام محركات البحث تاريخيًا (عندما كان الإنترنت بطيئًا): الوصول إلى صفحة نتائج البحث ، فتحت العديد من علامات التبويب في الخلفية ، وبينما كان الباقي يتم تحميله ، كان من الممكن بالفعل قراءة علامة التبويب الأولى. في حالة العثور على المعلومات اللازمة في إحدى علامات التبويب ، يجب إغلاق الباقي يدويًا. إذا لم يتم إغلاقها فورًا ، فستظل علامات التبويب معلقة ، مما يؤدي إلى تضخيم عدد علامات التبويب المفتوحة في المتصفح ، والتي نادرًا ما يتم إغلاقها بعد ذلك.

بالإضافة إلى ذلك ، إذا نقرت على الصفحة التي تحتوي على الروابط التي تفتح في نافذة جديدة ، فسيتم إنشاء العديد من علامات التبويب (منطقية). عندما تجد المعلومات التي تحتاجها ، لا يمكنك دائمًا تذكر علامات التبويب المتصلة ، ولا يمكنك إغلاق كل شيء ، مما يؤدي أيضًا إلى تضخيم عدد علامات التبويب المفتوحة.

لطالما احتجت إلى زر "Found" ، والذي من شأنه تنظيف عواقب البحث (دعنا نسميه "كنت محظوظًا" ). بعد الانغماس في عالم ملحقات المتصفح ، اعتقدت أنه شيء يمكن أن يساعد في هذه الحالة. لذلك بدأت تظهر بشكل خافت رغبة في كتابة ملحق من شأنه حل مشاكلي.

سأخبرك قصتي ، سأقود القصة بترتيب زمني ، قد تكون الاستنتاجات غير متوقعة.

الخطوة الأولى نحوه


أول شيء فعلته هو إنشاء البنية التحتية: webpack + babel . وعلى الفور لم يعجبني هذا الرمز المكرر من babel لمساعديها في كل وحدة. كان من الممكن تكوينه لاستخدام الكائن babelHelper، ولكن بعد ذلك babelHelperيجب أن يكون ملف التعليمات البرمجية متصلاً في تكوين حزمة الويب . كان الاحتفاظ بمثل هذا الملف في المشروع entryوتوجيهه قبيحًا ، لقد قمت بعمل مكون إضافي لحزمة الويب التي قامت بذلك تلقائيًا بالنسبة لي. بعد إنفاق الكثير من الجهد على الخطوة الأولى وكتابة المزيد من التعليمات البرمجية للملحق نفسه ، تباطأت قليلاً.

توصيل في

مؤسسة


مر الوقت ، ولم يكن هناك سوى مكون إضافي لحزمة الويب متاحًا ، وهو ما لم يحل مشاكلي بأي شكل من الأشكال. وفي كل مرة كنت أبحث فيها عن شيء ما ولم أغلق علامات التبويب ، كان هناك فكرة: "سيكون من اللطيف إكمال هذا الامتداد ..." نمت الرغبة ونمت ، والآن في أحد الأيام الجميلة ، نمت الكمية إلى الجودة.

حان الوقت لمعرفة الفكرة الرئيسية: وصول
المستخدم إلى صفحة نتائج البحث - SICKLE ، نقوم بتحليل النتائج ، وحفظ عناوين الروابط لأنفسنا ، بعد أن ينقر المستخدم على أحد العناوين ، ويظهر له إشعارًا مع بقية العناوين وزر "Found" لإغلاق علامات التبويب.

عند الانتقال إلى الصفحة ، قد تكون هناك خيارات مختلفة. أبسط: طلب واحد - رد واحد من الخادم ( 200) الأكثر صعوبة: طلب واحد - العديد من عمليات إعادة التوجيه للخادم ( 3xx ) ، وبعد ذلك إعادة توجيه العميل (باستخدام <meta/>أو جافا سكريبت) ، تكون واجهة برمجة تطبيقات السجل في المقدمة أيضًا . والمجموعات بينهما ، كقاعدة عامة ، تقع معظم المواقع في هذه الفئة.

حالة انتقال بسيطة:

حالة الانتقال البسيط (الإجابة 200)

حالة انتقال معقدة:

حالة انتقال معقدة (3xx + عمليات إعادة توجيه العميل)

أي أن حفظ عنوان الصفحة والتدقيق عليه لا يكفي دائمًا. لذلك ، تحتاج إلى إنشاء انتقال منطقي ، حيث يمكنك كتابة جميع العناوين التي تمت مواجهتها في المسار ، ثم التحقق من أن الانتقال المنطقي يحتوي على العنوان المخزن. المهمة واضحة ، ولكن ليس كل شيء واضحًا في التنفيذ.

في Chrome ، هناك نوعان من واجهات برمجة التطبيقات المتعلقة بالملاحة: webNavigation و webRequest - لكل منها أحداثها الخاصة. الأول - يربط بين الانتقالات وواجهة مستخدم المتصفح ، والأخير - طلبات الشبكة الأساسية. لذلك ، إذا حدث التغيير في العنوان على الصفحة بسبب واجهة برمجة تطبيقات السجل، لن تكون هناك أحداث لهذا الأخير ، وإذا حدثت عمليات إعادة التوجيه أثناء طلب الشبكة ، فلن يبلغ عنها الأول على الإطلاق. لذلك ، من الضروري استخدام كل من واجهات برمجة التطبيقات ، وجمع القليل من كل حدث من واجهات برمجة التطبيقات ، لتشكيل انتقال منطقي واحد.

بعض التفاصيل
, webNavigation (wN) :

onBeforeNavigate -> onCommitted -> onDOMContentLoaded -> onCompleted

webRequest (wR):

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

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

, , .

تطوير


... دعونا نعود إلى اللحظة التي نمت فيها الكمية إلى الجودة. لقد مر الكثير من الوقت من بداية التطوير إلى هذه النقطة: بدأت المتصفحات في دعم وحدات es6 و shadow DOM وميزات حديثة أخرى. لبناء المشروع ، انتقلت إلى Rollup ، هذه المرة لم يكن لدي لكتابة البرنامج المساعد. بعد بناء الأساس - القدرة على الحصول على معلومات حول أي انتقال في أي علامة تبويب ، يبقى تطبيق منطق تحليل SICKLES المدعومة وعرض الإشعارات على الصفحات ذات الصلة.

المهمة الأولى بدائية تمامًا: نحن نعلم عنوان SICKLE ، ونصعد إلى محتوى الصفحة باستخدام النص البرمجي للمحتوى ، واحصل على البيانات التي نهتم بها ، واحفظها ، وانتظر حتى ينتقل المستخدم إلى إحدى الصفحات ليعرض له إشعارًا بالصفحات الأخرى.

بالنسبة للمهمة الثانية ، تحتاج إلى تنفيذ الإخطار نفسه ، ما يظهر للمستخدم على الصفحة. وهنا أيضًا ، لا تستطيع نصوص المحتوى أن تفعل.

في البداية ، كان هناك معالج واحد فقط (يُعرف أيضًا باسم وحدة تحكم) هو المسؤول عن المنطق أثناء تفاعل المستخدم مع محركات البحث. ثم طرحت الفكرة ، فلماذا لا تظهر إشعارات على علامات التبويب ذات الصلة عندما ينقر المستخدم ببساطة على الروابط التي تفتح في علامات تبويب جديدة. كان علي إعادة المنطق ، لجعله أكثر عالمية. على غرار الوسيطة React / Redux، يمكنك توصيل العديد من معالجات النقل ، والتي ستسمح لك في المستقبل بتنفيذ القدرة على تعطيل / تمكين معالجات مختلفة في إعدادات التمديد.

خصوصية


نظرًا لأن الإشعار عبارة عن لوحة في الجزء السفلي من الشاشة ، وتتم إضافته إلى تخطيط الصفحة ، يمكن للبرنامج النصي في الصفحة الوصول إلى هذا العنصر بنفس طريقة أي عنصر آخر في هذه الصفحة. أي ، نظريًا ، يمكن للصفحة معرفة أي استفسار بحث استخدمته ، وفي أي محرك بحث وأي صفحات أخرى تم تقديمها لك ، وهذا ليس جيدًا جدًا.

تأتي تقنية تسمى shadow DOM في الإنقاذ . لا يُنصح باستخدامه closed modeعلى الويب عند إنشائه shadowRoot، لأنه لا معنى له (لا يزال عليك تخزين الرابط للعنصر في shadowRootمكان ما إذا كنت تريد الوصول إليه برمجياً ؛ يمكنك أيضًا إعادة تعريف الوظيفة attachShadowلإنشاءshadowRootفي الوضع المفتوح ، ثم تستخدم البرامج النصية التي تم تحميلها بعد إعادة التعريف بالفعل الإصدار الجديد من الوظيفة).

في حالة التوسع ، الأمر ليس كذلك. تعيش نصوص المحتوى ونصوص الصفحات في عوالم متوازية. لا يمكن للنصوص البرمجية الموجودة في الصفحة الوصول إلى الكائنات المحددة في البرامج النصية للمحتوى ، في حين تعمل البرامج النصية للمحتوى مع التنفيذ الأصلي لوظائف DOM للكائنات (لا تؤثر وظيفة تجاوزها بواسطة نص برمجي من الصفحة على الوظيفة التي يعمل بها البرنامج النصي للمحتوى). بدمج هذين الشرطين ، نرى أنه من الممكن إنشاء عنصر بعنصر خاص shadowRootعن طريق تخزين الارتباط به في متغير.

في هذه الحالة ، سيتمكن البرنامج النصي من الصفحة من الوصول إلى عنصر الغلاف فقط ، والذي سيكون فارغًا له. لن يتمكن من استلام نص الطلب أو الصفحات المقترحة. يجب الحرص على عدم إعطاء رابط لأي عنصر داخل الإخطار أو نص عادي في الأحداث التي تم إنشاؤها. لذلك ، في الملحق ، يتم استخدام المعرف الذي تم إنشاؤه في الأحداث ، ويفهم البرنامج النصي للخلفية بالفعل ما هو مطلوب منه بواسطة هذا المعرف. بالنسبة للصفحة ، هذا المعرّف لا معنى له تمامًا.

صعوبات الترجمة


في البداية ، تم تطوير الإضافة فقط لمتصفح Google Chrome ، ولكن منذ WebExtensions API ، حافظت في مكان ما في رأسي على القدرة على النقل إلى المتصفحات الأخرى. كما أن وجود webextension-polyfill ألهم الثقة. ولكن مهما حدث. جلبت polyphil لهذا التمديد فقط القدرة على استخدام واجهة برمجة تطبيقات chrome مع الوعود. أصبح

فايرفوكس خيبة أمل هذا العام. تبين أن عدم تطابق واجهة برمجة تطبيقات chrome في Firefox ( Bug 1543647 ، Bug 1595621 ) أمر بالغ الأهمية بالنسبة للإضافة للعمل ، يمكننا القول أنها لا تعمل في هذا المتصفح (كما هو متوقع). كان

فيفالدي الأقرب ، ولكن ليس أيضًا بدون تكلفة. حدثwN.onCreatedNavigationTargetلا يحدث ذلك عندما يفتح المستخدم الرابط بزر الماوس الأوسط أو عبر زر Shift|Ctrl+ الماوس الأيسر ، بدلاً من الحدث wN.onCommitted transitionType == 'start_page'، الذي لا يوجد في واجهة برمجة تطبيقات chrome ، ولهذا السبب ، لا تعمل الإضافة بشكل صحيح في جميع الحالات. أيضا في Vivaldi لا تعمل مفاتيح الاختصار للتمديدات. ما هي ميزة القاتل في هذه الحالة في Chrome ، تسمح لك بالتنقل بسرعة عبر علامات التبويب وإغلاقها ، دون الحاجة إلى استخدام الماوس لهذا الغرض.

استنتاج


أثناء كتابة الكود ، تغير منطق عرض الإخطارات عدة مرات ، مع التبسيط في كل مرة. ونتيجة لذلك ، اتضح أنه من الممكن عدم تسييج الحديقة باستخدام التحولات المنطقية ، ولكن للقبض على "التحولات ذات الصلة" للمستخدم (في حالة wN.onCommittedوجود علامة transitionTypeتشير إلى الغرض من الانتقال ، في كثير من الحالات يكون "ارتباط" ، مما يعني أن المستخدم قام بالتبديل بالرجوع إليها) ، والتي من شأنها أن تبسط إلى حد كبير التعليمات البرمجية والعمل في كثير من الحالات ، ولكن ليس في كل شيء.

أيضًا ، لم أكن في هذا الموضوع ، توقعت المزيد من التوافق من حيث webExtensions API. كما هو الحال دائمًا ، من الجيد أن تعيش في عالم من المتصفحات الحديثة عندما لا تحتاج إلى دعم للإصدارات القديمة. الرسوم المتحركة CSS شيء رائع: ما استخدمته في استخدام مكتبة js يتم الآن في بضعة أسطر على css. لا تعمل العناصر المخصصة في الامتدادات ، ولكن الظل DOM يعمل ، مما يسمح لك بالاستفادة من جميع ميزاته.

توسيع
chrome web store: Handy Search

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


All Articles