Feature stimulation


السلام عليكم و رحمه الله تعالى و بركاته

مقدمه
Browser Sniffing
Object Detection
Feature Stimulation


مقدمه

عندما تقوم بكتابه إطار عمل Framework فى بيئه غير مستقره مثل بيئه المتصفحات ، فإن كتابه كود و إفتراض انه سيعمل بشكل صحيح فى كل المتصفحات هو درب من دروب الخيال – المشكله تتناسب طرديا مع زياده امكانيات الاطار-  لأن هناك بعض الامكانيت موجود فى بعض المتصفحات و غير موجوده فى البعض الاخر ، او موجوده فى متصفح بشكل صحيح و فى الاخر لا تعمل بشكل صحيح ، لذلك فى الفتره الماضيه قام المطورين بممارسه بعض التكنيكات فى كتابه الكود حتى يظل ثابتا فى مواجهه العديد من البيئات المختلفه بدون اخطاء ، اما اذا كنت تستخدم جافاسكربت فى بيئه مستقره مثل AIR او من اجل Firefox extention  أو السيرفر Jaxer فلن يكون هناك عبأ كبير عليك لأن جميع الوظائف ستعمل كما ملعن عنها فى التوثيق و كما اعتدت استخدامها .

Browser Sniffing

هذا التكنيك يقوم على فحص ماهيه المتصفح –  هل المتصفح IE – و يقوم بتغير مسار منطق الكود بناءا على هذه النتيجه ، و لكنه لا يضمن وجود الميزه التى تريد استخدامها ، و لا يضمن عملها بشكل صحيح ، يتم ذلك الفحص عن طريق اختبار ميزه معينه و مميزه لهذا المتصفح مثل اختبار وجود ActiveXObject الذى هو دليل قاطع على استخدام Internet explorer كما يوضح الكود التالى :

var isIE = window.ActiveXObject ? true : false;

الكود السابق يستخدم trenary operator ليفحص هل الخاصيه ActiveXObject موجود فى الكائن window و هذا دليل على ان المتصفح IE ، و عليه يمكن تغيير مسار الكود كما يلى بفرض ان IE يستخدم طريقه بعينها فى عمل شىء معين مثل ajax مثلا :

if(isIE){
    // do something specific to IE
}else{
    // do something else
}

يمكنك أيضا فحص navigator.userAgent الذى ينتج عنه نص يمثل كل متصفح ، يرسله المتصفح إلى السيرفر فى رسائل بروتكول HTTP حتى يتعرف عليه السيرفر ، لكن عيب هذه الميزه ان ال userAgent يمكن تغييره عن طريق extention مثلما فى متصفح فايرفوكس ، او يمكن تغيرها من المتصفح نفسه مثل Safari كما يوضح الكود التالى من مكتبه jQuery 1.2.6 :

var userAgent = navigator.userAgent.toLowerCase();
jQuery.browser = {
    safari: /webkit/.test( userAgent ),
    opera: /opera/.test( userAgent ),
    msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
    mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
};

يقوم الكود السابق من مكتبه jQuery نسخه 1.2.6 بفحص المتغير userAgent داخل الكائن jQuery.browser من خلال مقارنته ببعض ال RegExp التى تميز كل متصفح عن الاخر ، فمثلا وجود كلمه Opera فى ال userAgent تدل على انا المتصفح Opera – او متصفح تانى بيستعبط – ، و فى اخر اختبار الخاص ب Mozilla يتأكد من ان كلمه Mozilla موجوده فى ال userAgent و أن كلمتى compatible و webkit غير موجودتين ، يستخدم jQuery نتائج هذا الاختبار كالتالى :

if(jQuery.browser.msie){
    // do something specific to IE
}
else if (jQuery.browser.mozilla){
    // do something for mozilla browsers
}

فى النسخه الجديد من jQuery النسخه 1.3 فام john resig بإستخدام تكنيك feature stimulation و قام بوضع تعليق داخل الكود بأن jQuery.browser موجود فقط من اجل ال backward compatibility و ال plugins و ان jQuery لا يستخدمه و بالتالى فرصه وجوده فى النسخ القادمه قليل .

// Use of jQuery.browser is deprecated
// It’s included for backwards compatibility and plugins
// although they should work to migrate away

Object Detection

هذا التكنيك يضمن لك ان الكائن الذى تريد إستخدامه موجود لا يهمه متصفح بعينه او بيئه بعينها ، لكنه لا يضمن هل يعمل بشكل صحيح ام لا ، ستجده كثيرا فى امثله استخدام Ajax حيث يفحص اولا وجود الكائن XMLHttpRequest و اذا كان متاحا يستخدمه و ان لم يكن متاح يستخدم بديل له مثل فحص وجود الكائن ActiveXObject  يوضح الكود التالى :

if(window.XMLHttpRequest){
    // do something with XMLHttpRequest 
} else if(window.ActiveXObject){
    // do something with ActiveXObject
}

كما يوجد ايضا هذه التكنيك فى الكود الذى يتعامل مع ال DOM حيث يختبرا مثلا وجود الوظيفه getElementsByClassName بالكائن document التى موجوده فى المتصفحات الجديده ، ان لم يجد الكائن يستخدم طريق اخر لإدراج هذه الامكانيه :

if(document.getElementsByClassName){
    // do something with getElementsByClassName
}else{
    // find a nother way to implement it 
}

للمزيد

Feature Stimulation

ال Feature stimulation هو اجدد تكنيك لفحص هل تعمل ميزه بطريقه صحيحه ام لا او وجود خاصيه او وظيفه بعينها ، لأن هناك اختلافات بين المتصفحات فى طريقه عمل الكثير من الوظائف ، استخدم john resig هذا التكنيك بدلا من browser userAgent sniffing فى نسخه jQuery1.3 ، يوجد شرح كامل لهذه التكنيك فى محاضره DOM is amess التى وضعتها من قبل ، و ايضا مشروحه فى محاضره jQuery internals التى وضعتها من قبل فى سلسله محاضرات the ajax experience ، هذا الكود جزأ من مكتبه jQuery 1.3  لكنى حذفت منه الكثير ، ابحث داخل jQuery عن jQuery.support  و ستجد الكود كامل :

var div = document.createElement("div");
div.style.display = "none";
div.innerHTML = '   <table></table>
<a style="color:red;opacity:.5;">a</a>
<object><param/></object>';

var all = div.getElementsByTagName("*")
var a = div.getElementsByTagName("a")[0];

jQuery.support = {
    // IE strips leading whitespace when .innerHTML is used
    leadingWhitespace: div.firstChild.nodeType == 3,
    // Make sure that tbody elements aren't automatically inserted
    // IE will insert them into empty tables
    tbody: !div.getElementsByTagName("tbody").length,
    // Make sure that you can get all elements in an <object> element
    // IE 7 always returns no results
    objectAll: !!div.getElementsByTagName("object")[0]
    .getElementsByTagName("*").length,
    // Get the style information from getAttribute
    // (IE uses .cssText insted)
    style: /red/.test( a.getAttribute("style") ),
    // Make sure that element opacity exists
    // (IE uses filter instead)
    opacity: a.style.opacity === "0.5",
}

السطر الاول يقوم بإنشاء عنصر من نوع div و السطر الثانى يخفيه عن طريق اعطاء الخاصيه style.display القيمه none ، السطر الثالث يقوم بوضع العديد من العناصر داخل div ، السطر الرابع يضع ال collection التى تمثل جميع العناصر التى داخل ال div  داخل المتغير all ، السطر الخامس ينشأ المتغير a الذى يمثل العنصر <a> داخل ال div ، ثم يبدأ السحر .

الاختبارات كلها داخل object literal بإسم jQuery.support حتى يتم استخدامها فيما بعد مثلا كالاتى jQuery.support.style .

الاختبار الاول leadingWhiteSpace يختبر هل العنصر الاول داخل ال div من نوع whitespace لأن IE ينزع ال whitespace عندما يتم حقنها عن طريق innerHTML و المتصفحات الاخرى لا تنزع ال whitespace و بذلك سيفشل هذا الاختبار مع IE و سينجح مع باقى المتصفحات .

الأختبار الثانى tbody يختبر هل المتصفح يحقن العنصر tbody داخل ال table الفارغ ، هذا الاختبار سيفشل مع جميع المتصفحات ، عدا انترنت اكسبلورر لأنه يحقن العنصر tbody داخل ال table الفارغ .

الأختبار الثالث objectAll يفحص هل المتصفح يجلب العناصر داخل العنصر object ام لا ، هذا الاختبار ينجح مع كل المتصفحات عدا انترنت اكسبلورر 7 لأنه لا يرجع العناصر التى داخل العنصر object مثل العنصر embed .

الاختبار الرابع style ، يفحص هل المتصفح يستخدم style مع getAttribute ، هذا الاختبار ينجح مع كل المتصفحات عدا انترنت اكسبلورر الذى يستخدم cssText بدلا من style .

الاختبار الخامس opacity يختبر هل المتصفح يستخدم opacity لمعرفه درجه الشفافيه للعنصر ، جميع المتصفحات ستنجح فى هذا الاختبار عدا انترنت اكسبلورر الذى يستخدم filter.alpha ، و بذلك يمكن استخدام هذا الاختبار لتغير مسار الكود كما يوضح الكود التالى :

if(jQuery.support.tbody){
    // do something
} else {
    // do something else
}

ميزه هذا التكنيك انه دقيق 100% حيث يختبر الميزه قبل استخدامها فعليا ، لا يكتفى بمعرفه انها موجوده مثل طريقه object detection ، كما ان اذا تم اصلاح هذه الميزه فى الاصدارات القادمه من هذا المتصفح فإن الكود سيظل ثابتا امام التغيير .

لا تستخدم Browser userAgent sniffing إطلاقا ، و إستخدم object detection مع الكائنات المستقره او لمعرفه انه موجوده فقط ، و طريقه feature stimulation لمعرفه ان الميزه موجوده و تعمل بطريقه صحيحه .

الأوسمة: ,

6 تعليقات to “Feature stimulation”

  1. almhajer Says:

    صحيح كما ذكرت اخي وانا من فترة جربت دالة innerHTML مع نفس العنصر مثلا
    مثال
    document.getElementById(‘one’).innerHTML=’تجربة’;
    alert(document.getElementById(‘tow’).innerHTML);

    سوف تلاحظ انه لايتم اطلاق الرسالة على الاطلاق في اكسبلور مع العلم يعمل في فايرفوكس والاخرون لكن المفاجئة انه غير الوسم الى اخر غير نفس النوع
    مثال
    document.getElementById(‘one’).innerHTML=’تجربة’;
    alert(document.getElementById(‘tow’).innerHTML);

    وكماذكرت سابقا المشكلة في تواجد الدالة او الخاصية او انها متوفرة المشكلة الحقيقية اذا عملت بشكل صحيح
    بارك الله فيك وشكرا جزيلا

  2. almhajer Says:

    ولي تعليق اخر على الكود
    tbody: !div.getElementsByTagName(“tbody”).length,

    objectAll: !!div.getElementsByTagName(“object”)[0]
    .getElementsByTagName(“*”).length,
    لماذا استخدم اول مرة !
    والثانية !! وشكرا جزيلا

  3. mostafa farghaly Says:

    @almhajer : إستخدم !! حتى تحول الرقم إلى boolean لأن انترنت اكسبلورر سيرجع القيمه صفر ، لكن جكويرى يريد الاستعلام عن booleans لذلك يتم تحويل تلك القيمه إلى false ، اما فى المتصفحات الاخرى سترجع واحد الذى سيتحول إلى true ، ان لم تضع !! فإن هذا الكود
    jQuery.support.objectAll سنتج عنه واحد ، نحن نريد true و لذلك قمنا بإضافه !!

    و قمنا بإضافه ! فى المثال الاول حتى يحول ال 0 إلى true و يحول ال 1 إلى flase ، قد يبدو هذا غير منطقيا ، لكنه يستخدمه داخل المكتبه بهذه الطريقه
    if(! jQuery.support.tbody
    لذلك الكود سيتحول ل true مع IE ، و ستحول إلى false مع الباقى .

  4. almhajer Says:

    شكرا على الايضاح هذا يدل ان جاك كيوري مستوعب اسلوب المستعرض بشكل كبير
    بارك الله فيك وشكرا جزيلا

  5. moatazpharma Says:

    العمل علي ملائمة كود لجميع محركات البحث تساعد كثيرا الاخوة اصحاب الاعمال الكثير وليس الهواه

  6. iesuccess Says:

    جزيت كل الخير
    نسأل الله لك التوفيق

أضف تعليقاً

إملأ الحقول أدناه بالمعلومات المناسبة أو إضغط على إحدى الأيقونات لتسجيل الدخول:

WordPress.com Logo

أنت تعلق بإستخدام حساب WordPress.com. تسجيل خروج   / تغيير )

صورة تويتر

أنت تعلق بإستخدام حساب Twitter. تسجيل خروج   / تغيير )

Facebook photo

أنت تعلق بإستخدام حساب Facebook. تسجيل خروج   / تغيير )

Google+ photo

أنت تعلق بإستخدام حساب Google+. تسجيل خروج   / تغيير )

Connecting to %s


%d مدونون معجبون بهذه: