هل تتساءل عن كيفية الحصول على طول وعرض نافذة المتصفح؟ وكيف لك أن تعرف الطول والعرض الكلي للصفحة بما فيه الجزء الذي لا يُؤشِر عليه شريط التمرير (الجزء من الصفحة غير الظاهر في النافذة)؟ وكيف يمكن تمرير محتوى الصفحة باستعمال لغة جافاسكربت؟ فيما يلي الأجوبة الشافية لكل هذه التساؤلات.
يمكن، في أغلب هذه الحالات، استعمال العنصر الجذر للصفحة document.documentElement
الذي يقابِل الوسم <html>
، بالإضافة إلى بعض الدوالّ والخاصيات التي يُستحسن أخذها في الحسبان نظرًا لأهميتها.
طول وعرض النافذة
تُستخدم الخاصيتان clientHeight
وclientWidth
لمعرفة طول وعرض النافذة.
حيث تُظهِرالتعليمة، في المثال التالي، طول نافذة المتصفح:
alert( document.documentElement.clientHeight );
ملاحظة: لا تستعمل window.innerWidth وwindow.innerHeight
تدعم المتصفحات الخاصيتين window.innerWidth
وwindow.innerHeight
، ويبدو أنهما تتوافقان مع ما نريده، فلماذا لا نستخدمهما بدلًا من الخاصيتين اللّتان ذكرناهما سابقا؟
في حالة وجود شريط تمرير في الصفحة، تعطي الخاصيتان clientHeight
وclientWidth
طول وعرض النافذة بعد طرح عرض شريط التمرير منه. أو بعبارة أخرى، تعطيان طول وعرض الجزء الظاهر من الصفحة والمخصص للمحتوى. وتعطي الخاصيتان window.innerWidth
وwindow.innerHeight
الطول والعرض الكليين للنافذة بما فيهما عرض شريط التمرير.
في حالة ما إذا كان لدينا شريط تمرير يشغل مساحة ما من النافذة، تعطي التعليمتان التاليتان نتائج مختلفة:
alert( window.innerWidth ); // العرض الكلي للنافذة alert( document.documentElement.clientWidth ); // عرض النافذة بعد طرح عرض شريط التمرير منه
نحتاج، في أغلب الحالات، معرفة عرض النافذة المتاح (المخصص للمحتوى)، لرسم شيء ما أو وضعه، أي دون احتساب عرض شريط التمرير إن وُجد، لذا علينا استعمال الخاصيتين documentElement.clientHeight
وdocumentElement.clientWidth
.
ملاحظة: التعليمة DOCTYPE مهمة
لاحظ أن الخاصيات رفيعة المستوى المتعلقة بالهندسة يمكن أن لا تعمل بالشكل المطلوب إذا لم يحوي ملف HTML التعليمة <!DOCTYPE HTML>
، فمن الممكن أن تحدث أشياء غريبة بسبب ذلك. أضف دائمًا إذًا التعليمة DOCTYPE
عند كتابة شيفرة HTML على الطريقة العصرية.
طول وعرض الصفحة
نظريا، وبما أن العنصر الجذر للصفحة هو document.documentElement
، ويضُم كلّ المحتوى، يمكن قياس العرض والطول الكليين للصفحة باستعمال الخاصيتين document.documentElement.scrollWidth
وdocument.documentElement.scrollHeight
، ولكن هاتين الخاصيتين، عند استعمالهما على هذا العنصر، لا تعملان بالشكل المطلوب إن لم يكن هناك شريط تمرير في كلّ من المتصفحات Chrome/Safari/Opera، حيث يمكن أن تعطي الخاصية documentElement.scrollHeight
قيمةً أصغر من القيمة التي تعطيها الخاصية documentElement.clientHeight
. يبدو الأمر غريبا نوعا ما، أليس كذلك؟
للحصول إذًا على القيمة الصحيحة للطول الكلي للصفحة، علينا أخذ أكبر قيمة من بين القيم التالية:
let scrollHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight ); alert('Full document height, with scrolled out part: ' + scrollHeight);
لماذا يحدث ذلك؟ يُستحسن عدم طرح هذا السؤال لأن هذه التناقضات موجودة منذ زمن ولا تخضع لتفكير منطقي "ذكي".
حساب إحداثيات الموضع الحالي لعنصر ما
تملك عناصر تمثيل الصفحة ككائن DOM خاصيتين تحملان إحداثيات موضعها من الصفحة وهما: elem.scrollLeft
وelem.scrollTop
. فبالنسبة لموضِع النافذة، تعمل الخاصيتان document.documentElement.scrollLeft
وdocument.documentElement.scrollTop
في أغلب المتصفحات، عدا تلك التي تعتمد على محرك WebKit مثل المتصفح Safari
(يوّلد استعمالها الخطأ البرمجي 5991)، حيث ينبغي في هذه الحالة استعمال document.body
بدلا من document.documentElement
.
ومن حسن الحظ أنه ليس علينا على الإطلاق تذكُّر كلّ هذه الخاصيات، حيث توجد خاصيتان غيرهما تعطيان الموضع الحالي للنافدة، إنهما الخاصيتان window.pageXOffset
وwindow.pageYOffset
، وهما خاصيتان قابلتان فقط للقراءة.
alert('Current scroll from the top: ' + window.pageYOffset); alert('Current scroll from the left: ' + window.pageXOffset);
التمرير باستعمال الدوال scrollTo وscrollBy وscrollIntoView
ملاحظة هامة
لا يمكن تمرير الصفحة إلّا بعد البناء الكلي لنموذج تمثيل الصفحة ككائن (DOM)، فمن غير الممكن كتابة شيفرة لتمرير الصفحة ووضعها في الجزء <head>
أي تنفيذها قبل أن تجهز الصفحة فلن يعمل ذلك حتما.
ويمكن تمرير العناصر العادية بتغيير قيم الخاصيتين scrollTop
وscrollLeft
، كما يمكن عمل الشيء نفسه للصفحة باستعمال الخاصيتين document.documentElement.scrollLeft
وdocument.documentElement.scrollTop
، عدا في المتصفح Safari
(حيث ينبغي استخدام الخاصيتين document.body.scrollLeft
وdocument.body.scrollTop
بدلا منها).
وهناك أيضا طريقةٌ بديلةٌ، أبسط من الأولى، تعمل في كافة المتصفحات، وتكون باستعمال الدالّتين window.scrollBy(x,y)
وwindow.scrollTo(pageX,pageY)
.
تحرّك الدالّة scrollBy(x,y)
النافذة من مكانها الحالي بمقدار معين. حيث تُحرِك التعليمة window.scrollBy(0,10)
مثلا الصفحة إلى الأسفل بمقدار عشرة بكسل.
وتحرِّك الدالّة scrollTo(pageX,pageY)
الصفحة إلى موضعٍ ذي إحداثياتٍ مطلقةٍ. بحيث تكون إحداثيات الركن العلوي الأيسر للجزء الظاهر من الصفحة هي (pageX, pageY)
إنطلاقا من الركن العلوي الأيسر للصفحة. تعمل هذه الدالّة تماما كما لو أننا نُسنِد قِيَمًا للخاصيتين scrollLeft
وscrollTop
.
مثلًا لتحريك النافذة إلى نقطة البداية (العودة إلى أعلى الصفحة)، يمكن استعمال التعليمة window.scrollTo(0,0)
. وتعمل هذه الدوالّ بنفس الطريقة (تعطي النتائج نفسها) على كلّ المتصفحات.
الدالة scrollIntoView
دعنا نكمل ما بدأناه بشرح الدالّة elem.scrollIntoView(top)
. ينتج عن مناداة هذه الدالّة تمرير الصفحة بحيث تجعل العنصر elem
ظاهرًا، ولها وسيط واحد:
-
إذا كانت قيمة الوسيط
top
تساويtrue
(وهي القيمة المبدئية -الافتراضية)، تُمرَّر الصفحة بحيث يظهر العنصرelem
أعلى النافذة فتتطابق حافته العلوية مع أعلى النافذة. -
وإذا كانت قيمة الوسيط
top
تساويfalse
، تُمرَّر الصفحة بحيث يظهر العنصرelem
أسفل النافذة فتتطابق حافته السفلى مع أسفل النافذة.
مثال: إذا كان لدينا زر، فإن هذه التعليمة this.scrollIntoView()
تُحرِك الصفحة بحيث يظهر هذا الزر أعلى النافذة. أما هذه التعليمة this.scrollIntoView(false)
، فتُحرِك الصفحة بحيث يظهر الزر أسفل النافذة.
تثبيط قابلية التمرير
نحتاج أحيانا إلى جعل الصفحة غير قابلة للتمرير، فنرغب مثلًا في إخفائها وراء رسالة طويلة للفت انتباه الزائر وحمله على التفاعل مع الرسالة وليس مع الصفحة. وهنا يكفي إسناد القيمة "hidden"
للخاصية document.body.style.overflow
حيث تثبِّت (تجمِّد) هذه التعليمة الصفحة في موضعها الحالي.
فلتجرب ذلك باستعمال التعليمتين document.body.style.overflow="hidden"
و document.body.style.overflow=""
.
هنا، تثبِّط التعليمة الأولى قابلية التحريك، أما التعليمة الثانية فتعاود تفعيلها. ويمكننا استعمال هذه الطريقة لتجميد/تثبيت عناصر أخرى أيضا، ليس العنصر document.body
فقط.
غير أن لهذه الدالّة نقطة سلبية، حيث يختفي شريط التمرير تماما بعد مناداتها، وبما أنه كان يشغل مساحة ما من الصفحة، فعند اختفائه، يتحرك محتوى الصفحة بعض الشيء لملء الفراغ الذي نتج عن اختفاء شريط التمرير. يبدو هذا غريبا بعض الشئ، ولكن يمكننا تفادي حدوث ذلك بموازنة قيمة الخاصية clientWidth
قبل وبعد التثبيط، فإذا ازداد العرض بعد اختفاء شريط التمرير، نضيف حاشية padding
للعنصرdocument.body
مكان شريط التمرير للإبقاء على عرض محتوى الصفحة كما هو.
الخلاصة
-
لمعرفة طول/عرض الجزء الظاهر من الصفحة (طول/عرض مساحة المحتوى) نستعمل الخاصيتين
document.documentElement.clientWidth/Height
. *لمعرفة الطول/العرض الكلي للصفحة بما فيها الجزء غير الظاهر في النافذة نبحث عن أكبر قيمة من بين القيم التالية:
let scrollHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight );
-
لقراءة إحداثيات موضع الجزء الظاهر من الصفحة إنطلاقا من الركن العلوي الأيسر للصفحة نستعمل الخاصيتين
window.pageYOffset/pageXOffset
. -
ولتغيير الموضع الحالي للنافذة نستعمل الدوالّ التالية:
-
window.scrollTo(pageX,pageY)
: التحريك نحو الموضع ذي الإحداثيات المطلقة (pageX,pageY). -
window.scrollBy(x,y)
: التحريك بمقدار (x,y) انطلاقا من الموضع الحالي. -
elem.scrollIntoView(top)
: التحريك لجعل العنصرelem
ظاهرًا، أي تحريكه بحيث يتطابق مع أعلى أو أسفل النافذة حسب قيمة الوسيطtop
.
-
ترجمة -وبتصرف- للفصل Window sizes and scrolling من كتاب Browser: Document, Events, Interfaces
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.