تعلّم jquery أساسيّات jQuery


محمد فوّاز عرابي

تُسهِّل مكتبة jQuery التّعامل مع محتويات صفحة HTML بعد أن يعرضها المتصفّح، وتوفّر أدوات تُساعدك في متابعة تفاعل المستخدم مع الصّفحة، وتحريك العناصر فيها، والتّواصل مع الخواديم دون إعادة تحميل الصّفحة. سنشرح هذه الأدوات بعد قليل. لنبدأ أوّلًا بالاطّلاع على أساسيّات jQuery، وكيف يمكن استخدام وظيفتها الأساسيّة: الوصول إلى عناصر مُحدَّدة في الصفحة وفعل شيءٍ ما بها.

ملاحظة: يفترض هذا الدّليل أنّك على علم بأساسيّات HTML ومُحدِّدات CSS. إن لم تكن تألف كيف يمكن استخدام مُحدّدات CSS للوصول إلى عناصر مُحدّدة في الصّفحة، فعليك أوّلًا تعلّم ذلك قبل الشروع في متابعة هذا الدّليل.

ما هذا الرمز: $؟

توفّر مكتبة jQuery الدّالّة jQuery، التي تتيح لك تحديد العناصر بمُحدّدات CSS.

var listItems = jQuery( 'li' );

إن قرأت من قبل برامج تستخدم jQuery، فلا بدّ أنّك اعتدت على هذا:

var listItems = $( 'li' );

كما ناقشنا في الجزء السّابق (أساسيّات JavaScript)، فكلّ الأسماء تكاد تكون سّليمة في JavaScript ما لم تبدأ برقم أو تحوي إشارة "-". ولذا فالاسم $ في المثال الأخير ليس إلّا اسمًا مُختصرًا للدّالّة jQuery، ولو اطّلعت على مصدر jQuery، لقرأت هذا قرب نهايته:

// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

عندما تستدعي الدّالّة ‎$()‎ وتمرّر لها مُحدّدًا، فإنّك تحصل على كائن jQuery جديدٍ. الدّوالّ في JavaScript هي الأخرى كائنات، وهذا يعني أنّ للدّالّة $jQuery بالطّبع) خصائص ووظائف أيضًا. مثلاً: يمكنك استخدام الخاصّة ‎$.support‎ لمعرفة ما الميزات الّتي يدعمها المتصفّح الحاليّ، كما يمكنك استخدام الوظيفة ‎$.ajax‎ لإرسال طلب AJAX.

ملاحظة: من الآن فصاعدًا سنستخدم $ بدلًا من jQuery في هذه السّلسلة سعيًا للاختصار. لاحظ أنّه إن احتوت صفحتك أكثر من مكتبة واحدة، فقد يُستخدم الاسم $ من مكتبة أخرى، ممّا يمنع عمل jQuery، فإن واجهتك مشكلة كهذه، جرّب استخدام jQuery.noConflict قبل تحميل المكتبات الأخرى.

‏‎$(document).ready()‎

قبل استخدام jQuery لفعل أيّ شيء في الصّفحة، علينا التأكّد من كون الصّفحة قد بلغت حالةً تسمح بتعديل محتوياتها. يمكن تنفيذ ذلك في jQuery بإحاطة برنامجنا ضمن دالّة ثمّ إمرار هذه الدّالة إلى ‎$(document).ready()‎. كما ترى في المثال التّالي، يمكن للدّالّة الّتي نمرّرها أن تكون مجهولة (بلا اسم):

$(document).ready(function() {
  console.log( 'ready!' );
});

هذا سيؤدّي إلى استدعاء الدّالّة الّتي مرّرناها إلى ‎.ready()‎ بعد أن يصبح المُستند (الصفحة) جاهزًا. ما الذي يحدث هنا؟ استخدمنا ‎$(document)‎ لإنشاء كائن jQuery من document في الصّفحة، ثمّ استدعينا الدّالّة ‎.ready()‎ على هذا الكائن، مُمرِّرين إليها الدّالّة الّتي نريد تنفيذها.

بما أنّك ستجد نفسك تُعيد كتابة هذا النّصّ مرارًا، فإنّ jQuery تقدّم لك طريقةً مُختصرةً لإنجازه، إذ تقوم الدّالّة ‎$()‎ بمهمّة مُختلفة عند إمرار دالّة إليها بدلًا من مُحدِّد CSS، وعندها تتصرّف وكأنّها اسم بديلٌ للوظيفة ‎$(document).ready()‎:

$(function() {
  console.log( 'ready!' );
});

ملاحظة: من الآن فصاعدًا، سنفترض أنّ النّصوص الّتي ترد في هذه السّلسلة مُحاطة بالعبارة ‎$(document).ready(function() { ... });‎، وسنترك هذه العبارة بغرض الإيجاز.

الوصول إلى العناصر

أبسط ما يمكن إنجازه بـjQuery تحديد بعض العناصر ثمّ فعل شيء ما بها. إن كنت تفهم مُحدّدات CSS، فستجد أنّ الوصول إلى بعض العناصر سهل ومباشر: ليس عليك إلا إمرار المُحدِّد المناسب إلى ‎$()‎.

$( '#header' ); // حدّد العنصر الّذي مُعرِّفه 'header'
$( 'li' );      // حدّد كل عناصر القوائم في الصّفحة
$( 'ul li' );   // حدّد كل عناصر القوائم الموجودة في قوائم غير مُرتّبة
$( '.person' ); // حدّد كل العناصر ذات الصّنف 'person'

من المهمّ أن تفهم أنّ أيّ تحديد تُجري لن يتضمّن إلّا العناصر الموافقة للمُحدّد والتي كانت موجودة في اللّحظة الّتي أجريت فيها التّحديد، بمعنى أنّك إذا كتبت ‎var anchors = $( 'a' );‎ ثمّ أضفت عنصر <a> إلى الصّفحة لاحقًا، فلن تحوي anchors العنصر الجديد.

طرق أخرى لإنشاء كائن jQuery

بالإضافة إلى إمرار مُحدّد بسيط إلى الدّالة ‎$()‎، يمكن إنشاء كائنات jQuery بطرق أخرى:

// أنشئ كائن jQuery من عنصر DOM
$( document.body.children[0] );

// أنشئ كائن jQuery من قائمة بعناصر DOM
$( [ window, document ] );

// أجرِ التّحديد بسياق عنصر DOM
var firstBodyChild = document.body.children[0];
$( 'li', firstBodyChild );

// أجرِ التّحديد ضمن تحديد سابق
var paragraph = $( 'p' );
$( 'a', paragraph );

هل يحتوي التّحديد الّذي أجريته على أيّة عناصر؟

ترغب أحيانًا في تنفيذ بعض الأوامر عندما يُطابق تحديدك عنصرًا أو أكثر فقط، ولكنّ الدّالّة ‎$()‎ تُعيدُ دومًا كائن jQuery، وهذا الكائن دائمًا صائب (truthy)، ولذا عليك فحص محتوى التّحديد لمعرفة إن كان يحوي أيّة عناصر.

تحذير: نصّ برمجيّ غير سليم

if ( $( '#nonexistent' ) ) {
  // خطأ! الأوامر هنا ستُنفَّذ دومًا!
}

if ( $( '#nonexistent' ).length > 0 ) {
  // صحيح! لن تُنفّذ الأوامر هنا إلّا إن احتوت الصّفحة على كائن مُعرّفه 'nonexistent'
}

بإمكاننا اختصار هذا الفحص أكثر بالاعتماد على كون 0 قيمة خاطئة (falsy):

if ( $( '#nonexistent' ).length ) {
  // لن تُنفّذ الأوامر هنا إلّا إن وجد عنصر مُطابق
}

الوصول إلى عناصر مُفردة من تحديد

إن كنت تحتاج التّعامل مع عنصر DOM خام من تحديد، فعليك الوصول إلى هذا العنصر من كائن jQuery. لنفترض مثلًا أنّك تريد الوصول إلى الخاصّة value لكائن <input> مباشرةً، عليك إذن التّعامل مع عنصر DOM الخام:

var listItems = $( 'li' );
var rawListItem = listItems[0]; // أو listItems.get( 0 )
var html = rawListItem.innerHTML;

لاحظ أنّه ليس بإمكانك استدعاء وظائف jQuery على عناصر DOM الخام، فلن يعمل المثال التّالي:

تحذير: نصّ برمجيّ غير سليم

var listItems = $( 'li' );
var rawListItem = listItems[0];
var html = rawListItem.html();
// Object #<HTMLInputElement> has no method 'html'

إن أردت العمل مع عنصر مُفرد في تحديد وأردت استخدام وظائف jQuery معه، فعليك إنشاء كائن jQuery جديد انطلاقًا منه باستخدام الدّالّة ‎.eq()‎، وإمرار دليل العنصر الّذي تريده:

var listItems = $( 'li' );
var secondListItem = listItems.eq( 1 );
secondListItem.remove();

جرب المثال في ساحة التّجربة (تأكد من ضغط زر Run with JS في هذا المثال وكل الأمثلة التالية)

إنشاء كائنات جديدة

للدّالّة $ دورٌ ثالث أخير: إنشاء عناصر جديدة. إن مرّرت قصاصة HTML إلى $()‎، فستُنشئ كائنًا جديدًا في الذّاكرة، بمعنى أنّ الكائن يُنشأ ولكن لا يُضاف إلى الصّفحة إلى أن تفعل ذلك بنفسك.

$( '<p>' ); // يُنشئ عنصر <p> بلا محتوى
$( '<p>Hello!</p>' ); // يُنشى عنصر <p> فيه نصّ
$( '<p class="greet">Hello!</p>' ); // يُنشى عنصر <p> فيه نصّ وله صنف

بإمكانك أيضًا إنشا عنصر جديد بإمرار كائنٍ يحوي معلومات تصف كيفيّة إنشاء العنصر:

$( '<p>', {
  html: 'Hello!',
  'class': 'greet'
});

لاحظ أنّه يجب أن نُحيط class بعلامتي اقتباس، لأنّ class كلمة محجوزة في JavaScript، وعدم إحاطتها بالعلامتين سيسبّب وقوع أخطاء في بعض المتصفّحات. راجع وثائق jQuery‏ لتفاصيل الخصائص المختلفة الّتي يمكنك تضمينها في هذا الكائن.

سنتعرّف كيف نُضيف العناصر في الصّفحة في الجزء القادم من السّلسلة، الّذي يشرح الانتقال عبر الصّفحة وتعديل محتوياتها.

التّعامل مع التحديدات

بعد إنشائك كائن jQuery يحوي تحديدًا، فإنّك غالبًا ما تريد فعل شيء ما به، وقبل ذلك عليك أن تتعرّف على أسلوب jQuery في التّعامل مع الكائنات.

فحص تحديد

بإمكاننا معرفة إن كان تحديد ما يُطابق معايير مُعيّنة باستخدام الوظيفة ‎.is()‎. أكثر الطّرق شيوعًا لاستخدام هذه الوظيفة تزويدها بمُحدِّد كمُعاملٍ مفرد لها، وعندها تُعيد true أو false حسب مُطابقة التّحديد للمُحدِّد:

$( 'li' ).eq( 0 ).is( '.special' ); // false
$( 'li' ).eq( 1 ).is( '.special' ); // true

بإمكانك تمرير كائن jQuery أيضًا إلى الوظيفة ‎.is()‎، أو حتّى كائن DOM خام، أو حتّى دالّة لإجراء اختبار أكثر تعقيدًا إن لزم. راجع الوثائق لمزيد من التّفاصيل.

وظائف القراءة والكتابة والسّرد الضّمنيّ

بعد عمل التّحديد، تتوفّر وظائف عديدة يمكنك استدعاؤها. تقع هذه الوظائف عمومًا في إحدى مجموعتين: وظائف القراءة (getters) ووظائف الكتابة (setters). فالأولى تعطينا معلومات عن التّحديد، والثّانية تُغيّر التّحديد بشكل من الأشكال. وفي معظم الحالات يقتصر عمل وظائف القراءة على العنصر الأول في التّحديد (‎.text()‎ إحدى استثناءات هذه القاعدة)؛ أمّا وظائف الكتابة فتشمل بعملها كلّ العناصر في التّحديد، مستخدمةً ما يُعرف بالسّرد الضّمنيّ (implicit iteration).

معنى السّرد الضّمنيّ أنّ jQuery ستمرّ تلقائيًّا على كلّ العناصر في التّحديد عندما تستدعي وظيفة كتابة على هذا التّحديد، أيّ أنّه ليس عليك استدعاء وظيفة على كلّ عنصر في التّحديد بمفرده عندما تريد فعل شيء على كل العناصر في تحديد واحدٍ، بل اكتفِ باستدعاء هذه الوظيفة على التّحديد نفسه، وستفهم jQuery أنّ عليها تنفيذه على كلّ العناصر في التّحديد.

لنفترض أنّنا نريد تغيير نصّ HTML في كل عناصر القوائم في الصّفحة، ولفعل ذلك علينا استخدام الوظيفة ‎.html()‎ الّتي تقوم بتغيير نصّ HTML في كلّ عناصر القوائم المُحدّدة.

$( 'li' ).html( 'New HTML' );

جرب المثال في ساحة التّجربة

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

$( 'li' ).html(function( index, oldHtml ) {
  return oldHtml + '!!!'
});

جرب المثال في ساحة التّجربة

السّرد الصّريح (Explicit Iteration)

في بعض الأحيان، لن تلبّي وظائف jQuery الأصليّة المهمّة الّتي تريد إنجازها بدقّة، وسيكون عليك حينها المرور على العناصر في التّحديد بشكل صريح، وهذا ما تتيحه الوظيفة ‎.each()‎. في المثال التّالي نستخدمها لإضافة وسم <b> في بداية عنصر القائمة، يحوي دليل العنصر:

$( 'li' ).each(function( index, elem ) {
  // this: عنصر DOM الخام الحالي
  // index: دليل العنصر الحالي في التّحديد
  // elem: عنصر DOM الخام الحالي (مثل this)
  $( elem ).prepend( '<b>' + index + ': </b>' );
});

جرب المثال ساحة التّجربة

ملاحظة: ستلاحظ أنّ عنصر DOM الخام مُتاح ضمن الدّالّة الّتي نُمرّرها إلى ‎.each()‎ بطريقتين: الأولى عبر this والثّانية عبر elem. وكما ناقشنا في الجزء السّابق (أساسيّات JavaScript)، فإنّ this كلمة خاصّة في JavaScript تُشير إلى الكائن الّذي يُمثّل سياق الدّالّة الحاليّ. وفي jQuery فإنّ this تُشير في معظم الحالات إلى عنصر DOM الخام الّذي تعمل عليه الدّالّة الحاليّة. لذا فإنّها تُشير في حالة ‎.each()‎ إلى العنصر الحاليّ في مجموعة العناصر الّتي نسردها.

السَّلسَلة (Chaining)

من أكثر الأمور فائدةً في jQuery إمكانيّة "سَلسَلة" الوظائف معًا. هذا يعني أنّ بإمكاننا استدعاء سلسِلة من الوظائف على تحديدٍ ما دون الحاجة لإعادة التّحديد أو حفظه في متغيّر. بإمكاننا حتّى إنشاء تحديدات جديدة بناء على التّحديد السّابق، دون كسر السّلسلة:

$( 'li' )
  .click(function() {
    $( this ).addClass( 'clicked' );
  })
  .find( 'span' )
    .attr( 'title', 'Hover over me' );

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

var listItems = $( 'li' );
var spans = listItems.find( 'span' );

listItems
  .click(function() {
    $( this ).addClass( 'clicked' );
  });

spans.attr( 'title', 'Hover over me' );

خاتمة

لدينا الآن معلومات ممتازة عن تفاصيل عمل jQuery؛ وسنستعرض في الجزء القادم كيف يمكننا تطبيق هذه المعلومات لإنجاز أشياء حقيقيّة بها!

مصادر إضافية

ترجمة (بشيء من التصرف) للجزء الثاني من سلسلة  jQuery Fundamentals لمؤلّفتها Rebecca Murphey.



1 شخص أعجب بهذا


تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن