الخلاصة

  • وصفت مسودة HTML 5 نشرها W3C في أبريل 2009 طريقة pushState() لإضافة مدخل ذي حالة، وحدث popstate عند تنشيط مدخل محفوظ. صارت مشاهد المستند الواحد قابلة لأن تكون محطات على طريق الرجوع.
  • جمعت توصية HTML5 لعام 2014 بين replaceState() وpushState()، وقدمت لعبة صغيرة تعيد رسم الشاشة من event.state بعد الرجوع. يحتفظ المتصفح بالتذكرة، وتعيد الصفحة ترتيب الخشبة.

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

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

وصفت مسودة HTML 5 الصادرة عن W3C في 23 أبريل 2009 وسيلة لهذا التبادل. ضمت واجهة History الأوامر المعروفة back وforward وgo. وأضافت pushState(data, title, url) مدخلاً يحمل حالة إلى سجل الجلسة، مع حدث popstate عندما يصبح مدخل حالة محفوظ نشطاً من جديد. صار بإمكان مشهد داخل المستند نفسه أن يحمل عنواناً وبيانات تخصه، فيستطيع المتصفح أن يجد طريقه بين تغيرات الصفحة.

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

وتصنع طريقة تسجيل المحطات فرقاً محسوساً. تشرح توصية W3C بشأن HTML5 الصادرة في 28 أكتوبر 2014 أن pushState() تضيف مدخلاً، بينما تعدل replaceState() المدخل الحالي. مشهد يرغب القارئ بالعودة إليه يستحق محطة جديدة. أما تصحيح المشهد الحالي فيمكن أن يبقى في المحطة نفسها. إذا صار لكل ضغطة مفتاح مدخل، احتاج الرجوع الواحد إلى رحلة طويلة. وإذا اختفت التغييرات المهمة من السجل، قفز الزر فوق خطوات قطعها القارئ فعلاً.

تقدم وثيقة 2014 لعبة بسيطة تتحرك فيها نقطة على خط. عند تغير الموضع تستدعي اللعبة history.pushState(...). وعندما يصل popstate، تمرر الدالة onpopstate قيمة event.state إلى setupPage() كي تعيد تجهيز الشاشة. في بضعة أسطر يظهر توزيع العمل كله: يختار المتصفح محطة من السجل، ويرسم التطبيق المشهد المناسب. عنوان صحيح فوق شاشة خاطئة يشبه ملصق مسرحية علق على باب قاعة تعرض عملاً آخر.

للعنوان حد أيضاً. تتحقق توصية 2014 من توافق عنوان URL الجديد مع المستند الحالي. وما زال فصل الملاحة وسجل التصفح في معيار HTML الحي لدى WHATWG يحدد حدود تعديل العنوان. في صفحات HTTP وHTTPS يمكن أن يتغير المسار أو الاستعلام أو الجزء الأخير ضمن الشروط المسموح بها؛ لا تستطيع الصفحة أن تدعي أنها موقع آخر بمجرد استدعاء دالة. ينبغي أن يدل العنوان المتغير على مكان حقيقي في التطبيق.

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

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

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

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