اذهب إلى المحتوى

لوحة المتصدرين

  1. Mohammed Abu Yousef

    Mohammed Abu Yousef

    الأعضاء


    • نقاط

      5

    • المساهمات

      245


  2. سامح أشرف

    سامح أشرف

    الأعضاء


    • نقاط

      4

    • المساهمات

      2934


  3. أحمد حبنكة

    أحمد حبنكة

    الأعضاء


    • نقاط

      4

    • المساهمات

      338


  4. علي العبدالله2

    • نقاط

      3

    • المساهمات

      254


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 02/01/21 في كل الموقع

  1. وعليكم السلام ورحمة الله وبركاته أولاً نعم يمكن استبدال connect بـuseSelector، كلاهما طريقتان لجلب state من redux إلى component الحالية. من ناحية الوظيفة لا يوجد فرق بينهما. الفرق الوحيد هو أن useSelector تستخدم React Hooks وهي طريقة جديدة لتعريف state ضمن function components أما connect فيستعمل ما يسمى HoC أي Higher Order Component وهي حين يكون لدينا تابع يأخذ component class or function كمعامل ويرد component class آخر. إذاً ماذا نستخدم طالما أنهما يؤديان نفس الوظيفة؟ اﻷمر يعتمد على ذوقك، شخصياً أجد useSelector أجمل وأسهل للفهم وتوفر علي بعض boilerplate، ربما يجد آخرون connect أفضل أو ﻷنهم اعتادوا عليها. أما بالنسبة لما هو شائع فاستخدام Hooks أصبح شائعاً جداً هذه اﻷيام وبالغالب useSelector معه إلا في التطبيقات التي ما زالت تعمل بنسخة React أقل من 16.8 والله أعلم. بالتوفيق وشكراً لك
    4 نقاط
  2. هل من الممكن تعلم لغه c++ بجانب دوره تطوير وجهات المستخدم نظرا لاني اريد تعلم مفهوم البررمجه بشكل عام بما لا يتوفر في هذه الدوره وايضا اتجنب التشتت؟
    2 نقاط
  3. لدي موقع ولدي صفحة واحدة يوجد سلايدر فيها فقط استطعت ان اضع السلايدر iframe داخل الموقع لكن الروابط عند الضغط عليها تظهر داخل الفريم هل يوجد طريقة ما تجعل الروابط داخل iframe تفتح في نفس النافذة ؟
    2 نقاط
  4. مرحبًا @Eslam Elbeak، هنالك فرق كبير بين Wordpress و Laravel حيث أن ورد بريس هو إطار عمل جاهز يحتاج إلى القليل من التعديلات ليصبح لديك موقع ويب جاهز من واجهات أمامية وخلفية. ويوفر لك وردبريس إضافات plugin يمكنك إضافتها إلى موقع الوردبريس الخاص بك ليصبح بالشكل الذي تريد، وغالبًا مستخدمي ورد بريس يستخدمون ثيمات جاهزة للورد بريس، وبهذا الأمر لم يبقى الكثير من العمل للمبرمج. أما إطار العمل لاريفيل فمن خلاله تقوم أنت ببناء الواجهات الخلفية للموقع الذي ترغب به من الصفر ومجال عمله مختلف عن مجال عمل الوردبريس، فالورد بريس يحتاج إلى معرفة قليلة باللغة PHP أما لاريفيل فأنت بحاجة إلى معرفة برمجة لغة PHP بشكل جيد لكي تفهم إطار العمل هذا بشكل أكبر، ويسمح لك لاريفيل بتحويل أي فكرة لديك إلى صفحة ويب رسمية، أما وردبريس فهو محدود. لهذا أنصحك في البداية تعمل على تعلم لاريفيل ﻷنه سوف ينفعك أكثر كمبرمج ومن ثم تعلم وردبريس ﻷنه لايحتاج إلى الكثير من الجهد فمبرمج لاريفيل لن يجد صعوبة أبدًا في تعلم وردبريس خلال ساعات قليلة. أتمنى لك التوفيق.
    2 نقاط
  5. الإصدار 1.0.0

    14180 تنزيل

    ما زال التسويق يمثل محور العمل في أي شركة، فهو يتعلق بتحديد حاجات الزبائن وإشباعها من خلال توفير منتجات قيّمة وتوضيح مزاياها لهم، ويمكن اعتماد ما سبق تعريفًا موجزًا للتسويق ويعرّف هذا الكتاب القارئ على استراتيجيات التسويق وأدواته التي يستخدمها المسوقون لتسويق منتجاتهم. لقد حرص المؤلف في هذا الكتاب على إبراز مجالات التسويق المختلفة وكيفية الدمج بينها لبناء إستراتيجية تسويق مترابطة، لذلك عمد في هذا الكتاب إلى تعريف كل مجال من مجالات التسويق وتوضيح نقاط الضعف والقوة فيه، ثم تطرق إلى كيفية الدمج بين أدوات التسويق لبناء خطة إستراتيجية متكاملة. ويبدأ الكتاب بنقاش حول التخطيط بشكل عام، ثم يتناول بالتفصيل الخطوات الأولى لبناء الخطة التسويقية، ثم ينتهي بأفضل الأساليب المتاحة للمسوّقين. ويهدف الكتاب إلى التعريف بكيفية تخطيط برنامج تسويقي فعّال وتنفيذه وتقييمه من الألف إلى الياء. يتناول فصل "مقدمة إلى التسويق" تأثير الأحداث العالمية على أساليب التسويق، فيما يتطرق فصل "التسويق في الأسواق العالمية" إلى تأثير التسويق على العالم، كذلك يتناول الكتاب في جميع أجزائه أمثلة مختلفة من السوق العالمي لشركات على أرض الواقع، إذ تساعد الأمثلة والقصص الواقعية القارئ على الربط بين استيعاب النظرية وتطبيقها، وتتسم هذه الأمثلة بكونها حيّة ومعاصرة ومتنوعة، فهي تتراوح بين قائمة فورتشن لأكبر 500 شركة أمريكية، إلى الشركات الصغيرة الخاصة كذلك يتناول الكتاب أمثلة لشركات دولية من جميع الأحجام. يناقش الكتاب أيضًا في مواضع مختلفة منه أهمية التكنولوجيا وتأثيراتها المختلفة إذ لا يخفى أثر التكنولوجيا على أساليب التسويق، كما تُعد شبكة الإنترنت وقواعد البيانات وأجهزة التعقب ومحاكيات السوق أمثلة جيّدة تعكس مدى تأثير التكنولوجيا في عالم التسويق. بني هذا الكتاب على كتاب Introducing Marketing لمؤلفه Prof. John Burnett (البروفيسور جون بورنِت) المرخص تحت رخصة CC BY والذي ألف وشارك في تأليف عشرين كتابًا وما يربو على 60 بحثًا أكاديميًا، وقد تقاعد مؤخرًا بعد 41 عامًا من العمل محاضرًا في مجال التسويق. ولقد انصبّ معظم تركيز البروفيسور خلال السنوات العشرين الماضية على التسويق لصالح المنظمات غير الربحية وقد كانت حصيلة مجهوداته إقامة العديد من ورش العمل، ووضع الكثير من الخطط التسويقية، بالإضافة إلى تأليف كتاب بعنوان "Nonprofit Marketing Best Practices" (أفضل أساليب التسويق للمنظمات غير الربحية). ساهم بالعمل على هذا الكتاب، علاء أيمن ترجمةً، والطبيب نادر حوري والبروفيسور علي اليعقوبي مراجعةً وتدقيقًا، وجميل بيلوني تحريرًا وإشرافًا، وأخرجه فنيًا فرج الشامي. نرجو أن نكون قد وفقنا في هذا العمل بتوفير مرجع أكاديمي نافع يثري المكتبة العربية. هذا الكتاب مرخص بموجب رخصة المشاع الإبداعي Creative Commons «نسب المُصنَّف - غير تجاري - الترخيص بالمثل 4.0». نشرنا فصول هذا الكتاب على شكل مقالات مبسَّطة على الويب تحت الوسم «مدخل إلى التسويق» لتسهيل قراءتها: الفصل الأول: مقدمة إلى التسويق مقدمة إلى علم التسويق أنواع التسويق الأساسية مكونات التسويق الاستراتيجية الفصل الثاني: فهم السوق والتعامل معه فهم السوق والتعامل معه تجزئة المستهلكين في العملية التسويقية تجزئة الشركات في العملية التسويقية الفصل الثالث: بحوث التسويق وصناعة القرار بحوث التسويق وصناعة القرار التسويقي تصميم خطة البحث التسويقي تنفيذ خطة البحث التسويقي الفصل الرابع: فهم سلوك المستهلكين فهم سلوك المستهلكين العوامل المؤثرة في سلوك المستهلكين سلوك الشراء لدى الشركات الفصل الخامس: أثر العوامل الخارجية على عملية التسويق أبرز العوامل السياسية والاقتصادية والقانونية المؤثرة على عملية التسويق أهم الاتجاهات الاجتماعية المؤثرة على عملية التسويق الفصل السادس: التسويق في الأسواق العالمية التسويق العالمي: الأهداف والأسباب والمعوقات والمراحل كيف تؤثر البيئة المحيطة على التسويق العالمي؟ الفصل السابع: طرح المنتج وإدارته تعريف المنتج وأنواعه التخطيط للمنتج واستراتيجيات الدخول إلى السوق تطوير منتج جديد خطوة بخطوة الفصل الثامن: التواصل مع الأسواق الاتصال التسويقي المتكامل: تعريفه وأهدافه وأنواعه أدوات الاتصال التسويقي المتكامل الفصل التاسع: تسعير المنتج أهداف تسعير المنتج، واستراتيجياته المختلفة كيف تختار السعر الملائم للمنتج؟ الفصل العاشر: قنوات توزيع المنتج قنوات توزيع المنتج: مهامها، وأبرز مؤسساتها كيف تدير قنوات توزيع المنتج؟
    1 نقطة
  6. الإصدار 1.0.0

    116596 تنزيل

    سطع نجم لغة البرمجة بايثون في الآونة الأخيرة حتى بدأت تزاحم أقوى لغات البرمجة في الصدارة وذاك لمزايا هذه اللغة التي لا تنحصر أولها سهولة كتابة وقراءة شيفراتها حتى أصبحت الخيار الأول بين يدي المؤسسات الأكاديمية والتدريبية لتدريسها للطلاب الجدد الراغبين في الدخول إلى مجال علوم الحاسوب والبرمجة. أضف إلى ذلك أن بايثون لغةً متعدَّدة الأغراض والاستخدامات، لذا فهي دومًا الخيار الأول في شتى مجالات علوم الحاسوب الصاعدة مثل الذكاء الصنعي وتعلم الآلة وعلوم البيانات وغيرها، كما أنَّها مطلوبة بشدة في سوق العمل وتعتمدها كبرى الشركات التقنية. دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن بني هذا العمل على كتاب «How to code in Python» لصاحبته ليزا تاغليفيري (Lisa Tagliaferri) وترجمه إلى العربية محمد بغات وعبد اللطيف ايمش، وحرره جميل بيلوني، ويأتي شارحًا المفاهيم البرمجية الأساسية بلغة بايثون، ونأمل في أكاديمية حسوب أن يكون إضافةً نافعةً للمكتبة العربيَّة وأن يفيد القارئ العربي في أن يكون منطلقًا للدخول إلى عالم البرمجة من أوسع أبوابه. رُبط هذا الكتاب مع توثيق لغة بايثون في موسوعة حسوب لتسهيل عملية الاطلاع على أي جزء من اللغة مباشرة وقراءة التفاصيل باللغة العربية. هذا الكتاب مرخص بموجب رخصة المشاع الإبداعي Creative Commons «نسب المُصنَّف - غير تجاري - الترخيص بالمثل 4.0». يمكنك قراءة فصول الكتاب على شكل مقالات من هذه الصفحة، «المرجع الشامل إلى تعلم لغة بايثون»، أو مباشرةً من الآتي: المقال الأول: دليل تعلم بايثون اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3 المقال الثاني: تثبيت بايثون 3 وإعداد بيئتها البرمجية المقال الثالث: كيف تكتب أول برنامج لك المقال الرابع: كيفية استخدام سطر أوامر بايثون التفاعلي المقال الخامس: كيفية كتابة التعليقات المقال السادس: فهم أنواع البيانات المقال السابع: مدخل إلى التعامل مع السلاسل النصية المقال الثامن: كيفية تنسيق النصوص المقال التاسع: مقدمة إلى دوال التعامل مع السلاسل النصية المقال العاشر: آلية فهرسة السلاسل النصية وطريقة تقسيمها المقال الحادي عشر: كيفية التحويل بين أنواع البيانات المقال الثاني عشر: كيفية استخدام المتغيرات المقال الثالث عشر: كيفية استخدام آلية تنسيق السلاسل النصية المقال الرابع عشر: كيفية إجراء العمليات الحسابية المقال الخامس عشر: الدوال الرياضية المضمنة المقال السادس عشر: فهم العمليات المنطقية المقال السابع عشر: مدخل إلى القوائم المقال الثامن عشر: كيفية استخدام توابع القوائم المقال التاسع عشر: فهم كيفية استعمال List Comprehensions المقال العشرون: فهم نوع البيانات Tuples المقال الحادي والعشرين: فهم القواميس المقال الثاني والعشرين: كيفية استيراد الوحدات المقال الثالث والعشرين: كيفية كتابة الوحدات المقال الرابع والعشرين: كيفية كتابة التعليمات الشرطية المقال الخامس والعشرين: كيفية إنشاء حلقات تكرار while المقال السادس والعشرين: كيفية إنشاء حلقات تكرار for المقال السابع والعشرين: كيفية استخدام تعابير break وcontinue وpass عند التعامل مع حلقات التكرار المقال الثامن والعشرين: كيفية تعريف الدوال المقال التاسع والعشرين: كيفية استخدام *args و**kwargs المقال الثلاثين: كيفية إنشاء الأصناف وتعريف الكائنات المقال الحادي والثلاثين: فهم متغيرات الأصناف والنسخ المقال الثاني والثلاثين: وراثة الأصناف المقال الثالث والثلاثين: كيفية تطبيق التعددية الشكلية (Polymorphism) على الأصناف المقال الرابع والثلاثين: كيف تستخدم منقح بايثون المقال الخامس والثلاثين: كيفية تنقيح شيفرات بايثون من سطر الأوامر التفاعلي المقال السادس والثلاثين: كيف تستخدم التسجيل Logging المقال السابع والثلاثين: كيفية ترحيل شيفرة بايثون 2 إلى بايثون 3
    1 نقطة
  7. تَسمَح بعض اللغات البرمجية كائنية التوجه (object-oriented programming)، مثل C++‎، للصَنْف بأن يَتمدَّد (extend) من أكثر من مُجرّد صَنْف أعلى (superclass) واحد، وهو ما يُعرَف باسم الوراثة المُتعدّدة (multiple inheritance). بالرسم التالي مثلًا، يَتمدَّد الصنف E من صنفين أعليين (superclasses) مباشرةً، هما الصنفين A و B، بينما يَتمدَّد الصنف F من ثلاثة أصناف أعلين (superclasses) مباشرةً: أراد مُصمِّمي الجافا أن يجعلوا اللغة بسيطة على نحو معقول، ولمّا وجدوا أن مزايا الوراثة المُتعدّدة (multiple inheritance) لا تَستحِقّ ما يُقابِلها من تعقيد مُتزايد، فإنهم لم يُدعِّموها باللغة. ومع هذا، تُوفِّر الجافا ما يُعرَف باسم الواجهات (interfaces) والتي يُمكِن اِستخدَامها لتحقيق الكثير من أهداف الوراثة المُتعدّدة. لقد تَعرَّضنا -بالقسم ٤.٥- لواجهات نوع الدالة (functional interfaces) وعلاقتها بتعبيرات لامدا (lambda expressions)، ورأينا أنها تُخصِّص تابعًا (method) وحيدًا. في المقابل، يُمكِن للواجهات (interfaces) أن تَكُون أكثر تعقيدًا بمراحل كما أن لها استخدامات آخرى كثيرة. من غَيْر المُحتمَل أن تحتاج إلى كتابة واجهات (interfaces) خاصة بك حاليًا؛ فهي ضرورية فقط للبرامج المُعقَّدة نسبيًا، ولكن هنالك عدة واجهات (interfaces) مُستخدَمة بحزم جافا القياسية (Java's standard packages) بطرائق مُهِمّة وتحتاج إلى تَعلُّم طريقة اِستخدَامها. تعريف الواجهات (interfaces) وتنفيذها (implementation) لقد تَعرَّضنا لمصطلح "الواجهة (interface)" ضِمْن أكثر من سياق، سواء فيما يَتَعلَّق بالصناديق السوداء (black boxes) في العموم أو فيما يَتَعلَّق بالبرامج الفرعية (subroutines) على وجه الخصوص. تَتكوَّن واجهة أي برنامج فرعي (subroutine interface) من اسمه، ونوعه المُعاد (return type)، وعدد مُعامِلاته (parameters) وأنواعها. تُمثِل تلك المعلومات كل ما أنت بحاجة إلى مَعرِفته لكي تَتَمكَّن من استدعاء البرنامج الفرعي. بالإضافة إلى ذلك، يَمتلك أي برنامج فرعي جزءًا تّنْفيذيًا (implementation)، هو كتلة الشيفرة المُعرِّفة له (defines) والتي تُنفَّذ عند استدعاءه. بلغة الجافا، كلمة interface هي كلمة محجوزة تَحمِل معنًى تقنيًا إضافيًا. وفقًا لهذا المعنى، تَتكوَّن الواجهة من مجموعة من واجهات توابع النُسخ (instance method interfaces) بدون أجزائها التّنفيذية (implementations). يستطيع أي صنف أن يُنفِّذ (implement) واجهة معينة بتوفير الأجزاء التّنْفيذية (implementation) لجميع التوابع المُخصَّصة ضِمْن تلك الواجهة. اُنظر المثال التالي لواجهة (interface) بسيطة جدًا بلغة الجافا: public interface Strokeable { public void stroke(GraphicsContext g); } تبدو الشيفرة بالأعلى مشابهة لتعريف صنف (class definition) باستثناء حَذْف الجزء التّنْفيذي (implementation) للتابع stroke()‎. إذا أراد صنف معين أن يُنفِّذ تلك الواجهة Strokeable، فلابُدّ له من أن يُوفِّر جزءًا تّنْفيذيًا للتابع stroke()‎ كما قد يَتَضمَّن أي توابع أو متغيرات آخرى. اُنظر الشيفرة التالية على سبيل المثال: public class Line implements Strokeable { public void stroke(GraphicsContext g) { . . . // ارسم خطًا } . . . // توابع ومتغيرات وبواني آخرى } لكي يُنفِّذ صنف واجهةً (interface) معينةً، ينبغي عليه أن يَفعَل أكثر من مُجرّد توفير الأجزاء التّنْفيذية (implementation) لجميع التوابع ضِمْن تلك الواجهة، فعليه تحديدًا أن يُعلن صراحةً عن تّنفيذه (implements) لتلك الواجهة باستخدام الكلمة المحجوزة implements كالمثال بالأعلى. لابُدّ لأي صنف حقيقي (concrete class) يَرغَب بتّنْفيذ الواجهة Strokeable من أن يُعرِّف تابع نسخة اسمه stroke()‎، لذا سيَتضمَّن أي كائن (object) مُنشَئ من هذا الصنف التابع stroke()‎. يُعدّ الكائن مُنفِّذًا (implement) لواجهة معينة إذا كان ينتمي لصنف يُنفِّذ (implements) تلك الواجهة، فمثلًا، يُنفِّذ أي كائن من النوع Line الواجهة Strokeable. في حين يستطيع الصنف أن يَتمدَّد (extend) من صنف واحد فقط، فإنه في المقابل يستطيع أن يُنفِّذ (implements) أي عدد من الواجهات (interfaces). وفي الواقع، يُمكِن للصنف أن يَتمدَّد (extend) من صنف آخر، وأن يُنفِّذ واجهة واحدة أو أكثر بنفس ذات الوقت، لذلك نستطيع كتابة التالي مثلًا: class FilledCircle extends Circle implements Strokeable, Fillable { . . . } على الرغم من أن الواجهات (interfaces) ليست أصنافًا (classes)، فإنها تُشبهها إلى حد كبير. في الواقع، أي واجهة (interface) هي أَشْبه ما تَكُون بصنف مُجرّد (abstract class) لا يُستخدَم لإنشاء كائنات، وإنما كقاعدة لإنشاء أصناف فرعية (subclasses). تُعدّ البرامج الفرعية (subroutines) ضِمْن أي واجهة توابعًا مجردةً (abstract methods)، والتي لابُدّ لأيّ صنف حقيقي (concrete class) يَرغَب بتّنْفيذ تلك الواجهة من أن يُنفِّذها (implement). تستطيع الموازنة بين الواجهة Strokeable والصَنْف المُجرّد (abstract class) التالي: public abstract class AbstractStrokeable { public abstract void stroke(GraphicsContext g); } يَكمُن الفرق بينهما في أن الصنف الذي يَتمدَّد (extend) من الصنف AbstractStrokeable لا يُمكِنه أن يَتَمدَّد من أي صنف آخر. أما الصنف الذي يُنفِّذ الواجهة Strokeable يستطيع أن يَتَمدَّد من أي صنف آخر كما يستطيع أن يُنفِّذ (implement) أي واجهات (interfaces) آخرى. بالإضافة إلى ذلك، يُمكِن لأي صنف مُجرّد (abstract class) أن يَتَضمَّن توابعًا غير مُجرّدة (non-abstract) وآخرى مُجرّدة (abstract). في المقابل، تستطيع أي واجهة (interface) أن تَتَضمَّن توابعًا مُجرّدة فقط، لذا فهي أَشْبه ما تَكُون بصنف مُجرّد نقي (pure). ينبغي أن تُصرِّح عن التوابع ضِمْن أي واجهة (interface) على أساس كَوْنها -أي التوابع- عامة public ومُجردّة abstract. ولمّا كان هذا هو الخيار الوحيد المُتاح، فإن تَخْصِيص هذين المُبدِّلين (modifiers) ضِمْن التّصْريح (declaration) ليس ضروريًا. إلى جانب التّصريح (method declarations) عن التوابع، يُمكِن لأي واجهة (interface) أن تُصرِّح عن وجود مُتْغيِّرات (variable declarations)، وينبغي عندها أن تُصرِّح عنها على أساس كَوْنها عامة public، وساكنة static، ونهائية final، ولذا فإنها تَصيِر عامة وساكنة ونهائية بأي صنف يُنفِّذ (implements) تلك الواجهة. ولمّا كان هذا هو الخيار الوحيد المُتاح للتّصْريح عنها، فإن تَخْصِيص تلك المُبدِّلات (modifiers) ضِمْن التّصْريح (declaration) ليس ضروريًا. اُنظر المثال التالي: public interface ConversionFactors { int INCHES_PER_FOOT = 12; int FEET_PER_YARD = 3; int YARDS_PER_MILE = 1760; } هذه هي الطريقة المناسبة لتعريف (define) ثوابت مُسماة (named constants) يُمكِن اِستخدَامها بعدة أصناف. يُمكِن لأي صنف يُنفِّذ (implements) الواجهة ConversionFactors أن يَستخدِم الثوابت المُعرَّفة بتلك الواجهة (interface) كما لو كانت مُعرَّفة بالصنف. لاحِظ أن أي مُتْغيِّر مُعرَّف ضِمْن واجهة (interface) هو بالنهاية ثابت (constant) وليس مُتْغيِّرًا على الإطلاق. وفي العموم، لا يُمكِن لأي واجهة (interface) أن تُضيف مُتْغيِّرات نُسخ (instance variables) إلى الأصناف التي تُنفِّذها (implement). يُمكِن لأي واجهة (interface) أن تَتَمدَّد (extend) من واجهة واحدة أو أكثر. على سبيل المثال، إذا كان لدينا الواجهة Strokeable المُعطاة بالأعلى، بالإضافة إلى الواجهة Fillable والتي تُعرِّف التابع fill(g)‎، نستطيع عندها تعريف الواجهة التالية: public interface Drawable extends Strokeable, Fillable { // المزيد من التوابع أو الثوابت } ينبغي لأي صَنْف حقيقي (concrete class) يُنفِّذ الواجهة Drawable من أن يُوفِّر الأجزاء التّنْفيذية (implementations) لكُلًا من التابع stroke()‎ من الواجهة Strokeable، والتابع draw()‎ من الواجهة Fillable، بالإضافة إلى أي توابع مُجرّدة (abstract methods) آخرى قد تُخصِّصها الواجهة Drawable مباشرة. عادة ما تُعرَّف (define) الواجهة (interface) ضِمْن ملف ‎.java الخاص بها، والذي لابُدّ أن يَكُون له نفس اسم الواجهة. فمثلًا، تُعرَّف الواجهة Strokeable بملف اسمه Strokeable.java. وبالمثل من الأصناف (classes)، يُمكِن للواجهة (interface) أن تقع ضِمْن حزمة (package)، كما يُمكِنها أن تَستورِد (import) أشياءً من حزم آخرى. التوابع الافتراضية (default methods) بداية من الإصدار الثامن من الجافا، تستطيع الواجهات (interfaces) أن تَتَضمَّن ما يعرف باسم "التوابع الافتراضية (default methods)"، والتي تَملُك جزءًا تّنْفيذيًا (implementation) بعكس التوابع المُجرّدة (abstract methods) المُعتادة. تُورَث التوابع الافتراضية من الواجهات (interfaces) إلى أصنافها المُنفِّذة (implement) بنفس الطريقة التي تُورَث بها التوابع العادية من الأصناف إلى أصنافها الفرعية. لذا عندما يُنفِّذ (implement) صنف معين واجهةً تَحتوِي على توابع افتراضية، فإنه لا يَكُون مضطرًا لأن يُوفِّر جزءًا تّنْفيذيًا (implementation) لأي تابع افتراضي (default method) ضِمْن الواجهة، مع أن بإمكانه القيام بذلك إذا كان لديه تّنْفيذًا (implementation) مُختلفًا. تَدفَع التوابع الافتراضية (default methods) لغة الجافا خطوة للأمام بطريق دَعْم الوراثة المُتعدّدة (multiple inheritance)، ولكنها مع ذلك ليست وراثة مُتعدّدة بحق؛ لأن الواجهات لا تستطيع تعريف مُتْغيِّرات نُسخ (instance variables). تستطيع التوابع الافتراضية (default methods) استدعاء التوابع المجردة (abstract methods) المُعرَّفة بنفس الواجهة، لكنها لا تستطيع الإشارة إلى أي مُتْغيِّر نسخة (instance variable). ملحوظة: تستطيع واجهات نوع الدالة (functional interfaces) أيضًا أن تَحتوِي على توابع افتراضية (default methods) بالإضافة إلى التابع المُجرّد (abstract method) الوحيد الذي بإمكانها تَخْصِيصه. ينبغي أن تُصرِّح عن التوابع الافتراضية (default methods) على أساس كَوْنها عامة public، ولمّا كان ذلك هو الخيار الوحيد المُتاح، فإن تَخْصِيص المبدل public ضِمْن التّصْريح (declaration) ليس ضروريًا. في المقابل، لابُدّ من كتابة المُبدِّل default بشكل صريح أثناء التّصْريح عن أي تابع افتراضي (default method). اُنظر المثال التالي: public interface Readable { // تمثل مصدر إدخال public char readChar(); // اقرأ المحرف التالي المُدْخَل default public String readLine() { //اقرأ حتى نهاية السطر StringBuilder line = new StringBuilder(); char ch = readChar(); while (ch != '\n') { line.append(ch); ch = readChar(); } return line.toString(); } } لابُدّ لأي صنف حقيقي (concrete class) يُنفِّذ الواجهة (interface) -بالأعلى- من أن يُوفِّر تّنْفيذًا (implementation) للتابع readChar()‎. في المقابل، سيَرِث ذلك الصنف تعريف readLine()‎ من الواجهة، ولكنه قد يُوفِّر تعريفًا (definition) جديدًا إذا كان ذلك ضروريًا. عندما يَتَضمَّن صنف معين تّنفيذًا (implementation) لتابع افتراضي (default method)، فإن ذلك التّنْفيذ الجديد يُعيد تعريف (overrides) التابع الافتراضي الموجود بالواجهة (interface). بالمثال السابق، يَستدعِي التابع الافتراضي readLine()‎ التابع المُجرّد readChar()‎، والذي يَتوفَّر تعريفه (definition) فقط من خلال الأصناف المُنفِّذة للواجهة، ولهذا تُعدّ الإشارة إلى readChar()‎ مُتعدِّدة الأشكال (polymorphic). كُتب التّنْفيذ الافتراضي للتابع readLine()‎ بحيث يَكُون ملائمًا لأي صنف يُنفِّذ الواجهة Readable. اُنظر الشيفرة التالية والتي تَتَضمَّن صنفًا يُنفِّذ الواجهة Readable كما يَحتوِي على البرنامج main()‎ لاختبار الصَنْف: public class Stars implements Readable { public char readChar() { if (Math.random() > 0.02) return '*'; else return '\n'; } public static void main(String[] args) { Stars stars = new Stars(); for (int i = 0 ; i < 10; i++ ) { // اِستدعي التابع الافتراضي String line = stars.readLine(); System.out.println( line ); } } } تُوفِّر التوابع الافتراضية (default methods) إمكانية شبيهة لما يُعرَف باسم "المخلوط (mixin)" المُدعَّم ببعض اللغات البرمجية الآخرى، والتي تَعنِي المقدرة على خَلْط وظائف مصادر آخرى إلى داخل الصنف. لمّا كان بإمكان أي صنف أن يُنفِّذ أي عدد من الواجهات (interfaces)، فإنه يستطيع خلط وظائف عدة مصادر آخرى مختلفة. الواجهات كأنواع كما هو الحال مع الأصناف المُجرّدة (abstract classes)، لا يُمكِنك إنشاء كائن فعليّ من واجهة (interface)، ولكن تستطيع التّصْريح (declare) عن مُتْغيِّر نوعه عبارة عن واجهة. لنَفْترِض مثلًا أن لدينا الواجهة Strokeable المُعرَّفة بالأعلى، ويُنفِّذها كُلًا من الصنفين Line و Circle، يُمكِنك عندها كتابة التالي: // صرح عن متغير من النوع‫ Strokeable والذي يمكنه الإشارة إلى أي // كائن ينفذ تلك الواجهة Strokeable figure; figure = new Line(); // ‫يشير إلى كائن من الصنف Line figure.stroke(g); // ‫اِستدعي التابع stroke() من الصنف Line figure = new Circle(); // ‫يشير الآن إلى كائن من الصنف Circle figure.stroke(g); // ‫اِستدعي التابع stroke() من الصنف Circle يُمكِن لأي مُتْغيِّر من النوع Strokeable أن يُشير إلى أي كائن طالما كان صَنْفه يُنفِّذ الواجهة Strokeable. لمّا كان figure مُتْغيِّرًا من النوع Strokeable، ولأن أي كائن من النوع Strokeable يَحتوِي على التابع stroke()‎، فحتمًا سيَحتوِي الكائن الذي يُشير إليه المُتْغيِّر figure على التابع stroke()‎، ولهذا فإن التَعْليمَة figure.stroke(g)‎ صالحة تمامًا. تُستخدَم الأنواع (types) في العموم إما للتّصْريح (declare) عن مُتْغيِّر، أو لتَخْصِيص نوع معامل برنامج فرعي (routine)، أو لتَخْصِيص النوع المُعاد (return type) من دالة (function). النوع في العموم إما أن يَكُون صنفًا أو واجهة (interface) أو أحد الأنواع البسيطة (primitive) الثمانية المَبنية مُسْبَقًا (built-in). ليس هنالك من أيّ احتمال آخر، ربما باستثناء بعض الحالات الخاصة كأنواع التعداد (enum) والتي هي بمثابة نوع خاص من الأصناف. من بين كل تلك الأنواع، الأصناف هي الوحيدة التي يُمكِن اِستخدَامها لإنشاء كائنات (objects). يُمكِنك أيضًا اِستخدَام الواجهات (interface) لتَخْصِيص النوع الأساسي (base type) لمصفوفة. فمثلًا، تستطيع أن تُصرِّح عن مُتْغيِّر أو أن تُنشِئ مصفوفة باستخدام نوع المصفوفة Strokeable[]‎، وفي تلك الحالة، يُمكِن لعناصر تلك المصفوفة الإشارة إلى أي كائن طالما كان يُنفِّذ الواجهة Strokeable. اُنظر الشيفرة التالية: Strokeable[] listOfFigures; listOfFigures = new Strokeable[10]; listOfFigures[0] = new Line(); listOfFigures[1] = new Circle(); listOfFigures[2] = new Line(); . . . تَملُك جميع عناصر تلك المصفوفة التابع stroke()‎، مما يَعنِي إمكانية كتابة تعبيرات مثل listOfFigures.stroke(g)‎. ترجمة -بتصرّف- للقسم Section 7: Interfaces من فصل Chapter 5: Programming in the Large II: Objects and Classes من كتاب Introduction to Programming Using Java.
    1 نقطة
  8. بدأت أخيرا في وضع اللمسات الأخيرة على مشروعك، وحان الوقت لتبحث عن استضافة مواقع مناسبة لتطلق موقعك في رحاب شبكة الإنترنت. الآن ستجد نفسك أسير مشكلة أخرى؛ أمام الكم الهائل من شركات استضافة المواقع، كيف ستختار الاستضافة المناسبة لمشروعك الناشئ؟ كثرة الخيارات تربك بشكل فضيع، وتدفع الشخص، غالبا، للانتقاء بشكل خاطئ. لمساعدتك في اختيار أنسب شركة استضافة لشركتك الناشئة أقدم لك هذه القائمة المختصرة التي توفر مجموعة من الخيارات المحدودة التي تتوافق مع كل مرحلة من مراحل مشروعك. لكن يجب أن أشير إلى أنني لم أجرب بنفسي كل هذه الشركات، إنما انتقيتها بناء على كثير من البحث وعدد من القراءات المختلفة لقصص تجارب رواد أعمال آخرين من دول مختلفة. الخطوة الأولى: WebFaction يكون المشروع صغيرا في بدايته، ولا يحتاج إلى سيرفرات خاصة، بل مجرد استضافة صغيرة عادية، من نوع الاستضافات المشتركة Shared Hosting، ستفي بالغرض. لولا أن تلك الاستضافات المشتركة تكون غالبا موجهة للمبتدئين ولا تتيح لك حرية التحكم في النظام كما تحب. لهذا قد تفكر في البدء فورا باستضافة من نوع VPS، إلا أن الوقت ما زال مبكرا على تبذير أموالك القليلة على ذلك النوع من الاستضافات، لذلك فإن الحل هو البحث عن خدمة استضافة وسط بين الاستضافات المشتركة وVPS. في هذه الحالة لن تجد أفضل من استضافة شركة Web Faction، التي تقدم لك تجربة أداء وتحكما كاملا يضاهي استضافات VPS لكن بسعر أقل بكثير. المرحلة الثانية: Linode بعد بضعة أشهر، لن تقل عن ستة، سيبدأ مشروعك الوليد في النمو. ربما عندها ستحتاج إلى استضافة توفر لك مواردا أفضل لتلبية الطلب على موقعك. الآن يحين الوقت لاختيار استضافة VPS. يمكنك آنذاك نقل موقعك كاملا، أو فقط بعض الأجزاء والاحتفاظ بأجزاء أخرى في استضافة Web Faction. أو على الأقل احتفظ بالاستضافة القديمة لتخزين الملفات الثابتة (مثل صور الأعضاء Avatar) والنسخ الاحتياطية من قاعدة البيانات. أفضل استضافة VPS وجدتها هي المقدمة من شركة Linode. توفر خيارات متعددة بأسعار مناسبة للغاية وجودة عالية. المرحلة الثالثة: الحوسبة السحابية قد يكبر بعد ذلك مشروعك بسرعة، وتود أن تنتقل لحلول استضافة سهلة الإدارة لا تتطلب الكثير من مدراء النظام المتفرغين. لن تجد في هذه الحالة أفضل من خدمات الحوسبة السحابية المقدمة من شركة أمازون، التي توفر صيغا متعددة تلبي الكثير من الاحتياجات. هذا الحل قد يكون مناسبا للكثيرين، وثمة من سيفضل الاعتماد عليه منذ أول خطوة أو في المرحلة الثانية. لكني شخصيا لا أحب كثيرا الاعتماد على هذا الحل في كل المراحل. المرحلة الرابعة: سيرفرات خاصة كثيرون سيفضلون استخدام حلول الحوسبة السحابية المقدمة من أمازون في هذه المرحلة أيضا. قد يكون ذلك مناسبا للبعض، لكن ليس دائما. لذلك إذا كانت لديك القدرة على توظيف مدير نظام (Sys Admin) كفؤ، الأفضل مغادرة الحوسبة السحابية حين تصير أغلى من تكلفة السيرفرات الخاصة (Dedicated Servers) وحين يبدأ أداؤها في الانخفاض. ثمة الكثير من الأسماء الموثوقة في مجال تقديم الاستضافة من النوع السيرفرات الخاصة، لكني أفضل شركة SoftLayer. سمعتها طيبة وأسعارها معقولة.
    1 نقطة
  9. ب استخدام لغه python مطلوب أخذ رقم من المستخدم ثم طباعه مجموع كل الاعداد من 1 و حتى الرقم المُدخل
    1 نقطة
  10. تجدر بنا الإشارة إلى قاعدة مهمة قبل الشروع في الحديث عن كيفية تعامل جافاسكربت مع الأنماط والأصناف. القاعدة بديهية جدًا ولكننا سنذكرها للإفادة. هناك طريقتان تُستخدمان لتنسيق عنصرٍ ما: إنشاء صنف في ملف CSS وإضافته للعنصر على الشكل التالي: <div class="..."‎> كتابة خاصيات السمة style مباشرة بين تسلسلات التهريب الخاصة بالعنصر على الشكل التالي: <div style="..."‎> تستطيع لغة جافاسكربت التعديل على خاصيات الأصناف وخاصيات الخاصية style. ويُستحسن استعمال أصناف CSS للتنسيق بدلا من السمة style، حيث نلجأ إلى الطريقة الثانية فقط إذا تعذّرعلينا إضافة التنسيق باستعمال الطريقة الأولى. فعلى سبيل المثال، يمكن استعمال الخاصية style إذا كان عليك حساب إحداثيات عنصر ما ديناميكيًا وتحديد قيمها باستعمال جافاسكربت كالآتي: let top = /* عمليات حسابية معقّدة */; let left = /* عمليات حسابية معقّدة */; elem.style.left = left; // e.g '123px', تُحسب أثناء التنفيذ elem.style.top = top; // e.g '456px' وفي حالات أخرى مثل تلوين النص بالأحمر، أو إضافة صورة للخلفية، يُستحسن وصف التنسيق باستعمال CSS ثم إضافة الصنف للعنصر (يمكن عمل ذلك باستعمال جافاسكربت)، حيث يمنحك ذلك أكثر مرونة وسهولة في البرمجة. اسم الصنف (className) وقائمة الأصناف (classList) يُعدّ تعديل الصنف أكثر عمليةٍ نُصادفها في السكربتات. وكانت جافاسكربت فيما مضى تتّسمُ بالمحدودية حين يتعلّق الأمر بالكلمة المحجوزة "class"، حيث لم تكن تسمح بأن تحمل خاصيةٌ من خواص الكائن (object) اسم "class" كالآتي : elem.class. حينها جاء التفكير في استحداث خاصية مشابهة تسمى "className" تُطبّق على الأصناف. حيث يمثِّل elem.className اسم السمة "class" كما هو مبين في المثال التالي: <body class="main page"> <script> alert(document.body.className); // main page </script> </body> See the Pen JS-p2-08-Styles and classes-ex1 by Hsoub (@Hsoub) on CodePen. في حالة ما إذا أسندنا قيمةً معينةً للخاصية elem.className، تعوِّض هذه القيمة مُجمل سلسلة الأصناف. هذا ما نحتاج إليه أحيانا، ولكننا نحتاج في غالبية الحالات إلى إضافة أو حذف صنفٍ واحدٍ فقط. ولهذا وُجدت خاصية أخرى؛ إنها خاصية elem.classList. تُعدّ هذه الخاصية كائنًا خاصًا بحد ذاته له دوالّه الخاصة (methods) لإضافة صنف ما (add) أو حذفه (remove) أو إما إضافته إن لم يكن موجودًا أو حذفه إن وُجد (toggle).كما هو مبين في المثال التالي: <body class="main page"> <script> // إضافة صنف document.body.classList.add('article'); alert(document.body.className); // main page article </script> </body> See the Pen JS-p2-08-Styles and classes-ex2 by Hsoub (@Hsoub) on CodePen. وبذلك يمكننا إجراء عمليات على مجمل سلسلة الأصناف دفعة واحدة باستعمال className أو على الأصناف، كلٌّ على حدى، باستعمال classList. اختيارنا لهذا أو ذاك مرتبط بما نحتاج القيام به. الدوالّ الخاصة بـالخاصية classList هي: *elem.classList.add/remove("class")‎: إضافة الصنف المذكور كوسيط للدلّة/حذف الصنف المذكور كوسيط للدلّة. *elem.classList.toggle("classe")‎: إضافة الصنف المذكور كوسيط للدلّة إن لم يكن موجودًا أو حذفه إن وُجد. *elem.classList.contains("class")‎: البحث عن الصنف المذكور كوسيط للدلّة، والنتيجة تكون صحيح أو خطأ (true/false). وتقبل الخاصية classList الإدماج داخل حلقة التكرار for....of لإظهار قائمة الأصناف كما في المثال التالي: <body class="main page"> <script> for (let name of document.body.classList) { alert(name); // main, and then page } </script> </body> See the Pen JS-p2-08-Styles and classes-ex3 by Hsoub (@Hsoub) on CodePen. تنسيق العنصر باستعمال الخاصية style تُعدّ الخاصية elem.style كائنًا يحمل محتوى السمة style. ويؤدي إسناد القيمة "100px" للخاصية elem.style.width على الشكل التالي: elem.style.width="100px" إلى النتيجة نفسها لو كانت السمة style تحمل السلسلة النصية "width:100px". إذا كان اسم السمة يتكون من عدة كلمات، يُشكَّل اسم الخاصية بجعل الحرف الأول من كل كلمة حرفا كبيرًا ماعدا الكلمة الأولى كما في المثال التالي: background-color => elem.style.backgroundColor z-index => elem.style.zIndex border-left-width => elem.style.borderLeftWidth ملاحظة: الخاصيات التي تبدأ ببادئة تتبع الخاصيات التي تبدأ ببادئة تُحدّد المتصفح نفس القاعدة، كالخاصيتين -moz-border-radius و-webkit-border-radius، حيث تُترجَم الشرطة إلى حرفٍ كبيرٍ كالآتي: button.style.MozBorderRadius = '5px'; button.style.WebkitBorderRadius = '5px'; تغيير قيمة خاصية التنسيق style يحدث أن تَرغب في إسناد قيمةٍ للخاصية style ثم حذفها لاحقا. يمكننا على سبيل المثال إسناد القيمة "none" للخاصية elem.style.display كالأتي elem.style.display = "none" ثم حذفها وكأننا لم نحدّد لها قيمةً من قبل. هنا، ينبغي إسناد سلسلة نصية فارغة للخاصية elem.style.display كالآتي elem.style.display = ""‎ بدلا من حذفها (delete). //عند تنفيذ هذا السكربت يختفي العنصر <body> ثمّ يُعاود الظهور document.body.style.display = "none"; // يختفي setTimeout(() => document.body.style.display = "", 1000); // يُعاود الظهور إذا أسندنا سلسلة نصية فارغة للخاصية style.display، يُطبِّق المتصفح أصناف CSS والأنماط التنسيقية المتضمَّنة بداخلها بطريقة عاديةٍ جدًا وكأن الخاصية style.display غير موجودة تماما. ملاحظة: التعديل على خاصيات الخاصية style جملةً واحدةً باستعمال الخاصية style.cssStyle تُستعمل عادة الخاصية *.style للتعديل على قيم خاصيات التنسيق، كلٌ على حدى، ولا يمكننا التعديل عليها دفعة واحدة كالآتي: div.style="color:red; width:100px"‎، لأن div.style هو كائنٌ لا يمكن التعديل عليه (ِread-only) بهذه الطريقة. يمكن تغيير التنسيق كاملا دفعة واحدة بإسناد سلسلة نصية (تحمل وصف التنسيق) للخاصية style.cssStyle كما في المثال التالي: <div id="div">Button</div> <script> // يمكننا استعمال رايات تنسيقية خاصة مثل الراية “important” div.style.cssText=`color: red !important; background-color: yellow; width: 100px; text-align: center; `; alert(div.style.cssText); </script> See the Pen JS-p2-08-Styles and classes-ex4 by Hsoub (@Hsoub) on CodePen. غير أنه من النادر استعمال هذه الخاصية كونها تحذف الأنماط التنسيقية السابقة وتستبدلها بالقيم الجديدة، أي أنها قد تحذف أشياء مازلنا بحاجتها. فيما يمكن أن تُستخدم لتنسيق العناصر الجديدة، فلن يؤدي إسناد القيم بهذه الطريقة إلى أيّ عملية حذف (بما أن العناصر الجديدة لا تملك تنسيقات بعد). ويمكننا عمل ذلك أيضا باستعمال الدالّة div.setAttribute('style', 'color: red...')‎. الوحدات لا تنس إضافة الوحدات للقيم في شيفرة CSS، فلا يصِحُّ إسناد القيمة "10" للخاصية elem.style.top بل القيمة 10px هي الأصح، وإلا فلن يعمل السكربت بالشكل المطلوب. <body> <script> // لا يعمل document.body.style.margin = 20; alert(document.body.style.margin); // '' (سلسلة نصية فارغة، إهمال عملية الإسناد) // يعمل بعد إضافة الوحدة document.body.style.margin = '20px'; alert(document.body.style.margin); // 20px alert(document.body.style.marginTop); // 20px alert(document.body.style.marginLeft); // 20px </script> </body> See the Pen JS-p2-08-Styles and classes-ex5 by Hsoub (@Hsoub) on CodePen. لاحظ في السطرين الأخيرين أن المتصفح يفكّك الخاصية style.margin إلى خاصيتين وهما: style.marginLeft وstyle.marginTop. الأنماط المحسوبة باستعمال الدالة getComputedStyle يُعدّ التعديل على الأنماط عمليةً سهلةً ولكن كيف تُقرأ الأنماط؟ نريد مثلا معرفة مقاس، هوامش ولون عنصرٍ ما، كيف نتحصل عليها؟ تعمل الخاصية style على تعديل قيمة السمة style فقط دون الوصول إلى الأنماط الموصوفة في الأوراق التنسيقية المتتالية CSS. وبالتالي لا يمكننا قراءة أيّ قيمٍ من أصناف CSS باستعمال الخاصية elem.style. فعلى سبيل المثال لا يمكن أن تصل الخاصية style في هذا المثال إلى الهامش. <head> <style> body { color: red; margin: 5px } </style> </head> <body> The red text <script> alert(document.body.style.color); // فارغة alert(document.body.style.marginTop); // فارغة </script> </body> See the Pen JS-p2-08-Styles and classes-ex6 by Hsoub (@Hsoub) on CodePen. ماذا لو أردنا على سبيل المثال إضافة 20px للهامش؟ سيكون علينا أولا الوصول إلى القيمة الحالية له حتى يتسنى لنا تعديلها. وهنا لدينا طريقة أخرى للحصول على ذلك وتكون باستعمال الدالة getComputedStyle وبنيتها كالآتي: getComputedStyle(element, [pseudo]) حيث يمثّل العنصر element العنصر الذي سنحسب قيمه ويمثل pseudo العنصر الزائف، مثلا before::. إذا كانت قيمة pseudo عبارة عن سلسلة نصية فارغة أو غير موجودة أصلا فهذا يعني أننا نقصد العنصر نفسه. وتكون مخرجات الدالّة (output) عبارة عن كائن يحوي أنماط تنسيقية مثله مثل elem.style ولكن يأخذ في الحسبان هذه المرة كلّ الأصناف الموجودة في ملف CSS. وفيما يلي مثال على ذلك: <head> <style> body { color: red; margin: 5px } </style> </head> <body> <script> let computedStyle = getComputedStyle(document.body); // يمكننا الآن قراءة اللون والهامش alert( computedStyle.marginTop ); // 5px alert( computedStyle.color ); // rgb(255, 0, 0) </script> </body> See the Pen JS-p2-08-Styles and classes-ex7 by Hsoub (@Hsoub) on CodePen. ملاحظة: القيم المحسوبة والقيم النهائية (المُحدَّدة) هناك مفهومان في لغة CSS هما: قيمة تنسيقية محسوبة وهي القيمة المتحصّل عليها بعد تطبيق مجمل القواعد التنسيقية وقواعد الوراثة المُتضمَّنة في ملف CSS. قد تكون على شكل height:1em أو font-size:125% . قيمة تنسيقية نهائية (مُحدَّدة) وهي القيمة التي يقع عليها الاختيار في آخر المطاف وتُطبَّق على العنصر. القيمتان 1em و125% هما قيمتان نسبيتان. يأخذ المتصفح كافة القيم المحسوبة ويجعل كافة الوحدات مطلقة كما في المثال التالي: height:20px ،font-size:16px. ويمكن للقيم النهائية الخاصة بالخاصيات الهندسية أن تكون عشرية مثل: width:50.5px. لقد اُستحدثت الدالّة getComputedStyle أساسا للحصول على قيم محسوبة ولكن تبيّن فيما بعد أن القيم النهائية (المُحدَّدة) أحسن، فتغيرت المعايير، وأصبحت الدالّة getComputedStyle تُخرِج القيم النهائية للخاصية والتي تكون غالبا بالبكسل px بالنسبة للخاصيات الهندسية. ملاحظة: تتطلب الدالة getComputedStyle ذكر الاسم الكامل للخاصية علينا البحث على الدوام عن الخاصية التي نحتاج إليها بدقة مثل: padingLeft، أو marginTop أو borderTopWidth وإلا فلن نتمكن من ضمان صحة النتيجة المتحصّل عليها. فمع وُجود، على سبيل المثال، الخاصيتين padingLeft/padingTop، على ماذا سوف نحصل عند تنفيذ الدالّة getComputedStyle(elem, pading)‎؟ لن نحصل على شيئ؟ أو ربما سنحصل على قيمة "مستوحاة" من قيم معرّفة مسبقا للحاشية (pading)؟ في الحقيقة لا يوجد أيّ معايير تتحدث عن هذا الموضوع. وهناك بعض التناقضات الأخرى، حيث تُظهِر بعض المتصفحات (Chrome مثلا) في مثال الموالي القيمة 10px، ولا تُظهِرها متصفحات أخرى (كالمتصفح Firefox). مثال: <style> body { margin: 10px; } </style> <script> let style = getComputedStyle(document.body); alert(style.margin); // نحصل على سلسلة فارغة عند استعمال المتصفح Firefox </script> See the Pen JS-p2-08-Styles and classes-ex8 by Hsoub (@Hsoub) on CodePen. ملاحظة: الأنماط التي تُطبَّق على الروابط ‎:visited تكون مخفية يمكن تلوين الروابط التي سبق وأن زيرت باستخدام الصنف الزائف ‎:visited في ملف CSS. لكن الدالّة getComputedStyle لا يمكنها الوصول إلى هذا اللون، لأن ذلك يمكِّن أيّ صفحة كانت من إنشاء الرابط على الصفحة والإطلاع على الأنماط وبالتالي معرفة ما إذا كان المستخدم قد زار الرابط من قبل. لا يمكن للغة جافاسكربت الإطلاع على الأنماط المعرّفة باستخدام الصنف الزائف ‎:visited، كما تمنع لغة CSS تطبيق تنسيقاتِ تغيير الشكل والأبعاد (geometry-changing styles) ضمن الصنف الزائف ‎:visited وذلك لغلق الطريق أمام أيّ صفحةٍ مشبوهةٍ تسعى لمعرفة ما إذا زار المستخدم الرابط أم لا، وبالتالي التعدي على خصوصيته. الخلاصة هناك خاصيتان تُستخدمان للعمل على الأصناف وهما: className: وهي سلسلة نصية تُستخدم للعمل على كافة الأصناف دفعةً واحدةً. classList: هي عبارة عن كائن له دوالّه الخاصة (add/delete/toggle/contains) وتستخدم للعمل على الأصناف، كلُ على حدى. ولتغيير التنسيق لدينا: الخاصية style؛ وهي عبارة عن كائن تُشكَّل خواصه بجعل الحرف الأول من كل كلمة حرفا كبيرًا ما عدا الكلمة الأولى. تُعدّ قراءته والتعديل عليه تماما كالتعديل على خاصيات السمة style، كلٌ على حدى. وللاطلاع على كيفية إضافة الراية important وغيرها، يمكنك زيارة موقع MDN حيث تجد قائمة من الدوالّ التي تُستخدم لذلك. الخاصية style.cssText: هي الخاصية التي تقابِل السمة "style" في مجملها، أي السلسلة النصية التي تحمل كافة الأنماط التنسيقية دفعةً واحدةً. ولقراءة الأنماط التنسيقية النهائية (التي تأخذ في الحسبان كافة الأصناف بعد تطبيق تنسيقات CSS وحساب القيم النهائية) وُجدَت الدالة getComputedStyle(elem, [pseudo])‎ والتي تخرِج/تعيد كائنا يحمل التنسيقات وهو قابلٌ للقراءة فقط. تمرين إنشاء إشعار درجة الأهمية: 5 اكتب شيفرة الدالّة showNotification(options)‎ التي تُنشِئ إشعارًا كالآتي: بالمحتوى الذي يُمرَّر لها كوسيط، حيث يختفي الإشعار بعد ثانية ونصف من إظهاره. وتُوفّر الخيارات التالية: // أظهِر عنصرًا يحمل النص "Hello" بالقرب من الركن العلوي الأيمن للنافذة showNotification({ top: 10, // عشرة بكسل بدءًا من أعلى النافذة والذي فاصلته 0 right: 10, // عشرة بكسل بدءًا من الحافة اليمنى للنافذة والتي ترتيبتها 0 html: "Hello!", // شيفرة HTML الخاصة بالإشعار className: "welcome" // صنف إضافي للحاوية ‘div’ (اختياري) }); استعمل تنسيقات CSS لتحديد موضع إظهار العنصر حسب الإحداثيات المعطاة بافتراض أن الصفحة تحتوي مسبقا على الأنماط التنسيقية الضرورية. الحل يمكنك الإطلاع على الحل من هنا ترجمة -وبتصرف- للفصل Styles and classes من كتاب Browser: Document, Events, Interfaces
    1 نقطة
  11. شريت سيرفر من شركه wd mycloud وبحثت عن طريقه اعداده لاعمل استضافه موقعي عليه ماعرفت حملت mysql ولاعرفت الباسوود لها كيف اجيبه وحاولت ماعرفت ممكن الاقي جواب منكم
    1 نقطة
  12. السلام عليكم كيف ممكن اثبت موقع ويب على desktop لعميل معين ، يعني موقع ولكن ليس الرابط link هو وسيلة الدخول بحيث انه يكون كل عميل يتم التثبيت له على حدى، وهل بختلف اذا كان مبني على laravel او ببيئة اخرى، في التثبيت؟
    1 نقطة
  13. مرحباً @Bahaeddine Touati، يجب عليك أيضاً إضافة الدومين الفرعي إلى حسابك ضمن Google Adsense كالتالي: أولاً: بعد تسجيل الدخول نتوجه إلى قائمة المواقع sites. ثانياً: نقوم بالضغط على السهم الموجود بجانب اسم الموقع الرئيسي ثم نختار إظهار التفاصيل (Show Details). ثالثا: نقوم بالظغط على إضافة نطاق فرعي (Add new subdomain) رابعاً: نقوم بإدخال النطاق الفرعي الجديد، ثم نضغط على الزر إضافة (Add). وبذلك سيتم ظهور الإعلانات أيضاً على الدومين الفرعي. ملاحظة، قد يتطلب بعض الوقت لتفعيل الإعلانات على الدومين الفرعي الجديد الذي قمت بإضافته. بالتوفيق،
    1 نقطة
  14. مرحبا مجدداً، جمعت لك بعض الأسئلة السابقة التي تتكلم عن نفس المشكلة - قبول العروض في مستقل - رابط 1 - رابط 2 - رابط 3 - رابط 4 ويوجد الكثير من النقاشات، كما يمكنك متابعة حلقات تقييم تصميمات الجمهور من مصممين مشهورين وستعرف في حال وجود نقاط ضعف لديك.
    1 نقطة
  15. مرحبا عبدو، إن تعلمك للغة برمجة بطريقة موسعة مفيد جداً إلى جانب تعلمك لدورة تطوير وجهات المستخدم. نصيحتي هي تعلم لغة جافاسكربت، لأنك سوف تستفيد منها للعمل في المتصفح وتطوير المواقع التي تقوم بتصميمها إعتماداً على الدورة، وبالإضافة لذلك، يوجد العديد من أُطر العمل المبنية على جافاسكربت وستعطيك وصول أفضل لسوق العمل. نذكر منها: مكتبة Reat.js وهي تسهل و تعمل في مجال تطوير المواقع Frontend. إطار عمل React Native والذي يعتمد على المكتبة السابقة و يستخدم لبناء تطبيقات متعددة المنصات android + IOS ويمكنك تعلم تقنية Node.js والتي تستطيع من خلالها بناء مخدم لمشاريعك Backend أيضا مع جافاسكربت بدل تعلم لغة برمجة إضافية مثل php - python .. إن تعلمك لـ ++c مفيد وأنا لا أنكر ذلك أبداـ لكن مجال عملها بعيد عن الأشياء التي تتعلمها و سوق العمل فيها صعب و متخصص (Hardware , أنظمة تشغيل) ، لذلك تعلم جافاسكربت مفيد أكثر. وإن تعلمك للغة جديدة سيعمل بعض الاختلاط لطريقة كتابة الشيفرة البرمجية و سيبطئ تطورك بعض الشيئ، حيث أن معظم المفاهيم البرمجية متشابه بين لغات البرمجة لكن بعد فترة ستلاحظ أن جافاسكربت أسهل وديناميكية أكثر. أتمنى لك التوفيق
    1 نقطة
  16. السلام عليكم .. فى تطبيقاتى التى تعلمتها ودرستها كنت دائما استخدم ال useSelector ولكن عندما ارى بعض اكواد الاخرين ومنها ايضا الشركة التى كنت اعمل بها كانو يستخدمون ال connect function لتمرير ال state ك props .. ولم اجد اى useSelcetor فى هذه الاكواد .. على عكسى لطالما كنت استخدم ال useSelector ولم استخدم ال connect من قبل .. انا فقط اتسائل هل يمكن تعويض ال connct ب useSelector ؟؟ وما هو الافضل ال connect function ام ال use Selector hook ؟؟ وما هو الشائع فى اغلب المشاريع حيث اننى اجد ان ال connect function شائعة اكثر هل انا محق ام ماذا ؟؟
    1 نقطة
  17. يقوم هذا الوسم بفتح كل الروابط في الصفحة الأب (أي الصفحة الأساسية) ويجب أن يتم إضافته داخل وسم head في الصفحة الداخلية (داخل صفحة iframe) لكي يعمل. وإن كنت تريد أن يتم فتح الروابط في نافذة جديدة يمكنك أن تجعل قيمية الخاصية target تساوي _blank <base target="_blank">
    1 نقطة
  18. <base target="_parent"> وكيف يعمل هذا ؟
    1 نقطة
  19. مرحبًا @Hamada Ahmed يمكنك إضافة الخاصية required إلى وسم input الخاص بالصورة ليكون بهذا الشكل <input type="file" name="image" id="" required> هكذا لن يستطيع المستخدم الضغط على زر submit إلا إن اختار صورة بالفعل. ثم يمكنك التحقق من ذلك في php من خلال الدالة isset والتي ستتحقق من إن كان هناك ملف باسم image في هذه الحالة، وعليك التحقق من وجود أي أخطاء أيضُا عن طريق العنصر error داخل متغير الصورة بهذه الطريقة: if(!isset($_FILES['image']) || $_FILES['image']['error'] == UPLOAD_ERR_NO_FILE) { echo "Error no file selected"; }
    1 نقطة
  20. مرحبًا @Mossad Ashraf عليك أولًا أن تأخذ الرقم من المستخدم من خلال الدالة input ثم تحويل هذا الرقم من نص '34' على سبيل المثال إلى رقم عن طريق الدالة int والتي ستحول النص المدخل إلى رقم بعد ذلك عمل حلقة for تبدأ من واحد وتنتهي إلى الرقم المدخل من قِبل المستخدم بهذا الشكل # تم تخزين الرقم المدخل في المتغير x for i in range(1, x): print(i) عليك أن تتأكد أيضًا من أن المستخدم قد أدخل رقم صحيح وليس أي حروف أو رموز أخرى من خلال جملة try except كالتالي: try: x = int(x) except ValueError: print('برجاء إدخال رقم صحيح')
    1 نقطة
  21. function name(num){ var sum = 0 for (i=1, i <= num, i++){ sum =+ i } return } سأكتب الكود بال javasceipt و كتابة الخطوات التي تقوم بعمل ال function ثم يمكنك من. خلال فهم الخطوات كتابة الكود بال python تقوم بعمل function مع اضافة argument ليدخل المستخدم الرقم ثم تعرف متغير ثم بعد ذلك تقوم بعمل loop تبدأ ب 1 وتنتهي بالرقم المدخل وزيادة الرقم ب 1 ثم تكتب داخل ال loop كود يقوم بإضافة ال index
    1 نقطة
  22. مرحباً علي وسم iframe يستخدم لعرض صفحة داخل صفحة أخرى ولا يمكن لأي منهما أن تأثر على الأخرى لأسباب أمنية، حيث يمكن لبعض المخترقين أن يستغلوا مثل هذا الوسم لسرقة المعلومات البنكية أو كلمات المرور. لذا لا يمكن أن تفتح روابط من داخل الفريم لتظهر في صفحة الموقع الأساسية. بدلاً من ذلك عليك أن تضع السيدبار داخل الصفحة الأساسية بدلاً من وسم iframe. إن أردت أن تحول المستخدم إلى الرابط الذي يضغط عليه (ويتم إعادة تحميل الصفحة بالكامل وليس وسم iframe فقط) فيمكنك أن تضع وسم base مع الخاصية target في الـ head الخلص بصفحة داخل الفريم كالتالي: <base target="_parent">
    1 نقطة
  23. مرحباً صديقي @Ali Ali19 لا أنصحك باتباع هذه الطريقة في الحصول على إجابات الأسئلة و الإختبارات، بل الأفضل أن تحاول حلها بنفسك و تعرض إجاباتك و محاولاتك هنا و نحن سنقوم بمساعدتك و تصويب الأخطاء إن وجدت. بشكل عام، يمكنك الاستفادة من الشرح التالي في أداء هذه المهمة: إن شكل (صيغة) تعريف دالة يعتمد على لغة البرمجة التي تستخدمها، فمثلاً في لغات PHP, JS يعرف التابع على الشكل التالي (اذا كنت تريد تطبيقها في جافا عليك باستخدام الـ synatax الخاص بجافا طبعا، هنا ساستخدم PHP): // PHP تعريف تابع في // fun_name تشير لاسم التابع المراد تعريفه // $var هو اسم المتغير الذي نقوم بتمريره للتابع و يمكنك تمرير أكثر من متغير و الفصل بينهما بفاصلة // لاحظ ان المتغيرات في PHP تكون مسبوقة بالرمز $ function fun_name($var){ // تعليمات جسم التابع } يمكنك المرور على عناصر مصفوفة من خلال استخدام حلقات for, while مثلا هنا في هذا المثال سأقوم بالمرور على مصفوفة و أفحص عناصرها وأضع آخر عنصر زوجي (يقبل القسمة على 2 بدون باقي) ضمن متحول اسمه num: $arr = array(2,5,6,9,8,66,4,7); $num; // عرفنا متغير لنضع فيه قيمة الرقم الذي يقبل القسمة على 2 for ($i=0; $i< count($arr); $i++){ if( $arr[$i] % 2 == 0) // نفحص اذا كان العدد زوجي $num = $arr[$i]; // نضعه في المتحول num } echo $num; // نطبع قيمة المتحول التي ستكون آخر عنصر زوجي في المصفوفة يمكنك الاستفادة من المنهجية السابقة (طريقة التفكير لحل المشكلة) و تطبيقها على مثالك مع بعض التعديلات لكي تلائم المهمة المطلوبة. تحياتي.
    1 نقطة
  24. مرحباً تميم، سابقاً كان يتم استعمال مكتبة تدعى vue-analytics ولكن للأسف تم التوقف عن دعمها منذ فترة قصيرة والسبب في ذلك بأن google قد انتقلت إلى إعتمادية جديدة اسمها gtag.js ولحسن الحظ تم تطوير مكتبة جديدة لمواكبة هذا التحديث. يمكنك الآن استعمال vue-gtag وهي عبارة عن إطار عمل يسمح لك بإرسال بيانات الأحداث إلى Google Analytics وإعلانات Google ومنصة Google للتسويق. يتم تضمين google analytics ضمن تطبيق Vue Js كالتالي: أولاً لتحميل المكتبة نقوم بتنفيذ الأمر التالي: npm add vue-gtag ثم يمكنك تضمنيها ضمن تطبيقك كالتالي: import Vue from "vue"; import App from "./App.vue"; import VueGtag from "vue-gtag"; Vue.use(VueGtag, { config: { id: "UA-1234567-1" } }); new Vue({ render: h => h(App) }).$mount("#app"); حيث id هو رقم المعرّف الذي ستحصل عليه من حسابك على Google Analytics. ثم يمكنك الآن إرسال (أحداث) وتتبع حركة المستخدم عن طريق التالي: export default { name: 'MyComponent', methods: { login () { this.$gtag.event('login', { method: 'Google' }) } } } وهذا مثال بسيط عن إمكانية إرسال حدث أثناء تسجيل المستخدم للدخول إلى موقعك. يمكنك أيضاً الإطلاع على كافة التفاصيل والأحداث الموجودة والتي يمكنك تطبيقها على الموقع الرسمي لهذه المكتبة. أتمنى لك التوفيق.
    1 نقطة
  25. تُعدّ الأفكار الأساسية التي تَرتَكِز عليها البرمجة كائنية التوجه (object-oriented programming) واضحة وبسيطة على نحو معقول، ومع ذلك فإنها ستَأخُذ منك بعض الوقت لكي تَعتَاد عليها تمامًا. بالإضافة إلى ذلك، هنالك الكثير من التفاصيل الدقيقة وراء تلك الأفكار الأساسية والتي قد تَكُون مزعجة في بعض الأحيان. سنُحاوِل أن نُغطِي بعضًا منها بالجزء المُتبقِي من هذا الفصل، وتَذَكَّر أنه ليس ضروريًا أن تَتَمكَّن من إِتقان كل تلك التفاصيل خاصة عند قرائتها لأول مرة. سنَفْحَص بهذا القسم تحديدًا المُتْغيِّرين this و super المُعرَّفين تلقائيًا بأي تابع نسخة (instance method) أو بَانِي كائن (constructor). المتغير الخاص this ما الذي يعنيه اِستخدَام مُعرِّف بسيط مثل amount أو process()‎ للإشارة إلى مُتْغيِّر أو تابع؟ تعتمد الإجابة بشكل أساسي على قواعد النطاق (scope rules)، والتي تُوضِح الأماكن التي يُمكِنها الوصول إلى أيّ مُتْغيِّر أو تابع قد صَرَّح عنه البرنامج وكيفية القيام بذلك. فمثلًا، قد يُشير اسم بسيط لمُتْغيِّر بتعريف تابع (method definition) إلى مُتْغيِّر محليّ (local variable) أو مُعامِل (parameter) في حالة وجود أي منهما ضِمْن النطاق (scope)، أيّ إن كان التَّصْريح (declaration) عن أيّ منهما ما يزال فعالًا بمكان حُدوث تلك الإشارة بالشيفرة، فإذا لم يَكُن كذلك، فإن ذلك الاسم لابُدّ وأنه يُشير إلى مُتْغيِّر عضو (member variable) مُعرَّف بنفس الصنف الذي حدثت فيه تلك الإشارة. بالمثل، أي اسم بسيط لتابع لابُدّ وأنه يُشير إلى تابع (method) مُعرَّف بنفس الصنف. يَملُك أي عضو ساكن (static member) بصنف اسمًا بسيطًا يُمكِن اِستخدَامه داخل تعريف الصَنْف (class definition) فقط. في المقابل، يُستخدَم الاسم الكامل للعضو . للإشارة إليه من خارج الصَنْف. فمثلًا، Math.PI هو مُتْغيِّر عضو ساكن (static member variable) اسمه البسيط هو PI داخل الصنف Math. لاحِظ أنه من المُمكن دومًا الإشارة إلى أي عضو ساكن باِستخدَام اسمه الكامل حتى من داخل الصنف المُعرَّف بداخله بل قد يَكُون ذلك ضروريًا في بعض الأحيان، مثلًا عندما يَكُون الاسم البسيط للمُتغير الساكن مخفيًا نتيجة وجود مُتْغيِّر محليّ (local variable) أو مُعامِل (parameter) بنفس الاسم. بالمثل، يَملُك أي عضو نسخة (instance member)، سواء كان مُتْغيِّر نسخة (instance variable) أو تابع نسخة (instance method)، اسمًا بسيطًا يُمكِن اِستخدَامه بتوابع النسخ (instance methods) -لا التوابع الساكنة (static methods)- بالصنف المُعرَّف بداخله. تَذَكَر أن أي مُتْغيِّر نسخة أو تابع نسخة هو جزء من الكائن ذاته وليس صَنْفه، فكل كائن يَمتلك نسخة خاصة به من ذلك المُتْغيِّر أو التابع. بالإضافة إلى الاسم البسيط، يَملُك أي عضو نسخة (instance member) اسمًا كاملًا، شطره الأول عبارة عن مَرجِع (reference) يُشير إلى الكائن المُتضمِّن لذاك العضو. مثلًا، إذا كان std مُتْغيِّر يُشير إلى كائن من النوع Student، فقد تُمثِل std.test1 الاسم الكامل لمُتْغيِّر نسخة (instance variable) اسمه test1 مُعرَّف ضِمْن الكائن. إذًا، عندما تَستخدِم الاسم البسيط لمُتْغيِّر نُسخة (instance variable) مثل test1 بداخل صنف معين، أين الكائن الذي يَتَضمَّن ذلك المُتْغيِّر؟ في الواقع، الأمر بسيط نوعًا ما. لنَفْترِض أنك أَشرت إلى الاسم test1 بتعريف تابع نسخة (instance method) معين، والذي هو بالتأكيد جزء من كائن من النوع Student. عندما يُنفَّذ ذلك التابع، فإن الاسم البسيط test1 يُشير عندها إلى المُتْغيِّر test1 المُعرَّف بذلك الكائن. في الواقع، هذا هو السبب وراء عدم إمكانية استخدام الأسماء البسيطة لأعضاء النسخ (instance members) ضِمْن أي تابع ساكن (static methods)؛ لأنه وبينما يُنفَّذ ذلك التابع الساكن، لا يَكُون هناك أي كائن، ومن ثم لا يَكُون هناك أي أعضاء نُسخ (instance members). يَضَعنا هذا أمام السؤال التالي: كيف نَستخدِم الاسم الكامل لعضو نسخة (instance members) داخل نفس الصَنْف المُعرَّف بداخله؟ نُريد ببساطة طريقة تُمكِّنا من الإشارة إلى "نفس ذات الكائن الحاضن للتابع". في الواقع، تُوفِّر الجافا المُتْغيِّر الخاص this لهذا الغرض. تستطيع اِستخدَام المُتْغيِّر this بتابع نسخة معين (instance method)؛ للإشارة إلى نفس ذات الكائن الحاضن لنفس ذات التابع. فمثلًا، إذا كان var هو مُتْغيِّر نسخة (instance variable) مُعرَّف بنفس ذات الكائن الحاضن لنفس ذات التابع، فإن this.var هو الاسم الكامل لذلك المُتْغيِّر. وبالمثل، إذا كان otherMethod()‎ هو تابع نسخة (instance method) بنفس ذات الكائن، فيُمكِن اِستخدَام this.otherMethod()‎ لاستدعاء ذلك التابع. عندما يُنفِّذ الحاسوب تابع نسخة (instance method) معين، فإنه تلقائيًا يَضَع المُتْغيِّر this بحيث يُشير إلى نفس ذات الكائن الحاضن للتابع. تَستخدِم بعض اللغات البرمجية كائنية التوجه (object oriented) الاسم self بدلًا من this. يُرَى عندها الكائن ككيان يَستقبِل الرسائل، ويَرُد عليها بتَّنْفيذ أمر معين. وفقًا لذلك الكيان، يُشير مُتْغيِّر نسخة (instance variable) مثل self.name إلى نسخة name الخاصة بالكيان، بينما يَكُون استدعاء تابع نسخة (instance method) مثل self.redraw()‎ بمثابة قوله "اِرسِل إلى نفسي رسالة redraw". يَشيع استخدام المُتْغيِّر الخاص this ببواني الكائنات (constructors)، كالتالي: public class Student { private String name; // اسم الطالب public Student(String name) { this.name = name; } . . // المزيد من المتغيرات والتوابع . } بباني الكائن (constructor) -بالأعلى-، أَصبَح مُتْغيِّر النسخة (instance variable)‏ name مَخفيًّا نتيجة اِستخدَام مُعامِل صُّوريّ (formal parameter) يَحمِل نفس الاسم name. مع ذلك، تستطيع اِستخدَام اسمه الكامل this.name للإشارة إليه. يُشير الاسم name على يمين تَعْليمَة الإِسْناد this.name = name إلى المُعامِل الصُّوريّ (formal parameter)، وتُسنَد قيمته إلى مُتْغيِّر النسخة this.name. يَشيِع اِستخدَام تلك الصياغة، وهي مقبولة في العموم؛ فليس هناك أي حاجة لاختيار أسماء جديدة للمُعامِلات الصُّوريّة المُستخدَمة فقط لتهيئة مُتْغيِّرات النُسخ (instance variables)، لذا اِستخدِم نفس الاسم لكليهما ببساطة. يُستخدَم المُتْغيِّر الخاص this لأغراض آخرى أيضًا. على سبيل المثال، بينما تَكْتُب تابع نسخة (instance method)، قد تحتاج إلى تمرير الكائن الحاضن للتابع إلى برنامج فرعي (subroutine) كمُعامِل فعليّ (actual parameter). في تلك الحالة، تستطيع ببساطة تمرير this. مثلًا، يُستخدَم System.out.println(this);‎ لطباعة تمثيل نصي (string representation) للكائن. بالإضافة إلى ذلك، قد تُسنِد this إلى مُتْغيِّر آخر ضِمْن تَعْليمَة إِسْناد (assignment statement) أو تُخزِّنه بمصفوفة. وفي العموم، تستطيع أن تَفعَل به أي شيء يُمكِنك فعله مع أي مُتْغيِّر آخر باستثناء تَعْدِيل قيمته (اِفْترِض أنه مُتْغيِّر نهائي مُعرَّف باِستخدَام المُبدِّل final). المتغير الخاص super تُعرِّف الجافا المُتْغيِّر الخاص super للاِستخدَام بتعريفات توابع النُسخ (instance methods) بالأصناف الفرعية (subclasses) تحديدًا. بالمثل من this، يُشير المُتْغيِّر الخاص super إلى نفس ذات الكائن الحاضن للتابع، ولكنه يَنسَى -إذا جاز التعبير- أن ذلك الكائن ينتمي إلى صَنْفه الفرعي (subclass)، ويَتَذكَّر فقط انتماءه إلى صَنْفه الأعلى (superclass). الفكرة ببساطة كالتالي: قد يَتَضمَّن الصَنْف الفرعي بعض الإضافات إلى الصَنْف الأعلى (superclass) أو حتى بعض التَعْديلات عليه، فكانت الحاجة إلى وجود طريقة للإشارة إلى التوابع (methods) والمُتْغيِّرات المُعرَّفة بالصَنْف الأعلى (superclass)، وهذا ما يُوفِّره المُتْغيِّر super فهو ببساطة لا يَعلَم أي شيء عن تلك الإضافات والتعديلات. لنَفْترِض أن لديك صَنْف فرعي يَحتوِي على تابع نسخة (instance method) اسمه doSomething()‎، ثُمَّ كَتبَت بأحد توابعه تَعْليمَة استدعاء البرنامج الفرعي التالية super.doSomething()‎. لمّا كان المُتْغيِّر super لا يَعلَم أي شيء عن التابع doSomething()‎ المُعرَّف بالصنف الفرعي، فهو فقط يَعلَم الأشياء المُعرَّفة بالصنف الأعلى (superclass)، فإنه سيُحاوِل تَّنْفيذ تابع اسمه doSomething()‎ من الصَنْف الأعلى (superclass)، فإذا لم يَجِدْه، أيّ في حالة كان التابع doSomething()‎ إضافةً وليس تعديلًا، فستَحصُل على خطأ في بناء الجملة (syntax error). وفَّرت الجافا المُتْغيِّر الخاص super لكي تَتَمكَّن من الوصول إلى أشياء كانت قد عُرِّفت بالصنف الأعلى (superclass)، ولكنها أصبحت مَخفيّة بواسطة بعض الأشياء المُعرَّفة بالأصناف الفرعية (subclasses). مثلًا، دائمًا ما سيُشير الاسم super.var إلى مُتْغيِّر النسخة (instance variable)‏ var المُعرَّف بالصنف الأعلى (superclass). يَكُون ذلك مفيدًا في بعض الحالات كالتالي: إذا اِحتوَى صنف معين على مُتْغيِّر نسخة (instance variable) له نفس اسم مُتْغيِّر نسخة بصنفه الأعلى (superclass)، فعندها سيَحتوِي أي كائن من الصَنْف الفرعي على مُتْغيِّرين لهما نفس الاسم، الأول مُعرَّف كجزء من الصنف نفسه، والآخر مُعرَّف كجزء من الصنف الأعلى، أيّ لا يَحلّ المُتْغيِّر بالصنف الفرعي (subclass) مَحلّ المُتْغيِّر بالصَنْف الأعلى حتى لو كان لهما نفس الاسم وإنما يُخفيه فقط، وعليه ما يزال المُتْغيِّر من الصنف الأعلى قابلًا للوصول باِستخدَام super. بالمثل، عندما يَتَضمَّن صنف فرعي (subclass) تابع نسخة (instance method) له نفس بصمة (signature) تابع مُعرَّف بالصنف الأعلى (superclass)، فإن التابع من الصنف الأعلى يُصبِح مَخفيًّا بنفس الطريقة، ويُقال عندها أن التابع من الصنف الفرعي أعاد تعريف (override) التابع من الصنف الأعلى. ومع ذلك، يُمكِن اِستخدَام المُتْغيِّر الخاص super للوصول إلى التابع من الصنف الأعلى (superclass). غالبًا ما يُستخدَم المُتْغيِّر super لتمديد (extend) سلوك تابع موروث بدلًا من أن يستبدله بالكامل، وذلك بكتابة تابع جديد يُعيد تعريف (override) التابع الأصلي. يَتَضمَّن التابع الجديد استدعاءً لتابع الصنف الأعلى (superclass) من خلال المُتْغيِّر super إلى جانب الشيفرة الجديدة المطلوب إضافتها بالأساس. لنَفْترِض مثلًا أن لدينا الصنف PairOfDice والذي يَتَضمَّن تابعًا اسمه roll()‎، والآن نريد إنشاء صنف فرعي GraphicalDice ليُمثِل حجري نَّرد مرسومين على الشاشة. ينبغي للتابع roll()‎ المُعرَّف بالصنف الفرعي GraphicalDice أن يُنفِّذ كل شيء يقوم به التابع roll()‎ المُعرَّف بالصنف الأعلى PairOfDice، وهو ما يُمكِننا التعبير عنه بالاستدعاء super.roll()‎، والذي سيَستدعِي نسخة التابع بالصنف الأعلى (superclass). بالإضافة إلى ذلك، ينبغي للتابع roll()‎ المُعرَّف بالصنف الفرعي GraphicalDice أن يُعيد رسم حجرى النَّرد لإظهار القيم الجديدة. يُمكِننا تعريف الصنف GraphicalDice كالتالي: public class GraphicalDice extends PairOfDice { public void roll() { super.roll(); // ‫استدعي roll من الصنف PairOfDice redraw(); // استدعي تابع لرسم حجري النرد } . . // ‫المزيد بما يتضمن تعريف redraw() . } يَسمَح ذلك عمومًا بتمديد (extend) سلوك التابع roll()‎ حتى لو لم تَكُن على علم بطريقة تَّنْفيذه (implementation) بالصنف الأعلى. super و this كبواني كائن لا تُورَث بواني الكائن (constructors) عمومًا، أي أنك إذا أنشأت صنفًا فرعيًا (subclass) من صنف موجود، فإن بواني الكائن المُعرَّفة بالصنف الأعلى (superclass) لا تُصبِح جزءًا من الصنف الفرعي. يُمكِنك إضافة بواني جديدة بالصنف الفرعي إذا أردت، وفي حالة عدم إضافتها، سيُنشِئ الحاسوب بَانِي كائن افتراضي (default constructor) بدون أي مُعامِلات (parameters). إذا كان الصنف الأعلى (superclass) يَحتوِي على باني كائن (constructor) يُنفِّذ الكثير من التهيئة الضرورية، فيبدو أنك ستَضطرّ إلى تَكْرار كل ذلك العمل بالصنف الفرعي. بالإضافة إلى ذلك، قد لا تَملُك شيفرة الصنف الأعلى (superclass)، ولا تَعلَم حتى طريقة تَّنْفيذها (implementation)، وهو ما قد يُمثِل مشكلة حقيقية، والتي قد تُصبِح مستحيلة إذا كان الباني المُعرَّف بالصنف الأعلى يَستخدِم مُتْغيِّرات أعضاء خاصة (private member variables)، ففي تلك الحالة، أنت لا تَملُك حتى صلاحية للوصول إليها من الصنف الفرعي. لابُدّ إذًا من وجود طريقة لإصلاح ذلك. في الواقع، قد يُستخدَم المُتْغيِّر الخاص super كأول تَعْليمَة بالباني (constructor) المُعرَّف بالصنف الفرعي؛ لكي يَستدعِي الباني (constructor) المُعرَّف بالصنف الأعلى (superclass). قد تَكُون طريقة كتابة ذلك مُضللة نوعًا ما؛ فهي تبدو كما لو كنت تَستدعِي super كبرنامج فرعي (subroutine) على الرغم من أنه ليس كذلك، وفي العموم لا يُمكِنك استدعاء البواني (constructors) بنفس طريقة استدعاء البرامج الفرعية. والآن، لنَفْترِض أن الصنف PairOfDice يَتَضمَّن باني كائن (constructor) يَستقبِل مُعامِلين (parameters) من النوع int، يُمكِننا إذًا أن نُعرِّف صنفًا فرعيًا (subclass) منه كالتالي: public class GraphicalDice extends PairOfDice { public GraphicalDice() { // باني كائن لهذا الصنف // استدعي الباني من الصنف الأساسي بقيم المعاملات 3 و 4 super(3,4); initializeGraphics(); // نفذ التهيئة الخاصة بالصنف الفرعي } . . // المزيد من البواني والمتغيرات والتوابع . } تَستدعِي التَعْليمَة super(3,4);‎ الباني (constructor) المُعرَّف بالصنف الأعلى. لابُدّ من كتابته بالسطر الأول من الباني المُعرَّف بالصنف الفرعي (subclass)، وفي حالة عدم استدعاء أي باني من الصنف الأعلى بصورة صريحة، يُستدعَى تلقائيًا بَانِي الصنف الأعلى الافتراضي (default constructor) أي ذلك الذي لا يَستقبِل أي مُعامِلات (parameters)، وإذا لم يَكُن موجودًا، سيُبلِّغ المُصرِّف (compiler) عن وجود خطأ في بناء الجملة (syntax error). يُستخدَم المُتْغيِّر الخاص this بنفس الطريقة تمامًا، ولكن لاستدعاء باني (constructor) آخر ضِمْن نفس الصنف. سيَبدُو عندها السطر الأول من الباني كما لو كان استدعاءً لبرنامج فرعي اسمه هو this، وسيُنفَّذ عندها مَتْن الباني المُستدعَى مما يُجنّبك تكرار نفس الشيفرة ضِمْن عدة بواني مختلفة. على سبيل المثال، يُستخدَم الصنف MosaicCanvas -من القسم ٤.٧- لتمثيل شبكة من المستطيلات الملونة، ويَتَضمَّن باني يَستقبِل أربعة مُعامِلات (parameters) كالتالي: public MosaicCanvas(int rows, int columns, int preferredBlockWidth, int preferredBlockHeight) يَستقبِل ذلك الباني مجموعة من الخيارات يُنفِّذ على أساسها الكثير من التهيئة (initialization). قد تحتاج إلى إضافة بواني (constructors) آخرى بعدد أقل من الخيارات لتَكُون أسهل في الاِستخدَام، ولكن ما يزال تَّنْفيذ التهيئة كاملة أمرًا ضروريًا. يَحتوِي الصنف على البواني التالية: public MosaicCanvas() { this(42,42); } public MosaicCanvas(int rows, int columns) { this(rows,columns,16,16); } يَستدعِى كل باني كائن (constructor) منهما باني كائن آخر بالإضافة إلى توفير قيم ثابتة للمُعامِلات الآخرى التي لم يَستقبِلها. على سبيل المثال، يَستدعِي التعبير this(42,42)‎ الباني الثاني، والذي بدوره يَستدعِي الباني الأساسي ذو المُعامِلات الأربعة. في الواقع، يُستدعَى الباني الأساسي بجميع الحالات وذلك لضمان تَّنْفيذ التهيئة (initialization) الضرورية كاملةً. ترجمة -بتصرّف- للقسم Section 6: this and super من فصل Chapter 5: Programming in the Large II: Objects and Classes من كتاب Introduction to Programming Using Java.
    1 نقطة
  26. يُمكّننا DOM من فعل أيّ شيء بالعناصر وما تحتويه، لكن نحتاج أوّلا إلى أن نصل إلى الكائن المحدّد من DOM. تبدأ جميع العمليّات على DOM بالكائن document. فهو "نقطة الدخول" الرئيسيّة إلى DOM، ويمكن من خلاله الوصول إلى جميع العقد. تمثّل الصورة التالية الروابط التي يمكن من خلالها التنقّل بين العقد في DOM. لنتناولها بمزيدٍ من التفصيل. في اﻷعلى: documentElement و body تُتاح العقد العلويّة للشجرة مباشرةً على شكل خاصّيّات لكائن document: <html> =‏ document.documentElement: تكون العقدة التي في قمّة الشجرة document.documentElement ، وهي عقدة DOM التي تمثّل وسم <html>. <body> =‏ document.body: من العقد التي يكثر استعمالاها أيضا عنصر <body> الذي يمثّله كائن document.body <head> =‏ document.head: يكون وسم <head> متاحا كـ document.head. هناك خدعة: قد يكون document.body عديم القيمة (أي null) لا يستطيع السكربت الوصول إلى عنصر غير موجود حال تنفيذه. فمثلا، إذا كان السكربت بداخل <head> فإنّ document.body غير متاح له، ﻷن المتصفّح لم يبلغ موضعه بعد حتى يقرأه. ففي المثال أدناه، يعرض لنا الـ alert اﻷوّل القيمة العدميّة null: <html> <head> <script> alert( "From HEAD: " + document.body ); // بعد <body> فليس هناك ،null </script> </head> <body> <script> alert( "From BODY: " + document.body ); // فهو الآن موجود ،HTMLBodyElement </script> </body> </html> في عالم DOM، تعني null أنّه "غير موجود" في DOM، تعني القيمة null أنّه "غير موجود" أو "لا وجود لهذه العقدة". اﻷبناء: lastChild ، firstChild ، childNodes هناك مصطلحان سنستعملهما من الآن فصاعد: العقد اﻷبناء (أو اﻷبناء باختصار) -- العناصر الذين هم أبناء مباشرون، أو بعبارة أخرى، هي العناصر المتفرعة عن العنصر المراد مباشرة. على سبيل المثال، العنصران <head> و <body> هما أبناء لعنصر <html>. العقد السليلة (descendants) -- جميع العناصر المتفرعة عن العنصر المراد، بما ذلك أبناؤه وأبناء أبنائه، إلى آخر ذلك. فمثلا هنا، للعنصر <body> اﻷبناء <div> و <ul> (وبعض العقد المتكوّنة من فراغات): <html> <body> <div>Begin</div> <ul> <li> <b>Information</b> </li> </ul> </body> </html> … وأمّا العقد السليلة لـ <body> فليست أبناءه المباشرين <div> و <ul> فحسب، بل تشمل كلّ العقد المتفرّعة منه، مثل <li> (الذي هو ابنً لـ <ul>) و <b> (الذي هو ابنٌ لـ <div>) -- الشجرة الفرعيّة بأكملها. تضمّ المجموعة childNodes كل العقد اﻷبناء، بما في ذلك العقد النصيّة. يقوم المثال أدناه بعرض أبناء document.body: <html> <body> <div>Begin</div> <ul> <li>Information</li> </ul> <div>End</div> <script> for (let i = 0; i < document.body.childNodes.length; i++) { alert( document.body.childNodes[i] ); // Text, DIV, Text, UL, ..., SCRIPT } </script> ...المزيد من اﻷشياء... </body> </html> See the Pen JS-p2-03-dom-navigation-ex01 by Hsoub (@Hsoub) on CodePen. يُرجى الانتباه ﻷمر دقيق هنا. لو أجرينا المثال السابق، سيكون <script> هو آخر العناصر التي تُعرض. في حقيقة اﻷمر، لاتزال هناك المزيد من اﻷشياء في المستند، لكن السكربت لم يرها، ﻷنّه حال تنفيذه، لم يكن المتصفّح قد اطّلع عليها بعد. تُمكّن الخاصّيات firstChild و lastChild الوصول بسهولة إلى أوّل اﻷبناء وآخرهم. هي فقط بمثابة اختصارات. إذا كان للعنصر elem عقدً أبناء، فإنّ العبارات التالية دائما صحيحة: elem.childNodes[0] === elem.firstChild elem.childNodes[elem.childNodes.length - 1] === elem.lastChild هناك أيضا دالّة خاصّة ()elem.hasChildNodes للتحقّق من أنّ له أبناءً. مجموعات DOM كما نلاحظ، تبدو childNode وكأنّها مصفوفة (array)، لكنّ الحقيقة أنّها ليست كذلك، بل هي باﻷحرى مجموعة (collection) -- كائن خاصّ شبيهً بالمصفوفة وقابل للتكرار عليه (iterable). ينجم عن هذا اﻷمر أثران مهمّان: يمكننا استعمال for..of للتكرار عليه: for (let node of document.body.childNodes) { alert(node); // يعرض هذا جميع العقد التي في المجموعة } See the Pen JS-p2-03-dom-navigation-ex02 by Hsoub (@Hsoub) on CodePen. هذا ﻷنّه قابل للتكرار (أي أنّه يتيح خاصّيّة Symbol.iterator كما يلزم). لا يمكننا استعمال توابع المصفوفة معها، ﻷنّها ليست مصفوفة: alert(document.body.childNodes.filter); // (filter غير معرّف (ليس هناك تابع اسمه الأمر اﻷوّل جيّد. كما أنّه لا بأس باﻷمر الثاني، ﻷنّه يمكننا استعمال Array.from ﻹنشاء مصفوفة "حقيقيّة" من المجموعة، إذا رغبنا في توابع المصفوفة: alert( Array.from(document.body.childNodes).filter ); // function See the Pen JS-p2-03-dom-navigation-ex03 by Hsoub (@Hsoub) on CodePen. مجموعات DOM هي للقراءة فقط مجموعات DOM، بل زد على ذلك، جميع خاصّيّات التنقّل التي ذكرناها في هذا المقال هي للقراءة فقط (read-only). فلا يمكن مثلا استبدال ابنٍ بشيء آخر بواسطة الإسناد ... = [childNodes[i. يتطلب تغيير DOM توابع أخرى سنتناولها في المقال التالي. مجموعات DOM حيّة كلّ مجموعات DOM تقريبا، مع بعض الاستثناءات القليلة، هي حيّة (live). ما يعني ذلك أنّها تعكس الوضع الحاليّ لـ DOM. إذا احتفظنا بمرجع للمجموعة elem.childNodes ، وأضفنا أو أزلنا عقدا من DOM، فإنّها تظهر في المجموعة تلقائيّا. لا تستعمل for..in للتكرار على المجموعات رغم أنّ المجموعات تقبل التكرار بواسطة for..in، لكنّه يُفضّل عدم استعمالها لذلك. تمرّ for..in على جميع الخاصّيّات التي يمكن تعدادها (enumerable)، وللمجموعات بعض الخاصّيّات "الإضافيّة" التي يندر استعمالها ولا نودّ أن نحصل عليها: <body> <script> // وأكثر ،values ،item ،length ،1 ،0 سيعرض هذا كلّا من for (let prop in document.body.childNodes) alert(prop); </script> </body> See the Pen JS-p2-03-dom-navigation-ex04 by Hsoub (@Hsoub) on CodePen. الإخوة واﻷب الإخوة (siblings) هم عقدٌ أبناء لنفس الأب. فمثلا هنا، <head> و <body> هما أخوين: <html> <head>...</head><body>...</body> </html> يُقال عن <body> أنّه اﻷخ "التالي" أو "اﻷيمن" لـ <head>. يُقال عن <head> أنّه اﻷخ "السابق" أو "الأيسر" لـ <body> . يكون اﻷخ التالي مُتاحا في الخاصّيّة nextSibling، والأخ السابق في الخاصّيّة previousSibling. بينما يكون اﻷب مُتاحا في الخاصّيّة parentNode. على سبيل المثال: // <html> هو <body> أب alert( document.body.parentNode === document.documentElement ); // صحيح // <body> يأتي<head> بعد alert( document.head.nextSibling ); // HTMLBodyElement // <head> يكون <body> قبل alert( document.body.previousSibling ); // HTMLHeadElement See the Pen JS-p2-03-dom-navigation-ex05 by Hsoub (@Hsoub) on CodePen. التنقّل بين العناصر فقط تربط خاصّيّات التنقّل المذكورة أعلاه بجميع أنواع العقد. فيمكننا مثلا من خلال childNodes الاطلاع على كلٍّ من العقد النصّيّة والعقد العنصريّة، بل وحتى العقد التعليقيّة إن وُجدت. لكنّنا في العديد من المهامّ لا نرغب في العقد النصّيّة والتعليقيّة. بل نرغب في معالجة العقد العنصريّة التي تمثّل الوسوم وتشكّل بنية الصفحة. لنرى إذًا بعض روابط التنقّل اﻷخرى التي تأخذ في الحسبان العقد النصيّة فقط: هذه الروابط مماثلة لتلك المذكورة أعلاه، مع إضافة كلمة Element في وسطها: children -- الأبناء الذين هم عقد عنصريّة فقط. firstElementChild و lastElementChild -- أوّل اﻷبناء وآخرهم من العقد العنصريّة. previousElementSibling و nextElementSibling -- العناصر المتجاورة. parentElement -- العنصر اﻷب. ما الداعي إلى parentElement ؟ أيمكن للأب ألّا يكون عنصرا؟ تُعيد خاصّيّة parentElement "العنصر" اﻷب، بينما تُعيد parentNode "أيّ عقدةٍ" أب. هاتان الخاصّيّتان متشابهتان في العادة: كلتاهما تُحصّل اﻷب. لكن هناك استثناءً وحيدا مع document.documentElement: alert( document.documentElement.parentNode ); // document alert( document.documentElement.parentElement ); // null See the Pen JS-p2-03-dom-navigation-ex06 by Hsoub (@Hsoub) on CodePen. سبب ذلك أنّ أب العقدة الجذر document.documentElement (التي تمثلّ <html>) هو document، و document ليس عقدة عنصريّة. فلهذا تعيده parentNode ولا تعيده parentElement. قد يفيد هذا التفصيل إذا ما أردنا التنقّل صعودا من عنصرٍ ما elem إلى <html>، لكن دون الوصول إلى document. while(elem = elem.parentElement) { // <html> اصعد إلى غاية alert( elem ); } لنُعدّل أحد اﻷمثلة التي في اﻷعلى. استبدل childNodes بـ children . ستظهر لك الآن العناصر فقط: <html> <body> <div>Begin</div> <ul> <li>Information</li> </ul> <div>End</div> <script> for (let elem of document.body.children) { alert(elem); // DIV, UL, DIV, SCRIPT } </script> ... </body> </html> See the Pen JS-p2-03-dom-navigation-ex07 by Hsoub (@Hsoub) on CodePen. المزيد من الروابط: الجدوال تناولنا إلى حدّ الآن خاصّيّات التنقّل اﻷساسيّة. قد تُتيح بعض أصناف العناصر في DOM خاصّيات إضافيّة تتميّز بها دون غيرها، لمزيدٍ من التسهيل. تُعدّ الجداول مثالا جيّدا لذلك، وتمثّل حالة خاصّة اﻷهميّة: يدعم عنصر <table> (إضافة إلى ما ذُكر في اﻷعلى) الخاصّيّات التالية: table.rows -- مجموعة عناصر <tr> التي في الجدول. table.caption/tHead/tFoot -- تشير إلى العناصر caption و thead و tfoot. table.tBodies -- مجموعة عناصر <tbody> (قد تكون هناك عدّةٌ منها كما ينصّ على ذلك المعيار، لكن سيكون هناك حتمًا واحد على اﻷقل -- حتى وإن لم يوجد في مصدر HTML، فسيضعه المتصفّح في DOM). تُتيح العناصر <thead> و <tfoot> و <tbody> خاصّيّة rows : tbody.rows -- مجموعة عناصر <tr> التي بداخله. <tr>: tr.cells -- مجموعة الخانات <td> و <th> التي بداخل <tr>. tr.sectionRowIndex -- موضع <tr> بداخل الـ <thead> أو <tbody> أو <tfoot> الذي يضمّه. tr.rowIndex -- رقم <tr> بالنسبة للجدول ككلّ (أي بين جميع أسطر الجدول). <td> و <th>: td.cellIndex -- رقم الخانة بداخل السطر الذي يضمّها. هذا مثال عن استعمالها: <table id="table"> <tr> <td>one</td><td>two</td> </tr> <tr> <td>three</td><td>four</td> </tr> </table> <script> // (السطر اﻷوّل، والعمود الثاني) "two" حدّد الخانة التي فيها let td = table.rows[0].cells[1]; td.style.backgroundColor = "red"; // لوّنها </script> See the Pen JS-p2-03-dom-navigation-ex08 by Hsoub (@Hsoub) on CodePen. للاطلاع على المواصفة: tabular data. هناك أيضا المزيد من خاصّيات التنقّل التي تتعلّق بنماذج HTML (أي forms). سنقف عندها لاحقا عندما نبدأ العمل بالنماذج. الملخص إنطلاقًا من أيّ عقدةٍ في DOM، يمكن الذهاب إلى العقد المجاورة لها مباشرة بواسطة خاصّيّات التنقّل. تنقسم هذه الخاصيّات إلى فئتين رئيسيّتن: لجميع العقد: parentNode childNodes firstChild lastChild previousSibling nextSibling للعقد العنصريّة فقط: parentElement children firstElementChild lastElementChild previousElementSibling nextElementSibling تُتيح بعض أصناف العقد في DOM كالجداول مثلا، خاصّيّات ومجموعات إضافيّة تمكّن من الوصول إلى محتواها. التمارين اﻷبناء في DOM اﻷهمية: 5 لاحظ هذه الصفحة: <html> <body> <div>Users:</div> <ul> <li>John</li> <li>Pete</li> </ul> </body> </html> اعط طريقة واحدة على اﻷقلّ للوصول إلى كلٍّ من عقد DOM التالية: العقدة <div>؟ العقدة <ul>؟ عقدة <li> الثانية (التي فيها Pete)؟ الحل هناك عدّة طرق، على سبيل المثال: العقدة <div>: document.body.firstElementChild // أو document.body.children[0] // أو -- لاحظ أن العقدة الأولى فراغ، لذا نأخذ الثانية document.body.childNodes[1] العقدة <ul>: document.body.lastElementChild // أو document.body.children[1] عقدة <li> الثانية (التي فيها Pete): // ومن ثمّ تحصيل آخر أبنائه العناصر <ul> تحصيل document.body.lastElementChild.lastElementChild سؤال عن الإخوة اﻷهميّة: 5 إذا كانت elem عقدةً عنصريّة من DOM … هل صحيح أنّ elem.lastChild.nextSibling دائمًا null؟ هل صحيح أنّ elem.children[0].previousSibling دائمًا null؟ الحل نعم، ذلك صحيح. يكون elem.lastChild دائما آخر اﻷبناء، فليس لديه nextSibling. لا ليس ذلك صحيحا، ﻷنّ [elem.children[0 هو أوّل ابنٍ بين العناصر، وقد تأتي قبله عقدٌ غير عنصريّة. فلا تكون بذلك previousSibling هي null بالضرورة، بل قد تكون عقدةً نصيّة مثلا. يرجى الانتباه إلى أنّه في كلتا الحالتين، إذا لم يكن هناك أبناء فسيُحدث ذلك خطأً. إذا لم يكن هناك أبناء، فإنّ elem.lastChild هو null فلا يمكننا الوصول إلى elem.lastChild.nextSibling، وتكون أيضا المجموعة elem.children فارغة (كمصفوفة فارغة [ ]). اختر الخانات القُطريّة اﻷهميّة: 5 اكتب الشفرة التي تُلوّن جميع الخانات التي على قُطر الجدول باﻷحمر. ستحتاج إلى تحصيل جميع الخانات <td> القطريّة من الجدول <table> وتلوينها باستخدام الشفرة التالية: // إلى خانة الجدول td تشير td.style.backgroundColor = 'red'; يجب أن تكون النتيجة كالتالي: افتح البيئة التجريبيّة لإنجاز التمرين الحل سنستخدم خاصّيّات rows و cells للوصول إلى الخانات القطريّة. شاهد الحلّ في البيئة التجريبيّة ترجمة وبتصرف لمقال Walking the DOM من كتاب The Modern JavaScript Tutorial
    1 نقطة
×
×
  • أضف...