سمات DOM الآن على سلسلة النموذج الأوّلي

أعلن فريق Chrome مؤخرًا عن نقل خصائص DOM إلى سلسلة النماذج الأولية. هذا التغيير، الذي تم تنفيذه في Chrome 43 - (إصدار تجريبي اعتبارًا من منتصف نيسان (أبريل) 2015) - يجعل Chrome أكثر توافقًا مع مواصفات Web IDL وعمليات تنفيذ المتصفحات الأخرى، مثل IE وFirefox. تعديل: توضيح المتصفحات القديمة المستندة إلى مجموعة أدوات الويب غير متوافقة حاليًا مع المواصفات، غير أن Safari أصبح متوافقًا الآن.

يتسم السلوك الجديد بالإيجابية من نواحٍ كثيرة. إذ إنه:

  • تحسين التوافق عبر الويب (يتيح كل من IE وFirefox هذا إجراء ذلك بالفعل) من خلال التوافق مع المواصفات
  • تسمح لك هذه الميزة بإنشاء رموز/أحرف على كل كائن DOM بشكل متسق وفعّال.
  • يزيد من إمكانية اختراق برمجة DOM. على سبيل المثال، ستُتيح لك هذه الميزة تنفيذ رموز polyfills التي تتيح لك محاكاة الوظائف غير المتوفّرة في بعض المتصفّحات ومكتبات JavaScript التي تلغي سلوكيات سمات DOM التلقائية.

على سبيل المثال، تتضمن مواصفات W3C الافتراضية بعض الوظائف الجديدة التي تسمّى isSuperContentEditable ولا يطبّقها متصفّح Chrome، ولكن من الممكن "تعويض" هذه الميزة أو محاكاتها باستخدام مكتبة. بصفتك مطوِّر المكتبة، ننصحك بطبيعة الحال باستخدام السمة prototype على النحو التالي لإنشاء رمز polyfill فعّال:

Object.defineProperty(HTMLDivElement.prototype, "isSuperContentEditable", {
    get: function() { return true; },
    set: function() { /* some logic to set it up */ },
});

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

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

ملخّص التغييرات

سيؤدي الآن استخدام hasOwnProperty على مثيل كائن DOM إلى عرض false

يستخدم مطوّرو البرامج في بعض الأحيان السمة hasOwnProperty للتحقّق من توفُّر موقع إلكتروني في عنصر. لن يعمل هذا الإجراء بعد الآن وفقًا للمواصفات لأنّ سمات DOM أصبحت الآن جزءًا من سلسلة النموذج الأوّلي ولا يفحص hasOwnProperty الكائنات الحالية إلا لمعرفة ما إذا كانت محدّدة عليها.

قبل استخدام Chrome 42 وتضمينه، سيتم عرض true.

> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");

true

في Chrome 43 والإصدارات الأحدث، سيتم عرض false.

> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");

false

ويعني هذا أنّه إذا كنت تريد التأكّد من أنّ السمة isContentEditable متاحة على العنصر، عليك التحقّق من النموذج الأولي على كائن HTMLElement. على سبيل المثال، يكتسب HTMLDivElement من السمة HTMLElement التي تحدّد السمة isContentEditable.

> HTMLElement.prototype.hasOwnProperty("isContentEditable");

true

أنت غير محظور باستخدام "hasOwnProperty". ننصح باستخدام المعامل in الأبسط إلى حدٍ كبير لأنّ هذا الإجراء سيتحقّق من الخاصية في سلسلة النموذج الأوّلي بالكامل.

if("isContentEditable" in div) {
    // We have support!!
}

لن يعرض Object.getOwnPropertyDescriptor على النسخة الافتراضية لكائن DOM واصف خاصية للسمات بعد الآن.

إذا كان موقعك يحتاج إلى الحصول على واصف الخصائص لسمة من كائن DOM، فستحتاج الآن إلى اتباع سلسلة النموذج الأولي.

إذا كنت ترغب في الحصول على وصف الخاصية في الإصدار 42 من Chrome والإصدارات الأقدم، فستكون قد أجريت ما يلي:

> Object.getOwnPropertyDescriptor(div, "isContentEditable");

Object {value: "", writable: true, enumerable: true, configurable: true}

وسيعرض Chrome 43 والإصدارات الأحدث undefined في هذا السيناريو.

> Object.getOwnPropertyDescriptor(div, "isContentEditable");

undefined

ويعني ذلك أنّه للحصول الآن على واصف السمة للسمة isContentEditable، عليك اتّباع سلسلة النموذج الأوّلي على النحو التالي:

> Object.getOwnPropertyDescriptor(HTMLElement.prototype, "isContentEditable");

Object {get: function, set: function, enumerable: false, configurable: false}

لن يتسلسل JSON.stringify سمات DOM بعد الآن

لا تسلسل JSON.stringify لخصائص DOM التي تتوفر في النموذج الأولي. على سبيل المثال، يمكن أن يؤثر ذلك في موقعك الإلكتروني إذا كنت تحاول إنشاء سلسلة من العناصر، مثل PushSubscription في الإشعارات الفورية.

كان الإصدار 42 من Chrome والإصدارات الأقدم التالية تعمل:

> JSON.stringify(subscription);

{
    "endpoint": "https://something",
    "subscriptionId": "SomeID"
}

لن يقوم Chrome 43 والإصدارات اللاحقة بتسلسل الخصائص التي تم تحديدها في النموذج الأولي وسيتم إرجاع كائن فارغ.

> JSON.stringify(subscription);

{}

سيتعين عليك تقديم طريقة التسلسل الخاصة بك، على سبيل المثال يمكنك إجراء ما يلي:

function stringifyDOMObject(object)
{
    function deepCopy(src) {
        if (typeof src != "object")
            return src;
        var dst = Array.isArray(src) ? [] : {};
        for (var property in src) {
            dst[property] = deepCopy(src[property]);
        }
        return dst;
    }
    return JSON.stringify(deepCopy(object));
}
var s = stringifyDOMObject(domObject);

ستؤدي الكتابة في خصائص القراءة فقط في الوضع المتشدد إلى ظهور خطأ.

من المفترض أن تتسبب الكتابة في خصائص القراءة فقط في طرح استثناء عند استخدام الوضع المتشدد. على سبيل المثال، اتبع الخطوات التالية:

function foo() {
    "use strict";
    var d = document.createElement("div");
    console.log(d.isContentEditable);
    d.isContentEditable = 1;
    console.log(d.isContentEditable);
}

أما بالنسبة إلى الإصدار 42 من Chrome والإصدارات الأقدم، فقد استمرت وظيفة واستمرت في تنفيذ الوظيفة بدون تنبيه صوتي، على الرغم من أن isContentEditable لم يتم تغييره.

// Chrome 42 and earlier behavior
> foo();

false // isContentEditable
false // isContentEditable (after writing to read-only property)

الآن في Chrome 43 وما يليه، سيكون هناك استثناء.

// Chrome 43 and onwards behavior
> foo();

false
Uncaught TypeError: Cannot set property isContentEditable of #<HTMLElement> which has only a getter

أواجه مشكلة، ماذا عليّ أن أفعل؟

اتبع الإرشادات أو اترك تعليقًا أدناه ودعنا نتحدث.

لقد شاهدتُ موقعًا إلكترونيًا به مشكلة، فماذا يجب أن أفعل؟

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

  • الإبلاغ عن مشكلة بشأن الموقع الإلكتروني المتأثر من خلال أداة تتبُّع المشاكل (Chrome)
  • يُرجى الإبلاغ عن مشكلة في رادار WebKit والإشارة إلى https://bugs.webkit.org/show_bug.cgi?id=49739.

أنا مهتم بشكل عام باتباع هذا التغيير