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

ابراهيم الخضور

الأعضاء
  • المساهمات

    164
  • تاريخ الانضمام

  • تاريخ آخر زيارة

كل منشورات العضو ابراهيم الخضور

  1. ماهو علم نفس الألوان؟ وما هي مشكلة علم نفس اللون في التسويق وفي الترويج للعلامات التجارية، وكيف تتخذ قرارات قابلة للتطبيق تتعلق باستخدام الألوان في التسويق والترويج؟ وكيف تجد لوحة الألوان التي تناسبك. إنّ استخدام علم نفس الألوان في الإقناع، هو أحد أكثر جوانب التسويق متعة وإثارة للجدل. إنّ المشكلة كانت دومًا في عمق التحليل. فعلى الرغم من أنّ نظرية الألوان موضوع معقد ومربك، لكن من السهل إيضاح علم نفس الألوان باستخدام الإنفوجرافيك الذي لا يغطي أفكارًا أكثر مما يعرضه. لن تجعلنا مثل هذه النقاشات ذات المستوى السطحي محضَّرين لاتخاذ قرارات ذكية حول استخدام الطيف اللوني في إيصال الرسالة الصحيحة لعلامتنا التجارية. لكن لماذا تتسم مثل هذه المحادثات اللونية بالسطحية الواضحة؟ ماهو علم نفس الألوان؟ يُعرَّف علم نفس الألوان بأنه دراسة لتحديد أثر اللون في التصوّرات والسلوكيات. يركز علم نفس الألوان في مجال التسويق والترويج للعلامات التجارية على تأثير الألوان في انطباعات العملاء عن علامة تجارية، وقدرتها على إقناعهم في التفكير بعلامة تجارية محددة أو شراء منتج ما. فهذا مجال ينبغي التفكير في استغلاله عند تحضير أدوات التسويق أو بناء عمل جديد أو إعادة الترويج لعمل قائم. تأمل التالي: وجد باحثون في دراسة حملت العنوان "Impact of color on marketing"، أنّ 90% من الأحكام السريعة على المنتجات قد اتُخذت بناء على اللون فقط! مشكلة علم نفس اللون في التسويق وفي الترويج لعلامات تجارية جرت محاولات لا تعد ولا تحصى لتصنيف طريقة تفاعل الأشخاص مع الألوان. يعتمد الإحساس بالألوان حقيقة على التجارب الشخصية، فمن الصعب وضع مقياس عالمي لكيفية إدراكها والشعور بها. لقد أظهرت دراسات أنّ ما يفضله الأشخاص بالإضافة إلى خبراتهم ونشأتهم والفوارق الثقافية والمجتمعية والسياق الذي قد يؤثر في اختيارهم لونًا سيشوب الانطباع الذي يولده اللون في الفرد. فدقة الفكرة التي مفادها أن اللون الأصفر أو البنفسجي قد يحرض نوعًا من المشاعر الخاصة، هي كدقة المعلومات التي تحصل عليها عند قراءة راحة يدك عند عرّافة. لن تكون دقيقًا عندما تتخذ قرارات فضفاضة كقولك "الأخضر يعني الهدوء"، إذ سيختلف الوضع باختلاف سياق الحديث. فقد يستخدم اللون الأخضر مع علامة تجارية لأغراض بيئية مثل Seventh Generation أو قد يُستخدم للترويج لفضاءات مالية مثل Mint. فبينما يعطي اللون البني مظهر الخشونة - انظر كيف تستخدمه Saddleback Leather- قد يعطي في سياق آخر شعورًا دافئًا وودودًا (كالعيد) أو لتحريك شهيتك (ككل إعلانات الشوكولا التي تراها). ويبقى لدينا الكثير لنتعلمه ونفكر به إن أدركنا ببساطة أنه لا أجوبة مضمونة على الأسئلة الجوهرية، ومفتاحنا هو البحث عن طرق تطبيقية لاتخاذ قراراتنا حول الألوان. كيف تتخذ قرارات قابلة للتطبيق تتعلق باستخدام الألوان في التسويق والترويج؟ خلاصة الكلام أنه لا توجد إرشادات واضحة وحاسمة لاختيار ألوان علامتك التجارية. فقد تتمكن من الاطلاع ببساطة على مخطط إنفوجرافيك وتقرر ما تريده، لكن في الواقع لن تجد جوابًا محددًا للسؤال "ماهو اللون الصحيح لعلامتك التجارية؟". إنها الحقيقة، وسيبقى للسياق الذي تعمل ضمنه الاعتبار الأول. فما يهم هو المشاعر والحالة النفسية والصورة التي يولدها المنتج أو العلامة التجارية. أما الخبر الجيد، فهو أنّ علم نفس الألوان سيساعدك على الاختيار المناسب. اللون الصحيح ملائم لعلامتك التجارية وجد باحثون في دراسة جرت عام 2006 أنّ العلاقة بين العلامات التجارية والألوان تتمحور حول الملاءمة المحسوسة للون الذي تستخدمه علامة تجارية محددة. وبكلمات أخرى: هل يناسب اللون المختار ما يُباع من منتجات؟ كما وجد الباحثون -فيما يتعلق بانتقاء اللون الصحيح- أن توقع ردود فعل العملاء على ملائمة اللون أهم بكثير من اللون بحد ذاته. وبالتالي عند انتقائك لألوان علامتك التجارية أو ما تسوق له، إسأل نفسك (أو بالأحرى استطلع آراء عملائك): "هل هذا اللون سيلائم ما أبيعه". سيظهر اللون الصحيح خصوصية علامتك التجارية تُأثر الألوان بشدة على ميل العملاء إلى الشراء نظرًا لتأثيرها على كيفية تصوّرهم للعلامة التجارية. حيث تؤثر الألوان بطريقة رؤية العميل لشخصية العلامة التجارية التي يقيّمها. وبينما تتماشى ألوان مع سمات محددة (كالبني مع الخشونة مثلًا)، تؤكد معظم الدراسات الأكاديمية حول الألوان والترويج للعلامات التجارية أن الأهم بلا منازع هو أن تدعم الألوان المنتقاة الشخصية والخصوصية التي تريد إظهارها بدلًا من تماشيها مع الرؤية النمطية لانتقاء اللون. قادت عالمة النفس والأستاذة في جامعة ستانفورد جينيفر إيكر دراسات على هذا الموضع بالتحديد، وأشارت دراستها التي تحمل العنوان "Dimensions of Brand Personality" إلى وجود خمسة أبعاد جوهرية تلعب دورًا في إبراز شخصية الشركة. وأن العلامات التجارية قد تبدي سمتين من سمات الخصوصية، لكنها في الغالب تحت هيمنة واحدةٍ من هذه السمات فقط. لذا اسأل نفسك: ما السمة الشخصية التي أريدها لعلامتي التجارية، وكيف سأستخدم اللون لإيصال هذه الشخصية؟ اللون المناسب يجذب عملاءك يعد عمل جو هالوك الذي يحمل العنوان "Colour Assignment" عن العلاقة بين علم نفس اللون والجنس من أكثر الدراسات أهمية في هذا المجال. حيث تظهر بيانات هالوك تفضيلًا واضحًا لألوان محددة وفقًا لجنس العميل. لكن من المهم أن تدرك أن معظم الذين أجابوا كانوا من المجتمعات الغربية. فبيئة الشخص -وخاصة إدراكه الثقافي- سيلعب دورًا قويًا في فرض ما يجده أحد الجنسين لونًا ملائمًا، وسيؤثر ذلك بدوره على التفضيلات الشخصية للألوان. وتظهر دراسات أخرى عن إدراك الألوان وتفضيل الألوان أن الرجال يفضلون عمومًا الألوان القاسية بينما تفضل النساء الألوان الأكثر نعومة، وذلك عندما يتعلق الأمر بتدرجات اللون وسطوعها وشدتها. وأشارت الدراسة أيضًا إلى ميل الرجال لاختيار الألوان التي تميل للقتامة (ألوان مع مسحة سوداء) بينما تميل النساء إلى الألوان الفاتحة (ألوان مع مسحة بيضاء). وعلى الرغم من الجدل المحتدم حول هذه النقطة، يمكن للعلامات التجارية أن تعمل خارج نطاق التصور النمطي للألوان التي يفضلها الجنسين. وفي الواقع ستجد العديد ممن تلقى جوائزًا لخروجه عن المألوف. لا ينبغي التشدد في مفهوم الملائمة المحسوسة وافتراض أن العلامة التجارية ستخفق خارج هذه الإطار، وذلك أنه لا اتفاق على اختيار الألوان بين من شاركوا في الاستبيانات، وهذا ما يقودنا مباشرة إلى النقطة التالية. اللون الصحيح سيميّز علامتك التجارية كشف دراسات أخرى أن أدمغتنا تفضل العلامات التجارية التي تميزها مباشرة، مما يجعل اللون عنصرًا مهمًا في تكوين هوية العلامة التجارية. وأشارت إحدى المقالات الصحفية إلى أهمية اختيار لون العلامة التجارية الجديدة لضمان تميزها عن المنافسين المعروفين. سيساعدك اختيار اللون الصحيح على إبراز علامتك التجارية. فكّر بالمبدأ النفسي المعروف بتأثير الإنعزال the Isolation Effect والذي ينص على أن أي عنصر "يبرز كإبهام متورم" سيرسخ على الأرجح في الذاكرة. حيث أشارت الدراسات بوضوح إلى أن المشتركين في الاختبارات كانوا قادرين على تمييز وتذكر العنصر بطريقة أفضل بكثير سواء كان نصًا أم صورة إن كان بارزًا بشكل ملفت عن محيطه. وخلصت دراستين عن التوليفات اللونية أحدهما تقيس الاستجابة الجمالية والأخرى عما يفضله العملاء، إلى أن العملاء يفضلون أيضًا اللوحات اللونية التي تعرض تباينًا شديدًا لألوان التمييز Accent colors، على الرغم من تفضيل الأغلبية العظمى للوحات اللونية ذات التباين المتشابه. ويعني هذا وفقًا لمصطلحات تنسيق الألوان إنشاء بنية بصرية تتكون من ألوان أساسية متماثلة ثم تغيير سطوعها باستخدام ألوان تمييز مكملة (وفقًا لأسلوب الألوان الثلاث). يلعب هذا المفهوم دورًا كبيرًا في عالم التسويق أيضًا، ويمكن أن نفكر فيه على أنه صفحة ويب بخلفية من لون أساسي تتداخل معها ألوان تمييز تحملها لبقية العناصر -كما يظهر في تصميم جوش بيرز الذي سنعرضه في الصورة التالية- مما يشكل بنية هرمية ضمن موقعك لتدرب العملاء على الألوان التي تشجع على تنفيذ إجراء ما. لم كل هذا الاهتمام؟ إن الفهم الصحيح لهذه المبادئ سيجنبك الوقوع في فخ تحسين نسبة المبيعات بناء على المبدأ اللوني الذي يضلل الكثيرين. تأمل الموقع التالي لإحدى العلامات التجارية الذي يشير إلى زيادة في نسبة المبيعات بعد تغيير اللون. عزز تغيير لون الزر إلى الأحمر المبيعات بنسبة 21%، لكن لا يمكننا بالتأكيد إتخاذ أية فرضيات حول "قوة تأثير اللون الأحمر" بمعزل عن بقية المؤثرات. من الواضح أن بقية عناصر الصفحة تميل إلى اللون الأخضر، ويعني هذا ببساطة أن زر اتخاذ القرار الشراء ذو اللون الأخضر سيتمازج مع بقية العناصر المحيطة، بينما يُبرز اللون الأحمر تباينًا شديدًا فهو مكمل للون الأخضر. فكر أخيرًا -وهذا أمر حساس جدًا- بتعريفك لنجاح اختبارات كهذه. فالمزيد من الإشتراكات والنقرات لا تشكل سوى مقاييس معزولة ومضللة غالبًا للمسوقين الذين يحاولون استخدامها ببساطة لمجرد أنها سهلة القياس. يمتلك اللون الصحيح اسما صحيحا على الرغم من التصور المختلف للألوان المختلفة، إلا أن الاسم الذي يصف اللون مؤثر أيضًا. فوفقًا لدراسة تحمل العنوان A rose by any other name …، طلب من المشتركين أن يقيّموا المنتجات بناء على أسماء ألوانها -مثل مساحيق التجميل- فكانت المنتجات المفضلة هي التي يحمل لونها اسمًا أنيقًا. فوُجد مثلًا أن اللون الذي يسمى "موكا mocha" كان محببًا أكثر من "البني" على الرغم من أن الاسمين يعرضان اللون نفسه. وقد أثبتت دراسة أخرى أن التأثير نفسه ينطبق على أنواع مختلفة من المنتجات، فقد رأى العملاء أن الأسماء المتقنة لألوان الطلاء ستجعلها تبدو للعين أكثر جمالًا من تلك التي سُميّت ببساطة. كما أظهرت الدراسة أن الأسماء الفريدة وغير الإعتيادية للألوان هي الأكثر تفضيلًا وبالنسبة لكل المنتجات ابتداءً بحبوب الهلام إلى الملابس. فقد تُختار أقلام التلوين التي تحمل اسم "رازماتاز" مثلًا أكثر مما ستُختار إن سُمّي لونها "أصفر ليموني" جد لوحة الألوان التي تناسبك ها قد وصلنا إلى ختام هذا المقال ولم نجد بعد طريقة مثالية لاختيار اللون أو مخطط الألوان المناسب. وربما نكون قد طرحنا أسئلة أكثر مما أجبنا. إن ازدحام مقالة بعبارات "ربما" و"نوعًا ما" لا يعني بأية حال التوقف عن التفكير الناقد لمحتواها. لذلك استخدم أساليب البحث المتاحة لتتحدى الأفكار المسبقة وتسأل أسئلة أفضل. فهذا هو أسلوب المثابرة للوصول إلى أجوبة أفضل. ترجمة -وبتصرف- للمقال Color Psychology in Marketing and Branding is All About Context لصاحبه Gregory Ciotti. اقرأ أيضًا الألوان في تصميم الرسوميات ونظرية الألوان كل ما يجب عليك معرفته عن نظرية الألوان لغير المصممين أدوات عديدة لانتقاء الألوان تفيدك في عملية التصميم كيف تنشئ ألوانك الخاصة في برنامج سكريبوس Scribus
  2. إن كنت تشعر أنك تقضي وقتًا عصيبًا في الاطلاع على الكم الهائل من المعلومات التي تحيط بك حول التسويق بالعمولة affiliate marketing، أو أنّ عملك كمسوق لا يتطور على الرغم من إضافة روابط التسويق بالعمولة إلى منشوراتك، سنرشدك عبر خطواتٍ عشر إلى احتراف التسويق المتقدم بالعمولة وتكوين استراتيجية مناسبة لعملك. مدخل موجز إلى التسويق المتقدم بالعمولة على الرغم من كون التسويق بالعمولة (تقديم منتجات من علامات تجارية أخرى إلى متابعيك مقابل عمولة) من أفضل الوسائل لكسب المال عبر الإنترنت وتأسيس قناة انسيابية لزيادة الدخل، لكن عليك أن تتذكر دائمًا أنّ التسويق المتقدم بالعمولة سيتعلق دائمًا بإيجاد حلول للمشاكل. فهذا النوع من التسويق لن يتعلق بك، بل هو موجه لقرّائك ومتابعيك. يضع البعض التسويق بالعمولة في إطار الكسب السريع للمال، ويعدونه طريقة للاسترخاء وانتظار الأموال حتى تتدفق إلى محفظتك. فأن توصي بالمنتجات التي تعجبك أمر رائع يدر عليك بالمال الذي سينساب بالتأكيد إلى محفظتك بمجرد أن يأتي العمل ثماره، لكن العمل الصعب الذي لا يمكنك تفاديه، هو بناء قاعدة من المتابعين الذين يثقون بك بما يكفي، وكذلك إبداع محتوى معين يأتي بنتائج جيدة باستمرار. لسوء الحظ، لن يكون وضع الروابط عشوائيًا ضمن مقالاتك أو منشوراتك ثم انتظار تدفق المال الأسلوب الأفضل في استراتيجية التسويق المتقدم بالعمولة، لكنه يبقى مع ذلك، الأسلوب الأكثر استخدامًا من قبل مالكي صفحات الويب والمؤثرين في هذا المجال. إن كنت تتطلع لتأسيس دخل يمكنك الاعتماد عليه مستخدمًا التسويق المتقدم بالعمولة، فلا بدّ أن تضيِّق شبكتك لاستهداف الأشخاص الذين يرغبون في الشراء لكن يلزمهم القليل من الثقة بالمصدر والذي ستلعب أنت دوره. عشرة نصائح لتسويق متقدم وناجح بالعمولة إليك مجموعة من النصائح التي ستحسن استراتيجيتك في التسويق بالعمولة، سواء أكنت بدأت العمل للتو أو أنك مستعد للتقدم في هذا المجال. 1. استعمل الكلمات المفتاحية الصحيحة تأكد دائمًا من كتابة محتوى يجذب الأشخاص المهتمين فعلًا بشراء المنتج. عليك من وجهة نظر مثالية، اختيار كلمات مفتاحية سهلة التصنيف مكتوبة بحجم صغير تشير إلى الشراء. 2. اختر منتجاتك بعناية وفكر بما تسوق له ينبغي عليك في الواقع تسويق المنتجات التي تمتلك بعض الخبرة فيها وهذا ما يبني الثقة مع القارئ. لكن المنتجات التي عليك تسويقها من وجهة نظر عالم الأعمال، هي تلك التي تحمل لك العمولة الأعلى. إن كنت بصدد كتابة محتوى أو تنفيذ حملة دعائية كاملة لمنتج تحصل منه على عمولة، لا بدّ أن تحصل منها على ما يستحق الوقت الذي ستقضيه في إنجازها. فالمنتجات المكلفة التي لن تضطر إلى بيع كميات كبيرة منها هي المفتاح. ستجد هذه المنتجات بسؤال نفسك أولًا عما قد ترغب بشرائه من المنتجات التي تختص بتسويقها، أو بتصور ما قد يحتاجه القراء. أجرِ بعض الأبحاث على الإنترنت عندما تضع قائمة بتلك المنتجات ووازن بينها لتجد الخيارات الأنسب لك ولقرائك. 3. تعرف إلى مديرك في التسويق نادرًا ما يستفيد المسوقون من إمكانيات مدير عملية التسويق بالعمولة على الرغم من أنهم موجودون لمساعدتك في تنفيذ المبيعات بالنيابة عن شركاتهم. فقد يقودك التواصل معهم لتطوير شراكات بما يلائم تخصصك إلى نتائج عظيمة بما في ذلك الحسومات التي قد يحصل عليها القرّاء، والصور الدعائية التي تلبي احتياجاتك وغيرها من الخيارات المربحة. 4. اطلع على أنواع مختلفة من المحتويات المتعلقة بالتسويق بالعمولة ينبغي أن تُركّز مقالات التسويق التي تكتبها على كلمات مفتاحية صحيحة وعلى المقدمة وصلب الموضوع بدلًا من كونها مجرد مكانٍ لتضع فيه روابط التسويق. لديك العديد من الأساليب التي قد تساعدك في كتابة مقالات للتسويق بالعمولة، وأكثرها شعبية أسلوب تجميع المنتجات كأن يكون عنوان المقال "أفضل عشرة آلات تصوير تناسب ميزانيتك". قد يتضمن المحتوى المتعلق بالتسويق بالعمولة أفكارًا أخرى مثل: موازنة عمولة بأخرى: كأن يكون العنوان ("أ" أو "ب" أي من الخيارين هو الأنسب للشركاء الجدد؟) أو ("أ" أو "ب" أي الخيارين الأفضل مذاقًا؟). ستجد طرقًا عدة لتختار العنوان، لكن عليك التأكد من أنه سيستهدف مجموعة محددة من الأشخاص (متابعيك بالطبع). كتابة مراجعة نقدية لمنتج: كأن تستخدم المفتاح "كيف تفعل كذا.." مثل "كيف تتناول طعامًا صحيًا عندما تكون مشغولًا (لشركة مثل هيلو فريش Hello Fresh)"، أو أن تبدأ مباشرة في كتابة المراجعة النقدية. 5. استخدم محتوى متفرعا في مقالاتك فبدل أن تبعثر روابط التسويق بالعمولة هنا وهناك في مقالتك بانتظار تحقيق ما تصبو إليه، عزز وادعم مقالات التسويق بمحتوى يتعلق فعليًا بما تختصه المقالة. ولن تحسّن فرص التقييم العالي لمقالتك بهذه الطريقة وحسب، بل ستجذب أشخاصًا ينصب اهتمامهم بالاطلاع عمومًا على المحتوى ليصبحو مهتمين ومتابعين لمقالاتك التسويقية. فإن كانت مقالتك عن بطاقة رحلة على القطار، أنشئ أدلة سياحية للبلد أو البلدان التي يمكن استخدام البطاقة ضمنها واربطها مع مقالتك الأصلية. 6. استخدم محفزات ملفتة لإغراء المشترين إن أردت جعل مقالاتك التسويقية لا تقاوم وبالتالي تحقيق المبيعات بسرعة فلا تنسى أن معظمنا يحب الصفقات المربحة والهدايا المجانية، وغالبًا ما يزيد ذلك من مردود العملية. فإن زوّدت مقالتك برموز حسم Discount code حصلت عليها من مدير التسويق أو بمكافآت إضافية Extra bonuses حققتها بنفسك (يمكن مشاركتها عبر جوجل درايف أو أية روابط قابلة للمشاركة)، فسيعنى ذلك أن العملاء قد يفضلون استخدام روابطك التسويقية بدلًا من روابط غيرك. يمكنك استخدام هذه الطريقة أيضًا لإضافة صيغة استعجال إلى أحداث ستجري خلال فترة زمنية مؤقتة، وستحسن فرص ظهور مقالاتك عند البحث عن كلمات مفتاحية مثل مكافآت Bonus أو رموز حسم Discount code أو هدايا مجانية Free gifts. تتنوع المكافآت الإضافية التي يمكنك استخدامها بطرق شتى، لكن مع ذلك لابدّ أن تتعلق مباشرة بمحتوى المقال. من الأمثلة البسيطة التي قد نذكرها: كتاب إلكتروني (مثل دليل سياحي يتعلق بعملية التسويق التي ننفذها) أو مفكرة أو وصول مجاني إلى مجموعة فيس بوك أو دورة تعليمية قصيرة أو حسومات. إن كنت تسوق لمجموعة أو حزمة من المنتجات (كتب إلكترونية أو دورات تعليمية عادة) فقد تضيف دفاتر أو جداول إلكترونية تساعد الأشخاص في تتبع المحتوى وتقودهم خلال تصفحه. 7. أنشئ صفحات ارتباط للمشاركة السريعة إن المكوّن الرئيسي لتسويق متقدم بالعمولة هم المتابعين الشغوفين كالزوار الذين يعودون باستمرار أو مشتركي البريد الإلكتروني. سيساعدك وجود صفحات هبوط أو ارتباط في تحويل المتابعين غير المهتمين إلى متابعين شغوفين، ويظهر الأمر الجيد في ذلك تحديدًا عند تسويق منتجات ليست من اختصاصك تمامًا. فإن سألك أحدهم النصيحة بشأن شبكة تواصل اجتماعي ستتمكن من تحويلهم إلى صفحات الارتباط المخصصة لهذا الأمر. يمكنك ضمن هذه الصفحات الحديث عن المنتج الذي تحبه ولماذا كما يمكنك تضمين عروض متنوعة، وتسهل على الزوار اتخاذ قرار الشراء. ومن الرائع جدًا استخدامها مع روابط الجر swipe-up على إنستغرام أو كردود على أسئلة في فيس بوك. ويمكنك بالتأكيد ربطها بمحتوى مناسب ضمن موقعك. 8. استخدم طريقة البيع الخاطفة Flash sale سجّل ضمن قوائم الرسائل الإخبارية وضمن صفحات فيس بوك لتعرف متى ستصدر الشركات منتجات جديدة أو متى ستدفع بعضها إلى السوق. يمكنك حينها استخدام حسابات التواصل الاجتماعي الخاصة بك وقوائم البريد الإلكتروني لتنبيه متابعيك إلى الأمر. تتيح لك متابعة المبيعات كتابة مراجعات نقدية باكرًا لمنتج طرح أو دُفع به إلى السوق وهذا ما يعطيها وقتًا ليرتفع تقييمها أو أن تلفت الانتباه على بينتريست Pinterest. تأكد من امتلاكك لصفحات ارتباط جاهزة لكي تنشرها بسهولة على وسائل التواصل الاجتماعي. خطط لهذا الأمر مسبقًا لتجعل الأمر سلسًا ومجدٍ من ناحية الوقت قدر الإمكان بأن تُجهّز مجلدات التواصل الاجتماعي والرسوميات والعناوين وتضع جداول زمنية لإرسال البريد الإلكتروني. استثنِ من قوائم بريدك الإلكتروني أي شخص غير مهتم بآخر تحديثات هذا المنتج لكي لا يشعر أيًا من عملائك أنه يتلقى بريدًا غير مرغوب به Spammed. سيكون تقديم المكافآت هنا أمرًا ممتازًا، فالمنافسة على أشدها خلال هذه الفترات. 9. فكر باستخدام العروض المفاجئة إن أردت توسيع دخلك أو أعمالك تدفع العروض المفاجئة العميل نحو اختيار عرض لمرة واحدة. من المحتمل أنك صادفت أمرًا مماثلًا عندما تصفحت مدونات أشخاص آخرين أو ربما بعد أن نزّلت هدية مجانية مثل دورة تدريبية بحسم يصل إلى 50% إن اشتركت خلال الساعة القادمة. استخدم إبداعك في استخدام هذه العروض. وعلى الرغم من تجنب الكثيرين استخدامها، لكن فعاليتها تضاهي بلا شك المبيع الخاطف. فإن اشترى أحدهم مثلًا الغرض الذي تسوقه خلال الفترة الزمنية لسريان العرض المفاجئ، فقد يمنحك هؤلاء غرضًا آخر مجانًا ككتاب إلكتروني أو دورة تعليمية أو عرض تقديمي على الإنترنت، وهذا مجرد مثال عن فائدة هذه العروض. 10. استغلال البريد الإلكتروني في التسويق بالعمولة يمكن أن يكون التسويق باستخدام البريد الإلكتروني جزءًا من استراتيجية التسويق المتقدم بالعمولة التي تتبعها طالما أن جمهورك لن يشعر بأنها رسائل إلكترونية غير معروفة المصدر(غير مرغوبة). إذ ينبغي أن يكون الجمهور قادرًا على الإنسحاب بسهولة من حملتك التسويقية الآلية عندما تبدأ وإلا قد تخسر مشتركيك. فليس أسوأ من أن تُقصف فقط برسائل مبيعات مصدرها مؤلف محتوى إلكتروني أحببت عمله لأشهر. مع ذلك، وطالما أن ما تسوقه بالعمولة جدير باهتمام متابعيك، سيكون التسويق بالاستفادة من البريد الإلكتروني أداة عظيمة ضمن صندوق أدواتك وخاصة مع اقتراب مناسبات خاصة وعند الإعلان عن تخفيضات، كما يمكنك أتمتة الكثير من المهام التي تتطلبها العملية. تعد هذه المنصات سهلة الاستخدام وقابلة للنمو ولها ميزات متعددة تبسط أمور الإشارة إلى جمهورك ووضعهم في مجموعات وإعداد سلاسل الرسائل الإلكترونية الموجهة إليهم. تأكد من أخذ الوقت الكافي لزيادة حجم قوائم البريد الإلكتروني بإضافة أشخاص جدد إليها باستخدام مغانط لجذب العملاء magnet lead ( كتقديم أدلة مجانية أو نصائح لتوفير المال والوقت أو عروض تقديمية مجانية على الإنترنت) والحرص على التواصل معهم بوتيرة منتظمة وأسلوب صادق يظهر خبرتك ويبني الثقة بينكم. إليك فكرة عن سلاسل بريد إلكتروني بسيطة يمكنك الاستفادة منها: رسائل الترحيب: وتتألف من رسالتين إلى ثلاث يمكنك من خلالها استعراض خبرتك وكسب الثقة وإيصال مغناطيس لجذبهم وكذلك إثارة حماستهم لتلقي البريد التالي ودفعهم لاتخاذ خطوات ملموسة وتوضيح ما هو المتوقع من بريدك الإلكتروني. رسائل لفت الانتباه: وتتألف من رسالتين إلى ثلاث تتحدث عن قيم وتلميحات وقصص وأفكار ملهمة وإشارات إلى المنتجات لكن لا تتجاوز الحدود (تذكر أن إخلاء مسؤوليتك أمر مطلوب). حافظ على عوامل الإعجاب والثقة بما تقدمه وابق المواضيع المطروحة متعلقة بالمنتجات المعنية. رسائل متابعة التطورات: يمكنك البدء خلالها في تقديم منتجاتك والشركات التي تسوق لها بشكل أكبر. ترجمة -وبتصرف- للمقالة 10 Steps to Mastering Advanced Affiliate Marketing لصاحبته Jessica Esa. اقرأ أيضًا كيف أبدأ بالتسويق بالعمولة كعامل مستقل كيف تُنوّع نشاطك كمستقل عبر التسويق بالعمولة كيف تصنع المال عبر التسويق بالعمولة عمل تسويق بالعمولة وتتبعه والمشاكل التي قد تصادفك
  3. إنّ التسويق الرقمي عمل مزدهر، ومن أهم ما على المسوقين فعله هذه الأيام هو إضافة التسويق عبر الهاتف المحمول إلى حملاتهم التسويقية. يجعل تعاملنا جميعًا مع الهواتف المحمولة -ولو نظريًا- من هذه الأجهزة وسيلة واسعة الانتشار كما هو حال البريد الإلكتروني. وتركز استراتيجيات التسويق للأعمال الصغيرة من خلالها على استخدام آليات بسيطة ترفع من نسب المبيعات. إذ يمكن أن تصل الأعمال الصغيرة إلى عملاء أكثر إذا ما استفدنا من هذه الاستراتيجيات كجزء من حلول التسويق متعدد الأقنية، وذلك بتوفير عروض مخصصة لهؤلاء العملاء. كيف تعزز استراتيجيات التسويق عبر الهاتف المحمول نسب المبيعات يمكن أن يزيد التسويق عبر الهواتف الذكية من اهتمام الناس بالعلامة التجارية التي تسوق لها، وأن يحسّن نسب مبيعاتك نظرًا لوجود أكثر من خمسة مليارات مستخدم لهذه الأجهزة. وتشير الأرقام إلى المستوى الذي وصل إليه استخدام أجهزة الهاتف المحمولة حيث: ثمانية وستون في المئة من حملات التسويق عبر البريد الإلكتروني يتابعها المهتمون عبر أجهزة الهاتف المحمولة. بيع في الولايات المتحدة حسابات للشراء عبر إعلانات الهاتف المحمول ما نسبته 72% من إجمالي الإعلانات الرقمية. ينفق المسوقون أكثر من نصف ميزانياتهم على إعلانات الهاتف المحمول. ترتفع المبيعات عندما يُستخدم التسويق عبر الهاتف المحمول كجزء من مقاربة التسويق متعدد الأقنية. يشجع استخدام الهواتف الذكية أكثر من 70% من الأشخاص على الشراء من المتاجر بعد استخدام أجهزتهم في الحصول على معلومات أكثر حول المنتج أو الخدمة المقدمة. شهد أكثر من 80% من الأعمال نموًا في العائدات عام 2018 عندما استخدمت استراتيجية التسويق الموجه المتقدمة. أنجزت أكثر من 40% من المعاملات المالية على الإنترنت عبر أجهزة الهاتف المحمولة. تساعد استراتيجيات التسويق للأعمال الصغيرة عبر الهاتف المحمول الناس على إيجاد معلومات عن منتجاتك والتي ستحوّلهم بالتأكيد إلى عملاء لك. عشرة استراتيجيات تسويق عبر الهاتف المحمول تقود بالفعل الأعمال الصغيرة إن أردت تحويل حركة المبيعات إلى موقعك، عليك أن تضع خطة عصرية تستغل استراتيجيات التسويق للأعمال الصغيرة عبر الهاتف المحمول. 1. التسويق المعتمد على الموقع الجغرافي إن توفر لديك تطبيق للهاتف المحمول يدعم أعمالك الصغيرة، ستكون قادرًا على استخدام تقنيات التسويق المعتمدة على الموقع الجغرافي مثل geofencing لتسوق منتجاتك إلى مستخدمي الهاتف المحمول في منطقة محددة. وتظهر فائدة الأمر خصوصًا للأعمال الصغيرة التي تمتلك متاجر شعبية أو أكشاك على الأرصفة، وستكون عملية عند استخدامها مع مواقع التجارة الإلكترونية التي تقدم خدمات محلية مثل توصيل الوجبات أو خدمات السفر. ويعد أكثر من 80% من المسوقين أنّ التسويق المعتمد على الموقع الجغرافي سيقود إلى زيادة في قيمة ثلاثة مؤشرات أساسية هي: زيادة بنسبة 85% في قاعدة العملاء، و83% في معدلات التجاوب، و83% في انخراط العملاء في عمليات الشراء. 2. تصميم مواقع متجاوبة مع الأجهزة المتصفحة لها ستحتاج إلى مواقع ويب وإعلانات الهاتف المحمول ومحتوى تسويقي مهيأ للعمل على الهواتف المحمولة وليس قابلًا للعرض عليه فحسب. فقد تضاعف مواقع الويب المصممة للعمل على الهواتف المحمولة ثلاثة مرات فرصة زيادة نسبة المبيعات على الهواتف المحمولة بنسبة 5% أو أكثر، ومع ذلك لا تتعدى الشركات التي تستخدم هذا الأسلوب نسبة 35%. هنالك عدة أساليب أخرى -بالإضافة إلى التصميم المتجاوب- قد تساعدك في إعداد موقعك ليتعامل مع صنف محدد من الأجهزة. ومن أفضل الطرق لإنجاز ذلك هي المنصات المخصصة لتطوير مواقع الويب المخصصة للهواتف المحمولة واستخدام اللغة HTML5 في تصميم الموقع واعتماد التصميمات المتكيفة Adaptive design. 3. الإعلانات على مواقع التواصل الاجتماعي على الرغم من هيمنة التسويق عبر البريد الإلكتروني، ستجد أن التسويق عبر مواقع التواصل الاجتماعي تشق طريقها بنجاح في عالم الأعمال الصغيرة وينبغي التركيز على ذلك. إن اضطررت إلى إنشاء حسابات كثيرة على منصات التواصل الاجتماعي الأكثر شعبية، لست مضطرًا لاستخدامها جميعًا لتطوير أعمالك. أجر اختبار موازنة A/B testings لتقف على أداء منشوراتك عبر المنصات المختلفة. تشجع مواقع التواصل الاجتماعي الأشخاص على شراء الأشياء من العلامات التجارية التي يفضلونها. وتشير الإحصائيات إلى أن 76% من المستهلكين الأمريكيين قد اشتروا شيئًا ما لمجرد مشاركة العلامة التجارية منشورًا يصف ميزات المنتج. فمعرفة الناس لوجود هذه العلامة التجارية، هو الهدف الرئيسي لمعظم الشركات بما يخص استراتيجية استخدام مواقع التواصل الاجتماعي. 4. المحتوى الملائم للهاتف المحمول تستهدف تهيئة التصميم للعمل على الهاتف المحمول عناصر في البنية الخارجية لموقعك عادةً، وهذا أمر مختلف عن كون الموقع ملائمًا للعرض على الهاتف المحمول. فتقديم المحتوى على الهواتف المحمولة مختلف عن حواسب سطح المكتب. ستحتاج إلى جمل أقصر وإلى إدراج عناوين رئيسية ووسائط مناسبة كالصور والفيديوهات ذات الدقة العالية. كما يرغب متابعيك على الأغلب بالتصفح السريع وأخذ لمحة مختصرة، لذا سهّل هذا الأمر عليهم. قد يساعدك استخدام العناوين عند إنشائك لمقاطع الفيديو في دفع الناس إلى المتابعة، إذ يشغّل معظم المتابعين (85% منهم) مقاطع الفيديو على فيس بوك دون صوت. ستساعدك العناوين على توصيل فكرتك لهم حتى لو كتموا صوت الفيديو. 5. تعزيز البحث الصوتي يتوجه الناس إلى البحث الصوتي مع تطور إمكانياته التي أوصلتها الأجهزة الذكية إلى منازلهم. ستزوّد أكثر من نصف التجهيزات المنزلية بمعدات تفعّل صوتيًا بحلول العام الحالي وزيادة بمقدار 42% فوق العدد الحالي لمالكيها. وستجد أنّ 34% من الأشخاص الذين لا يمتلكون هذه التقنية مهتمون باقتنائها. يمتلك البحث الصوتي الإمكانية لتحريك المبيعات، فأكثر ما يفعله الناس بعد تنفيذ بحث صوتي هو التواصل مع ممثلي الأعمال التي يعثرون عليها أو تصفح موقع الشركة الإلكتروني أو زيارة متجر محلي. وتحفز جميع هذه الأفعال المبيعات. 6. التسويق عبر الرسائل النصية تبدأ حملات التسويق عبر الرسائل النصية بمنح الأشخاص فرصة الاشتراك في الرسائل مستقبلًا، فلا يمانع 75% من الأشخاص من استقبال رسائل نصية قصيرة من الشركات التي يحبونها ويقرؤها 90% من مستقبليها خلال ثلاث دقائق من وصول الرسالة. ويدل هذا على معدلات الفتح الخيالية للرسائل التي يقرؤها الناس بالكامل تقريبًا. ستلاحظ فعالية بطاقات الحسم الرقمية عندما تستخدم الرسائل النصية ضمن استراتيجيات التسويق عبر الهاتف المحمول. إذ يزيد استخدام الناس للبطاقات التي تصل إليهم عبر الرسائل النصية عشرة مرات عن تلك التي تصلهم من مصادر أخرى. 7. الفيديوهات والرسوميات المتحركة GIFs ولّت الأيام التي يقرأ فيها الناس كلمات الرسائل النصية التي ترد إلى صناديق بريدهم، إذ يفضلون المحتوى المسلي وسهل المتابعة، مما يجعل الفيديوهات والرسوميات المتحركة المرشحين الرئيسيين لتحسين استراتيجيتك في التسويق عبر الهاتف المحمول. يفضل قرابة 75% من الناس متابعة الفيديوهات عندما يتعلق الأمر بالاطلاع على منتج جديد بغض النظر عن مدته. يشجع استخدام الفيديوهات في حملات التسويق عبر مواقع التواصل الاجتماعي العملاء على المتابعة، فأكثر من نصف العملاء سيتابعون أخبار علامة تجارية بعد متابعة فيديو على مواقع التواصل الاجتماعي، وسيرتفع هذا الرقم عندما ينتمي العميل إلى جيل هذه الألفية. 8. دعم المستخدم عبر مواقع الويب وضمن التطبيقات من أفضل الوسائل التي ترفع معدلات المحافظة على العملاء، هي التجربة الجيدة التي تقدمها لهم. وتعد آليات الدعم التي يسهل الوصول إليها والتعامل معها طريقة ملائمة لتعزيز تجربة العميل. وسواء أكانت وسيلة الدعم المقدمة هي ميزة المحادثة المباشرة على الموقع أو ميزة الاتصال المباشر مع أحد المعنيين ضمن التطبيق، سيؤثر وجودها بشدة على تجربة العميل. يتوقع قرابة 40% من زوار موقعك وجود ميزة المحادثة المباشرة، وسترتفع هذه النسبة إلى 50% إن استخدم العملاء الهواتف النقالة في الوصول إلى موقعك. إذ يعد نصف عدد الزوار أن المحادثة المباشرة هي الوسيلة المفضلة للتواصل. 9. الحملات الدعائية الموجهة يعد توجيه التسوق نحو فئة من العملاء من أكثر الاستراتيجيات فعالية في التسويق للأعمال الصغيرة. فمن الممكن إطلاق حملات دعائية تعتمد على موقع العملاء أو على الطريقة التي يتفاعلون بها مع موقعك بمجرد أن تجمع بعض المعلومات عن زوار موقعك وعملائك. يقول 52% من الأشخاص أنهم سيتسوقون في مكان آخر إن تلقوا بريدًا إلكترونيًا تسويقيًا لا يخاطبهم تحديدًا. إذ يتوقع العملاء أن يكون البريد كالتالي مثلًا: يتعدى توجيه البريد الإلكتروني والمخاطبة الشخصية مجال التسويق عبر البريد الإلكتروني، حيث يرغب 51% من الأشخاص أن تلبي الشركات مايحتاجونه وأن تصلهم إعلانات تعتمد على تجاربهم الشرائية السابقة، كما يزداد احتمال شراء 80% من الأشخاص من الشركات التي تقدم عروضًا شخصية. 10. نماذج الاشتراك عندما يسمح لك العملاء في التواصل معهم فقد امتلكت المفتاح المثالي لتطبيق التسويق الرقمي. وستجد أنك بحاجة إلى استخدام نماذج الاشتراك opt-in forms سواء أكنت تحاول بناء قائمة بريد إلكتروني أو أردت التوسع في التسويق عبر الرسائل النصية. قد يكون نموذج الاشتراك بسيطًا كنافذة منبثقة popup على موقعك وقد يكون أكثر تعقيدًا بأن تعرض على العميل بداية تحميل كتاب إلكتروني يتطلب بريده الإلكتروني. نصائح لاستعمال استراتيجيات التسويق للأعمال الصغيرة عبر الهاتف المحمول عليك أن تضع خطة عصرية تستغل عدة استراتيجيات في التسويق للأعمال الصغيرة عبر الهاتف المحمول إن أردت أن تجني ثمار تعبك في التسويق. قد لا يحتاج موقعك للتجارة الإلكتروني إلى كل هذه الاستراتيجيات، لكن استخدام المناسبة منها ستحسن بالتأكيد نسب مبيعاتك. من الممكن أن تقودك مقاربة التسويق المعتمدة على أقنية متعددة إلى نجاح أكبر موازنة بالتزامك إحدى هذه القنوات. لهذا استخدم الإرشادات التالية في دمج استراتيجيات التسويق عبر الهاتف المحمول ضمن خطتك للتسويق متعدد الأقنية: تجزئة القوائم: فقد تقود القوائم المجزأة بناءً على معايير محددة إلى صفحة الهبوط وبالتالي المنتجات الصحيحة. أتمتة البريد الإلكتروني: إذ ستصل الحملات الدعائية الآلية (المؤتمتة) إلى مشتركيك في التوقيت الصحيح. تعزيز الحملات الدعائية: حيث تستخدم الحملات المعدة لأغراض محددة وسائل التواصل الاجتماعي والتسويق عبر البريد الإلكتروني والإعلانات الرقمية للوصول إلى العملاء المحتملين. وباختيارك للأدوات الصحيحة، ستتمكن من إعداد حملة رقمية تعمل بطريقة صحيحة لإرسال البريد الإلكتروني في التوقيت الصحيح ونشر المحتوى المناسب عبر منصات التواصل الاجتماعي المستهدفة. تحضر للانطلاق تختلف فعالية الاستراتيجيات المتبعة في التسويق للأعمال الصغيرة عبر الهاتف المحمول من صناعة لأخرى، لكن هذه التقنيات واسعة الانتشار في عالم التسويق. تذكر هذه النصائح عندما تعد حملتك الدعائية القادمة: يختلف التسويق عبر الهاتف المحمول عن التسويق عبر أجهزة سطح المكتب: لذلك حضر محتوى يأخذ هذا الأمر بالحسبان ويساعد على انخراط أكبر للعملاء. يحب الناس أن يروا خصوصية في التسويق: يقود البريد الإلكتروني وبطاقات الحسم الموجهة شخصيًا إلى مبيعات أعلى. الحملة الدعائية الآلية هي الأسرع والأكثر فعالية: تسهل أدوات التسويق الوصول إلى عملائك بوتيرة أعلى. ستحقق النجاح في حملتك الدعائية القادمة إن ركزت على توظيف بعض الاستراتيجيات التي طرحناها في التسويق للأعمال الصغيرة عبر الهاتف المحمول. ترجمة -وبتصرف- للمقالة 10 mobile marketing strategies for small businesses that actually drive traffic اقرأ أيضًا هل آن الأوان للتخلي عن المكالمات الباردة في عالم التسويق؟ كيف يصبح الاتصال البارد (cold calling) أفضل من AdWords خطوات نجاح المزيج التسويقي الرقمي ما هو التسويق التحادثي وكيف تستثمره في إنجاح أعمالك؟
  4. يمكن برمجة عمل مكوّنات فيزيائية إضافةً إلى تطوير البرمجيات التي تُنفّذ على الشاشة، مثل المكوّنات الإلكترونية التي تتصل مع باي عبر أرجل المنصة GPIO، أو ما يُعرف باسم الحوسبة الفيزيائية physical computing. يتبادر إلى الأذهان أثناء التفكير بمصطلحي برمجة programming أو كتابة شيفرة Coding، بأنها برمجيات الحاسوب software مباشرةً، لكن الأمر ليس كذلك دومًا؛ فقد نكتب برمجياتٍ تتعامل مباشرةً مع العتاد الصلب hardware، ويُعرف هذا النوع من البرمجة باسم الحوسبة الفيزيائية أو برمجة المكونات الفيزيائية، حيث ترتبط الحوسبة الفيزيائية كما يوحي اسمها بالتحكم بتجهيزات فيزيائية حقيقية؛ فعندما تغيّر برنامجًا في الغسالة الآلية لضبط درجة حرارة حساس الحرارة القابل للبرمجة، أو عندما تضغط زرًا عند إشارة المرور لتعبر الطريق بأمان، فأنت تُنفِّذ حوسبةً فيزيائيةً. يُعد حاسوب راسبيري باي أداة رائعة لتعلم الحوسبة الفيزيائية بفضل منصة أرجل الدخل والخرج ذات الأغراض العامة general-purpose input/output -أو اختصارًا GPIO-. التعرف على منصة الأرجل GPIO ستجد منصة أرجل الدخل والخرج العامة GPIO، المكونة من صفين من الأرجل أو الدبابيس المعدنية عند الحافة العلوية لراسبيري باي، وستمنحك هذه المنصة القدرة على توصيل تجهيزات فيزيائية مثل المؤشرات الضوئية LEDs، أو القواطع switches إلى باي للتحكم بها من خلال برامجٍ تصممها بنفسك. قد يكون اسم المنصة مربكًا، لكنه يصف بالفعل ما تتكون منه، حيث يمكنك استخدام أي رجلٍ لاستقبال إشارةٍ كهربائية وعندها تُدعى رجل دخل input pin أو لإرسال إشارة كهربائية وتدعى عندها رجل خرج output pin. كما تُعرف باسم منصة Header، لأن الأرجل مجمعةٌ ومرتبةٌ وظاهرةٌ على اللوحة الإلكترونية للجهاز، ومن هنا يأتي اسم "منصة الدخل والخرج ذات الأغراض العامة general-purpose input/output header". تتكون المنصة من 40 رجلًا معدنيًا، حيث يمكنك استخدام بعضها في الاتصال مع تجهيزاتٍ خارجية، بينما يزوّدك بعضها بالتغذية الكهربائية، ويُحجز بعضها لأغراض التواصل مع تجهيزات مخصصة لتوسيع راسبيري باي، مثل Sense HAT التي سنشرحها مفصلًا في مقال لاحق. إذًا، هناك فئاتٌ مختلفةٌ للأرجل ولكلٍّ منها وظيفته الخاصة والتي سنلخصها في الجدول التالي: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } نوع الرجل التيار الكهربائي مصدر التغذية والوظيفة أرجل 3V3 تعطي تغذية كهربائية جهدها 3.3 فولت مصدر تغذية كهربائية جهده 3.3 فولت وهو نفسه الجهد الذي يعمل عليه راسبيري باي داخليًا أرجل 5v تعطي تغذية كهربائية جهدها 5 فولت مصدر تغذية كهربائية جهده 5 فولت وهو نفسه الجهد الذي يدخل إلى راسبيري باي عبر منفذ USB-C أرجل الأرضية (Ground (Gnd وتمثل أرجل الأرضية التي يُقاس الجهد بالنسبة إليها وتُعد 0 فولت تُستخدم وصلة الأرضية لإكمال الدارة الكهربائية المرتبطة بمصدر التغذية. أرجل دخل وخرج GPIO XX أرجل الدخل والخرج للأغراض العامة وأرقامها من خانتين XX وهي الأرجل التي تتحكم بسلوكها من خلال برامجك وتُعرّف بأرقام من 2 وحتى 27 أرجل توصيل تجهيزات موسِّعة ID EEPROM أرجل محجوزة لاستخدامات خاصة محجوزة للاتصال بالتجهيزات المرتبطة بالأعلى Hardware Attached on Top -أو اختصارًا HAT- وغيرها من التجهيزات الملحقة. تمنحك المنصة GPIO طريقةً ممتعةً وآمنةً في نفس الوقت لتتمرن على الحوسبة الفيزيائية، لكن ينبغي الحذر في التعامل معها؛ لذلك لا تحاول ثني الأرجل عند فصل أو وصل التجهيزات؛ ولا تصل أبدًا رجلين ببعضهما مباشرةً عن طريق الخطأ أو متعمدًا إذا لم يُطلب منك ذلك بوضوحٍ في توجيهات المشروع الذي تبنيه، حيث تُعرف هذه الحالة بالدارة المقصورة، وقد تؤدي إلى ضررٍ غير قابلٍ للإصلاح في راسبيري تبعًا للأرجل التي قُصرت. العمل مع العناصر الإلكترونية تمثل المنصة GPIO جزءًا فقط مما ستحتاجه لتبدأ مسيرتك في الحوسبة الفيزيائية، بينما تمثل العناصر الإلكترونية، وهي الأجهزة التي ستتحكم بها عبر GPIO، الجزء الآخر. ستجد آلاف العناصر الإلكترونية المتاحة، لكن معظم مشاريع GPIO مكوّنةٌ من العناصر التالية: لوحة اختبار مثقبة breadboard وتعرف أيضًا باللوحة التي لا تحتاج إلى لحام solderless، حيث تسهل هذه الأداة تأمين الاتصال بين العناصر الإلكترونية لمشروعك بسهولة؛ فبدلًا من وصل العناصر عن طريق الأسلاك، تؤمن لك لوحة الاختبار ثقوبًا تدفع فيها أرجل العناصر لتتصل ببعضها عبر مساراتٍ معدنيةٍ مخفيةٍ تحت السطح البلاستيكي للّوحة. ستجد في كثيرٍ من لوحات الاختبار أقسامًا منفصلةً لتوزيع التغذية الكهربائية، وهذا سينعكس على سهولة بناء الدارات. لن تحتاج إلى لوحة الاختبار للبدء بالحوسبة الفيزيائية طبعًا، لكنها أداةٌ مفيدةٌ جدًا. وصلات طرفية jumpers تُستخدم لوصل العناصر الإلكترونية إلى باي أو مع بعضها بعضًا إذا لم تستخدم لوحة الاختبار. يتوفر ثلاثة أنواع من الوصلات الطرفية، هي: وصلة مذكرة- مؤنثة "M2F"، والتي ستحتاجها لوصل لوحة الاختبار مع أرجل المنصة GPIO. وصلة مؤنثة- مؤنثة "F2F"، والتي تُساعد في ربط العناصر ببعضها إذا لم تستخدم لوحة اختبار. وصلة مذكرة- مذكرة "M2M"، وهي تُستخدم لربط نقطةٍ (مجموعة ثقوب متصلة ببعضها) من لوحة اختبار بنقطةٍ أخرى. ستحتاج بعض هذه الأنواع من الوصلات الطرفية أو جميعها تبعًا لمشروعك؛ فإذا استخدمت لوحة الاختبار مثلًا، فلن تحتاج الوصلة F2F. قاطع آني أو زر كبس push button وهو نوعٌ القواطع أو الأزرار مشابهة للتي نستخدمها في مقبض الألعاب، وتأتي عادةً برجلين أو أربعة ويعمل كلاهما مع باي. يُعد زر الكبس عنصر دخل، حيث يمكن لبرنامجك مراقبة هذا الزر عندما يُكبس ليُنفِّذ مهمةً ما. يتواجد أيضًا نوعٌ آخر من القواطع المعروفة باسم القواطع الدائمة latching، وهي تُبقِي التيار الكهربائي موصولًا عند تحويلها إلى وضع التوصيل على خلاف أزرار الكبس، التي يجب عليك الاستمرار في ضغط أزرار الكبس حتى يستمر التيار الكهربائي بالمرور. المؤشرات الضوئية LEDs أو ثنائي المساري الضوئي Light Emitting Diode وهي أجهزة خرج يمكن التحكم بها من خلال البرامج مباشرةً، حيث يُضيء المؤشر عندما يمر فيه التيار الكهربائي، ومن المؤكد أنك تستخدمها في منزلك سواءً الصغيرة منها، مثل التي تنبهك أن غسالتك في وضع التشغيل، أو الكبيرة التي تُنير بها الغرفة. تأتي هذه الأضواء بأشكالٍ وألوانٍ وأحجامٍ كثيرة، لكنها لا تتناسب جميعها مع راسبيري باي، فلا تستخدم تلك التي صُممت للعمل على جهدٍ 5 أو 12 فولت. المقاومات Resistors وهي عناصر إلكترونية تتحكم بتدفق التيار الكهربائي، وتتوفر بقيمٍ متنوعة تُقاس بواحدة الأوم Ohms ويرمز لهذه الواحدة بالرمز Ω. وكلما زادت قيمة المقاومة مقدرةً بالأوم قلَّ تدفق التيار الكهربائي عبرها. تُعد حماية المؤشرات الضوئية من استجرار تيار كهربائي مرتفع قد يؤدي إلى تضررها أو إحداث ضررٍ بباي من أكثر استخدامات المقاومات شيوعًا في مشاريع الحوسبة الفيزيائية الخاصة براسبيري باي، ولهذا السبب ستحتاج إلى مقاوماتٍ قيمتها بحدود Ω 330. يُقدّم الكثير من مزوّدي العناصر الإلكترونية مجموعاتٍ كاملةً من المقاومات تتضمن عددًا من القيم المختلفة للاستخدامات الشائعة مما يمنحك مرونةً أكثر في اختيار المقاومات المناسبة. جرس تنبيه كهروانضغاطي Piezoelectric buzzer ويدعى عادةً منبه buzzer، أو مصوت sounder؛ وهو جهاز خرج يصدر ضجيجًا صوتيًا كما تُصدر المؤشرات الضوئية أضواءً، ويتألف المنبه من غلافٍ بلاستيكي يضم صفيحتين معدنيتين تهتزان باتجاهين متعاكسين عند مرور التيار في الجهاز، فيصدر الصوت المميز له. للمنبه نوعان، فعال Active أو غير فعّال passive، فاحرص على استخدام المنبه الفعّال لأنه أبسط استخدامًا. مكونات وعناصر إلكترونية شائعة مثل المحركات التي تحتاج إلى لوحة تحكمٍ خاصةٍ لتوصيلها إلى باي، وحسّاسات الأشعة تحت الحمراء IR sensors التي تستشعر الحركة، وحسّاسات الرطوبة والحرارة التي يمكن استخدامها لتوقع حالة الطقس، والمقاومات الضوئية LDRs وهي أجهزة دخلٍ تلتقط الضوء على عكس المؤشرات الضوئية. يزوّدك الباعة في كافة أنحاء العالم بمكوّناتٍ مخصصةٍ للحوسبة الفيزيائية لاستخدامها مع راسبيري باي، ويمكن أن تكون مفردةً أو ضمن علب أدوات تزوّدك بكل ما تحتاجه لتبدأ، انظر حولك من الباعة والموزعين المحليين أو أصحاب المتاجر الإلكترونية أو الدوليين الذين يشحنون الطلبات إلى بلدك. لإكمال المشاريع في هذا الفصل ينبغي تأمين العناصر والمكوّنات التالية: ثلاث مؤشرات ضوئية LEDs، أحمر وأخضر وأصفر أو كهرماني. قاطعين آنيين أو زري كبس. منبّه فعّال Active وصلات طرفية من النوعين مذّكرة- مؤنثة "M2F" ومؤنثة-مؤنثة "F2F". لوحة اختبار ووصلات طرفية من نوع مذّكرة- مذّكرة "M2M" ولك الحرية في استخدام هذين المكونين أو عدمه. قراءة الرموز اللونية للمقاومات وتقدير قيمتها تُصنّع المقاومات لتغطي مجالاتٍ واسعةٍ من القيم، ابتداءً من مقاومةٍ معدومةٍ تماثل قطعةً من سلك، وحتى قيمٍ مرتفعةٍ جدًا يمكن أن يصل حجمها إلى حجم ساقك. لن تجد قيمة المقاومة مطبوعةً عليها سوى في بضعةٍ أنواعٍ من المقاومات، وبدلًا من ذلك يستخدم المصنعون ترميزًا لونيًا خاصًا على شكل خطوطٍ أو أشرطةٍ تلتف حول جسم المقاومة. لقراءة قيمة المقاومة: احمل المقاومة بحيث تكون مجموعة الخطوط المتقاربة إلى اليسار والخط المفرد إلى اليمين. انظر إلى لون الخط الأول وخذ القراءة من العمود الأول المُسمى خط أول/ ثانيفي الجدول، ثم انظر إلى الخط الثاني وخذ قيمته من نفس العمود فستحصل على الرقمين الأول والثاني من قيمة المقاومة؛ فلو كان الخطان برتقاليان، فسيكون الرقمان الأول 3 والثاني 3 ويشكلان العدد 33؛ وإذا احتوت المجموعة اليسارية ثلاث خطوط، كرّر الأمر بالنسبة للخط الثالث وستحصل على الرقم الثالث من قيمة المقاومة؛ وفي حال احتوت أربعة خطوط، فعليك الرجوع إلى الإنترنت لقراءة الترميز. table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } اللون خط أول/ثاني مضاعفات (خط ثالث) السماحية (الخط المفرد) أسود 0 ‎×100‎ - بني 1 ‎×101‎ ±1% أحمر 2 ‎×102‎ ±2% برتقالي 3 ‎×103‎ - أصفر 4 ‎×104‎ - أخضر 5 ‎×105‎ ±0.5% أزرق 6 ‎×106‎ ±0.25% بنفسجي 7 ‎×107‎ ±0.1% رمادي 8 ‎×108‎ ±0.05% أبيض 9 ‎×109‎ - ذهبي - ‎×10-1‎ ±5% فضي - ‎×10-2‎ ±10% بلا لون - - ±20% يمثّل الخط الثالث أو الرابع في المجموعة اليسارية القيمة الواجب جدائها بالعدد الذي شكلته الخطوط السابقة للحصول على القيمة الاسمية للمقاومة. انتبه إلى أن ‎100=1 و 101‎=10 و 102‎=100 و 103‎=1000 وهكذا؛ فلو كان الخطان الأول والثاني برتقاليان والثالث برتقالي، فهذا يعني أن قيمة المقاومة هي العدد 33 مضروبًا بالعدد 1000 وستكون النتيجة 3000 أوم. يمثّل الخط المفرد السماحية tolerance؛ وهي مقياسٌ لاقتراب القيمة الاسمية للمقاومة من القيمة الفعلية التي تعطيها، حيث تعني المقاومات الرخيصة التي تأتي بخط سماحيةٍ فضي مثلًا أن القيمة الفعلية للمقاومة ستزيد أو تقل عن القيمة الإسمية بمقدار 10%، أي أن مقاومةً قيمتها الاسمية 1000 أوم قد تكون فعليًا في المجال 900- 1100 أوم؛ بينما تأتي المقاومات المرتفعة السعر مثلًا بخط سماحية رمادي، أي باختلافٍ لا يتعدى 0.05 % أعلى أو أدنى من القيمة الاسمية. لن تؤثر السماحيات كثيرًا في مشاريع الهواة، حيث ستعمل أية مقاومة كما هو مطلوب بغض النظر عن سماحيتها. يبقى علينا الإشارة إلى موضوع المضاعفات، فعندما تتجاوز قيمة المقاومة 1000 أوم ستُقدّر بواحدة الكيلو أوم "kΩ"؛ أي إذا كانت قيمة المقاومة 2200 أوم، فستكتب على الشكل 2.2 كيلو أوم؛ أما عندما تتجاوز قيمته 1000 كيلو أوم أو 1000000 أوم، فستُقدَّر عندها بالميغا أوم  "MΩ"، أي إذا كانت قيمة المقاومة 22000000، فستكتب 2.2 ميغا أوم. مشروعك الأول: مرحبا أيها الضوء يمثّل تشغيل مؤشرٍ ضوئي الخطوة التقليدية الأولى في الحوسبة الفيزيائية، تمامًا كما تمثّل طباعة عبارة "!Hello world" على الشاشة الخطوة الأولى لتعلم البرمجة. سنحتاج في مشروعنا هذا إلى: مؤشر ضوئي LED. مقاومة قيمتها 330 أوم أو أية مقاومة قريبةٍ منها وصلات طرفية مؤنثة-مؤنثة. ابدأ بالتحقق من صلاحية المؤشر الضوئي الذي ستستخدمه من خلال قلب لوحة باي حتى تصبح المنصة GPIO عموديةً وفي الجهة اليمنى من اللوحة. صِل أحد طرفي المقاومة 330 أوم إلى أي رجل 3.3 فولت (يُشار إليها في لوحة باي بالرمز 3V3) مستخدمًا سلكًا مزودًا بوصلةٍ طرفية مؤنثة-مؤنثة، ثم صل الطرف الآخر للمقاومة بالرجل الأطول (الرجل الموجبة) للمؤشر الضوئي والتي تُعرف بالمصعد أو الأنود Anode. صِل بعد ذلك الرجل الأقصر (الرجل السالبة) للمؤشر الضوئي والتي تُعرف بالمهبط أو الكاثود cathode إلى أي رجٍل أرضيةٍ GND في المنصة GPIO، كما هو موضحٌ في الشكل التالي. شكل 1-6 صل المؤشر الضوئي إلى أرجل باي ولاتنس المقاومة! سيضيء المؤشر طالما باي يعمل، وإذا لم يحدث ذلك، تأكّد من توصيلات الدارة من خلال التحقق من قيمة المقاومة، حيث من المفترض ألّا تكون عالية جدًا، وتحقق من التوصيل الجيد للأسلاك والوصلات الطرفية، ثم تأكد من استخدامك للأرجل الصحيحة للمنصة GPIO والأرجل الصحيحة للمؤشر الضوئي الذي لن يعمل إلا إذا وصلت رجله الأطول إلى جهدٍ موجب والأخرى إلى جهدٍ سالب، حيث تُعد الرجل الأرضية بمثابة جهدٍ سالب. بمجرد أن يضيء المؤشر فهو جاهزٌ للبرمجة، لذلك افصل الوصلة الطرفية من الرجل "3V3" وصلها بالرجل رقم 25 للمنصة GPIO، والتي يُشار إليها على لوح باي بالرمز GP25، وسينطفئ عندها المؤشر الضوئي. شكل 2-6 افصل السلك عن الرجل 3V3 وصله بالرجل GP25 أصبحت الدارة جاهزةً، وتستطيع الآن كتابة برنامج بلغة سكراتش أو بايثون لتشغيل وإطفاء المؤشر الضوئي. التحكم بالمؤشر الضوئي باستخدام برنامج سكراتش 2 افتح برنامج سكراتش 2 من قائمة راسبيري باي، ثم انقر على زر "كتل أخرى More Blocks" ضمن لوح الكتل البرمجية، واختر بعدها "إضافة موسِّع Add an Extension"، واختر الموسِّع "Pi GPIO" ثم انقر الزر OK. سيُحمّل الأمر الكتل البرمجية اللازمة للتحكم بأرجل المنصة GPIO باستخدام سكراتش، حيث سترى هذه الكتل البرمجية في لوحة الكتل البرمجية ضمن الفئة "كتل أخرى More Blocks". شكل3-6 إضافة الموسِّع Pi GPIO إلى سكراتش 2 ابدأ بسحب الكتلة إلى منطقة بناء البرنامج، ثم ضع تحتها الكتلة . عليك الآن اختيار رقم رجل المنصة الذي تستخدمه، لذلك انقر على السهم الصغير المتجه للأسفل في الكتلة السابقة واختر الرقم 25 من القائمة المنسدلة لتخبر سكراتش أنك ستتحكم بالرجل رقم 25 من المنصة. انقر على الراية الخضراء وسترى أنّ المؤشر يضيء، وهكذا ستكون برمجت بنفسك أول مشروع حوسبةٍ فيزيائية. عند النقر على المثمن الأحمر لإيقاف البرنامج لن ينطفئ المؤشر الضوئي، لأنك أنهيت البرنامج دون أن تخبر باي بأن تطفئه؛ فكل ما طلبته منه في برنامجك هو تشغيله من خلال output high أو خرج مرتفع، وهذا يعني أن تقدّم للرجل جهدًا موجبًا يعادل 3.3 فولت في راسبيري. لإطفائه مجددًا انقر على السهم الصغير المتجه للأسفل والمجاور لعبارة "output high" واختر "output low". انقر على الراية الخضراء مجددًا، فسينطفئ المؤشر. لجعل الأمر أكثر متعةً، أضف كتلة حلقةٍ لا متناهية مع كتلتي لبناء برنامجٍ يومض المؤشر باستمرار أي ينطفئ ثانيةً ويضيء ثانية. انقر على الراية الخضراء وراقب كيف سيضيء المؤشر لمدة ثانية ثم ينطفئ لمدة ثانية ويستمر بالوميض باستمرار دون توقف. انقر على المثمن الأحمر لإيقاف البرنامج وتحقق من حالة المؤشر لحظة إيقاف البرنامج فيما إذا كان يضيء أم لا. التحكم بالمؤشر الضوئي باستخدام بايثون افتح برنامج ثوني Thonny انطلاقًا من قائمة راسبيري باي، ثم انقر أيقونة جديد New في شريط أدوات ثوني لإنشاء برنامجٍ جديد، ثم انقر أيقونة Save لحفظ البرنامج باسم "Hello LED". لا بُدّ من استخدام مكتبة GPIO Zero للتعامل مع أرجل المنصة GPIO، لكننا لن نحتاج إلى المكتبة بأكملها في هذا المشروع. أدرج هذا الجزء من المكتبة بكتابة الأمر التالي: from gpiozero import LED انظر المقال السابق البرمجة باستخدام لغة بايثون للتعرف على بيئة ثوني. ستخبر مكتبة GPIO Zero الآن عن الرجل التي يتصل بها المؤشر الضوئي من خلال الشيفرة التالية: led = LED(25) يعطي السطران السابقان بايثون القدرة على التحكم بالمؤشر الضوئي المتصل براسبيري باي، ويخبرانه بالرجل أو الأرجل في حال كنت تتحكم بأكثر من مؤشرٍ في دارتك. اكتب السطر التالي لإضاءة المؤشر: led.on() والسطر التالي لإطفائه: led.off() تهانينا، فأنت تتحكم بأرجل المنصة GPIO باستخدام بايثون. حاول تكرار تعليمتي التشغيل والإطفاء. في حال كان كان المؤشر مطفأً أصلًا، فلن تُنفَّذ التعليمة: led.off() ويحصل الأمر نفسه إذا استخدمت تعليمة تشغيل المؤشر وهو مضاءٌ أصلًا. لجعل برنامجك أكثر واقعية، اكتب الشيفرة التالية: from gpiozero import LED from time import sleep led = LED(25) while True: led.on() sleep(1) led.off() sleep(1) يُدرج هذا البرنامج الدالة LEDمن المكتبة GPIO Zero والدالة sleep من المكتبة time، ثم يبني حلقةً لا متناهية لتكرار إضاءة المؤشر لمدة ثانية ثم إطفائه لمدة ثانية. انقر على أيقونة التشغيل Run لترى المؤشر يومض. راقب حالة المؤشر عند النقر على أيقونة الإيقاف Stop عندما يكون المؤشر مضاءً أو مُطفأً. استخدام لوحة الاختبار المثقبة سيكون المشروع التالي أسهل تنفيذًا في حال استخدمت لوحة اختبارٍ لترتيب وتوصيل العناصر، حيث يغطي وجه لوحة الاختبار الثقوب الموزعة وفق نظامٍ محددٍ لتلائم العناصر، ويتباعد أي ثقبين عن بعضهما مقدار 2.54 ميليمتر. ستجد أسفل هذه الثقوب شرائطًا معدنيةً تصل بين كل مجموعةٍ من الثقوب كما تفعل الوصلات الطرفية التي تعاملنا معها سابقًا. الشكل: لوحة الاختبار المثقبة تصطف الثقوب في صفوفٍ وأعمدة، وتُقسم اللوحة إلى قسمين، أو ثلاثة أقسامٍ منفصلةٍ من الثقوب، وقد تجد على بعض اللوحات أرقامًا من الأعلى للصفوف وأحرفًا على الجانب للأعمدة لتحديد مكان ثقبٍ معيّن؛ حيث ستجد مثلًا الثقب A1 في الصف 1 والعمود الأول A أقصى وأعلى اليسار، والثقب B3 في الصف الثالث والعمود الثاني B، وهكذا. ترتبط الثقوب في كل صفٍ ببعضها عبر شريطٍ معدني مخفي؛ حيث تمثّل بمجموعها نقطة توصيلٍ واحدة، أي أن كل الثقوب التي تحمل الرقم 1 مرتبطةٌ معًا والتي تحمل رقم 2 كذلك؛ بينما لا ترتبط ثقوب الصف 1 مع ثقوب الصف 2 إطلاقًا ما لم يصل بينهما سلكٌ فيتحول الصفّان إلى نقطةٍ واحدة. يمكن أن تضم لوحات الاختبار الكبيرة شريطين جانبيين من كل جهة، معلّمين بخطين أحمر وأسود، أو أحمر وأزرق، وقد صُممت هذه الأعمدة من الثقوب لتسهيل توصيل التغذية الكهربائية إلى بقية الثقوب، حيث يمكن وصل سلكٍ من رجل راسبيري باي "3V3" أو "5V" إلى خط التغذية ذو اللون الأحمر، والإشارة الموجبة وسلك من الرجل GND إلى الخط الأسود أو الأزرق ذي الإشارة السالبة. تجدر الإشارة إلى أن ثقوب الخط الأحمر متصلةٌ معًا وكذلك ثقوب الخط الآخر، ولا يوجد اتصالٌ أبدًا بين الخطين. من السهل إضافة العناصر الإلكترونية إلى لوحة الاختبار، فما عليك فعله هو ثني أرجل العنصر الإلكتروني الطرية ودفعها بلطفٍ في الثقوب المناسبة حتى تأخذ مكانها. استخدم وصلاتٍ طرفية M2M للوصل بين نقطة (صف ثقوب) وأخرى، ومن النوع M2F لوصل نقاطٍ من اللوحة مع أرجل باي. لا تحاول حشر أرجل عدّة عناصرٍ في ثقبٍ واحد؛ وإذا أردت وصلها معًا، فتذكر أن وضعها في صفٍ واحدٍ يجعلها متصلةً معًا بالشريط المعدني المخفي. مراقبة إشارة صادرة عن ضغطة زر إنّ عملية تمرير التيار الكهربائي من باي إلى المؤشر الضوئي والمعروفة بعملية خرج إشارة، هي أحد شقي الوظيفة المختلطة "دخل/ خرج input/output" لبعض أرجل منصة GPIO، حيث يمكن استخدام الرجل نفسها لاستقبال تيار كهربائي، وتُعرف بعملية دخل إشارة إلى باي أيضًا. سنحتاج في هذا المشروع إلى: لوحة اختبار. أسلاك بوصلات طرفية M2M وأخرى M2F. قاطع آني أو زر كبس. يمكن استخدام أسلاك بوصلة طرفية F2F بدلًا من لوحة الاختبار، لكنك ستواجه صعوبة في الضغط على الزر دون أن تتسبب في تفلّت بعض الأسلاك. ابدأ بإضافة الزر إلى اللوحة؛ فإذا كان للزر رجلين فقط، فعليك حشر كل رجلٍ في صفٍ مختل؛ أما إذا كان للزر أربعة أرجل، فاحشر رجلي الطرف الأول في عمودٍ واحد وسيدخُل رجلي الطرف الثاني تلقائيًا في عمودٍ آخر. صل بين رجل الأرضية GND في باي وخط التغذية السالب على لوحة الاختبار باستخدام سلكٍ ذو وصلاتٍ طرفية M2F، ثم صل أحد أرجل الزر بخط التغذية السالبة مستخدمًا سلك M2M، كما هو موضح في الشكل التالي. أخيرًا، صِل الرجل الآخرى للزر إذا كان ذا رجلين، أو الرجل التي تقع على نفس الجانب إذا كان الزر بأربعة أرجل إلى الرجل GP2 في المنصة GPIO. شكل 4-6 توصيل الزر إلى المنصة GPIO مراقبة إشارة صادرة عن ضغطة زر باستخدام سكراتش ابدأ مشروع سكراتش جديد واسحب الكتلة إلى منطقة بناء البرنامج، ثم أضف تحتها الكتلة وغيّر gpio إلى 2 gpio بالنقر على السهم المجاور واختيار هذه القيمة من القائمة المنسدلة ليتطابق مع الرجل التي وصلتها بالزر. انقر كذلك على السهم الصغير بجوار "output high" وحوِّلها إلى "input" لتهيئة الرجل على أنها رجل دخل لاستقبال الإشارات الكهربائية. لن يحدث الآن شيء عند النقر على الراية الخضراء لأنك أخبرت سكراتش باستخدام الرجل GP2 على أنها رجل دخل، لكنك لم تخبرها ما الذي ستفعله عند تلّقي إشارة الدخل؛ لذلك اسحب الكتلة وضعها في نهاية السلسلة، ثم ضع ضمنها الكتلة ابحث عن الكتلةوضعها في الفراغ الذي يأخذ شكل مسدس داخل الجزء ، ثم انقر على السهم الصغير بجوار "gpio" واختر 2 لتخبر الكتلة الشرطية أن تتحقق من دخل الزر رقم 2 في منصة GPIO. اسحب أخيرًا الكتلة وضعها في فراغ الجزء من الكتلة الشرطية، ثم غيِّر الكلمة "!Hello" إلى "!Button pushed"، ودع الجزء فارغ حاليًا. تجري الكثير من الأحداث في الشيفرة السابقة، لكننا سنبدأ باختبارها أولًا. لذلك انقر الراية الخضراء، ثم اضغط الزر على لوحة الاختبار. من المفترض أن تخبرك الشخصية الاعتيادية على مسرح سكراتش وهي القط أنك ضغطت الزر، وبالتالي ستكون قد أنجزت مهمتك بقراءة إشارة دخل وصلت إلى منصة GPIO بنجاح. ربما لاحظت أن ما داخل الجزء من العبارة الشرطية هو المكان الذي يجب أن توضع فيه الشيفرة الفعلية للتعامل مع الضغط على زر الكبس في لوحة الاختبار، إلا أن هذه الشيفرة في الجزء الآخر . سيسبب هذا الأمر ارتباكًا، لأنك تتوقع أن ضغط الزر سينقل رجل المنصة إلى حالة الجهد المرتفع "high"، لكن الحالة المعاكسة هي الصحيحة في راسبيري باي؛ فعندما تخصص رجلًا من أرجل المنصة على أنها رجلٌ لاستقبال إشارة الدخل، فسيصبح جهدها مرتفعًا "high"؛ وعندما نضغط الزر، فإننا في الواقع سنصل رجل الدخل إلى جهد الأرضية GND، أي سنسحب جهده إلى الحالة المنخفضة "low". أمعن النظر في دارتك، ستجد اتصال الرجل GP2 التي تمثّل الجهد الموجب في الدارة مع رجل الأرضية عن طريق زر الكبس، وبالتالي ستصبح صفرًا (حالة منخفضة) عند ضغط الزر ولن يُنفَّذ الجزء من العبارة الشرطية بل الجزء . تذكر دائمًا أن راسبيري باي تستشعر ضغطة الزر عندما تنتقل حالة رجل الدخل من الحالة المرتفعة إلى المنخفضة. سنضيف الآن مؤشرًا ضوئيًا إلى الدارة؛ لذلك صل الرجل GP25 بمقاومة، وصِل طرفها الآخر برجل المؤشر الضوئي الطويلة، ثم صِل أخيرًا رجل المؤشر الأقصر بخط التغذية السالب في لوحة الاختبار. اِسحب الكتلة خارج الكتلة الشرطية واحذفها، ثم أضِف الكتلة إلى الجزء من العبارة الشرطية، وتذكر اختيار العدد 25 بالنقر على سهم القائمة المنسدلة، ثم أضف الكتلة إلى الجزء الآخر . انقر على الراية الخضراء ثم اضغط الزر. لاحظ أنّ المؤشر سيضيء طالما أنك تستمر بالضغط على الزر، وسينطفئ إذا حررته. تهانينا، تستطيع الآن التحكم برجلٍ من أرجل المنصة GPIO بناءً على إشارة دخلٍ تتلقاها رجلٌ أخرى. مراقبة إشارة صادرة عن ضغطة زر باستخدام بايثون انقر على أيقونة جديد New في شريط أدوات ثوني لتُنشئ مشروعًا جديدًا، ثم احفظه باسم "Button Input". سنستخدم رجلًا من GPIO على أنها رجل دخل بنفس طريقة استخدامها مثل رجل خرج، لكننا سنحتاج إلى جزءٍ آخر من المكتبة GPIO Zero، لذلك اكتب الشيفرة التالية: from gpiozero import Button button = Button(2) لجعل شيفرةٍ ما تعمل عند ضغط الزر، سنستخدم الدالة wait_for_press المدمجة مع المكتبة GPIO Zero، لذلك اكتب الشيفرة التالية: button.wait_for_press() print("You pushed me!") انقر على أيقونة التشغيل Run ثم اضغط الزر، فتظهر العبارة "!You pushed me" في نافذة المفسِّر أسفل نافذة ثوني. تهانينا، لقد قرأت بنجاحٍ إشارة الدخل القادمة إلى المنصة GPIO. انقر من جديد على الأيقونة Run إذا أردت اختبار البرنامج مجددًا، لأن شيفرته لا تحتوي حلقاتٍ لمراقبة الزر على الدوام، وسيتوقف كل شيءٍ بمجرد طباعة العبارة الموجودة في نهاية الشيفرة. أعِد توصيل المؤشر الضوئي والمقاومة إذا لم تكن قد فعلت ذلك وفقًا للطريقة المُعتمدة في الفقرة السابقة. ولقراءة دخل الزر وإضاءة المؤشر، لا بدّ من إدراج جزئي المكتبة GPIO Zero المخصصين لذلك. أضِف سطري الشيفرة التاليين إلى بداية البرنامج: from gpiozero import LED from time import sleep ثم أضِف السطر: led = LED(25) بعد السطر: button = Button(2) ثم احذف سطر التعليمة print وضع مكانها الأسطر التالية: led.on() sleep(3) led.off() سيبدو برنامجك الآن على النحو التالي: from gpiozero import LED from time import sleep from gpiozero import Button button = Button(2) led = LED(25) button.wait_for_press() led.on() sleep(3) led.off انقر على أيقونة Run ثم اضغط على الزر، سيضيء المؤشر لثلاث ثوانٍ ثم ينطفئ وينتهي البرنامج. تهانينا، تستطيع الآن التحكم برجلٍ من أرجل المنصة GPIO بناءً على إشارة دخل تتلقاها رجلٌ أخرى باستخدام بايثون. تشغيل منبه صوتي إن التحكم بجهاز للإنذار والتنبيه باستخدام المؤشرات الضوئية أمرٌ عظيم، لكنه لن يخدمك كثيرًا إذا كنت تنظر بالاتجاه الآخر، وسيكون الحل باستخدام منبهٍ صوتي buzzer مسموعٍ في كل أرجاء الغرفة. سنحتاج في هذه الفقرة إلى: لوحة اختبار. أسلاك بوصلات طرفية منوعة M2F وF2F، إذا لم تشأ استخدام لوحة اختبار. منبه صوتي فعّال Active. يُعامل المنبه الصوتي الفعّال مثل المؤشر الصوتي من ناحية التوصيل والبرمجة. استخدم دارة توصيل المؤشر الضوئي نفسها لكن استبدل المؤشر الضوئي بالمنبه ولا تستخدم مقاومة لأن المنبه يحتاج إلى تيارٍ أعلى ليعمل. إذًا، صِل الرجل "GP15" بأحد رجلي المنبه مباشرةً، وصِل الرجل الأخرى له بأحد أرجل الأرضية "GND" للمنصة GPIO؛ أما في الحالة التي يمتلك فيها المنبه ثلاثة أرجل، صِل الرجل المعلّمة بإشارة "+" إلى رجل "3V3" والمعلمة بإشارة "-" إلى رجل أرضية "GND" والثالثة المُعلّمة بالحرف "s" (إشارة signal) إلى الرجل GP15. شكل 5-6 توصيل المنبه الصوتي إلى المنصة GPIO التحكم بالمنبه الصوتي باستخدام سكراتش أنشئ مشروعًا جديدًا مطابقًا لمشروع تشغيل المؤشر الضوئي، أو حمّله إذا كنت قد خزنته، وغيّر رقم الرجل في الكتل ليصبح 15، وبالتالي سيتحكم سكراتش بالرجل GP15. انقر على الراية الخضراء وسيبدأ المنبه بإصدار صوتٍ لمدة ثانية ثم يتوقف لمدة ثانية. إذا لم يصدر سوى صوت نقرةٍ فقط وليس صوتًا متواصلًا خلال فترة تشغيل المنبه، فما تستخدمه هو منبهٌ غير فعّال passive؛ والذي يحتاج إلى إشارةٍ مهتزةٍ مستمرة حتى تتحرّض الصفيحتان المعدنيتان وتهتزان لإنتاج الصوت؛ بينما يولد المنبه الفعّال active إشارةً مهتزةً سريعة بنفسه. عند تنفيذ برنامج سكراتش على منبهٍ غير فعّال، ستهتز الصفيحتان مرةً واحدةً وتتوقفان بعدها، ويصدر صوت النقرة الذي لن يتكرر حتى يبدّل برنامج سكراتش حالة الرجل من منخفضة إلى مرتفعة. انقر الآن على المثمن الأحمر لإيقاف البرنامج، واحرص أن يكون ذلك عندما لا يصدر المنبه صوتًا، وإلا سيستمر في ضجيجه حتى يعمل البرنامج مرةً ثانية. التحكم بالمنبه الصوتي باستخدام بايثون يُعد التحكم بمنبهٍ صوتي مشابهًا تمامًا للتحكم بمؤشر ضوئي عند استخدام المكتبة GPIO Zero، فللمنبه أيضًا حالتان: تشغيل أو إطفاء. سنحتاج بالطبع إلى دالةٍ مختلفة، وهي buzzer. ابدأ مشروعًا جديدًا في ثوني واحفظه باسم Buzzer، ثم اكتب الشيفرة التالية: from gpiozero import Buzzer from time import sleep عليك أيضًا تحديد رجل GPIO التي تتصل بالمنبه الصوتي، حتى تتمكن من التحكم به، لذا اكتب الشيفرة التالية: buzzer = Buzzer(15) تتطابق بقية الشيفرة مع مثيلاتها التي تتحكم بالمؤشر الضوئي ما عدا أنك ستستخدم كلمة "buzzer" بدلًا من "led"، وأنّ رقم رجل GPIO مختلف. اكتب إذًا الشيفرة التالية: while True: buzzer.on() sleep(1) buzzer.off() sleep(1) انقر على أيقونة Run وستسمع مباشرةً صوت المنبه لمدة ثانية ثم يختفي الصوت مدة ثانية، ولن تسمع سوى صوت نقرةٍ وجيزة كل ثانية بدلًا من صوتٍ مستمر في حال استخدمت منبهًا غير فعّال، كونه يفتقر إلى مولد إشارةٍ قادرٍ على توليد إشارةٍ سريعة التغير لإنتاج اهتزازٍ متواصلٍ للصفيحتين المعدنيتين. انقر الآن على المثمن الأحمر لإيقاف البرنامج، واحرص أن يكون ذلك عندما لا يصدر المنبه صوتًا، وإلا سيستمر في ضجيجه حتى يعمل البرنامج مرةً ثانية. المشروع الثاني: إشارات المرور الضوئية لقد اطلعت حتى الآن على طريقة استخدام المؤشرات الضوئية والأزرار والمنبهات الصوتية مثل أجهزة دخلٍ وخرج، لذلك حان الوقت لتستفيد مما تعلمته في مشروع حوسبةٍ فيزيائيةٍ واقعي، وهو مشروع إشارات مرور ضوئية مزودةٍ بزرٍ يمكنك ضغطه لعبور الشارع. ستحتاج في هذا المشروع إلى: لوحة اختبار. ثلاث مؤشرات ضوئية أحمر وأصفر وأخضر. ثلاث مقاومات قيمة كل منها 330 أوم. منبه صوتي. زر. مجموعة من الأسلاك بوصلات طرفية M2M وM2F. لبناء الدارة: صِل المنبه بالرجل "GP15"، والمؤشر الضوئي الأحمر بالرجل "GP25"، والأصفر بالرجل "GP8"، والأخضر بالرجل "GP7"، والزر بالرجل "GP2"، ولا تنس وصل مقاومة 330 أوم بين الرجل الطويلة لكل مؤشرٍ ضوئي ورجل GPIO المتصل بها، ثم صِل الأرجل القصيرة للمؤشرات بخط التغذية السالب على لوحة الاختبار. صِل أخيرًا خط التغذية السالبة بأي رجلٍ أرضية GND من أرجل GPIO باستخدام سلكٍ ذي نهاياتٍ طرفية M2F. شكل 6-6 مخطط التوصيل لمشروع الإشارات الضوئية ابدأ مشروعًا جديدًا في سكراتش 2 ثم اسحب الكتلة إلى منطقة تنفيذ البرنامج. سنخبر سكراتش بعد ذلك بأن الرجل "GP2" المتصلة بالزر هي رجل دخل وليس خرج؛ لذلك اسحب الكتلة من فئة "كتل أخرى More Blocks" إلى أسفل الكتلة . انقر السهم بجوار الرقم 0 واختر الرقم 2، ثم انقر على السهم الصغير الآخر بجوار "output high" واختر "input". سننشئ تاليًا سلسلة الكتل المتحكمة بإشارات المرور، لذلك اسحب الكتلة إلى منطقة بناء البرنامج، ثم ضع داخلها الكتل التي تسمح بتشغيل وإطفاء المؤشرات الضوئية الثلاث وفق نمطٍ محدد، أي كم ثانية سيعمل الأحمر ثم ينطفئ ثم الأصفر ثم الأخضر. لا تنس أنّ المؤشر الأحمر مرتبطٌ بالرجل "GP25" والأصفر بالرجل "GP8" والأخضر بالرجل "GP7". انقر على الراية الخضراء وراقب المؤشرات الضوئية، حيث سيضيء أولًا المؤشر الأحمر ثم كلا المؤشرين الأحمر والأصفر، ثم ينطفئان ليعمل الأخضر ثم الأصفر وتتكرر العملية. يتناسب النمط السابق مع نمط إشارات المرور في المملكة المتحدة، عدّله بما يناسب النمط المستخدم في بلدك إذا أردت. لمحاكاة مرور المشاة، لا بدّ لبرنامجك من مراقبة الزر إذا ضُغط أم لا. أوقف البرنامج بالنقر على المثمن الأحمر في حال كان يعمل. اسحب الكتلة إلى برنامجك لتكون داخل الكتلة مباشرةً، ثم انقل الكتل التي تتحكم بإشارات المرور إلى الجزء ولا تضع شيئًا في الوقت الحالي ضمن الفراغ الذي سيحمل شرط تنفيذ هذا الجزء. لا يغير المشاة الضوء إلى الأحمر بالضغط على الزر ساعة يشاؤون كي يعبروا الشارع، بل سينتظرون تحوُّل الإشارة إلى الأحمر. لبناء ذلك، اسحب كتلة أخرى تليها كتلة ، ثم اسحب كتلة إلى داخلها، وضع المعامل في فراغ الشرط للجزء ، ثم ضع الكتلة ضمن فراغ المعامل. أنشئ أخيرًا متغيرًا جديدًا باسم "pushed"، ثم ضع الكتلة داخل الجزء من الكتلة الشرطية. ستراقب هذه السلسلة من الكتل الحالة التي يُضغط فيها الزر ومن ثم تسند القيمة 1 إلى المتحول pushed، أي ستتذكر أنك ضغطت على الزر دون أن تنفذ شيئًا في الوقت الحالي. عُد إلى السلسلة السابقة من الكتل واسحب العامل إلى داخل فراغ الشرط في الجزء ، ثم اسحب الكتلة إلى فراغ المعامل الأول واكتب 0 في فراغه الآخر. انقر على الراية الخضراء وراقب الإشارات الضوئية. اضغط الزر على لوحة الاختبار، فلن تلاحظ شيئًا للوهلة الأولى؛ لكن عندما ينتهي نمط عمل الإشارات وذلك بإضاءة المؤشر الأصفر، ستنطفئ المؤشرات الضوئية وتبقى على هذا الحال، وذلك بفضل المتغير pushed. يبقى علينا الآن إسناد مهمةٍ أخرى لزر عبور المشاة غير إطفاء الإشارات. اسحب الكتلة إلى داخل الجزء للكتلة الشرطية في تسلسل الكتل الرئيسي، وتذّكر تغيير رقم الرجل ليطابق الرجل الموصولة مع المؤشر الأحمر. ابقى داخل الجزء وانشئ نمطًا لتشغيل المنبه الصوتي وذلك بسحب الكتلة ووضع تسلسل الكتل التالي: ، ثم ، ثم الكتلة ، ثم ضمنها، ولا تنس تغيير رقم الرجل لتلائم تلك المتصلة مع المنبه. أخيرًا، ضع الكتلة مباشرةً تحت الكتلة وبعدها الكتلة التي تغير قيمة المتغير pushed إلى 0 لتنهي حالة ضغط الزر فلا يتكرر تسلسل تشغيل المنبه إلى ما لانهاية. انقر الآن على الراية الخضراء، ثم اضغط الزر على لوحة التحكم، وبعد انتهاء نمط تشغيل الإشارات الضوئية، سيضيء المؤشر الأحمر ويبدأ المنبه بإصدار صوتٍ ينبه المشاة بأن الوضع آمنٌ لعبور الشارع. سيتوقف الصوت بعد ثانيتين وتعود إشارات المرور إلى العمل وفق النمط المحدد. تهانينا، لقد أنجزت برنامجًا يتحكم بمجموعة إشارات مرورية مزودةٍ بآلية لمساعدة المشاة في العبور الآمن. مشروع بلغة بايثون: لعبة سرعة رد الفعل لقد اطلعت حتى الآن على طريقة استخدام المؤشرات الضوئية والأزرار مثل أجهزة دخل وخرج، لذلك حان الوقت لبناء مشروع حوسبةٍ فيزيائيةٍ واقعي، وهو لعبةٌ مؤلفةٌ من لاعبين لقياس سرعة رد فعل كلٍ منهما وتحديد زمن الاستجابة الأسرع. ستحتاج في هذا المشروع إلى: لوحة اختبار. مؤشر ضوئي. مقاومة 330 أوم. زري كبس. بعض الأسلاك ذات الوصلات الطرفية M2F وM2M. سنبدأ بناء الدارة بوصل الزر الأول الذي نضعه على الجانب اليساري للوحة الاختبار مع الرجل "GP14" للمنصة GPIO، والزر الآخر في الجانب اليميني مع الرجل "GP15". نصل بعد ذلك طرف المقاومة بالرجل "GP4" وطرفها الآخر بالرجل الطولية للمؤشر الضوئي. نصل الأرجل الباقية للزرين والمؤشر مع خط التغذية السالب في لوحة الاختبار، ثم نصل الخط مع أي رجلٍ أرضية GND للمنصة GPIO، كما هو موضح في الشكل التالي. شكل 7-6 توصيل عناصر لعبة رد الفعل الأسرع أنشئ مشروعًا جديدًا في ثوني واحفظه باسم"Reaction Game". سنستخدم لكتابة الشيفرة الدالتين LED و button من المكتبة GPIO Zero، والدالة sleep من المكتبة time. سندرج دالتي المكتبة GPIO Zero على سطرٍ واحد باستخدام الفاصلة ",". اكتب الشيفرة التالية: from gpiozero import LED, Button from time import sleep حدد الآن أرجل GPIO المتصلة مع المؤشر الضوئي والزرين، لذلك اكتب الشيفرة التالية: led = LED(4) right_button = Button(15) left_button = Button(14) أضِف بعد ذلك تعليمات تشغيل وإطفاء المؤشر الضوئي للتحقق من عمله: led.on() sleep(5) led.off() انقر على أيقونة التشغيل Run وسترى أن المؤشر سيضيء مدة خمس ثوانٍ ثم ينطفئ وينتهي البرنامج. لكن سيكون إطفاء المؤشر الضوئي بعد 5 ثوانٍ أمرًا متوقعًا في لعبةٍ مثل التي نبنيها، لذلك أضف السطر التالي: from random import uniform بعد السطر: from time import sleep تتيح لك المكتبة random إمكانية توليد أعدادٍ عشوائية وفق قاعدة التوزيع المنتظم uniform distribution)، لذلك استبدل تعليمة (5)sleep بالسطر التالي: sleep(uniform(5, 10)) إذا شغّلت البرنامج مجددًا، سترى أن المؤشر يضيء مدةً عشوائيةً بين خمس وعشر ثوان. جرّب ذلك بتشغيل البرنامج مراتٍ عديدة وقياس مدة الإضاءة في كلِّ مرة. لاحظ كيف ستختلف أزمنة الإضاءة، مما يجعل توقع لحظة توقف المؤشر عن الإضاءة غير متوقعة. سنضيف الآن الدالة المُسماة pressed لتفعيل عمل زري اللاعبين، لذلك اكتب الشيفرة التالية في آخر برنامجك: def pressed(button): print(str(button.pin.number) + " won the game") تميّز بايثون التعليمات الواقعة داخل دالةٍ من خلال إزاحتها إلى اليمين، وهذا ما يفعله ثوني تلقائيًا. أضِف أخيرًا السطرين التاليين لاستشعار ضغط اللاعب على زره: right_button.when_pressed = pressed left_button.when_pressed = pressed لا تزح السطرين السابقين كي لا يعدّهما بايثون جزءًا من الدالة. شغّل البرنامج وحاول هذه المرة الضغط على أحد الزرين في اللحظة التي ينطفئ فيها المؤشر الضوئي، ستظهر عندها رسالةً في نافذة المفسِّر أسفل نافذة ثوني مفادها أن الزر قد ضُغط، لكن ستظهر الرسالة في كل مرةٍ يُضغط فيها أيٌّ من الزرين دون تمييز، وستعرض رقم الرجل التي تلقت إشارة الزر بدلًا من إظهار اسمٍ ملائمٍ للاعب. لتحسين الوضع، سنبدأ بسؤال اللاعبين عن اسميهما، لذلك اكتب الشيفرة التالية: left_name = input("Left player name is ") right_name = input("Right player name is ") تحت السطر: from random import uniform عُد إلى الدالة واستبدل محتواها بالشيفرة التالية: if button.pin.number == 14: print (left_name + " won the game") else: print(right_name + " won the game") شغِّل البرنامج من جديد، ثم اختر اسمين للاعبين وحاول الضغط على الزر بأقصى سرعة عند توقف إضاءة المؤشر. سترى هذه المرة ظهور اسم اللاعب بدلًا من رقم الرجل، لكن ستظهر الرسالة بمجرد ضغطت الزر دون أن تعرف من هو الأسرع. لإصلاح الأمر سندرج الدالة exit من المكتبة "sys" اختصارًا للكلمة System، تحت آخر سطرٍ لإدراج الدوال في برنامجك: from os import _exit اكتب التعليمة التالية في آخر سطرٍ من أسطر الدالة pressed: _exit(0) وانتبه إلى إزاحة التعليمة بمقدار أربع مسافاتٍ فارغة عن بداية تعريف الدالة لأنها جزءٌ منها. ستنهي هذه التعليمة البرنامج بمجرد أن يُضغط أحد الزرين، وبالتالي يفوز اللاعب الذي يضغط أولًا. سيبدو برنامجك بشكله النهائي على النحو التالي: from gpiozero import LED, Button from time import sleep from random import uniform from os import _exit left_name = input("Left player name is ") right_name = input ("Right player name is ") led = LED(4) right_button = Button(15) left_button = Button(14) led.on() sleep(uniform(5, 10)) led.off() def pressed(button): if button.pin.number == 14: print(left_name + " won the game") else: print(right_name + " won the game") _exit(0) right_button.when_pressed = pressed left_button.when_pressed = pressed شغِّل البرنامج واختر اسمين للاعبيك، ثم انتظر حتى ينطفئ الضوء واضغط على الزرين بأقصى سرعة، فسيظهر فقط اسم اللاعب الأسرع الذي حقق الفوز. ستشاهد أيضًا في نافذة المفسِّر سطرين تظهرهما بايثون، أولهما (Backend terminated (returncode: 0؛ والذي يعني أن بايثون تلّقى الأمر (exit(0_ وأوقف البرنامج، والثاني . . . Use 'Stop/Restart' to restart the backend؛ والذي يخبرك أن البرنامج قد أُوقِف وعليك النقر على أيقونة الإيقاف Stop لإنهائه. شكل 8-6 حالما يتحدد الفائز عليك إيقاف برنامجك تهانينا، لقد أنجزت لعبةً إلكترونيةً حقيقية. ترجمة -وبتصرف- للفصل السادس "Physical computing with scratch and python" من كتاب The official Raspberry Pi beginner's guide. اقرأ أيضًا المقال السابق: البرمجة باستخدام لغة بايثون في تطبيقات راسبيري باي تجميع راسبيري باي والتحضير لاستعماله إنشاء لعبة أضواء باستخدام برنامج سكراتش وحاسوب راسبيري باي لعبة تخفيف التوتر باستخدام سكراتش وحاسوب راسبيري باي تصميم لعبة السلك والحلقة باستخدام برنامج سكراتش وحاسوب راسبيري باي
  5. تحتوي كل متصفحات الويب الحديثة مجموعة أدوات فعّالة لمطوري الويب تنفذ مجالًا واسعًا من الوظائف من فحص ملفات HTML وCSS وجافاسكريبت إلى عرض ملف دعم طلبته الصفحة والمدة التي يستغرقها حتى يُحمّل. يشرح هذا المقال كيفية استعمال الوظائف الأساسية لأدوات مطوري ويب DevTools الخاصة بمتصفحك. فتح أدوات مطوري ويب في متصفح ستجد أدوات مطوري الويب ضمن نافذة فرعية تبدو نوعًا ما كالصورة التالية وذلك بحسب المتصفح الذي تستخدمه. لكن كيف ستظهر هذه الأدوات؟ باستخدام لوحة المفاتيح: اضغط على الأزرار CTRL + Shift + I، ماعدا المتصفحات التالية: مايكروسوفت إنترنت إكسبلورر وإيدج: اضغط على F12. ماك أو إس: اضغط على ⌘ + ⌥ +I. باستخدام شريط القائمة Menu Bar: اضغط زر القائمة ثم: فايرفوكس: اضغط على "مطوري ويب Web Developer" ثم اختر "تبديل الأدوات Toggle Tools" أو "أدوات Tools" ثم اختر "مطوري الويب Web Developer" ثم اختر "تبديل الأدوات Toggle Tools". كروم: اضغط على "المزيد من الأدوات More Tools" ثم اختر "أدوات المطورين Developer Tools". سفاري: اضغط على "تطوير Develop" ثم اختر "إظهار فاحص الويب Show Web Inspector"، وإن لم تجد قائمة "تطوير Develop" انتقل إلى المتصفح سفاري Safari ثم اختر "تفضيلات Preferences" ثم اختر "متقدم Advanced" ثم فعّل الخيار "أظهر قائمة التطوير في شريط القائمة Show Develop menu in menu bar". أوبرا: اضغط على "مطورون Developer" ثم اختر "أدوات المطورين Developer tools". باستخدام قوائم السياق Context Menu: اضغط باستمرار بالزر الأيمن للفأرة على أي عنصر في صفحة الويب (انقر CTRL في ماك) واختر "فحص عنصر Inspect Element" من قائمة السياق التي ستظهر (فائدة إضافية: تظلل هذه الطريقة مباشرة شيفرة العنصر الذي نقرت عليه). فحص شجرة العناصر DOM ومحرر تنسيقات CSS تُظهر أدوات مطوري ويب عند فتحها نافذة الفاحص Inspector افتراضيًا والذي يبدو تقريبًا كما تعرضه لقطة الشاشة التالية: تعرض هذه الأداة نتيجة شيفرة HTML في زمن التنفيذ، كما تعرض تنسيقات CSS المطبقة على كل عنصر من عناصر الصفحة. تتيح لك الأداة أن تعدّل عناصر HTML وCSS أيضًا، وأن تشاهد أثر التغييرات التي أحدثتها مباشرة في المتصفح. إن لم تظهر نافذة الفاحص مباشرة: اضغط أو المس النافذة "فاحص Inspector" في فايرفوكس. اضغط أو المس النافذة "مستكشف DOM Explore" أو اضغط CTRL + 1 في إنترنت إكسبلورر. اضغط أو المس النافذة "عناصر Elements" في مايكروسوفت إيدج وأوبرا وكروم. لا تظهر عناصر التحكم بصورة واضحة في سفاري، لكن من المفترض أن ترى نافذة HTML إن لم تختر شيئًا آخر. اضغط على زر "تنسيق Style" لعرض تنسيقات CSS. استكشاف عمل فاحص DOM انقر في البداية بالزر اليميني للفأرة (أو اضغط CTRL) على عنصر HTML ضمن فاحص شجرة DOM وتحقق من محتويات قائمة السياق التي ستظهر. تختلف عناصر القائمة من متصفح لآخر، لكن المهمة منها موجودة غالبًا في جميع المتصفحات. حذف عقدة Delete Node: (تجدها أحيانًا "حذف عنصر Delete Element") تحذف العنصر المحدد. تحرير كملف HTML: (تجده أحيانًا "إضافة سمة Add Attribute/‎ تحرير نص Edit Text") وذلك لتعديل ملف HTML ومشاهدة نتيجة التعديلات مباشرة، وهو مفيد جدًا للتنقيح والاختبار. تمرير Hover/‎ تفعيل Active/‎ تركيز Focus: تجبر العنصر على تغيير الحالة التي يُعرض بها، وبالتالي ستتمكن من مشاهدة تنسيقه في كل حالة. نسخ Copy/‎ نسخ بصيغة HTML: عنصر HTML الذي تختاره. يمكن أن تجد في بعض المتصفحات خيارات مثل "نسخ CSS" و"نسخ Xpath" لكي تنسخ مُحدِّد CSS أو تعبير Xpath المرتبط بعنصر HTML الحالي. حاول أن تعدّل في شجرة DOM، انقر نقرًا مزدوجًا على عنصر ثم انقر بالزر اليميني عليه واختر "تحرير كملف HTML" من قائمة السياق التي تظهر. يمكنك إحداث التغييرات التي تريد لكن ليس بالإمكان حفظ هذه التغييرات. استكشاف محرر تنسيقات CSS يعرض محرر CSS افتراضيًا القواعد المطبقة على العنصر المختار: تُساعدك هذه الميزات في النقاط التالية: عرض قواعد CSS المطبقة على العنصر الحالي مرتبة من الأكثر تخصيصًا لهذا العنصر إلى الأقل. عرض ما يحدث عند حذف تصريح ما، ولكن لا بدّ أن تنقر قبل ذلك على صندوق التحقق الموجود إلى جوار التصريح. عرض المكافئات الطويلة لخاصية محددة عند النقر على السهم الصغير الموجود إلى جوارها. عرض نتيجة تغيير التنسيق مباشرة بعد وضع قيم جديدة للخاصيات. انقر على اسم الخاصية أو قيمتها ليظهر لك مربع نص ثم اكتب ضمنه القيمة الجديدة. ستجد إلى جانب قاعدة اسم الملف ورقم السطر الذي عُرِّفت القاعدة ضمنه. انقر على القاعدة لتنتقل إلى عرض القاعدة في مكان وجودها الأصلي حيث يمكنك عادةً تعديلها وحفظ التعديلات التي أجريتها. يمكنك أن تنقر أيضًا على القوس المعقوص لأي قاعدة لإظهار مربع نص ضمن سطر جديد إذ يمكنك كتابة قاعدة جديدة كليًا وفقًا لما تحتاج. لاحظ وجود عدة نوافذ فرعية يمكن النقر عليها في نافذة CSS: التنسيق المحوسب Computed: وتعرض لك التنسيق كما هو مطبق على العنصر (القيم النهائية الجاهزة للتطبيق ضمن المتصفح). عرض المخطط Layout: تتكون هذه المنطقة في فايرفوكس من: نموذج صندوقي Box Model: ويعرض نموذجًا صندوقيًا بصريًا لخصائص العنصر لتتمكن مباشرة من الاطلاع على الهوامش والحدود والمساحات الفارغة حوله، وحجم المحتوى الذي يضمه. شبكة العرض Grid: إن استخدام تنسيق الشبكة CSS Grid ضمن الصفحة التي تتفحصها، سيساعدك هذا القسم على رؤية تفاصيل هذه الشبكة. الخطوط Fonts: وتظهر الخطوط المطبقة على العنصر. منقح جافاسكربت يتيح منقح جافاسكربت مراقبة قيمة المتغيرات وضبط نقاط إيقاف التنفيذ Breakpoints، وهي أماكن في شيفرتك تريد إيقاف تنفيذ الشيفرة عندها لتتحقق من المشاكل التي تمنع الشيفرة من العمل بالطريقة المطلوبة. للوصول إلى المنقح: فايرفوكس: اضغط على زر القائمة ثم اضغط على "أدوات المطور Web Developer" ثم اضغط على "المنقح Debugger". كما يمكن الضغط على المفاتيح CTRL + Shift + I معًا. وإن كانت أدوات تطوير ويب مفتوحة مسبقًا، اضغط فقط على نافذة "المنقح Debugger". إنترنت إكسبلورر 11 وإيدج: اضغط على المفتاح F12 ثم المفتاحين CTRL + 3. إن كانت أدوات مطوري ويب مفتوحة مسبقًا، انقر على نافذة "المنقح Debugger". سفاري: افتح نافذة أدوات مطور ويب ثم اضغط على نافذة "المنقح Debugger". استكشاف منقح جافاسكربت ستجد ثلاثة أقسام في منقح جافاسكربت على فايرفوكس قائمة الملفات وهو القسم الأول على يسار نافذة المنقح، يتضمن لائحة الملفات المرتبطة بالصفحة التي تنقحها. اختر الملف الذي ترغب بالعمل عليه بالنقر عليه لتظهر محتوياته ضمن القسم الأوسط من نافذة المنقح. الشيفرة المصدرية وتساعدك في وضع نقاط إيقاف التنفيذ أينما ترغب في ملف الشيفرة. لاحظ نقطة الإيقاف في الصورة التالية، وهي عند السطر المظلل الذي يحمل الرقم 18: مراقبة التعابير ونقاط إيقاف التنفيذ تعرض لك هذه الأداة العبارات التي أضفتها ونقاط إيقاف التنفيذ التي وضعتها، وهي موجودة على يمين نافذة المنقح. تُرتّب نقاط إيقاف التنفيذ في القسم الثاني "نقاط إيقاف التنفيذ Breakpoints". لاحظ كيف وضعت نقطة إيقاف في ملف الشيفرة "example.js" قبل السطر البرمجي: listItems.push(inputNewItem.value); يظهر القسمان الأخيران فقط عند تنفيذ الشيفرة. إذ يعرض القسم "مكدس الاستدعاءات Call Stack" الشيفرة التي جرى تنفيذها حتى الوصول إلى السطر الحالي. لاحظ أنّ الشيفرة موجودة في الدالة التي تعالج نقرة الفأرة، وأن الشيفرة في حالة إيقاف بفعل نقطة الإيقاف. وأخيرًا يعرض القسم "المجالات Scopes" القيم المختلفة التي تنتجها الشيفرة وبالإمكان متابعتها. تعرض الصورة التالية على سبيل المثال الكائنات الموجودة في الشيفرة إضافة إلى الدالة "AddItemClick". طرفية جافاسكربت وهي أداة غاية في الفائدة لتنقيح ملفات جافاسكربت التي لا تعمل كما هو متوقع. تسمح لك الأداة بتنفيذ أسطر الشيفرة بالموازنة مع الصفحة التي يعرضها المتصفح، وتبلغك بالأخطاء التي يصادفها المتصفح عندما يحاول تنفيذ الشيفرة. للولوج إلى طرفية جافاسكربت المدمجة مع المتصفح: إن كانت نافذة أدوات مطوري ويب مفتوحة انقر على نافذة "طرفية Console"، وإن لم تكن مفتوحة يمكنك في فايرفوكس الضغط على المفاتيح CTRL + SHIFT + K معًا أو من خلال: اضغط على رمز القائمة ثم اضغط على "أدوات المطورين Web Developer" ثم اضغط على "طرفية ويب Web Console" أو "أدوات Tools" ثم اضغط على "أدوات المطورين Web Developer" ثم اضغط على "طرفية الويب Web Console". في بقية المتصفحات، افتح نافذة أدوات مطوري ويب ثم انقر على نافذة الطرفية. ينتج عن فتح الطرفية نافذة مشابهة للنافذة في الصورة التالية: لتختبر الطرفية، حاول كتابة مقطع الشيفرة التالي ضمنها مقطعًا مقطعًا (ثم اضغط "Enter"). لنكتب أولًا التعليمة التالية: alert('hello!'); ثانيًا جرب كتابة الشيفرة التالية: document.querySelector('html').style.backgroundColor = 'purple'; const myWordmark = document.createElement('img'); myWordmark.setAttribute('src','https://blog.mozilla.org/press/wp-content/themes/OneMozilla/img/mozilla-wordmark.png'); document.querySelector('h1').appendChild(myWordmark); حاول الآن إدخال نسخة خاطئة من الشيفرة وراقب ما يحدث: alert('hello!); أو هكذا: document.cheeseSelector('html').style.backgroundColor = 'purple'; const myWordmark = document.createElement('img'); myBanana.setAttribute('src','https://blog.mozilla.org/press/wp-content/themes/OneMozilla/img/mozilla-wordmark.png'); document.querySelector('h1').appendChild(myWordmark); ستبدأ بملاحظة طبيعة الأخطاء التي يعيدها المتصفح. يمكن أن تكون هذه الأخطاء مشفرة، ولكن من السهل تحليلها وإيجاد المشاكل الكامنة وراءها. ترجمة -وبتصرف- للمقال How does the Internet work. اقرأ أيضًا مدخل إلى أدوات التطوير في متصفح الويب DevTools أدوات المطور ما هي الأدوات المستخدمة في بناء مواقع ويب؟ كيف تستخدم أدوات المطوِّر في المتصفحات الحديثة كيف تستخدم أدوات المطور DevTools في Chrome
  6. سنلقي الضوء في هذا المقال على بعض الأشياء التي ينبغي التفكير بها عند تثبيت محرر نصوص لتطوير مواقع الويب. ننصحك قبل الشروع بقراءة المقال أن تطلع على مقال ما هي الأدوات المستخدمة في بناء مواقع ويب؟ مقدمة عن المحررات البرمجية لتطوير الويب تتكون مواقع الويب في معظمها من ملفات نصية، ولكي تختبر تجربة مريحة وممتعة في رحلة تطوير موقع ويب، لا بدّ من اختيار محرر النصوص بحكمة! ستجد عددًا كبيرًا من محررات النصوص لكونها أمرًا أساسيًا في علوم الحاسوب (وبالطبع تطوير الويب جزء من علوم الحاسوب). عليك -إن أردنا التكلم بمثالية- أن تجرب أكبر عدد ممكن من المحررات ثم تختار ما تشعر أنه المناسب لاحتياجاتك، لكننا سنحاول إرشادك لتبدأ بطريقة صحيحة. إليك بعض التساؤلات الأساسية التي ينبغي أخذها بعين الاعتبار: أي نظام تشغيل سأعمل عليه؟ ما هي التقنيات التي أريد أن أتعامل معها؟ ما الميزات الأساسية التي أتوقع وجودها في محرر النصوص؟ هل أريد إضافة ميزات إضافية إلى محرر النصوص؟ هل أحتاج إلى دعم أو مساعدة أثناء استخدام محرر النصوص؟ هل يهمني مظهر محرر النصوص وشعوري عند العمل عليه؟ لاحظ أننا لم نذكر التكلفة وهي أمر هام بكل وضوح، لكن تكلفة المنتج لا ترتبط بالضرورة بجودته أو إمكاناته. ويمكن جدًا تجد محرر نصوص مجاني ومناسب. إليك قائمة ببعض المحررات الأكثر شعبية: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } المحرر رخصة الاستخدام السعر نظام التشغيل آلية دعم المنتج توثيقات المنتج قابل للتوسّع Atom MIT/BSD مجاني ويندوز، ماك، لينوكس منتديات دليل استخدام على الإنترنت نعم Bluefish GPL 3 مجاني ويندوز، ماك، لينوكس قوائم بريدية، مستندات تعاونية wikis دليل استخدام على ويب نعم Brackets MIT/BSD مجاني ويندوز، ماك، لينوكس منتديات، محادثة عبر الإنترنت IRC مستندات تعاونية على غت-هاب GitHub Wiki نعم Coda مغلق المصدر $99 ماك تويتر، منتديات، بريد إلكتروني كتاب إلكتروني نعم CodeLobster مغلق المصدر مجاني ويندوز، ماك، لينوكس منتديات، بريد إلكتروني) دليل استخدام على الإنترنت نعم Emacs GPL 3 مجاني ويندوز، ماك، لينوكس الأسئلة الأكثر شيوعًا، قوائم بريدية، مجموعات إخبارية دليل استخدام على الإنترنت نعم Espresso مغلق المصدر $75 ماك الأسئلة الأكثرشيوعًا، البريد الإلكتروني لا توجد توثيقات موجهة إلى المستخدم النهائي، فقط توثيقات للإضافات plug-in doc نعم Gedit GPL مجاني ويندوز، ماك، لينوكس قوائم بريد إلكتروني، محادثات عبر الإنترنت دليل استخدام على الإنترنت نعم Kate LGPL, GPL مجاني ويندوز، ماك، لينوكس قوائم بريد إلكتروني، IRC دليل استخدام على الإنترنت نعم Komodo Edit MPL مجاني ويندوز، ماك، لينوكس منتديات دليل استخدام على الإنترنت نعم Notepad++ GPL مجاني ويندوز منتديات Wiki نعم PSPad مغلق المصدر مجاني ويندوز FAQ، منتديات مساعدة عبر الإنترنت نعم Sublime Text مغلق المصدر $70 ويندوز، ماك، لينوكس منتديات رسمية،غير رسمية نعم TextMate مغلق المصدر $50 ماك تويتر، محادثة عبر الإنترنت، قوائم بريد إلكتروني، بريد إلكتروني دليل استخدام على الإنترنت، مستندات تعاونية نعم TextWrangler مغلق المصدر مجاني ماك الأسئلة الأكثر شيوعًا، منتديات دليل استخدام PDF لا Vim رخصة مصدر مفتوح خاصة مجاني ويندوز، ماك، لينوكس قوائم بريد إلكتروني دليل استخدام على الإنترنت نعم Visual Studio Code مفتوح المصدر خاضع لرخصة MIT/ (رخصة خاصة بالمنتج) مجاني ويندوز، ماك، لينوكس الأسئلة الأكثر شيوعًا توثيق نعم سنلقي نظرة في الفقرات التالية على بعض النقاط التي يجب أن نأخذها بعين الاعتبار عند اختيار محرر نصي. معايير الاختبار ولكن ما الذي عليك التفكير به عند اختيار محرر نصي؟ هيا بنا لنخوض أكثر في التفاصيل. نظام التشغيل الذي تعمل عليه بالرغم من أن الموضوع ما هو إلا تفضيلات شخصية، ولكن تذكر أن بعض المحررات متاحة فقط لأنظمة تشغيل محددة. وإن أردت التنقل من نظام تشغيل إلى آخر، سيحد ذلك من خياراتك. تسهل عليك محررات النصوص التي تعمل عبر المنصات المختلفة Cross-Platform في هذه الحالة أمر الانتقال من نظام إلى آخر. تأكد في البداية من نظام التشغيل الذي تستخدمه ثم اعثر على محرر نصوص يدعمه. تحدد محررات النصوص على مواقعها الإلكترونية الأنظمة التي تدعمها، يمكن ألّا تدعم بعضها سوى إصداراتٍ معينة من أنظمة التشغيل (ويندوز 7 وما بعد وليس فيستا مثلًا). إن كنت تعمل على نظام التشغيل أوبونتو فمن الأفضل البحث ضمن مركز برامج أوبونتو Ubuntu Software Center. إنّ عالم أنظمة التشغيل لينوكس/ يونكس واسع ومتنوع ويمكن ألّا تتوافق حزم البرمجيات بين توزيعة وأخرى. وبالتالي إن وقع اختيارك على محرر نصوص معين لا تدعمه توزيعة لينكس التي تعمل عليها، عليك ترجمة الشيفرة المصدرية للبرنامج بنفسك لتناسب توزيعتك (وهذا عمل للمتمرسين وليس لضعاف القلوب!). التقنيات التي أريد التعامل معها يمكن لأي محرر نصوص أن يقرأ ويحرر أي نص عمومًا. وهذا أمر جيد إن أردت أن تترك لنفسك ملاحظات هنا وهناك، لكن عند تطوير مواقع ويب وكتابة شيفرات HTML وCSS وجافاسكربت، يمكن أن يصل بك الأمر إلى كتابة ملفات كبيرة ومعقدة. لهذا وفر على نفسك العناء واستخدم محرر نصوص يفهم التقنيات التي تتعامل معها. تساعدك الكثير من المحررات النصية في هذا الأمر من خلال مميزاتها التي تقدمها مثل: تلوين العبارات البرمجية Syntax Highlighting: سيغدو الملف أكثر وضوحًا عند تلوين شيفرات الأوامر والكلمات المفتاحية بألوان مختلفة تناسب التقانة التي تستخدمها. الإكمال التلقائي للشيفرة Code Completion: توفر عملية الإكمال التلقائي للبنى البرمجية التي تكتب شيفرتها الوقت كأن يغلق المحرر واسمات HTML المفتوحة، أو أن يقترح عليك خاصية معينة عند كتابة تنسيق CSS. استخدام مقاطع شيفرة (أو قصاصات برمجية) Code Snippets: تستخدم العديد من التقنيات هيكلية متشابهة عند كتابة مستنداتها كما تلاحظ عند كتابة مستندات HTML. لذلك عند استخدامك لمقاطع شيفرة جاهزة سيوفر عليك عناء إعادة كتابتها مرة تلو الأخرى. تدعم معظم محررات النصوص حاليًا تلوين العبارات البرمجية، ولا تدعم بالضرورة الميزتين الباقيتين. لذلك تأكد قبل كل شيء من دعم المتصفح الذي ستعتمده ميزة تلوين العبارات البرمجية لكل من HTML وCSS وجافا سكربت. الميزات الأساسية التي تتوقع أن تجدها في محرر النصوص يعتمد ذلك على احتياجاتك ومخططاتك. إليك بعض الميزات الوظيفية التي تساعدك غالبًا في عملك: البحث والاستبدال في مستند أو أكثر اعتمادًا على التعابير النمطية Regular Expressions أو غيرها من العبارات التي تحتاجها. الانتقال السريع إلى سطر محدد. عرض قسمين من ملف طويل معًا. عرض شيفرة HTML التي تكتبها كما ستظهر على المتصفح. اختيار عدة أسطر من أماكن مختلفة معًا. إظهار مجلدات مشروعك وما تحويه من ملفات. التنسيق التلقائي لشيفراتك باستخدام محسنات مظهر الشيفرة Code Beautifier. التدقيق الإملائي. الإزاحة التلقائية للشيفرة وفقًا لإعدادات الإزاحة. إمكانية إضافة ميزات إضافية إلى المحرر تأتي بعض المحررات القابلة للتوسيع مع عدد قليل من الميزات المدمجة، ويمكن توسيع إمكاناتها بميزات إضافية وفقًا لاحتياجاتك. إن لم تكن متأكدًا من المميزات التي تحتاجها أو افتقر محررك لهذه المميزات، عليك البحث عن محرر قابل للتوسع. وأفضل المحررات هي التي تزودك بالعديد من الإضافات وتقدم لك طريقة للبحث عن هذه الإضافات وتثبيتها تلقائيًا (نتكلم عن محرر مثالي هنا). إن رغبت باستخدام الكثير من الميزات الوظيفية التي أبطأت محررك نظرًا لزيادة الإضافات التي ثبّتها، جرّب استخدام بيئة تطوير متكاملة Integrated Development Environment واختصارًا IDE. تؤمن لك هذه البيئات الكثير من الأدوات ضمن واجهة واحدة، وعلى الرغم من صعوبتها على المبتدئين تبقى خيارًا قائمًا إن شعرت أن محررك محدود القدرة. إليك بعض بيئات العمل المتكاملة: Aptana Studio. Eclipse. Komodo IDE. NetBeans IDE. Visual Studio. WebStorm. الحاجة إلى الدعم أو المساعدة أثناء استخدام المحرر من الجيد أن تعلم إن كنت ستتلقى مساعدة أو دعمًا عندما تستخدم برنامجًا معينًا. تحقق من أمرين اثنين عندما يتعلق الأمر بمحرر النصوص: المحتوى الموجه للمستخدم (الأسئلة الأكثر شيوعًا ودليل المستخدم والمساعدة المباشرة عبر الإنترنت). النقاشات مع المطورين ومستخدمين آخرين (المنتديات والبريد الإلكتروني ومحادثات عبر الإنترنت IRC). استخدم التوثيق المكتوب عندما ترغب في تعلم استخدام محرر النصوص، وتواصل مع الآخرين إن واجهت مشاكل في تثبيت البرنامج أو أثناء استخدامه. أهمية مظهر المحرر وتجربة استخدامه بالرغم من أن الأمر مجرد تفضيلات شخصية إلّا أنه يمكن أن يرغب البعض في تخصيص كل تفصيل في واجهة المستخدم ابتداءً بالألوان وانتهاءً بمواقع الأزرار. تتنوع المحررات النصية تبعًا لهذا المنظور، لذا تحقق من ذلك أولًا. لن تجد صعوبة في إيجاد محرر نصوص يغير سماته اللونية، لكن إن أردت تفاصيلًا أكثر خصوصية لن تجد مفرًا من استخدام IDE. تثبيت المحرر وإعداده للعمل لن تجد أي تعقيدات في تثبيت محرر النصوص، لكن طريقة التثبيت ستختلف من منصة لأخرى، ولا ينبغي أن تكون صعبة إطلاقًا: ويندوز: ستجد ملف التثبيت بإحدى اللاحقتين exe. أو msi. ويأتي البرنامج مضغوط ضمن أرشيف مثل zip. أو 7z أو rar.، وعليك في هذه الحالة تثبيت برنامج إضافي لاستخراج البرنامج من الأرشيف المضغوط. يدعم ويندوز zip. افتراضيًا، فلا حاجة لتثبيت أية برامج إضافية. ماك: يمكنك تنزيل ملف التثبيت ذو اللاحقة dmg. من موقع الويب الخاص بالمحرر، كما ستجد الكثير من المحررات النصية ضمن متجر آبل مما يسهِّل عملية التثبيت. لينوكس: بإمكانك الانطلاق من الواجهة الرسومية لبرنامج مدير الحزم Packet Manager في التوزيعات الأكثر شعبية من لينوكس مثل Ubuntu Software Center أو Mintinstall أو Gnome Software وغيرها من البرامج. ستجد أيضًا ملفًا لاحقته deb. أو rpm. للبرنامج في مرحلة ما قبل التجميع أو الحزم Prepackaging، لكنك ستستخدم في غالب الأحيان خادم المستودعات Repository Server الخاص بالتوزيعة التي تعمل عليها، أما الحالة الأسوء فهي ترجمة الملفات المصدرية للمحرر ليعمل على توزيعتك. خذ وقتك في قراءة تعليمات التثبيت التي يوفرها موقع ويب الخاص بالمحرر. يستمر نظام التشغيل في فتح الملفات النصية باستخدام محرر النصوص الافتراضي حتى تغير ارتباط الملف File Association. ويعني ذلك تحديد المحرر المفضل الذي يستخدمه نظام التشغيل في فتح الملف النصوص عند النقر المضاعف عليه. بعد أن تُثبت المحرر النصوص الذي يلبي احتياجاتك، لا بدّ من وضع اللمسات الأخير على بيئتك الأساسية لتطوير مواقع ويب، أو يمكنك أن تكتب بنفسك شيفرة أول صفحة ويب إن أردت استخدام بيئة عملك مباشرة. ترجمة -وبتصرف- للمقال What text editors are available. اقرأ أيضًا ما هو عنوان URL في الويب؟ ما التكلفة المادية الكاملة لبناء موقع ويب؟ مفهوم الروابط التشعبية في مواقع الويب
  7. سنغطي في هذا الفصل التوابع المتنوعة التي تعمل مع التعابير النمطية بشيء من التفصيل بعد أن غطينا موضوع التعابير النمطية تغطية شاملة بدءًا من مقال أساسيات التعابير النمطية وحتى مقال كتابة تعابير نمطية متقدمة (إن لم تتطلع عليها، فننصحك بالرجوع إليها أولًا). التابع (str.match(regexp يبحث هذا التابع عن تطابقات للتعبير regexp في النص str، وله ثلاثة أنماط: النمط الأول، الراية g غير مفعّلة: يعيد التابع التطابق الأول ضمن مصفوفة، تحوي مجموعات ملتقطةً capturing groups وخصائص، هي موقع التطابق index، والنص الذي نبحث فيه input، وهو النص str. let str = "I love JavaScript"; let result = str.match(/Java(Script)/); alert( result[0] ); // JavaScript (تطابق كامل) alert( result[1] ); // Script (المجموعة الملتقطة الأولى) alert( result.length ); // 2 // Additional information: alert( result.index ); // 7 (موقع التطابق) alert( result.input ); // I love JavaScript (النص الأصلي) النمط الثاني، الراية g مفعلة: سيعيد التابع مصفوفةً تضم كل التطابقات الموجودة في صيغة قيم نصية، دون مجموعات ملتقطة، أو غيرها من التفاصيل. let str = "I love JavaScript"; let result = str.match(/Java(Script)/g); alert( result[0] ); // JavaScript alert( result.length ); // 1 النمط الثالث، إذا لم يوجد تطابق فسيعيد التابع القيمة null، سواء استخدمنا الراية g أم لم نستخدمها، انتبه جيدًا إلى أنه لا يعيد مصفوفةً فارغةً عندما لا يجد تطابقات، بل يعيد القيمة null: let str = "I love JavaScript"; let result = str.match(/HTML/); alert(result); // null alert(result.length); // Error إذا أردنا الحصول على النتيجة في مصفوفة، فيمكننا كتابة الشيفرة على الشكل: let result = str.match(regexp) || []; التابع (str.matchAll(regexp يمثل التابع نسخةً محدثةً ومطورةً عن التابع str.match، ويستخدَم لإيجاد جميع التطابقات وفق المجموعات المحددة، ويختلف عن التابع str.match في ثلاثة أمور، هي: لا يعيد مصفوفةً بل كائنًا قابلًا للتكرار iterable object، ويمكن إنشاء مصفوفة نظامية منه باستخدام Array.from. عند استخدام الراية g يعيد كل تطابق في مصفوفة تحتوي مجموعات. عندما لا يجد تطابقات فلا يعيد null، بل كائنًا فارغًا قابلًا للتكرار. أمثلة عن استخدامه: let str = '<h1>Hello, world!</h1>'; let regexp = /<(.*?)>/g; let matchAll = str.matchAll(regexp); alert(matchAll); // ليس مصفوفة بل كائن matchAll = Array.from(matchAll); // الآن مصفوفة let firstMatch = matchAll[0]; alert( firstMatch[0] ); // <h1> alert( firstMatch[1] ); // h1 alert( firstMatch.index ); // 0 alert( firstMatch.input ); // <h1>Hello, world!</h1> إذا استخدمنا الحلقة for..of للحصول على تطابقات matchAll، فلن نحتاج إلى تحويل الكائن إلى مصفوفة من خلال Array.from. التابع (str.split(regexp|substr, limit يقسم النص وفقًا لتعبير نمطي (أو نص فرعي)، ويمكن استخدامه دون نص بالشكل التالي: alert('12-34-56'.split('-')) // array of ['12', '34', '56'] كما يمكن التقسيم وفقًا لتعبير نمطي بنفس الأسلوب: alert('12, 34, 56'.split(/,\s*/)) // array of ['12', '34', '56'] التابع (str.search(regexp يعيد التابع موقع التطابق الأول، أو يعيد 1- إذا لم يجد تطابقًا: let str = "A drop of ink may make a million think"; alert( str.search( /ink/i ) ); // 10 (first match position) المحدودية الأكبر للتابع هي إيجاده لأول تطابق فقط. فإذا أردنا مواقع بقية التطابقات فلا بدّ من استخدام طرق أخرى، مثل البحث عن جميع التطابقات باستخدام matchAll. التابع (str.replace(str|regexp, str|func وهو التابع الأساسي للبحث والاستبدال، والأكثر فائدةً، ويمكن استخدامه للبحث عن أجزاء من النص دون الحاجة لتعابير نمطية. // بدل الشرطة القصيرة بنقطتين متعامدين alert('12-34-56'.replace("-", ":")) // 12:34-56 مع ذلك قد يصعب استخدامه أحيانًا. عندما يكون المعامل الأول replace نصًا فسيستبدل التطابق الأول فقط حيث ستلاحظ في المثال الأول استبدال الشرطة القصيرة الأولى فقط بالنقطتين المتعامدتين، ولإيجاد بقية التطابقات واستبدالها، لا بدّ من استخدام التعبير النمطي g/-/ بدلًا من النص "-"، مع التفعيل الإجباري للراية g. // بدل كل شرطة قصيرة بنقطتين متعامدين alert( '12-34-56'.replace( /-/g, ":" ) ) // 12:34:56 يمكن استخدام محارف خاصة في الوسيط الثاني كونه النص البديل. table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } الرمز ما يفعله ضمن النص replacment &$ يمثل نص التطابق `$ يمثل النص الواقع قبل نص التطابق. '$ يمثل النص الواقع بعد نص التطابق. n$ يمثل التطابق ذا الرقم n من مجموعة التطابق (الموجود ضمن قوسي تجميع"()" ) وسنتعرف لاحقًا عليها في فصل: المجموعات الملتقطة. ‎$<name>‎ يمثل التطابق ذا الاسم name من مجموعة التطابق (الموجود ضمن قوسي تجميع"()" )، وسنتعرف لاحقًا ععليها في فصل: المجموعات الملتقطة. $$ يمثل المحرف $ إليك مثالًا: let str = "John Smith"; // swap first and last name alert(str.replace(/(john) (smith)/i, '$2, $1')) // Smith, John يمكن أن نمرر دالةً ضمن الوسيط الثاني، إذا كانت الحالة تتطلب ذلك. وستُستدعى هذه الدالة عند كل تطابق، وستصبح القيمة التي تُعيدها بمثابة النص البديل، أما شكل الدالة فهو: func(match, p1, p2, ..., pn, offset, input, groups) حيث: match: التطابق. p1, p2, ..., pn: محتويات المجموعات الملتقطة، إن وجدت. offset: موقع التطابق. input: النص الأصلي. groups: كائن يضم المجموعات المُسمّاة. إذا لم توجد أقواس ضمن التعبير النمطي فسيكون لدينا ثلاثة وسطاء فقط (func(str, offset, input. وسنعرض بعض الأمثلة: تحويل التطابقات إلى أحرف كبيرة: let str = "html and css"; let result = str.replace(/html|css/gi, str => str.toUpperCase()); alert(result); // HTML and CSS استبدال كل تطابق بموقعه في النص: alert("Ho-Ho-ho".replace(/ho/gi, (match, offset) => offset)); // 0-3-6 في المثال التالي، ستجد قوسين مفتوحين في التعبير النمطي وبالتالي ستقبل الدالة خمسة وسطاء، الأول للتطابق بأكمله، ثم محتوى القوسين، وبعدهما (لم يستخدما في مثالنا) موقع التطابق والنص الأصلي: let str = "John Smith"; let result = str.replace(/(\w+) (\w+)/, (match, name, surname) => `${surname}, ${name}`); alert(result); // Smith, John يفضل استخدام التفكيك destruction عند وجود مجموعات عدة: let str = "John Smith"; let result = str.replace(/(\w+) (\w+)/, (...match) => `${match[2]}, ${match[1]}`); alert(result); // Smith, John عندما نستخدم المجموعات المسماة، فسيكون الكائن groups مع المجموعات دائمًا في الموقع الأخير، وبالتالي سنحصل عليها بالشكل التالي: let str = "John Smith"; let result = str.replace(/(?<name>\w+) (?<surname>\w+)/, (...match) => { let groups = match.pop(); return `${groups.surname}, ${groups.name}`; }); alert(result); // Smith, John سيتيح لنا استخدام دالة عند استبدال النصوص قدرةً كبيرةً، لأنها ستزودنا بكل المعلومات عن التطابق، ولها القدرة على الوصول إلى المتغيرات الخارجية، وتنفيذ أي شيء نريده. التابع (str.replaceAll(str|regexp, str|func وله وظيفة التابع str.replace نفسها، مع وجود اختلافين رئيسيين: سيستبدل كل التطابقات الموجودة إذا كان وسيطه الأول نصًا، بينما يستبدل replace التطابق الأول فقط. يعمل تمامًا مثل التابع replace إذا كان وسيطه الأول تعبيرًا نمطيًا والراية g مفعلةً، ويعطي خطأً إذا لم تكن كذلك. ويستخدم بشكل رئيسي عندما نريد استبدال جميع التطابقات، وإليك مثالًا: // استبدل كل الشرطات بنقطتين عموديتين alert('12-34-56'.replaceAll("-", ":")) // 12:34:56 التابع (regexp.exec(str يعيد هذا التابع تطابقًا مع نمط إذا وجده ضمن النص، وعلى خلاف التوابع السابقة سيُستدعى من قبل كائن تعبير نمطي regexp وليس من قبل نص str، ويسلك سلوكًا مختلفًا عند تفعيل الراية g أو عدم تفعيلها، فإذا لم تكن هذه الراية مفعلةً فسيعيد التطابق الأول فقط، تمامًا مثل التابع (str.match(regexp، ولن يقدم هذا السلوك أي جديد، ولكن مع وجود الراية g: سيعيد التطابق الأول، ويخزن الموقع الذي يلي التطابق مباشرةً ضمن الخاصية regexp.lastIndex. عندما يُستدعى مجددًا سيبدأ البحث انطلاقًا من الموقع المُخزّّن ضمن الخاصية regexp.lastIndex معيدًا التطابق التالي، وسيخزن الموقع الذي يليه مباشرةً ضمن الخاصية regexp.lastIndex محدّثًا قيمتها. وهكذا يستمر العمل. إذا لم يجد تطابقات فسيعيد القيمة null، ويسند القيمة 0 إلى الخاصية regexp.lastIndex. سيعيد الاستدعاء المتكرر لهذا التابع كل التطابقات كما شرحنا في الخطوات السابقة، بينما قبل وجود هذا التابع، كان لا بدّ من استخدام الحلقات للحصول على التطابقات جميعها: let str = 'More about JavaScript at https://javascript.info'; let regexp = /javascript/ig; let result; while (result = regexp.exec(str)) { alert( `Found ${result[0]} at position ${result.index}` ); // Found JavaScript at position 11, then // Found javascript at position 33 } سيعمل الأسلوب المتبع في المثال السابق أيضًا، على الرغم من أنّ استخدام التابع str.matchAll سيناسب المتصفحات الحديثة أكثر. يمكن استخدام التابع (regexp.exec(str للبحث انطلاقًا من موقع محدد بضبط قيمة الخاصية regexp.lastIndex يدويًا. وإليك مثالًا: let str = 'Hello, world!'; let regexp = /\w+/g; //lastIndex يتجاهل المحرك قيمة الخاصية "g" دون الراية regexp.lastIndex = 5; // البحث انطلاقًا من الموقع 5 alert( regexp.exec(str) ); // world يفرض وجود الراية y البحث في الموقع المحدد ضمن الخاصية regexp.lastIndex تمامًا، وليس بعده. لنستبدل الراية y بالراية g في المثال السابق، وسنلاحظ عدم وجود تطابقات: let str = 'Hello, world!'; let regexp = /\w+/y; regexp.lastIndex = 5; // search exactly at position 5 alert( regexp.exec(str) ); // null يناسب هذا الأمر الحالات التي نحتاج فيها إلى قراءة شيء ما من نص باستخدام التعابير النمطية انطلاقًا من موقع محدد تمامًا. التابع (regexp.test(str يتأكد هذا التابع من وجود تطابق، ويعيد إحدى القيمتين true/false، وإليك مثالًا: let str = "I love JavaScript"; // ينفذ الاختباران التاليان العمل نفسه alert( /love/i.test(str) ); // true alert( str.search(/love/i) != -1 ); // true مثال مع جواب سلبي: let str = "Bla-bla-bla"; alert( /love/i.test(str) ); // false alert( str.search(/love/i) != -1 ); // false في الحالة التي نفعل فيها الراية g، سيبحث التابع عن الخاصية regexp.lastIndex ويحدّث قيمتها، تمامًا مثل التابع regexp.exec، لذلك يمكن استخدامه للبحث في موقع محدد: let regexp = /love/gi; let str = "I love JavaScript"; // يبدأ البحث من الموقع 10 regexp.lastIndex = 10; alert( regexp.test(str) ); // false (لا تطابق) لاحظ أنه قد يخفق الاختبار المستمر لتعبير نمطي عام على نصوص مختلفة، لأن التابع regexp.exec يستدعي قيمًا متقدمةً للخاصية regexp.lastIndex، وبالتالي قد يبدأ البحث في نص آخر ابتداءً من موقع مختلف عن الصفر. لاحظ في هذا المثال كيف سنختبر النص ذاته مرتين متتاليتين، وسيخفق الاختبار الثاني: let regexp = /javascript/g; // (regexp just created: regexp.lastIndex=0) alert( regexp.test("javascript") ); // true (regexp.lastIndex=10 now) alert( regexp.test("javascript") ); // false للالتفاف على هذه المشكلة، يمكننا ضبط قيمة الخاصية regexp.lastIndexعلى الصفر قبل البدء بكل بحث، أو استخدام توابع النصوص، مثل .../str.match/search، بدلًا من توابع التعابير النمطية، فهي لا تستخدم الخاصية lastIndex. ترجمة -وبتصرف- للفصل Methods of RegExp and string من سلسلة The Modern JavaScript Tutorial. اقرأ أيضًا المقال السابق: فهم التعقب التراجعي الكارثي في التعابير النمطية RegEx مطابقة عدة مجموعات نمطية في التعابير النمطية RegEx المحددات الكمية وأنماط استخدامها في التعابير النمطية المجموعات والمجالات في التعابير النمطية
  8. يمكن ألّا تنفق شيئًا عند نشر موقع الويب الخاص بك أو يمكن أن تتخطى الميزانية المحددة، ولهذا يمكن أن تتساءل كم سيُكلفك بناء موقع ويب كامل؟ وكيف ستجني ما أنفقته؟ سنستعرض في هذا المقال عملية تطوير موقع ويب بأكمله وحساب التكلفة المادية المتوقعة لكل خطوة، فيمكن ألّا يكون دخولك عالم الويب رخيصًا كما تعتقد. قبل الشروع في قراءة هذا المقال عليك أن تطلع على الفرق بين صفحة الويب وخادم الويب وغيرها من المصطلحات، كما عليك أن تكون على دراية بمفهوم أسماء النطاقات. البرمجيات سنتعرف في الفقرات القادمة على بعض البرمجيات الأساسية التي تحتاجها لتطوير موقع ويب والتكلفة المادية لها. محررات النصوص من المرجح أنك تملك محرر نصوص مثل المفكرة Notepad في ويندوز أو جي-إدت Gedit في لينوكس أو محرر النصوص TextEdit في ماك أو إس. لكن استخدام محرر نصوص يلوّن الشيفرات ويتحقق من صحتها قواعديًا ويساعدك في تنظيمها سيريحك ويسهِّل تطوير المواقع. يمكنك الحصول على الكثير من محررات النصوص مجانًا مثل: Atom. Brackets. Bluefish. TextWrangler. Eclipse. Netbeans. Visual Studio Code. كما يمكنك اختبار Sublime Text المدة التي تشاء لكنه سيظهر لك رسائل تشجعك على شراءه بينما يكلفك PhpStorm ما بين 20 إلى 200 دولار وفقًا للخطة التي تحتاجها. يحصل المطورون الأفراد أو مطوري المشاريع مفتوحة المصدر على Visual Studio Express مجانًا. وعادة ما تحصل على فترة تجريب مجانية للمحررات المدفوعة. ننصحك كبداية أن تجرب عدة محررات لتقرر ما يناسبك منها. كما ننصحك باستخدام محرر بسيط إن كنت ستكتب ملفات HTML وCSS وجافاسكربت بسيطة. لا يعكس ثمن المحرر جودته بالضرورة، عليك أن تجرب هذا المحرر وتقرر بنفسك إن كان يلبي احتياجاتك. يعدّ محررًا Sublime Text رخيص الثمن لكنه يأتي مع الكثير من الإضافات المجانية التي توسّع قدراته كثيرًا. محررات الصور من المرجح أن يزوّدك نظام التشغيل الذي تستخدمه بمحرر أو مستعرض صور بسيط مثل Paint في ويندوز وبرنامج Eye of Gnome في أوبونتو وبرنامج Preview في ماك. وبالطبع فهي برمجيات محدودة نسبيًا وسرعان ما تحتاج إلى محررات صور أكثر قوة لإضافة الطبقات والتأثيرات والمجموعات. يمكن أن تكون هذه المحررات مجانية مثل GIMP أو بتكلفة معقولة أقل من 100 دولار مثل PaintShop Pro أو بتكلفة عالية نسبيًا مثل أدوبي فوتوشوب Adobe Photoshop. اختر أيًا من تلك المحررات فهي تقدم وظائف متشابهة. وبالرغم من أنّ بعضها يشمل الكثير من الميزات، لكنك لن تستخدمها كلها. اطلع على الأدوات التي يستخدمها المطورون الآخرون إن كنت ستتبادل المشاريع معهم في مرحلة ما. إذ يمكن لجميع المحررات تصدير المشاريع المنجزة على شكل ملفات بتنسيقات معيارية لكنها تخزّن المشاريع التي لا تزال تحت التطوير بتنسيقات خاصة. تتمتع معظم الصور على الإنترنت بحقوق نشر، لذا عليك التحقق من رخصة استخدام الصورة قبل استخدامها. تزوّدك بعض المواقع مثل Pixabay بصور تحمل الرخصة CC0 لذا يمكنك استخدامها وتعديلها ونشرها بشكلها المعدّل لأغراض تجارية. محررات الوسائط إن أردت إضافة مقاطع فيديو أو مقاطع صوتية إلى موقعك، يمكنك تضمين خدمات ويب موجودة مثل يوتيوب YouTube أو ديلي موشن Dailymotion أو فيميو Vimeo أو تضمين مقاطع فيديو خاصة بك (تحقق من تكلفة عرض الحزمة التي سترد لاحقًا في المقال). يمكنك استخدام برامج مجانية للعمل مع المقاطع الصوتية (مثل Audacity وWavosaur) أو مدفوعة بتكاليف يمكن أن تصل لمئات من الدولارات (مثل Sony Sound Forge وAdobe Audition). وكذلك الأمر مع محررات الفيديو إذ يمكنك استخدام المحررات مجانية مثل PiTiVi وOpenShot لنظام التشغيل لينوكس وبرنامج iMovie لنظام التشغيل ماك أو إس أو يمكنك استخدام محررات معتدلة التكلفة أقل من 100 دولار مثل Adobe Premiere Elements أو بتكلفة تصل إلى مئات الدولارات (مثل Adobe Premiere Pro وAvid Media Composer وFinal Cut Pro. وغالبًا ما يغطي محرر الفيديو الذي يأتي مع كاميرتك الرقمية كل احتياجاتك. أدوات نشر المواقع ستحتاج إلى وسيلة لرفع ملفات موقعك من القرص الصلب على حاسوبك إلى خادم الويب، لذلك تساعد بعض أدوات النشر مثل S)FTP client) أو RSync أو Git/GitHub في إنجاز الأمر. يحتوي كل نظام تشغيل على برنامج عميل S)FTP) كجزء من مدير الملفات مثل Windows Explorer في ويندوز وNautilus وهو مدير ملفات شائع في أنظمة التشغيل لينوكس وMac Finder في ماك أو إس. يختار المطورون عادة برامج S)FTP) مخصصة لاستعراض المجلدات الموجودة على الحاسوب أو الخادم بشكل متجاور وتخزين كلمات مرور الخادم. هناك العديد من الخيارات الموثوقة والمجانية إن أردت أن تثبّت برنامج عميل S)FTP) مثل FileZilla لكل المنصات وWinSCP لنظام التشغيل ويندوز وCyberduck لكل من ويندوز وماك وغيرها الكثير. إنّ بروتوكول FTP غير آمن بطبيعته لذلك تأكد من استخدام SFTP وهي النسخة الآمنة المشفّرة من FTP التي تتعامل معها معظم مزودات الخدمة هذه الأيام افتراضيًا. يمكنك بالطبع استخدام تقنيات آمنة أخرى مثل Rsync مع SSH. المتصفحات إما أن يكون لديك بالفعل متصفح أو يمكنك تحميل أي متصفح مجاني مثل فايرفوكس أو كروم. الولوج إلى ويب سنتعرف الآن على التجهيزات والخدمات الأساسية التي تحتاجها لدخول ويب. حاسوب ومودم يتطلب بناء ونشر موقع ويب إلى حاسوب بتكلفة تختلف بشدة وفقًا لميزانيك ومكان إقامتك. فإن أردت نشر موقع بسيط ستحتاج إلى حاسوب بسيط قادر على تشغيل محرر ومتصفح ويب وبالتالي ستكون تكلفته قليلة عند هذا المستوى. لكن إن أردت إنتاج تصاميم أكثر تعقيدًا لموقعك تضم صورًا مؤثرة أو أن تنتج مقاطع فيديو أو مقاطع صوتية فستحتاج إلى حاسوب أفضل. تحتاج أيضًا إلى رفع الملفات إلى خادم بعيد لذلك لا بدّ من وجود مودم Modem. يمكن لمزود خدمة الإنترنت ISP أن يمنحك اتصالًا بالإنترنت مقابل بضعة دولارات شهريًا ولكن يختلف الميزانية وفقًا لمكان إقامتك. الولوج إلى مزود خدمة انترنت تأكد من أنك تستخدم حزمة اتصال (أو حيز نطاق تراسلي) bandwidth كافي: يمكن أن يكون الولوج إلى مزود الخدمة عبر حزمة اتصال منخفضة ملائمًا لدعم موقع ويب بسيط يضم صورًا بأحجام معقولة ونصوصًا وبعض ملفات التنسيق CSS وبعض ملفات جافاسكريبت، وسيكلفك ذلك بضع عشرات من الدولارات شهريًا بما في ذلك أجرة المودم. ستحتاج في المقابل إلى حزمة اتصال عريضة مثل DSL أو خدمة الكابل أو الولوج عبر الألياف الضوئية (فايبر) إن أردت موقعًا أكبر يضم مئات الملفات، أو إن أردت تزويد متابعيك بملفات فيديو أو صوت بأحجام عالية. يمكن ألا يكلفك الأمر أكثر من كلفة الحزمة المنخفضة ويمكن أن تصل التكاليف إلى مئات الدولارات شهريًا لأغراض أكثر احترافية. استضافة موقع ويب نناقش في الفقرات القادمة ما تحتاجه من خدمات لرفع موقع على ويب وتكلفة هذه الخدمات. مفهوم عرض حزمة الاستهلاك تتعلق الكلفة التي تتقاضاها مزودات الخدمة لاستضافة موقعك بعرض الحزمة التي يستهلكها الموقع. يعتمد الأمر على عدد الأشخاص الذين يزورون موقعك وعدد روبوتات ويب التي تدخل إلى موقعك لتوثيقه خلال فترة زمنية معينة، بالإضافة إلى المساحة التخزينية التي تستهلكها ملفاتك. لهذا السبب يخزن الأشخاص مقاطع الفيديو الخاصة بهم ضمن خوادم تقدم خدمات مخصصة لهذا الأمر مثل يوتيوب وديلي موشن وفيميو. يمكن أن يقدم لك مزود الخدمة عرضًا يسمح بدخول عدة آلاف من المستخدمين يوميًا وبمقدار تبادل بيانات (عرض حزمة استهلاك) معقول، ولكن يجدر بك الانتباه إلى أن ما ذكرناه سيُفسَّر بصورة مختلفة من مزود خدمة استضافة إلى آخر. وكقاعدة أساسية توقع أن تكلفك استضافة موثوقة لاستخدام شخصي ما بين 10 إلى 50 دولار شهريًا. أسماء النطاقات لا بد من شراء اسم نطاق خاص بك من خلال مزود خاص (شركة مُسجِّلة Registart أو مسجِّل)، ويمكن أن يكون مزود خدمة الاستضافة هو أيضًا مُسجّلًا (أي الشركة تقدم خدمة حجز النطاقات والاستضافة). سيكلّفك تسجيل اسم نطاق عادةً ما بين 5-15 دولار سنويًا، وتختلف هذه الكلفة للأسباب التالية: التزامات محلية: اختيارك لأسماء نطاقات عليا تحمل اسم دولة (مثل uk.) أكثر تكلفة وتختلف من دولة لأخرى. الخدمات المرتبطة باسم النطاق: تزودك بعض الشركات المسجِّلة بخدمات مثل الحماية من الإزعاجات عن طريق حجب عنوانك البريدي وعنوان بريدك الإلكتروني خلف عناوينهم الخاصة. فلن يستسطع أحد الوصول إلى عنوانك البريد إلى عن طريق الشركة المسجلّة بينما تحجب بريدك الإلكتروني وفق آلية التقنيع التي يعتمدها المُسجِّل. استضافة موقعك بنفسك أو باستخدام خدمات الاستضافة المدفوعة بإمكانك نشر موقعك بنفسك خطوة خطوة كأن تجهز قاعدة بيانات (عند الحاجة) ونظام إدارة المحتوى CMS مثل (ووردبريس Wordpress أو دوت كلير Dotclear أو spip وغيرها) وترفع قوالب المحتويات الجاهزة أو قوالبك الخاصة. كما يمكنك استخدام بيئة التشغيل الخاصة بمزود الاستضافة مقابل 10-50 دولار شهريًا، أو أن تشترك مباشرة بمزود استضافة مخصص له نظام إدارة محتوى جاهز مثل ووردبريس Wordpress أو تمبلر Tumblr أو بلوغر Blogger). لن يكلف هذا الأخير أي شيء حرفيًا، لكنك لن تكون قادرًا على التحكم الكامل بالقوالب وغيرها من الخيارات. الاستضافة المجانية مقابل الاستضافة المدفوعة يمكن أن يخطر في ببالك أنه لم عليك أن تدفع مقابل خدمة استضافة بالرغم من وجود العديد من عروض الاستضافة المجانية؟ إليك بعض المميزات للاسضافات المدفوعة: لديك حرية أكبر عندما تدفع. سيكون موقعك ملكك، وبإمكانك نقله بسلاسة من مزود خدمة إلى آخر. يمكن أن يضيف مزودي الخدمة المجانية إعلانات إلى محتوى موقعك دون أن تتحكم بذلك. يمزج البعض بين المقاربتين السابقتين، إذ يستضيفون مثلًا المدونة الرئيسية على مزود استضافة مدفوعة وباسم نطاق مستقل وخاص بالكامل، بينما يرفعون المحتوى الأقل أهمية إلى مزود استضافة مجانية. تصميم مواقع ويب والاستضافة الاحترافية عن طريق شركات خاصة إن أردت موقع ويب احترافي فيمكن أن ترغب بتوكيل المهمة لوكالة خاصة وبالتالي ستتغير التكلفة بناء على عوامل عدة مثل: هل الموقع بسيط مكون من عدة صفحات نصية؟ أم أنه أكثر تعقيدًا ويتكون من ألف صفحة مثلًا؟ هل تريد تحديث محتواه بانتظام؟ أو سيكون موقع ويب ساكن. هل ينبغي ربط الموقع بمنظومة المعلومات الخاصة بشركتك لجمع محتوى معين (مثل البيانات الداخلية)؟ هل تريد بعض الميزات الجديدة البرّاقة التي تمثل الموضة الحالية؟ حاليًا يطلب العملاء مواقع من صفحة واحدة ذات مظهر مركب. هل ترغب أن تتولى الوكالة أمر مشاكل المستخدمين أو حل مشاكل تتعلق بتجربة المستخدم UX؟ كأن تضع لك استراتيجية لتشجيع المستخدمين أو تصميم تجربة لاختيار حل من بين عدة خيارات. فيما يتعلق بالاستضافة ستتغير التكلفة بحسب عدة عوامل منها: هل تريد خوادم احتياطية في حال توقف الخادم الأساسي عن العمل؟ هل تكفي وثوقية أداء 95% أم أنك تحتاج إلى 99% وخدمة مستمرة على مدار الساعة؟ هل تريد خادمًا مخصصًا Dedicated Server عال المواصفات فائق التجاوب أم يكفيك خادم مشترك أبطأ؟ اعتمادًا على إجاباتك على كل سؤال سيكلفك الموقع من بضع آلاف وحتى مئات آلاف الدولارات. اطلعنا في هذا المقال على التكلفة المادية لبناء موقع ويب في كل خطوة من خطوات بنائه حتى نشره، وحان الوقت لتبدأ تصميم مواقع ويب وإعداد بيئة العمل المناسبة لك. ترجمة -وبتصرف- للمقال How much does it cost to do something on the Web. اقرأ أيضًا مفهوم الروابط التشعبية في مواقع الويب ما هو عنوان URL في الويب؟ ما هي الأدوات المستخدمة في بناء مواقع ويب؟ ما هي أدوات مطوري الويب المدمجة في المتصفحات؟
  9. يمكنك تنزيل معظم البرامج التي تحتاجها لتطوير صفحات ومواقع الويب مجانًا وسنزوّدك بعدة روابط خلال هذا المقال. عمومًا ستحتاج إلى أدوات التطوير لكي: تنشئ أو تحرر صفحة ويب. رفع الملفات إلى خادم ويب. استعراض موقع ويب. تحتوي معظم أنظمة التشغيل على محرر نصي ومتصفح ويب يمكن استخدامهما لعرض مواقع الويب. وبالتالي لن تحتاج سوى برامج لنقل الملفات إلى خادم ويب. إذًا، سنتعلم في هذا المقال عن المكونات البرمجية التي تحتاجها إن أردت تحرير أو رفع أو عرض موقع ويب والتي تساعدك في عملك أثناء تطوير مواقع الويب. ننصحك قبل الشروع في قراءة المقال أن تطلع على مقال الفرق بين صفحات الويب ومواقع الويب وخوادم الويب ومحركات البحث. إنشاء وتحرير صفحات الويب تحتاج إلى محرر نصي لتتمكن من تحرير أو إنشاء صفحات الويب، تساعدك محررات النصوص على تعديل الملفات النصية غير المنسّقة إذ تسمح لك بعض أنواع محررات الملفات مثل المحررات النصية الغنية Rich Text Format واختصارًا RTF، بإضافة تنسيقات إلى الخطوط المستخدمة كتثخين الخط أو وضع سطر تحت الكلمات، ولكن بالرغم من ذلك لا تعد محررات النصوص تلك ملائمة لكتابة صفحات الويب. لهذا عليك التفكير قليلًا قبل أن تقرر ما المحرر الذي ستستخدمه لأنك ستعمل عليه كثيرًا أثناء بناء موقع الويب. تأتي معظم أنظمة التشغيل المخصصة للحواسب المكتبية مع محرر نصوص بسيط وسهل الاستخدام لكنه يفتقر إلى بعض الميزات المفيدة عند كتابة شيفرات صفحات الويب. لكن إن أردت شيئًا أكثر أناقة، فستجد الكثير من الأدوات التي توفرها شركات خارجية. تأتي محررات النصوص التي تقدمها الشركات مع ميزات إضافية كتلوين العبارات القواعدية والإكمال التلقائي للشيفرة البرمجية وإخفاء أو إظهار مقاطع محددة، والبحث في الشيفرة. إليك قائمة مختصرة ببعض المحررات: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } نظام التشغيل المحرر المدمج مع نظام التشغيل محررات يؤمنها طرف ثالث ويندوز Notepad Notepad++, Visual Studio Code, Web Storm, Brackets ShiftEdit, Sublime Text ماك أو إس TextEdit TextWrangler, Visual Studio Code, Brackets ShiftEdit, Sublime Text لينوكس Vi (All Unix) GEdit (Gnome) Kate (KDE) LeafPad (Xfce) Emacs, Vim, Visual Studio Code, Brackets ShiftEdit, Sublime Text كروم أو إس ShiftEdit إليك لقطة شاشة لأحد محررات النصوص المتقدمة: إليك أيضًا لقطة شاشة لمحرر نصوص على الويب: رفع الملفات إلى ويب عليك أن ترفع صفحات موقعك إلى خادم ويب عندما يكتمل بناؤه ويصبح جاهزًا لاتاحته للناس. يمكنك شراء مساحة تخزين من أي مزود خدمة تختاره والذي سيرسل لك بدوره -عند إكمال عملية الشراء- بريدًا إلكترونيًا يضم معلومات الوصول إلى مساحة التخزين الخاصة بك على شكل عنوان SFTP URL (عنوان يستخدم برتوكول FTP الآمن)، بالإضافة إلى اسم المستخدم وكلمة المرور وغيرها من المعلومات اللازمة للاتصال بخادم الويب. تذكر أنّ بروتوكول SFTP أصبح قديم الطراز وبدأت أنظمة رفع ملفات جديدة باكتساب شعبية مثل RSync وGit/GitHub. تُعد خطوة رفع الملفات إلى خادم الويب خطوة مهمة جدًا من خطوات بناء الموقع، إليك قائمة مختصرة لبعض البرامج المجانية التي تعمل من ناحية العميل لرفع الملفات: نظام التشغيل برمجيات FTP ويندوز WinSCP Moba Xterm (FileZilla (All OS لينوكس (Nautilus/Files (Gnome) Dolphin (KDE ماك أو إس Cyberduck كروم أو إس (ShiftEdit (All OS تصفح مواقع ويب لا بد من وجود متصفح ويب لاستعراض المواقع وستجد الكثير من الخيارات التي تلبي احتياجاتك. لكن عندما تطور موقع ويب لا بدّ من اختباره على أحد المتصفحات الرئيسية التالية لتتأكد أن موقعك سيعمل عند معظم المستخدمين: موزيلا فايرفوكس. جوجل كروم. مايكروسوفت انترنت أكسبلورر أو مايكروسوفت إيدج. آبل سفاري. فإن كنت تستهدف مجموعة محددة (منصة تقنية أو بلد محدد)، لا بدّ أن تختبر موقعك على متصفحات أخرى مثل أوبرا وKonqueror أو UC Browser. تتعقد عملية اختبار المواقع لأن بعض المتصفحات لن تعمل إلا على أنظمة تشغيل محددة. فلن يعمل آبل سفاري سوى على أنظمة تشغيل آبل أي أو إس وماك أو إس ولن يعمل إنترنت إكسبلورر سوى على ويندوز. في حالات كهذه من الأفضل استخدام خدمات مثل Browsershots أو Browserstack. إذ سيعرضُ لك موقع Browsershots لقطات شاشة لموقعك كما سيبدو على عدة متصفحات، بينما يمنحك Browserstack إمكانية الوصول الكاملة عن بعد إلى محاكيات افتراضية Virtual Machines تساعدك على تجربة موقعك على أكثر البيئات شيوعًا. يمكنك أيضًا إعداد محاكي افتراضي خاص بك، لكن الأمر سيتطلب الأمر خبرات إضافية (إن قررت المضي بهذا الخيار، تزوّدك مايكروسوفت ببعض الأدوات التي تساعدك بما فيها محاكي افتراضي جاهز للاستخدام). اختبر موقعك بشتى الوسائل على أجهزة حقيقية وخاصة أجهزة الهواتف المحمولة الحقيقية، فالمحاكيات هي تكنولوجيا جديدة لا زالت قيد التطوير لذلك فهي أقل وثوقية من محاكيات أجهزة سطح المكتب. وطالما أن أجهزة الهاتف المحمولة غالية الثمن، ننصحك أن تلق نظرة على Open Device Lab initiative. يمكنك أيضًا مشاركة الأجهزة إن أردت اختبار موقعك على منصات عدة دون أن تنفق الكثير من المال. ترجمة -وبتصرف- للمقال What software do I need to build a website. اقرأ أيضًا ما هو عنوان URL في الويب؟ ما التكلفة المادية الكاملة لبناء موقع ويب؟ ما هي محررات النصوص المستعملة في تطوير مواقع الويب؟ ما هي أدوات مطوري الويب المدمجة في المتصفحات؟
  10. قد تبدو بعض التعابير النمطية regular expressions بسيطةً لكن قد يستغرق تنفيذها وقتًا طويلًا، وقد يسبب توقف محرك JavaScript عن الاستجابة، وسيواجه المطورون عاجلًا أم آجلًا هذا السلوك، ومن أعراضه توقف استجابة محرك تعبير نمطي يعمل جيدًا في بعض الأحيان، عندما يبحث ضمن نص معين مستهلكًا موارد المعالج 100%، حيث سيقترح المتصفح في حالة مثل هذه إيقاف تنفيذ السكربت، وإعادة تحميل الصفحة، وليس جيدًا بالطبع أن يُوقف سكربت JavaScript يعمل في الواجهة الخلفية استجابة عملية من عمليات الخادم، فلا بد إذًا من إلقاء نظرة على ذلك. مشكلة انتظار انتهاء التعبير النمطي لنفترض وجود نص نريد أن نتحقق من كونه يتألف من كلمات +w\ يفصل بينها فراغات اختيارية ?s\، حيث ستكون إحدى الطرق الواضحة إنشاء تعبير نمطي يبحث عن كلمة يليها فراغ اختياري ?w+\s\، وأخيرًا نضيف المحدد الكمي * لتكرار العملية، ويقود هذا التعبير إلى استخدام التعبير $*(?w+\s\)^ الذي يبحث عن كلمة على الأقل بالمواصفات السابقة، بحيث يبدأ البحث من بداية النص ^ وينتهي بنهايته $. let regexp = /^(\w+\s?)*$/; alert( regexp.test("A good string") ); // true ناجح alert( regexp.test("Bad characters: $@#") ); // false فاشل يبدو أنّ التعبير سيعمل والنتيجة صحيحة، لكنه في نصوص معينة سيستغرق وقتًا طويلًا حتى تتوقف استجابة محرك JavaScript، وتُستهلك موارد المعالج 100%. قد لا تلاحظ شيئًا إن نفّذت المثال التالي، لأن محرك JavaScript سيتوقف عن الاستجابة، وسيتوقف المتصفح عن التجاوب مع الأحداث، وستتوقف واجهة المستخدم عن العمل (تتيح معظم المتصفحات ميزة التمرير فقط)، وسيقترح المتصفح بعد فترة إعادة تحميل الصفحة، فكن على حذر. let regexp = /^(\w+\s?)*$/; let str = "An input string that takes a long time or even makes this regexp hang!"; // سيأخذ بعض الوقت alert( regexp.test(str) ); وعلينا القول -حتى نكون منصفين- بأن بعض محركات التعابير النمطية تتعامل مع هذا النوع من البحث بفعالية، فالمحرك "V8" وابتداءً من النسخة 8.8 قادر على ذلك، فلن تتوقف استجابة المتصفح 88 Chrome في حالات مثل هذه، بينما ستتوقف استجابة متصفح Firefox. السؤال الذي طرح نفسه، ما المشكلة؟ لماذا تتوقف استجابة التعبير النمطي؟ لتوضيح ذلك دعونا نبسّط المثال السابق بإزالة الفراغات ?S\، وبالتالي سيصبح التعبير النمطي على الشكل $*(?w+\s\)^، ولتوضيح الأمر أكثر دعونا نستبدل الصنف d\ بالصنف w\، وستتوقف مع ذلك استجابة التعبير الجديد أيضًا، فمثلًا: let regexp = /^(\d+)*$/; let str = "012345678901234567890123456789z"; // انتبه، سيأخذ بعض الوقت alert( regexp.test(str) ); ما المشكلة في هذا التعبير النمطي؟ قد يلاحظ القارئ أنّ التعبير *(+d\) غريب بعض الشيء، فوجود المحدد الكمي * يبدو مبالغًا فيه، فإن أردنا عددًا يمكن استخدام d\، ومع ذلك يبدو التعبير الجديد المبسط عمليًا أكثر، لكن سبب بطئه أيضًا لم يتغير، لهذا علينا دراسته بالتفصيل للوقوف على المشكلة، فما الذي يحدث أثناء البحث عن النمط $*(+d\)^ ضمن النص 123456789z، واختُصر قليلًا للوضوح، ولماذا يستغرق الأمر وقتًا؟ إليك ما يفعله المحرك: أولًا، يحاول المحرك بدايةً البحث عن محتوى الأقواس، وهي الأعداد +d\، وطالما أنّ + محدد كمي جشع greedy افتراضيًا فسيضم كل الأرقام في النص. \d+....... (123456789)z عند ضم الأرقام جميعها يعدُّ المحرك أن البحث عن +d\ قد أنجز، وأن النتيجة هي 123456789، ثم ينتقل بعد ذلك إلى تطبيق المحدد الكمي *، لكن الأرقام في النص قد استهلكت جميعها، فلن يقدم مرتكز البداية ^ أي شيء، ثم يبحث المحرك عن آخر محارف النمط $، ولن يجده لأنّ المحرف الباقي من النص هو z: X \d+........$ (123456789)z ثانيًا، وطالما أنّ التطابق غير موجود فسينقص المُكمِّم + عدد المحارف واحدًا ويعيد البحث، لذلك ستكون نتيجة +d\ كل الأرقام عدا الأخير 12345678: \d+....... (12345678)9z ثالثًا، يحاول المحرك الآن البحث في الموقع التالي بعد 12345678، وعندها يمكن تطبيق المكمِّم *، وسيعطي النمط *(+d\) تطابقًا جديدًا وهو 9. \d+.......\d+ (12345678)(9)z ثم يحاول المحرك من جديد إيجاد آخر محرف من النمط $ فلن يجده، بل سيجد المحرف الباقي من النص، وهو z: X \d+.......\d+ (12345678)(9)z رابعًا، لن يحصل المحرك على التطابق المطلوب؛ وسيستمر في العودة والتعقب مخفضًا عدد التكرارات وهذا ما يسمى بعملية التعقب التراجعي Backtracking أو التراجع والمطابقة ببساطة، وتجري عملية التعقب التراجعي عادةً بالشكل التالي: يقلل آخر محدد كمي جشع عدد التكرارات حتى يصل إلى الحد الأدنى، ثم يأتي دور المحدد الكمي الجشع الذي يسبقه في إنقاص عدد التكرارات وهكذا، إلى أن يتقصى المحرك كل الحالات الممكنة، وإليك بعض الأمثلة عن هذه الحالات: العدد الأول مؤلف من 7 أرقام، ثم عدد برقمين: X \d+......\d+ (1234567)(89)z العدد الأول من 7 أرقام، ثم عددين كل منهما مكون من رقم واحد: X \d+......\d+\d+ (1234567)(8)(9)z العدد الأول من 6 أرقام، والثاني من ثلاثة: X \d+.......\d+ (123456)(789)z العدد الأول من 6 أرقام، يليه عددان آخران: X \d+.....\d+ \d+ (123456)(78)(9)z ويوجد عدد كبير من الاحتمالات التي نفصل فيها سلسلةً من الأرقام 123456789 إلى أعداد، ولنكون أكثر دقة توجد ‎2<sup>n</sup>-1 طريقة، حيث n هو طول سلسلة الأرقام، ففي حالة 9 أرقام -كما في حالتنا- لدينا 511 احتمال، أما في حالة 20 رقمًا فلدينا 1048575 احتمال، وبالتالي سيسبب مرور المحرك بهذه الحالات التأخير. العودة إلى الكلمات والنصوص يحدث الأمر ذاته كما في مثالنا الأول، عندما بحثنا عن كلمات باستخدام النمط $*(?w+\s\)^ ضمن النص التالي: An input that hangs!‎ والسبب طبعًا أن الكلمة +w\ قد تُمثَّل بعدد كبير من الحالات: (input) (inpu)(t) (inp)(u)(t) (in)(p)(ut) ... قد يكون عدم وجود التطابق واضحًا، لأن النص ينتهي بإشارة تعجب، لكن ما يتوقعه التعبير النمطي هو محرف كلمة w\ أو فراغ s\ في النهاية، وهذا ما لا يعرفه المحرك، إذ سيبحث عن كل الحالات التي يحتمل أن تطابق فيها النمط *(?w+\s\) كل محارف النص، بما في ذلك الحالات التي تضم الفراغ *(w+\s\) أو التي لا تضمها *(+w\)، لأن النمط ?s\ اختياري، وسيستغرق وقتًا طويلًا نظرًا لوجود عدد كبير من الحالات التي سيستكشفها المحرك، فما العمل؟ هل علينا تفعيل البحث الكسول lazy mode؟ لن يساعدنا ذلك لسوء الحظ، ستتوقف الاستجابة أيضًا إذا استبدلنا النمط ?+w\ بالنمط +w\، وسيتغير ترتيب الحالات التي سيبحث فيها المحرك فقط، وليس عددها. تتجنب بعض محركات التعبير النمطي المرور على كل الحالات من خلال بعض الاختبارات، أو استخدام وسائل أتمتة محدودة، أو قد تجعل العملية أكثر سرعةً، ومع ذلك لا تتبع معظم المتصفحات هذه الأساليب، كما أنها لا تساعد دومًا. ما هو الحل؟ توجد مقاربتان لحل المشكلة، الأولى تخفيض عدد الحالات الممكنة، فمثلًا لنجعل المساحة الفارغة إجباريةً، بجعل النمط بالشكل التالي $*w+\s)*\w\)^، أي سنبحث عن أي عدد من الكلمات التي يفصل بينها فراغ، عدا الكلمة الأخيرة فستكون اختيارية w\*، سينتهي البحث سواء وجدت أم لا، انظر إلى التعبير التالي المكافئ للسابق (يحصل على التطابقات نفسها) ويعمل جيدًا: let regexp = /^(\w+\s)*\w*$/; let str = "An input string that takes a long time or even makes this regex hang!"; alert( regexp.test(str) ); // false لماذا اختفت المشكلة؟ لأن الفراغ بين الكلمات أصبح إجباريًا، فلو حذفنا الفراغ في التعبير السابق فسيقود إلى عدد أكبر من حالات +w\ ضمن الكلمة ذاتها، إذ يمكن الحصول على الكلمة input من تكرارين +w\ بالشكل التالي: \w+ \w+ (inp)(ut) لكن النمط الجديد مختلف، فالكلمة متبوعة بفراغ حتمًا *(w+\s\)، وبالتالي لن نحصل على الكلمة من خلال تكرارين للنمط w+\s\، وبهذا لن يهدر المزيد من الوقت في البحث عن كل الحالات الممكنة للحصول على كلمة. منع التعقب التراجعي في التعابير النمطية لن تساعدنا إعادة كتابة النمط دائمًا، إذ كانت العملية سهلةً وواضحةً في المثال السابق، لكنها عادةً ليست كذلك، كما ستقود إعادة كتابة النمط إلى أنماط أكثر تعقيدًا، وهذا أمر سيء، فالتعابير النمطية معقدة بطبيعتها، لحسن الحظ توجد مقاربة بديلة تقتضي منع التعقب التراجعي backtracking للمحدد الكمي، فأصل المشكلة هو تجربة المحرًك للكثير من الحالات الخاطئة -من وجهة نظرنا طبعًا-، فمن الواضح أنّ تعقب + في النمط $*(+d\) سيسبب مشكلةً، ولن يتغير شيء إن بدّلنا النمط +d+\d\ بالنمط +d\: \d+........ (123456789)! \d+...\d+.... (1234)(56789)! وقد نرغب في مثالنا الأصلي $*(?w+\s\)^ بمنع تعقب +w\، لأنها من المفترض أن تبحث عن كلمة كاملة بأكبر طول ممكن، ولا حاجة لتخفيض عدد التكرارات، أو فصلها إلى كلمتين +w+\w\ وهكذا. تدعم محركات التعابير النمطية الحديثة المحددات الكمية الاستحواذية possessive quantifiers عن طريق إضافة الإشارة + بعد المحدد الكمي، أي نضع ++d\ بدلًا من +d\، وذلك لمنعه من الوقوع في فخ التعقب التراجعي، فالمحددات الكمية الاستحواذية أبسط من النظامية، حيث تطابق ما تستطيع من المحارف دون الوقوع في التعقب التراجعي، وسيكون البحث آنذاك أبسط. كما يوجد ما يُسمى "المجموعات الذرية الملتقطة" atomic capturing groups، وهو وسيلة لمنع التعقب التراجعي ضمن الأقواس، والخبر السيئ هو أنها غير مدعومة في JavaScript، لكن يمكن تقليدها باستخدام شرط التحقق مما يلي المطابقة lookahead transform. البحث عن الخلاص لقد وصلنا إلى موضوع متقدم فعلًا، إذ نريد منع المحددات الكمية -مثل +- من التعقب التراجعي، لأن تعقب بعض الأمور غير منطقي على الإطلاق. إنّ النمط الذي يأخذ أكبر عدد ممكن من تكرارات w\ دون تعقب تراجعي هو 1\((+w\)=?)، وبالطبع يمكن اختيار أي نمط بدل w\، وقد يبدو النمط غريبًا، لكنه في الواقع تحويل بسيط، لنصفه: سيبحث نمط البحث قُدُمًا =? عن أطول كلمة +w\ ابتداءً من الموقع الحالي. لن يتذكر المحرك محتوى ما بين القوسين المسبوق بالمحارف =?، لذلك وضعنا +w\ ضمن أقواس، ثم سيتذكر المحرك محتوى القوسين التاليين. ثم نشير إلى الأقواس الخارجية بالرقم 1. سيتقدم البحث إلى الأمام وعند وجود كلمة +w\ فسيحددها بالرقم 1\، وبكذا سنكون قد صممنا محددًا كميًا استحواذيًا من المحدد الكمي +، حيث يلتقط الكلمة +w\ كاملةً فقط، وليس جزءًا منها، فيمكن مثلًا الحصول على الكلمة Java من الكلمة JavaScript، وترك الكلمة Script لتتطابق مع بقية النمط، وإليك موازنةً بين نمطين: alert( "JavaScript".match(/\w+Script/)); // JavaScript alert( "JavaScript".match(/(?=(\w+))\1Script/)); // null في الحالة الأولى: سنحصل على الكلمة كاملةً، لكن المحدد الكمي سيتعقب بقية النمط متراجعًا محرفًا محرفًا، محاولًا إيجاد بقية النمط، ثم سينجح أخيرًا، عندما يتطابق النمط +w\ الكلمة Java. في الحالة الثانية: سيجري البحث قُدمًا وسيجد الكلمة JavaScript كاملةً، وسيحددها بالرقم 1، وبالتالي لا طريقة بعد ذلك لإيجاد الكلمة Script. يمكن استخدام تعابير نمطية أكثر تعقيدًا من w\ ضمن 1\((+w\)=?) عندما نريد منع التعقب التراجعي للمحدد الكمي +. لنكتب مثالنا الأول باستخدام التحقق مما يلي التطابق لمنع التعقب التراجعي: let regexp = /^((?=(\w+))\2\s?)*$/; alert( regexp.test("A good string") ); // true let str = "An input string that takes a long time or even makes this regex hang!"; alert( regexp.test(str) ); // false, يعمل وبسرعة وضعنا 2\ بدلًا من الرقم 1\ لوجود أقواس خارجية إضافية، كما يمكننا تسمية الأقواس أيضًا (+<word>\w>?). // ?<word>وتُسمى الأقواس كالتالي, \k<word>يشار إلى الأقواس كالتالي let regexp = /^((?=(?<word>\w+))\k<word>\s?)*$/; let str = "An input string that takes a long time or even makes this regex hang!"; alert( regexp.test(str) ); // false alert( regexp.test("A correct string") ); // true خلاصة تُسمى المشكلة التي وصفناها في هذا المقال بالتعقب التراجعي الكارثي، وغطينا طريقتين لحلها: تخفيض عدد الحالات الممكنة التي تتطابق مع نمط إلى الحد الأدنى. منع التعقب التراجعي. ترجمة -وبتصرف- للفصل Catastrophic backtracking من سلسلة The Modern JavaScript Tutorial. اقرأ أيضًا أساسيات البحث باستخدام التعابير النمطية في جافاسكربت المجموعات والمجالات في التعابير النمطية التعابير النمطية (regexp/PCRE) في PHP
  11. يمكن أن يشير المصطلح "خادم ويب Web Server" إلى العتاد الصلب أو البرمجيات، أو كلاهما معًا. من ناحية العتاد الصلب: يُعد خادم الويب حاسوبًا يُخزّن البرمجيات اللازمة لإدارة خادم الويب كما يخزّن الملفات التي تتكون منها مواقع الويب (مثل ملفات HTML وCSS وملفات جافاسكربت). يتصل خادم الويب بالإنترنت ويدعم التبادل الفيزيائي للبيانات مع الأجهزة الأخرى المتصلة بالإنترنت. من ناحية البرمجيات: يتألف خادم الويب من عدة أقسام تتحكم بكيفية دخول مستخدمي ويب إلى الملفات التي يستضيفها. يتكون خادم ويب على الأقل من خادم HTTP ويضم برمجيات قادرة على فهم عناوين ويب URL وبرتوكول HTTP (البروتوكول الذي يستخدمه المتصفح لعرض محتوى صفحات الويب). يمكن الولوج إلى خادم HTTP من خلال أسماء النطاقات الخاصة بمواقع الويب التي يُخزّنها ويعيد محتوى هذه المواقع التي يستضيفها إلى جهاز المستخدم النهائي عندما يطلبها. ولو أردنا التكلم ببساطة شديدة نقول: عندما يحتاج المتصفح إلى ملف يستضيفه خادم ويب، يطلب المتصفح هذا الملف عبر بروتوكول HTTP، وعندما يصل الطلب إلى خادم الويب الصحيح (خادم الويب كعتاد صلب)، يقبل خادم HTTP (الناحية البرمجية من خادم ويب) الطلب ويبحث عن الملف المطلوب، ويعيده إلى متصفح الخاص بالمستخدم عبر بروتوكول HTTP أيضًا. إن لم يعثر الخادم على الملف فسيستجيبُ برسالة خطأ ذات الرمز 404. ستحتاج لخادم ويب ساكن Static أو ديناميكي Dynamic لنشر موقع الويب الخاص بك. والفرق بين هذه الخوادم هو: خادم الويب الساكن: هو حاسوب مزوّد بخادم HTTP يعيد الملفات التي يستضيفها كما هي تمامًا إلى المتصفح الذي يطلبها. خادم الويب الديناميكي: يتكون من خادم ويب ساكن بالإضافة إلى برمجيات إضافية تتمثل عادة بخادم تطبيقات وقاعدة بيانات، ويُعد هذا الخادم ديناميكيًا لأن خادم التطبيقات سيُحدّثُ الملفات التي يستضيفها قبل إرسال محتوياتها إلى المتصفح عبر خادم HTTP. لكي ترى صفحة الويب بشكلها النهائي على المتصفح، سيملأ خادم التطبيقات -على سبيل المثال- قالب HTML معين بمحتويات مصدرها قاعدة بيانات ثم يرسلها. تحتوي مواقع الويب الضخمة مثل MDN أو ويكيبيديا مثلًا على آلاف صفحات الويب، وهذه المواقع مكوّنة أساسًا من عدة قوالب HTML جاهزة وقاعدة بيانات ضخمة جدًا بدلًا من آلاف مستندات HTML الجاهزة للتسليم. إذ تتيح هذه التقنية سهولة في الصيانة وتسليم المحتوى. سنتعرف في هذا المقال على ماهية خادم الويب وأنواعه ونكتسب فهمًا عامًا لآلية عمله. ننصحك قبل الشروع في قراءة هذا المقال بالاطلاع على المقال كيف تعمل شبكات الإنترنت؟ وأن تكون على دراية بالفرق بين صفحة الويب وموقع الويب وخادم الويب ومحرك البحث. الملفات المستضافة قبل أن نتعمق أكثر، لنتذكر سريعًا أن المتصفح يُرسل طلبًا إلى خادم ويب عندما يريد إحضار صفحة ويب والذي يبحث بدوره عن الملف المطلوب ضمن مخازنه. عندما يجد الخادم الملف يقرأه أو يعالجه بالطريقة المطلوبة ثم يرسله إلى المتصفح. لننظر إذًا إلى هذه الخطوات بشيء من التفصيل. يجب على خادم الويب في البداية أن يخزّن جميع الملفات المرتبطة بموقع ويب معين وتحديدًا جميع مستندات HTML والملفات المساعدة لها كملفات تنسيق الصفحات CSS، وملفات المعالجة كملفات جافاسكربت، وخطوط الكتابة والفيديوهات وغيرها. بالإمكان استضافة كل أنواع الملفات السابقة تقنيًا على حاسوبك الشخصي، لكن من الأفضل تخزينها على خادم ويب بعيد ومخصص وذلك للأسباب التالية: خوادم الويب المخصصة لاستضافة الملفات متاحة دومًا (أي في حالة عمل مستمر). خوادم الويب متصلة دومًا بالإنترنت باستثناء أوقات الصيانة وعند حدوث مشاكل آنية في منظوماتها. يبقى لخادم الويب عنوان آي بي ثابت دومًا (ما يعرف بعنوان آي بي مخصص Dedicate IP)، إذ لا تؤمن جميع مزودات خدمة الإنترنت ISPs عنوان آي بي ثابت للخطوط المنزلية. تُصان الخوادم المخصصة تقليديًا من قبل جهة مستقلة (طرف ثالث). وبالتالي فإن إيجاد مضيف جيد لملفات وموارد موقعك هي خطوة مفتاحية من خطوات بناء الموقع. تفحص الخدمات المتنوعة التي تقدمها شركات الاستضافة، واختر الشركة التي تقدم الخدمات التي تحتاجها ضمن حدود ميزانيتك فيمكن أن تكون الاستضافة مجانية ويمكن أن تصل إلى آلاف الدولارات شهريًا. عليك في الخطوة التالية أن ترفع ملفاتك إلى الخادم بعد أن تؤمن استضافة موقعك على مزود خدمة. الاتصال عبر بروتوكول HTTP يدعم خادم ويب بروتوكول النقل HTTP ويأتي الاسم كاختصار للعبارة Hypertext Transfer Protocol وهو بروتوكول نقل النصوص التشعبية. يحدد البروتوكول طريقة نقل النصوص التشعبية (مستندات ويب مترابطة) بين حاسوبين. والبروتوكول: هو مجموعة من القواعد التي يجب على حاسوبين اتباعها ليتواصلا بطريقة صحيحة. ويعدّ بروتوكول HTTP بروتوكولًا نصيًا Textual أي لا يتعلق بالحالة Stateless. عمومًا الفرق بين البروتوكول النصي وعديم الحالة هو على الشكل التالي: بروتوكول نصي Textual: جميع الأوامر على شكل نصوص يمكن للبشر قراءتها. بروتوكول عديم الحالة Stateless: لا يمكن للخادم ولا العميل أن يتذكرا أي شيء عن الاتصال السابق بينهما. فمثلًا بالاعتماد على بروتوكول HTTP لا يمكن أن يتذكر الخادم كلمة السر التي أدخلتها أو المرحلة التي وصلت إليها خلال عملية تحويل غير مكتملة، ولإدارة خدمات كهذه ستحتاج إلى خادم تطبيقات. يحدد بروتوكول HTTP قواعد واضحة لآلية التواصل بين الخادم والعميل. عليك في هذه المرحلة أن تنتبه إلى النقاط التالية: عندما يطلب المتصفح ملفًا من خادم ويب عبر بروتوكول HTTP لا بد أن يزود الخادم بعنوان URL للملف. على خادم الويب أن يجيب على كل طلب HTTP يصله برسالة خطأ على الأقل. يُعد خادم HTTP المثبت على خادم الويب مسؤولًا عن معالجة الطلبات القادمة والرد عليها، ومن مسؤولياته نذكر: يتحقق خادم HTTP عند استلام الطلب إن كان هناك تطابق بين عنوان URL وأحد الملفات التي يستضيفها الخادم. يعيد الخادم محتوى الملف المطلوب إن وجد تطابقًا، وإن لم يجد يحضّر خادم التطبيقات ملف الاستجابة اللازم لفشل الطلب. إن لم يتمكن الخادم من تنفيذ أي من الخطوتين السابقتين سيعيد رسالة خطأ إلى المتصفح، وهي عادةً رسالة الخطأ 404 الصفحة غير موجودة. يعدّ هذا الخطأ كثير الحدوث لذلك يحاول مصممو مواقع الويب بذل الجهد في إخراج صفحات الخطأ بطريقة لبقة. المحتوى الثابت والمحتوى المتغير لصفحة ويب يمكن القول أن خادم ويب قادر على التعامل مع المحتويات الثابتة والمتغيرة (الديناميكية). لكن تذكر أن مصطلح "محتوى ساكن (أو ثابت)" يعني "يقدم كما هو". لذلك ستجد أن مواقع الويب الساكنة هي الأسهل إعدادًا ونقترح أن يكون موقعك الأول موقع ويب ساكن. ويعني المصطلح "محتوى متغير" أن الخادم سيعالج هذا المحتوى أو يولّده أثناء المعالجة انطلاقًا من قاعدة بيانات. يتيح لك هذا الخيار مرونة أكثر لكن تبعاته التقنية أعقد، مما يجعل عملية بناء مواقع ديناميكية أكثر صعوبة. هناك العديد من خوادم التطبيقات وكل واحد منها له تقنيات مختلفة لذلك من الصعب أن نقترح عليك خادمًا محددًا. لأن خوادم التطبيقات مثلًا تتعلق بفئة معينة من مواقع الويب مثل المدونات أو مواقع المحتوى القابل للتغيير wikis أو مواقع التجارة الإلكترونية، بينما يكون بعضها الآخر أكثر عموميةً. خذ وقتك في إنتقاء خادم التطبيقات الذي يناسبك عندما تفكر في بناء موقع ديناميكي. إلا إذا رغبت في تعلم برمجة خوادم الويب وبناء خادمك الخاص (وهو أمر مثير بحد ذاته)، وعمومًا لا تُعد اختراع العجلة وانتق خادم تطبيقات جاهز. ترجمة -وبتصرف- للمقال What is a web server اقرأ أيضًا دورة علوم الحاسوب ماهي أسماء النطاقات في شبكة الإنترنت؟ ما هي الأدوات المستخدمة في بناء مواقع ويب؟ ما التكلفة المادية الكاملة لبناء موقع ويب؟ ما هي أدوات مطوري الويب المدمجة في المتصفحات؟
  12. يُعد عنوان URL بالإضافة إلى النص التشعبي Hypertext وبروتوكول HTTP أحد المفاهيم المفتاحية للويب فهو الآلية التي تستخدمها المتصفحات browsers للوصول أي مورد موجود في الويب. عنوان URL هو مجرّد عنوان فريد لمورد على الويب، نظريًا يدل كل عنوان URL صحيح على مورد فريد ومحدد كصفحة HTML أو ملف CSS أو صورة أو غيرها من الموارد، ولكن في واقع هناك بعض الاستثناءات، وأكثرها شيوعًا عنوان URL يشير إلى مورد لم يعد موجودًا أو تغيّر موقعه. وطالما أن المورد يُمثّل بعنوان URL والخادم هو من يتعامل مع عنوان URL فلذلك تقع على عاتق مالك الخادم مهمة إدارة الموارد وعناوين URL المرتبطة بها بعناية. سنتعرف في هذا المقال على تفاصيل عنوان URL وكيفية عمل هذه العناوين على الويب. ننصحك قبل الشروع في إكمال قراءة المقال أن تطلع على مقال كيف تعمل شبكة الإنترنت؟ وأن يكون مفهوم الروابط التشعبية واضحًا بالنسبة لك. تشريح عنوان URL إليك بعض الأمثلة عن عناوين URL: https://developer.mozilla.org https://developer.mozilla.org/en-US/docs/Learn/ https://developer.mozilla.org/en-US/search?q=URL يمكن كتابة أيًا من تلك العناوين في شريط العنوان في المتصفح لتحميل الصفحة أو المورد المرتبط به. يتكون عنوان URL من أجزاء مختلفة بعضها إلزامي وبعضها اختياري. لاحظ الأجزاء المظللة في العنوان التالي والتي تُعد الأكثر أهمية في عنوان URL: لتوضيح الفكرة يمكن أن نشبّه عنوان URL بعنوان بريدي نمطي، إذ يمثل المخطط Scheme الخدمة البريدية التي تريد استخدامها، ويمثل اسم النطاق Domain name اسم المدينة أو البلدة، وستعمل المنفذ Port عمل الرمز البريدي، وسيمثل المسار Path البناء الذي ينبغي تسليم البريد إليه. أما المعاملات Parameters فستمثل أي معلومات إضافية كرقم الشقة وستمثل المرساة Anchor مستلم الرسالة الفعلي الذي وجَّهت رسالتك إليه. بروتوكول عنوان URL وهو القسم الأول من URL ويشير إلى البروتوكول الذي ينبغي استخدامه لطلب مورد معين من الخادم (البروتوكول هو طريقة لإعداد آلية لتبادل البيانات ونقلها عبر شبكة من الحواسيب). يُستخدم عادة برتوكولي HTTP و HTTPS (النسخة الآمنة) في مواقع الويب ولا بد من مخاطبة صفحات الويب باستخدام أحدهما. مع ذلك تدرك المتصفحات تمامًا كيف تتعامل مع بروتوكولات Schemes أخرى مثل :mailto (لفتح واجهة بريد إلكتروني) فلا تتفاجأ إن رأيت بروتوكولات أخرى. التصريح Authority يأتي بعد البروتوكول التصريح ويفصل بينهما النمط //:. يتضمن التصريح في حال وجوده اسم النطاق (www.example.com مثلًا) ورقم المنفذ (80 مثلًا) يفصل بينهما الرمز :. يشير النطاق Domain إلى خادم الويب الذي يُرسل إليه الطلب ويكون عادة على شكل اسم، كما يمكن استخدام عنوان آي بي لكن استخدامه نادر وغير ملائم في معظم الأحيان. يشير المنفذ Port إلى البوابة المستخدمة للوصول إلى المورد. يُحذف المنفذ عادة عند استخدام الخادم المنافذ المعيارية للبروتوكول HTTP، إذ يستخدم المنفذ 80 لبروتوكول HTTP والمنفذ 443 لبروتوكول HTTPS عند منح الإذن بالوصول إلى المورد. ما عدا ذلك لا بد من كتابة المنفذ المستخدم. في بعض الحالات لا يستخدم URL قسم التصريح كما هو الحال في واجهات البريد الإلكتروني (mailto:foobar). إذ يحتوي URL مخططًا فقط دون تصريح، لذلك لن تجد النمط //، وإنما ستجد فقط النقطتين المتعامدتين التي تعمل فقط كفاصل بين المخطط وعنوان البريد الإلكتروني. المسار إلى مورد ويمثل الطريق للوصول إلى مورد موجود على خادم ويب (path/to/myfile.html/‎ مثلًا). مثَّلت هذه المسارات في بدايات الويب الموقع الفيزيائي لملف على خادم، لكنه حاليًا مجرد اختصار يتعامل معه الخادم بطريقة معينة للوصول إلى المورد وغالبًا لا يشير إلى المكان الحقيقي لوجود المورد. المعاملات وهي قائمة من العناصر الثنائية على شكل"مفتاح/قيمة" يفصل بينها الرمز & مثل القائمة key1=value1&key2=value2 كما في الصورة السابقة. يمكن لخادم ويب استخدام هذه المعاملات في تنفيذ عمليات إضافية قبل أن يعيد المورد المطلوب. لكل خادم ويب قواعده الخاصة المتعلقة بمعالجة المعاملات، ومن الأفضل دومًا أن تسأل مالك الخادم عن طريقة تعامل خادمه مع المعاملات. المربط يمثل المربط # (ويشار إليه المرساة أحيانًا) طريقة للاشارة إلى جزء معين من المورد نفسه، وتشبه فكرته فكرة "الاشارة المرجعية" داخل المورد نفسه. فلو كان المورد ملف HTML مثلًا، سينتقل المتصفح إلى النقطة التي يُعرّفها المربط "#"، وفي حال كان المربط يشير إلى نقطة زمنية معينة من ملفات الصوتية أو الفيديو سيحاول المتصفح الانتقال إلى الزمن الذي يحدده المربط. وتجدر الإشارة هنا، إلى أن القسم الذي يقع بعد الرمز "#" (ويُدعى "مُعرِّف القطعة Fragment Identifier") لن يُرسل أبدًا إلى الخادم مع الطلب. كيف تستخدم URL بإمكانك كتابة أي URL ضمن شريط العنوان في المتصفح لتحضر المورد الذي يمثله، لكن هذا الاستخدام ما هو إلا رأس الهرم فقط! تستخدم لغة HTML عناوين URL بكثرة لكي: تنشئ روابطًا مع مستندات أخرى باستخدام العنصر <a>. تربط مستندًا مع موارده عبر عناصر متعددة مثل <link> أو <script>. تعرض الوسائط مثل الصور (باستخدام العنصر <img>) والفيديو (باستخدام العنصر <video>) والملفات الصوتية (باستخدام العنصر<audio>). تعرض ملفات HTML أخرى باستخدام العنصر <iframe>. تستخدم التقنيات الأخرى مثل CSS وJavaScript عناوين URL بكثرة أيضًا، وهذه التقنيات هي ما تشكل الويب في الواقع. عناوين URL المطلقة والنسبية تُعد الأمثلة التي أوردناها سابقًا عن عنوان URL عناوينًا مطلقة Absolute URLs، لكن لا يزال هناك نمط آخر وهي العناوين النسبية Relative URLs ولا بدّ من الإشارة إلى الفوارق بينهما بشيء من التفصيل. تعتمد الأجزاء التي ينبغي استخدامها من عنوان URL والأخرى التي يمكن إهمالها على السياق الذي يستخدم فيه عنوان URL. فمثلًا في شريط عنوان متصفحك لا يوجب أي سياق محدد لعناوين URL لهذا لا بدّ من كتابة URL بشكله الكامل (أو المطلق) كما فعلنا في الأمثلة السابقة. لا حاجة بالطبع في حالة المتصفح أن تذكر البروتوكول لأن المتصفح يستخدم البروتوكول HTTP افتراضيًا، ولا نذكر أيضًا المنفذ الذي نحتاجه إلا في الحالة التي نتصل فيها مع الخادم عبر منفذ غير اعتيادي، ولكن لا بد من كتابة بقية أجزاء عنوان URL. عندما يُستخدم عنوان URL داخل مستند كصفحة HTML ستختلف الأمور قليلًا. إذ يمتلك المتصفح في هذه الحالة عنوان URL الخاص بالمستند ككل، وبالتالي سيتمكن من استخدام معلوماته لإكمال الأجزاء الناقصة لعنوان URL الموجود داخل المستند. يمكن التمييز بين عنوان URL المطلق والنسبي بالنظر فقط إلى جزء المسار، فإذا بدأ عنوان URL بالرمز / فسيحضر المتصفح المورد من أعلى عنوان جذري للخادم دون الحاجة إلى المكان الذي يشير إليه المستند. لنلق نظرة على بعض الأمثلة لتوضيح الأمر. أمثلة عن عناوين URL مطلقة يُعد العنوان الآتي مطلقًا أو كاملًا https://developer.mozailla.org/docs/learn بينما يعد العنوان التالي غير كامل إذ سيستخدم هذا العنوان البروتوكول الضمني للمستند الذي يتضمن عنوان URL. developer.mozilla.org/en-us/docs/Learn// أما العنوان الآتي فهو اسم نطاق ضمني، وهي الحالة الأكثر استخدامًا لعناوين URL المطلقة داخل مستندات HTML. /en-us/docs/learn/ يستخدم المتصفح في هذه الحالة نفس البروتوكول واسم النطاق المستخدمان في تحميل المستند الذي يحتوي على عنوان URL لاحظ أنه لا يمكن حذف اسم النطاق دون حذف البروتوكول أيضًا. أمثلة عن عناوين URL نسبية لتفهم الأمثلة التالية بطريقة صحيحة، سنفترض أن عناوين URL ستُستدعى من داخل المستند الموجود على عنوان URL التالي: https://developer.mozilla.org/en-us/docs/Learn يستخدم العنوان "Skills/Infrastructure/Understanding_URLs" فكرة الموارد الفرعية، فطالما أنّ عنوان URL لم يبدأ بالرمز / سيحاول المتصفح أن يجد المستند في مجلد فرعي ضمن المجلد الذي يحتوي المورد الحالي أي سنرغب في مثالنا في الوصول إلى عنوان URL التالي: https://developer.mozilla.org/en-us/docs/Learn/Skills/Infrastructure/Understanding_URLs. بينما يستخدم العنوان "‎../CSS/display" فكرة التراجع إلى الخلف في مسار الشجرة، ونستخدم في هذه الحالة النمط /.. الموروث من نظام ملفات يونكس لكي نخبر المتصفح أن ينتقل إلى المجلد الأعلى مباشرة. أي أننا نريد هنا الوصول إلى عنوان URL التالي: https://developer.mozilla.org/en-US/docs/Learn/../CSS/display والذي يمكن اختصاره إلى: https://developer.mozilla.org/en-US/docs/CSS/display عناوين URL الدلالية بالرغم من الصبغة التقنية الواضحة لهذا النوع، إلا أن عناوين URL الدلالية Semantic URLs هي طريقة دخول إلى موقع ويب معين يمكن للبشر فهمها. أي يمكن أن يحفظها المستخدم بسهولة ويدخلها بنفسه في شريط عنوان المتصفح، وطالما أنّ المستخدمين هم مركز اهتمام الويب، فمن أفضل الممارسات التي ينبغي نشرها هي بناء ما يُدعى عناوين URL واضحة ومقروءة Clean URL، وهي عناوين تستخدم كلمات في صلب موضوع محتوى العناوين يمكن لأي شخص فهمها دون أن تكون لديه أي فكرة تقنية عن كيفية إنجاز الأمر. لا علاقة بالطبع للدلالات اللغوية بالحواسيب، فلربما بدت لك عناوين URL كخليط من الرموز العشوائية، لكن هناك إيجابيات عدة لكتابة URL مقروء من قبل المستخدم منها: سهولة تعديلها. تجعل الكثير من النقاط أكثر وضوحًا للمستخدم مثل الموقع الذي يتواجد فيه وما الذي يفعله في هذا الموقع أو ما الذي يقرأه أو يتفاعل معه على الويب. يمكن لعناوين URL المقروءة أن تحسن ترتيب وتصنيف الصفحات في محركات البحث. ترجمة -وبتصرف- للمقال What is a URL. اقرأ أيضًا ما هو خادم الويب؟ ما هي الأدوات المستخدمة في بناء مواقع ويب؟ ما هي أدوات مطوري الويب المدمجة في المتصفحات؟ ما هي أسماء النطاقات في شبكة الإنترنت؟
  13. بعد أن تعرفنا على أساسيات التعابير النمطية ثم تعرفنا على المجموعات ثم المحددات الكمية ثم تعلمنا كيفية التقاط عدة مجموعات عبر التعابير النمطية، سنقدم فيما يلي مجموعةً من الأفكار المتقدمة في بناء وتنفيذ تعابير نمطية أكثر كفاءةً في البحث عن التطابقات المطلوبة، مثل المراجع References، والمحرف البديل OR، والبحث قُدُمًا lookahead، والبحث إلى الخلف lookbehind، والبحث في موقع محدد باستخدام الراية y. المراجع إلى المجموعات بالأعداد والأسماء يمكن استخدام محتويات أقواس المجموعات الملتقطة (...) في النتيجة أو في النص البديل، وحتى في النمط نفسه. المراجع باستخدام الأعداد يمكن الإشارة إلى مجموعة ضمن نمط باستخدام N\، حيث N هو رقم المجموعة، ولتوضيح أهمية هذه الإشارة المرجعية لنتأمل المهمة التالية: نريد إيجاد ما داخل إشارتي التنصيص المفردتين '...' أو المزدوجتين "..." في نص ما، فكيف سننجز ذلك؟ يمكن وضع نوعي إشارة التنصيص في أقواس مربعة ['"](?*.)['"]، لكنه في هذه الحالة سيجد محتويات مختلطةً، مثل "...' و'..."، مما سيقودنا إلى تطابقات خاطئة عندما يظهر نوع من الإشارات ضمن آخر، مثل "!She's the one". let str = `He said: "She's the one!".`; let regexp = /['"](.*?)['"]/g; // النتيجة ليست كما نتوقع alert( str.match(regexp) ); // "She' وجد النمط -كما توقعنا- إشارة تنصيص البداية "، ثم استهلك النص بعدها حتى وجد إشارة تنصيص أخرى ' أنهت التطابق، وللتأكد من مطابقة إشارة التنصيص الختامية لإشارة تنصيص البداية، يمكن وضعها ضمن قوسي مجموعة، والإشارة إليها بعدد مرجعي 1\(?*.)(["']) إليك الشيفرة الصحيحة: let str = `He said: "She's the one!".`; let regexp = /(['"])(.*?)\1/g; alert( str.match(regexp) ); // "She's the one!" سيجد محرك التعبير النمطي إشارة تنصيص البداية (["'])، ويتذكر محتواها الذي يمثل المجموعة الملتقطة الأولى، حيث يعني العدد 1\ في النمط إيجاد نفس التطابق الموجود في المجموعة الأولى، وهي في حالتنا إشارة تنصيص تطابق تمامًا إشارة البداية. وسيعني العدد 2\ محتويات المجموعة الثانية، والعدد 3\ محتويات الثالثة، وهكذا. لاحظ، لن نتمكن من الإشارة إلى مجموعة إذا استخدمنا نمط الاستثناء :?، ولن يتذكر المحرك محتوى المجموعات المستثناة (...:?). انتبه، لا تخلط بين الإشارة 1\ في نمط ما، والإشارة 1$ في النص البديل، حيث نستخدم إشارة الدولار 1$ في الإشارة المرجعية ضن النص البديل، والشرطة المعكوسة 1\ ضمن الأنماط. المراجع باستخدام الأسماء إذا احتوى التعبير النمطي على عدة أقواس، فمن الأنسب استخدام الأسماء للدلالة عليها، نستخدم <k<name\ في الدلالة على القوس بالاسم، فإذا سُميت مجموعة ضمن التعبير النمطي بالاسم <quote>?، فسيكون الاسم المرجعي لها هو <k<quote\، وإليك مثالًا: let str = `He said: "She's the one!".`; let regexp = /(?<quote>['"])(.*?)\k<quote>/g; alert( str.match(regexp) ); // "She's the one!" البديل باستخدام OR في التعابير النمطية يعني مصطلح "البديل" Alternation في التعابير النمطية استخدام العملية المنطقية "OR"، ويرمز لها ضمن التعابير النمطية بالخط العمودي |، فلو أردنا مثلًا إيجاد لغات برمجة مثل HTML أو PHP أو Java أو JavaScript، فسيكون التعبير النمطي المناسب هو ?(html|php|java(script، وإليك مثالًا تطبيقيًا: let regexp = /html|php|css|java(script)?/gi; let str = "First HTML appeared, then CSS, then JavaScript"; alert( str.match(regexp) ); // 'HTML', 'CSS', 'JavaScript' لكننا رأينا سابقًا أنّ الأقواس المربعة تنفذ أمرًا مشابهًا، فهي تسمح باختيار أحد المحارف التي توضع ضمنها، فإذا استخدمنا النمط gr[ae]y مثلًا فسنحصل على التطابقين gray أو grey، إذ تسمح الأقواس المربعة باستخدام المحارف أو أصناف المحارف ضمنها، بينما يسمح البديل باستخدام أي عبارات، حيث يعني التعبير A|B|C أيًا من العبارات A أو B أو C، وإليك بعض الأمثلة: يماثل النمط gr(a|e)y النمط gr[ae]y. يعني النمط gra|ey أيًا من gra أو ey. ولتطبيق البديل على جزء محدد من نمط، يمكن وضع هذا الجزء داخل قوسين: يطابق النمط I love HTML|CSS كلًا من I love HTML أو CSS. يطابق النمط (I love (HTML|CSS كلًا من I love HTML أو I love CSS مثال: تعبير نمطي لإيجاد الوقت صادفنا في المقالات السابقة مهمة بناء تعبير نمطي يبحث عن الوقت وفق التنسيق hh:mm، مثل 12:00، لكن التعبير الذي استُخدم d\d:\d\d\ سطحي جدًا، إذ يقبل هذا النمط قيمًا خاطئة للتوقيت مثل 25:99، فكيف سننجز نمطًا أفضل؟ بالنسبة للساعات: إذا كان الرقم الأول 0 أو1 فيمكن أن يكون الثاني أي رقم. إذا كان الرقم الأول 2، فيجب أن يكون الثاني [‎0-3]. لا يسمح بأي رقم آخر غير ذلك. يمكن كتابة تعبير نمطي يضم الحالتين باستخدام البديل بالشكل التالي: [01]\d|2[0-3] أما بالنسبة للدقائق: ينبغي أن تكون الدقائق بين 00 و59، ويكتب هذا في التعبير النمطي بالشكل ‎[0-5]\d، أي يمكن أن تكون الآحاد أي رقم، والعشرات من 1 إلى 5. وعند ضم الساعات والدقائق معًا سنحصل على التعبير: [01]\d|2[0-3]:[0-5]\d انتهينا تقريبًا لكن مع وجود مشكلة صغيرة، إذ وضعنا محرف البديل | بالشكل السابق فصل التعبير إلى قسمين منفصلين: [01]\d | 2[0-3]:[0-5]\d إليك ما سيحدث، سيبحث النمط عن أحد النمطين، لكن هذا خاطئ، لأنّ البديل سيستخدَم فقط في قسم الساعات من التعبير النمطي، وسنصلح ذلك بوضع قسم الساعات ضمن قوسين ([01]\d|2[0-3]):[0-5]\d إليك الحل النهائي: let regexp = /([01]\d|2[0-3]):[0-5]\d/g; alert("00:00 10:10 23:59 25:99 1:2".match(regexp)); // 00:00,10:10,23:59 التحقق مما يلي أو يسبق التعبير النمطي نحتاج في بعض الأحيان إلى إيجاد تطابقات بشرط أن يأتي بعدها أو قبلها تطابقًا أو نمطًا محددًا دون أن تدخل تلك التطابقات ضمن قيم النتيجة النهائية، ولهذه الغاية سنجد صيغتا تحقق تُدعيان "انظر أمام النمط" lookahead،" وانظر خلف النمط "lookbehind،" وقبل أن نبدأ موضوعنا، سنأخذ مثالًا نحاول فيه إيجاد السعر ضمن النص ‎1 turkey costs 30€، وهو عدد تتبعه الإشارة €. انظر أمام التعبير النمطي النمط (X(?=Y يعني "ابحث عن X، لكن أعد نتيجة التطابق فقط إذا كان بعدها Y"، ويمكن أن تجد أي نمط مكان X أو Y، فمن أجل عدد صحيح تتبعه الإشارة €، سيكون النمط المناسب هو (€=?)+d\: let str = "1 turkey costs 30€"; alert( str.match(/\d+(?=€)/) ); // 30, € يهمل الرقم 1 لأنه غير متبوع بالإشارة لاحظ أنّ مطابقة ما أمام النمط هو اختبار وعملية تحقيق فقط ببساطة، ولا يشكل محتوى ما بين القوسين جزءًا من النتيجة، فعندما نبحث عن النمط (X(?=Y، فسيجد المحرك X ومن ثم يتحقق من وجود Y بعدها مباشرةً إن وجده أعاد X فقط وإلا لم يعد شيئًا، ثم يتابع البحث. يمكن كتابة اختبارات أكثر تعقيدًا، مثل النمط (x(?=y)(?=z الذي يعني: جد X. تحقق من وجود Y مباشرةً بعد X، وتجاوز التطابق إن لم يتحقق ذلك. تحقق أيضًا من وجود Z مباشرةً بعد X، وتجاوز التطابق إن لم يتحقق ذلك. إذا نجح الاختباران السابقان فأعد قيمة X، وإلا فتابع البحث. أي أننا نبحث عن X التي تتبعها القيمتان Y وZ في نفس الوقت. وسيبحث النمط (d+(?=\s)(?=.*30\ عن عدد +d\ يتبعه فراغ (s\=?)، ثم العدد 30 في مكان ما من النص: let str = "1 turkey costs 30€"; alert( str.match(/\d+(?=\s)(?=.*30)/) ); // 1 التطابق الوحيد المناسب في المثال السابق هو 1. لنفترض بأننا سنحتاج إلى الكمية وليس السعر من النص نفسه، وبالتالي سنحتاج إلى عدد +d\ غير متبوع بالإشارة €، يمكن إنجاز ذلك باستعمال النمط الاختباري (x(?!y، أي "انظر أمام النمط، يجب أن لا يتحقق الشرط" بمعنى ابحث عن X التي لا يتبعها Y مباشرةً. let str = "2 turkeys cost 60€"; alert( str.match(/\d+\b(?!€)/g) ); // 2 (the price is not matched) انظر خلف التعبير النمطي يشابه هذا النمط نمط التحقق مما يلي التعبير، لكنه يضع شرطًا على ما قبل التعبير المتطابق ويمكن أن نستخدمه بالصيغ التالية: "التحقق من مطابقة ما يسبق التعبير" Positive lookbehind عبر الصيغة Y)X=>?): أوجد X إذا سبقتها Y. "التحقق من عدم مطابقة ما يسبق التعبير" Negative lookbehind عبر الصيغة Y)X!>?): أوجد X إذا لم تسبقها Y. لنغير على سبيل المثال السعر إلى دولار، حيث تكون إشارة الدولار $ عادةً قبل السعر، فللبحث عن 30$ سنستخدم النمط +d\($\=>?): let str = "1 turkey costs $30"; // \$ سنتجاوز الإشارة alert( str.match(/(?<=\$)\d+/) ); // 30 وإذا أردنا الكمية، فسنبحث عن عدد لا تسبقه الإشارة $، وبالتالي نستخدم البحث السلبي خلفًا +d\($\!>?): let str = "2 turkeys cost $60"; alert( str.match(/(?<!\$)\b\d+/g) ); // 2 إدخال الشرط ضمن نتيجة التطابق لا يظهر محتوى ما بين القوسين جزءًا من النتيجة عادةً، فلن تكون الإشارة € مثلًا ضمن نتيجة التطابق مع النمط (€=?)+d\. وهذا أمر طبيعي، لأننا نبحث عن العدد الذي قبلها، وهي مجرد اختبار، لكن قد نحتاج في بعض الحالات إلى ما حول التطابق أو إلى جزء منه، ويمكن إنجاز ذلك بوضع الجزء المطلوب ضمن قوسين إضافيين، سنعيد في المثال التالي السعر مع إشارة العملة (kr|€): let str = "1 turkey costs 30€"; let regexp = /\d+(?=(€|kr))/; // €|kr أقواس إضافية حول alert( str.match(regexp) ); // 30, € إليك مثالًا مع البحث خلفًا: let str = "1 turkey costs $30"; let regexp = /(?<=(\$|£))\d+/; alert( str.match(regexp) ); // 30, $ الراية y والبحث في موقع محدد تسمح الراية y بالبحث في موقع محدد ضمن النص الأصلي، ولفهم عمل هذه الراية وأساليب استخدامها في التعابير النمطية جيدًا سنطرح مشكلةً عمليةً، حيث تعتبر عملية التحليل التجريدي لنص lexical analysis من المهام الأساسية لمحركات التعابير النمطية، ففي نصوص الشيفرة في لغات البرمجة تلعب محركات التعابير الدور الأساسي في إيجاد العناصر البنيوية، مثل وسوم HTML والسمات التي في داخلها، وستساعد في JavaScript على إيجاد المتغيرات والدوال وغيرها، ولن ندخل في موضوع إنشاء المحللات التجريدية فهي خارج نطاق موضوعنا، لكن توجد مهمة مشتركة وهي إيجاد شيء ما في موقع محدد، لنفترض مثلًا أنّ لدينا الشيفرة التالية "let varName = "value في صيغة نص، ونحتاج إلى تحديد اسم المتغير الذي سيبدأ في الموقع الرابع، سنبحث عن اسم المتغير من خلال التعبير +w\، وطبعًا نحتاج إلى تعابير أكثر تعقيدًا للبحث الدقيق عن أسماء المتغيرات في JavaScript لكن لن نهتم بذلك حاليًا. سيجد التابع (/+str.match(/\w الكلمة الأولى فقط في السطر وهي (let)، وطبعًا ليست هي الكلمة المطلوبة. ولو استخدمنا الراية g فسيبحث التابع عن جميع الكلمات في النص، لكننا لا نحتاج سوى الكلمة الموجودة في الموقع الرابع. كيف سنبحث عن نمط محدد ابتداءً من موقع محدد؟ لنحاول استخدام التابع (regexp.exec(str، حيث سيبحث هذا التابع عن التطابق الأول بطريقة مشابهة للتابع (str.match(regexp عندما يُستخدم دون الرايتين g أو y، لكنه سيبحث في النص ابتداءً من الموقع المخزن في الخاصية regexp.lastIndex عندما نفعّل الراية g، فإذا وجد تطابقًا فسيخزن الموقع الذي يلي التطابق في الخاصية regexp.lastIndex، أي ستكون الخاصية regexp.lastIndex نقطة بداية للبحث، وسيغير كل استدعاء للتابع (regexp.exec(str قيمتها إلى القيمة الجديدة -بعد إيجاد تطابق-، وبالتالي سيعيد الاستدعاء المتكرر للتابع (regexp.exec(str التطابقات واحدًا تلو الآخر، وإليك مثالًا: let str = 'let varName'; // لنبحث عن كل الكلمات في هذه السلسلة let regexp = /\w+/g; alert(regexp.lastIndex); // 0 ( lastIndex=0) let word1 = regexp.exec(str); alert(word1[0]); // let (الكلمة الأولى) alert(regexp.lastIndex); // 3 (الموقع بعد التطابق) let word2 = regexp.exec(str); alert(word2[0]); // varName (الكلمة الثانية) alert(regexp.lastIndex); // 11 (الموقع بعد التطابق) let word3 = regexp.exec(str); alert(word3); // null (لا تطابقات) alert(regexp.lastIndex); // 0 (يصفر قيمة الخاصية) ويمكن الحصول على كل التطابقات من خلال حلقة: let str = 'let varName'; let regexp = /\w+/g; let result; while (result = regexp.exec(str)) { alert( `Found ${result[0]} at position ${result.index}` ); // Found let at position 0, then // Found varName at position 4 } يمثل استخدام التابع regexp.exec أسلوبًا بديلًا عن str.matchAll مع بعض السيطرة على مجرى العملية. بالعودة إلى مهمتنا، سنتمكن من تحديد الموقع بإسناد القيمة 4 إلى الخاصية lastIndex لنبدأ البحث من الموقع المطلوب بالشكل التالي: let str = 'let varName = "value"'; let regexp = /\w+/g; // "g" دون استخدام lastIndex يتجاهل المحرك الخاصية regexp.lastIndex = 4; let word = regexp.exec(str); alert(word); // varName لقد حُلِّت المشكلة! والنتيجة صحيحة، لكن ينبغي أن نتروّى قليلًا.. يبدأ التابع regexp.exec البحث انطلاقًا من الموقع lastIndex، ثم يستأنف البحث، فإذا لم يكن التطابق موجودًا في هذا الموقع بل في موقع يأتي بعده فسيجده أيضًا: let str = 'let varName = "value"'; let regexp = /\w+/g; // ابدأ البحث في الموقع 3 regexp.lastIndex = 3; let word = regexp.exec(str); // سيجد التطابق في الموقع 4 alert(word[0]); // varName alert(word.index); // 4 إنّ هذا الأمر خاطئ في العديد من المهام ومنها التحليل التجريدي، إذ يجب إيجاد التطابق في الموقع المحدد تمامًا وليس بعده، وهذا سبب وجود الراية y. حيث تجبر الراية y التابع regexp.exec على البحث في الموقع lastIndex بالتحديد وليس انطلاقًا منه. إليك مثالًا: let str = 'let varName = "value"'; let regexp = /\w+/y; regexp.lastIndex = 3; alert( regexp.exec(str) ); // null (يوجد فراغ في هذا الموقع وليس كلمة) regexp.lastIndex = 4; alert( regexp.exec(str) ); // varName (الكلمة في الموقع 4) لاحظ أننا لن نحصل على التطابق مع التعبير w+/y\/ في الموقع 3 (على عكس g) لكن في الموقع 4، وليس هذا فحسب، بل توجد فائدة أخرى لاستخدام الراية y، تخيل أن لدينا نصًا طويلًا ولا توجد فيه أية تطابقات للنمط الذي نبحث عنه، سيبحث المحرك عند تفعيل الراية g حتى نهاية النص ولن يجد نتيجةً، وهذا ما سيستهلك الوقت مقارنةً باستخدام الراية y التي تتحقق فقط في الموقع المحدد. سنواجه في المهام التي تشبه التحليل التجريدي عمليات بحث متعددةً في مواقع محددة، للتحقق مما هو موجود، وسيكون استخدام الراية y المفتاح لإنجاز مثل هذه العمليات بدقة وفعالية. خلاصة يفيدنا التحقق مما يلي التطابق ويسبقه في إيجاد تطابق بناءً على ما قبله أو بعده. يمكن استخدام تعابير نمطية بسيطة لإنجاز ذلك يدويًا، كأن نبحث عن كل التطابقات المطلوبة ونرشحها من خلال الحلقات وفق السياق المطلوب. تذكر أن التابع str.match (مع الراية g) والتابع str.match (دائمًا) سيعيدان مصفوفةً لها الخاصية index، وبالتالي سنعلم تمامًا موقع التطابق في النص، ثم نتحقق مما قبله أو بعده. إذا نفِّذ البحث خلفًا أو قدمًا آليًا فسيكون أفضل من الطريقة اليدوية، مثلما فعلنا في هذا المقال: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } النمط نوع البحث ماذا يُطابق؟ (X(?=Y بحث إيجابي قُدمًا X إذا جاءت بعدها Y (X(?!Y بحث سلبي قدمًا X إذا لم تكن بعدها Y y)x=>?) بحث إيجابي خلفًا X إذا جاءت بعد Y y)x!>?) بحث سلبي خلفًا X إذا لم تأت بعد Y تجبر الراية y التابع regexp.exec على البحث في الموقع lastIndex بالتحديد وليس انطلاقًا منه. مهام لإنجازها إيجاد لغات البرمجة اكتب تعبيرًا نمطيًا يبحث عن أسماء لغات البرمجة الموجودة في النص Java JavaScript PHP C++ C let regexp = /your regexp/g; alert("Java JavaScript PHP C++ C".match(regexp)); // Java JavaScript PHP C++ C الحل: تقتضي الفكرة الأولى بترتيب اللغات بحيث يفصل بينها المحرف|، لكن هذا الحل لن ينفع: let regexp = /Java|JavaScript|PHP|C|C\+\+/g; let str = "Java, JavaScript, PHP, C, C++"; alert( str.match(regexp) ); // Java,Java,PHP,C,C سيبحث محرك التعابير النمطية عن البدائل واحدًا تلو الآخر، فلو تحقق بداية من "Java" ووجدها، فلن يجد بالطبع "JavaScript" وكذلك الأمر بالنسبة للغتين "C" و "++C". هنالك حلين للمشكلة: غير ترتيب اللغات لتكون اللغة ذات الاسم الأطول أولًا: JavaScript|Java|C\+\+|C|PHP ادمج اللغات التي لها نفس البداية : Java(Script)?|C(\+\+)?|PHP إليك الشيفرة: let regexp = /Java(Script)?|C(\+\+)?|PHP/g; let str = "Java, JavaScript, PHP, C, C++"; alert( str.match(regexp) ); // Java,JavaScript,PHP,C,C++ إيجاد زوجي وسوم [tag]…[/tag] لنفترض وجود زوج الوسوم [tag]...[/tag]، حيث يمثّل tag أحد العناصر b أو url أو quote، إليك مثالًا: [b]text[/b] [url]http://google.com[/url] قد تكون هذه الوسوم متداخلةً، لكن لا يمكن أن يتداخل العنصر مع نفسه: Normal: [url] [b]http://google.com[/b] [/url] [quote] [b]text[/b] [/quote] Can't happen: [b][b]text[/b][/b] ليس بالضرورة أن تكون وسوم البداية والنهاية لعنصر على نفس السطر: [quote] [b]text[/b] [/quote] اكتب تعبيرًا نمطيًا للبحث عن تلك الوسوم ومحتوياتها، إليك مثالًا: let regexp = /your regexp/flags; let str = "..[url]http://google.com[/url].."; alert( str.match(regexp) ); // [url]http://google.com[/url] إذا كانت الوسوم متداخلةً فنريد فقط العنصر الخارجي: let regexp = /your regexp/flags; let str = "..[url][b]http://google.com[/b][/url].."; alert( str.match(regexp) ); // [url][b]http://google.com[/b][/url] الحل: يُعطى التعبير النمطي للبحث عن وسم البداية بالشكل: \[(b|url|quote)] ولإيجاد المحتوى كاملًا حتى بلوغ وسم النهاية سنستخدم النمط ?* مع الراية s لالتقاط أي محرف بما في ذلك محرف بداية السطر ثم سنضيف مرجعًا للخلف إلى وسم النهاية. \[(b|url|quote)\].*?\[/\1] إليك الشيفرة: let regexp = /\[(b|url|quote)].*?\[\/\1]/gs; let str = ` [b]hello![/b] [quote] [url]http://google.com[/url] [/quote] `; alert( str.match(regexp) ); // [b]hello![/b],[quote][url]http://google.com[/ur إيجاد ما بين إشارتي التنصيص "…." أنشئ تعبيرًا نمطيًا لإيجاد سلسلة نصية بين إشارتي تنصيص"….". يجب أن يدعم النص فكرة تجاوز المحارف تمامًا كما في جافا سكربت. أي يمكن أن نضع علامة التنصيص بالشكل "\ وأن نضع علامة السطر الجديد بالشكل n\ والشرطة المائلة بالشكل \\. let str = "Just like \"here\"."; وانتبه إلى أن علامة التنصيص التي يجري تجاوزها "\ لن تعتبر نهاية للسلسلة النصية. وبالتالي لا بدّ من البحث من إشارة تنصيص إلى أخرى متجاهلين علامات التنصيص التي يجري تجاوزها. أمثلة عن نصوص وتطابقاتها: .. "test me" .. .. "Say \"Hello\"!" ... (داخلها علامة تنصيص جرى تجاوزها) .. "\\" .. (داخلها شرطة مائلة مزدوجة) .. "\\ \"" .. (داخلها شرطة مائلة مزدوجة وعلامة تنصيص جرى تجاوزها) لا بد في جافاسكربت من مضاعفة الشرطات المائلة لتمريرها إلى النصوص كالتالي: let str = ' .. "test me" .. "Say \\"Hello\\"!" .. "\\\\ \\"" .. '; // the in-memory string alert(str); // .. "test me" .. "Say \"Hello\"!" .. "\\ \"" .. الحل: /"(\\.|[^"\\])*"/g نتبع الآتي خطوةً بخطوة: نبحث أولًا عن إشارة تنصيص البداية ". إن كان هناك شرطة عكسية \\ لا بد من مضاعفتها في التعبير لأنها محرف خاص. بعدها يمكن أن يأتي أي محرف. باستثناء الحالتين السابقتين يمكن أن نأخذ أية محارف ما عدا إشارة التنصيص (التي تعني نهاية النص) والشرطة العكسية (تستخدم الشرطة العكسية فقط مع رموز أخرى بعدها لمنع ظهورها مفردة): [^"\\] وهكذا حتى نصل إلى إشارة تنصيص نهاية النص. إليك الشيفرة: let regexp = /"(\\.|[^"\\])*"/g; let str = ' .. "test me" .. "Say \\"Hello\\"!" .. "\\\\ \\"" .. '; alert( str.match(regexp) ); // "test me","Say \"Hello\"!","\\ \"" إيجاد وسم بأكمله اكتب تعبيرًا نمطيًا لإيجاد الوسم <style> كاملًا. قد لا يضم الوسم أية صفات attributes أو عددًا منها: <style type="..." id="..."> لا يجب أن يطابق التعبير الوسم <styler> مثلًا: let regexp = /your regexp/g; alert( '<style> <styler> <style test="...">'.match(regexp) ); // <style>, <style test="..."> الحل: من المؤكد أن بداية النمط هي <style. لكن لا يمكن أن تكون بقية النمط ببساطة <?*.style> لأن وسمًا مثل <styler> سيكون نتيجة محتملة. نحتاج إلى فراغ بعد <style ثم محارف اختيارية بعده أو النهاية، وبالتالي سيكون النمط المطلوب: <style(>|\s.*?>) إليك الشيفرة: let regexp = /<style(>|\s.*?>)/g; alert( '<style> <styler> <style test="...">'.match(regexp) ); // <style>, <style test إيجاد أعداد صحيحة موجبة لدينا سلسلة نصية من الأعداد الصحيحة . أنشئ تعبيرًا نمطيًا يبحث عن الأعداد الموجبة فقط (يُسمح بالتقاط الصفر) مثال عن الاستخدام: let regexp = /your regexp/g; let str = "0 12 -5 123 -18"; alert( str.match(regexp) ); // 0, 12, 123 الحل: التعبير النمطي المناسب لإيجاد عدد صحيح هو : \d+ يمكن التخلص من الأعداد السالبة باستخدام النظر خلفًا إلى الإشارة السالبة : (?<!-)\d+ لو استخدمنا هذا النمط فقد نلاحظ ظهور نتيجة إضافية: let regexp = /(?<!-)\d+/g; let str = "0 12 -5 123 -18"; console.log( str.match(regexp) ); // 0, 12, 123, 8 كما ترى فقد وجد 8 بدلًا من -18. لحل المشكلة، لا بدّ من التحقق أن التعبير النمطي لن يبدأ المطابقة من منتصف رقم آخر غير مطابق. يمكن إنجاز الأمر بتخصيص عملية بحث أخرى للخلف عن الإشارة السالبة : (?<!-)(?<!\d)\d+ يتحقق النمط (?<!\d) أن المطابقة لن تبدأ بعد رقم آخر، بل فقط ما نحتاجه، ويمكن ضمهما أيضًا في عملية بحث للخلف واحدة: . let regexp = /(?<![-\d])\d+/g; let str = "0 12 -5 123 -18"; alert( str.match(regexp) ); // 0, 12, 123 إضافة شيفرة بعد الوسم Head لدينا نص ضمن مستند HTML. اكتب تعبيرًا نمطيًا يدخل الشيفرة <h1>Hello</h1> بعد الوسم <body> مباشرة ولا تنس أنّ هذا الوسم قد يحوي صفات داخله. إليك مثالًا: let regexp = /your regular expression/; let str = ` <html> <body style="height: 200px"> ... </body> </html> `; str = str.replace(regexp, `<h1>Hello</h1>`); يجب أن تكون قيمة str بعد ذلك : <html> <body style="height: 200px"><h1>Hello</h1> ... </body> </html> الحل: علينا أولًا إيجاد الوسم <body>وذلك باستخدام التعبير النمطي: <body.*?> لا حاجة لتعديل الوسم <body> بل فقط إضافة النص بعده. إليك ما يمكن فعله: let str = '...<body style="...">...'; str = str.replace(/<body.*?>/, '$&<h1>Hello</h1>'); alert(str); // ...<body style="..."><h1>Hello</h1>... يعني النمط في النص المُستبدل التطابق الذاتي أي الجزء من النص الأصل المرتبط بالتعبير النمطي <?*. body> حيث سيُستبدل بنفسه إضافة إلى "<h1>Hello</h1>". يقتضي الحل البديل استخدام البحث خلفًا: let str = '...<body style="...">...'; str = str.replace(/(?<=<body.*?>)/, `<h1>Hello</h1>`); alert(str); // ...<body style="..."><h1>Hello</h1>... لاحظ وجود جزء البحث خلفًا فقط في هذا التعبير النمطي حيث يعمل كالتالي: تحقق عند كل موقع في النص إن تبعه النمط <?*. body>. إن كان الأمر كذلك فقد حصلنا على التطابق. لن يُعاد الوسم <?*. body> وستكون النتيجة نصًا فارغًا يتطابق الموقع الذي يتبعه النمط <?*. body>. عندها سيُستبدل النص الفارغ بالنمط <?*. body> يليه النص <h1>Hello</h1>. يمكن الاستفادة من الرايات s و i في النمط كالتالي: /<body.*?>/si تدفع الراية s المحرف "." إلى مطابقة سطر جديد وتدفع الراية i النص <body> لمطابقة النص <BODY> (تحسس لحالة الأحرف). ترجمة -وبتصرف- للفصول Backreferences in Patten وAlternation OR وlookahead and lookbehind وsticky flag y, searching at position من سلسلة The Modern JavaScript Tutorial اقرأ أيضًا التعابير النمطية Regular Expressions في جافاسكريبت مقدمة في التعابير النمطية Regular Expressions التعابير النمطية (regexp/PCRE) في PHP
  14. تُعد أسماء النطاقات جزءًا مفتاحيًا من أجزاء البنية التحتية للإنترنت، فهي التي تزوّد المستخدم بعناوين مقروءة لأي خادم ويب موجود على الإنترنت. يمكن الوصول إلى أي حاسوب متصل بالإنترنت من خلال عنوان آي بي IP Address سواء بنسخته الرابعة IPv4 (مثل 173.194.121.32) أو السادسة IPv6 (مثل 2027:0da8:8b73:0000:0000:8a2e:0370:1337 ). يمكن أن تتعامل الحواسيب مع هذه العناوين بسهولة، ولكن الأمر صعب بالنسبة للمستخدم الذي يحاول إيجاد من يدير الخادم أو ما هي الخدمات التي يقدمها موقع ويب، فعناوين آي بي صعبة التذكر ويمكن أن تتغير مع الوقت. لحل هذه الإشكالات نستخدم عناوين سهلة على المستخدمين ومقروءة تدعى أسماء النطاقات. إذًا، نهدف في هذا المقال إلى التعرف على مفهوم اسم النطاق Domain Name وكيف يعمل وأهميته في تقانة الويب. ننصحك قبل الشروع في قراءة المقال أن تطلع على مقال كيف تعمل شبكات الإنترنت؟، وأن تكون تفاصيل عنوان URL واضحة بالنسبة لك. بنية أسماء النطاقات يتكون اسم النطاق من بنية بسيطة مكونة من عدة أجزاء، ويمكن تتكون من جزء واحد فقط أو اثنين أو ثلاثة …إلخ، وتفصل بينها نقاط وتقرأ من اليمين إلى اليسار: يزودنا كل جزء من هذه الأجزاء بمعلومات محددة عن اسم النطاق عمومًا. نطاق المستوى الأعلى TLD توضح نطاقات المستويات الأعلى Top-Level Domain واختصارًا TLD الغاية من الخدمة التي يقدمها النطاق عمومًا. لا تتطلب أكثر النطاقات العليا شيوعًا (com. وorg. وnet.) أية خدمات ويب لتحقق معايير محددة، بالمقابل تطبق بعض النطاقات العليا الأخرى سياسات أكثر صرامة، وبالتالي ستكون الغاية من استخدام هذه النطاقات واضحة أكثر. يمكن أن تفرض النطاقات العليا المحلية (الخاصة بالدول) مثل us. أو fr. أو se. أن تكون الخدمات أو الموارد بلغة محددة، أو مُستاضفة في بلد محدد، بينما لا يُسمح باستخدام النطاقات العليا gov. إلّا للمنظمات الحكومية، وكذلك الأمر بالنسبة للنطاقات التي تتضمن edu، فهي مسموحة للاستخدام مع المؤسسات التعليمية والأكاديمية فقط. تتكون أسماء النطاقات العليا من 36 محرفًا كحد أقصى علمًا أن معظمها مكون من محرفين أو ثلاثة، كما يمكن أن تضم محارفًا خاصة مثل الأحرف اللاتينية. يمكنك الاطلاع على القائمة الكاملة بأسماء النطاقات العليا على موقع ICANN. العنوان (أو المكون) تأتي العناوين بعد أسماء النطاقات العليا مباشرة على شكل سلسلة من المحارف غير الحساسة لحالة الأحرف والتي يمكن أن يتراوح عددها بين محرف وحتى 63 محرفًا. تتضمن هذه المحارف الحروف الأبجدية اللاتينية من A حتى Z والأرقام من 0 حتى 9 والمحرف - الذي لا يجوز أن يتواجد في بداية أو نهاية سلسلة المحارف. يمكن أن يكون العنوان على سبيل المثال a أو 97 أو hello-strange-person-16-how-are-you. يُدعى العنوان الأقرب إلى النطاق الأعلى بنطاق المستوى الثاني Secondary Level Name واختصارًا SLD، ويمكن لاسم النطاق أن يضم عدة عناوين (أو مكونات). ليس من الضروري إطلاقًا أن يتكون اسم النطاق من ثلاثة عناوين، فاسم النطاق www.inf.ed.ac.uk هو اسم صحيح، كما أن اسم النطاق hsoub.com صحيح أيضًا. وتجدر الإشارة إلى إمكانية إنشاء نطاقات فرعية Subdomains وهي مواقع ويب لها محتوياتها الخاصة ضمن الموقع ذاته باستخدام العناوين كالتالي: Academy.hsoub.com أو accounts.hasoub.com. شراء اسم نطاق بعد أن تعرفنا على هيكلية أسماء النطاقات لنتعرف كيف يمكننا شراء نطاق معين. من يمتلك أسماء النطاقات؟ يمكن شراء أي اسم نطاق غير محجوز وفي حال كان اسم نطاق مستخدم بالفعل فلا يمكنك شراءه حتى يتخلى صاحبه عنه، بالاضافة إلى ذلك لا يمكننا شراء النطاق إلى الأبد لأن ذلك سيؤدي لامتلاء الويب بأسماء غير مستخدمة ومغلقة لا يمكن استخدامها مجددًا. بدلًا من شراء أسماء النطاقات للأبد يمكنك دفع مبلغ معين مقابل حصولك على حق استخدام اسم النطاق الذي تريده لمدة زمنية محددة (عام أو أكثر)، كما يمكنك تجديد حق الاستخدام والذي سيمنح الأولوية لطلبك على طلبات الآخرين، ولكن تذكر بأنك لا تملك اسم النطاق هذا للأبد. تستخدم بعض الشركات التي تُدعى "مُسجِّلات Registrar" سجلات أسماء النطاقات لتتبع المعلومات التقنية والإدارية التي تربطك باسم النطاق الذي تحجزه. العثور على اسم نطاق لتتأكد أن اسم النطاق الذي تختاره متاح للاستخدام أم محجوز اتبع الخطوات التالية: ادخل على موقع شركة مسجّلة فهي تقدم خدمة تدعى “whois” أو "هو إز" تخبرك عن توفر اسم نطاق معين أم لا. إن كنت تستخدم نظام تشغيل مزوّد بمفسّر أوامر Shell، افتح المفسر واكتب الأمر whois يتبعه اسم النطاق ثم اضغط الزر "Enter". إليك مثالًا عمليًا وليكن اسم النطاق الذي نريد البحث عنه هو hsoub.com سيكون الأمر والنتيجة على الشكل التالي: $ whois Hsoub.com Domain Name: HSOUB.COM Registry Domain ID: 1623716742_DOMAIN_COM-VRSN Updated Date: 2019-09-29T14:11:16Z Creation Date: 2010-11-03T21:39:38Z Registrar Registration Expiration Date: 2028-11-03T21:39:38Z Registrar: Name.com, Inc. Registrar IANA ID: 625 Reseller: Domain Status: clientTransferProhibited Registry Registrant ID: Not Available From Registry Registrant Name: Whois Agent Registrant Organization: Domain Protection Services, Inc. Registrant Street: PO Box 1769 Registrant City: Denver Registrant State/Province: CO Registrant Postal Code: 80201 Registrant Country: US Registrant Phone: +1.7208009072 Registrant Fax: +1.7209758725 Registrant Email: https://www.name.com/contact-domain-whois/hsoub.com كما ترى، لا يمكن تسجيل اسم النطاق لأن شركة "حسوب Hsoub" حجزته بالفعل. لنرى إن كان بالإمكان تسجيل اسم النطاق afunkydomainname.org: $ whois afunkydomainname.org NOT FOUND كما ترى لا وجود لاسم النطاق هذا في قاعدة بيانات whois (حتى لحظة الكتابة) وبالتالي يمكنك الاستعلام عنه وحجزه! الحصول على اسم نطاق العملية مباشرة وفق الخطوات التالي: افتح موقع ويب إحدى الشركات المسجِّلة. ستجد عادة زر أو رابط دائمًا بعنوان "احصل على اسم نطاق Get a domain name". إملأ الاستمارة التي تظهر بالمعلومات المطلوبة، وتأكد من أنك لم تخطئ كتابة اسم النطاق الذي ترغب بحجزه، فبمجرد أن تدفع لن تتمكن من التراجع! ستعلمك الشركة المسجّلة متى أصبح اسم النطاق الذي حجزته مسجّلًا وجاهزًا للاستخدام. خلال عدة ساعات ستتعرف كل خوادم أسماء النطاقات Domain Name System اختصارًا DNS على معلومات اسم النطاق الذي حجزته. تحديث خوادم أسماء النطاقات تُخزن قواعد بيانات دي إن إس في جميع خوادم أسماء النطاقات في العالم وترتبط هذه الخوادم جميعها بعدة خوادم خاصة تدعى "خوادم أسماء النطاقات الموثقة Authoritative Name Servers" أو "خوادم دي إن إس المستوى الأعلى Top-Level DNS Servers" وهذه الخوادم بمثابة المدراء للمنظومة ككل. عندما تسجل أي شركة مسجّلة اسم نطاق أو تحدث اسمًا موجودًا فلا بدّ من تحديث المعلومات في قواعد البيانات لجميع خوادم أسماء النطاقات. فعندما يعرف خادم أسماء النطاقات بوجود اسم نطاق ما فسيخزنُ معلوماته لبعض الوقت قبل أن يتأكد من سلامتها ثم يحدّثها (يستعلم خادم أسماء النطاقات من خادم أسماء النطاقات الموثوقة عن اسم النطاق ويحضر المعلومات المحدثة منه). لهذا تستغرق العملية بعض الوقت ليحصل خادم أسماء النطاقات على المعلومات المحدثة لاسم نطاق مسجل لديه (يعلم بوجوده). آلية عمل استعلام دي إن إس DNS كما رأينا سابقًا من السهل أن تكتب اسم النطاق في شريط عنوان المتصفح عندما تريد الوصول إلى صفحة ويب بدلًا من عنوان آي بي لها. لنلق نظرة على العملية: اكتب مثلًا Hsoub.com في شريط عنوان متصفحك. يسأل المتصفح حاسوبك إن كان على دراية بعنوان آي بي الذي يحدده اسم النطاق الذي كتبته (من خلال البحث في ذاكرة دي إن إس مؤقتة على الحاسوب). إن وجدت المعلومات يترجم المتصفح اسم النطاق إلى عنوان آي بي الموجود في الذاكرة المؤقتة ثم يحضر المتصفح المحتوى المطلوب من الخادم المحدد بعنوان آي بي. إن لم يتعرف حاسوبك على عنوان آي بي المرتبط باسم النطاق الذي كتبته سيتوجه المتصفح إلى خادم أسماء النطاقات لسؤاله، لأن عمله بالتحديد هو معرفة عنوان آي بي لكل اسم نطاق مسجل لديه. يعرف حاسوبك الآن عنوان آي بي المطلوب وبالتالي سيتمكن المتصفح من إحضار المحتوى المطلوب من خادم ويب الصحيح. ترجمة -وبتصرف- للمقال What is a Domain Name. اقرأ أيضًا الفرق بين صفحة الويب وموقع الويب وخادم الويب ومحرك البحث. ما هي الأدوات المستخدمة في بناء مواقع ويب؟ ما التكلفة المادية الكاملة لبناء موقع ويب؟ ما هي أدوات مطوري الويب المدمجة في المتصفحات؟
  15. يُعد مفهوم الروابط التشعبية (تُدعى معظم الأحيان "روابط" فقط) مفهومًا جوهريًا ساهم في تأسيس الويب. فإن أردنا شرح هذا المفهوم لابد من العودة إلى أكثر الأساسيات بساطة في معمارية الويب. تحدث تيم بيرنرز-لي مخترع الويب عام 1989 عن الأعمدة الثلاث التي تستند إليها الويب: محدد موقع المورد URL: هو نظام عنونة يحدد مكان وجود ملفات الويب. HTTP (بروتوكول نقل النصوص التشعبية): بروتوكول نقل يستخدم لإيجاد الملفات عندما يعطي عنوانها بشكل URL. لغة HTML: وهي لغة توصيفية لإنشاء صفحات الويب وتطبيقات الويب وتسمح بتضمين الروابط التشعبية داخل الصفحات. تدل الأعمدة الثلاث أن كل ما هو موجود على الويب مرتبط بالمستندات وكيفية الوصول إليها، لأن الغرض الأساسي من الويب هو الوصول إلى الملفات النصية وقراءتها والتنقل بينها. لكن تطور الويب مع الزمن مكّن المستخدمين من الوصول إلى الصور والفيديوهات والبيانات الثنائية وبالكاد أثرت هذه التغيرات على الأعمدة الثلاث التي ترتكز عليها ويب. لم يكن سهلًا الوصول إلى المستندات والتنقل بينها قبل وجود الويب بالرغم من أن عناوين URL بشكلها المفهوم للمستخدم سهلت الأمر. إلا أنه من الصعب كتابة أو تذكر عنوان طويل كلما أردت الوصول إلى مستند، ولهذا السبب ظهرت الروابط التشعبية Hyperlinks التي أحدثت نقلة ثورية في تقانة الويب. إذ يمكن للروابط أن تقرن أي نص بعنوان URL ولن يبقى على المستخدم سوى النقر على الرابط ليصل مباشرة إلى المستند المطلوب. تُميَّز الروابط التشعبية عن النص المحيط بها بلونها الأزرق والخط الذي يُرى أسفلها. انقر أو المس الرابط حتى تنتقل إلى محتوى الرابط، أو يمكنك الضغط على الزر "TAB" إن كنت تستخدم لوحة المفاتيح حتى يُحدَّد الرابط (يصل تركيز الدخل إليه) ثم يمكنك النقر على الزر "ENTER" أو "SPACE" للولوج إلى محتوى الرابط. أحدثت الروابط التشعبية نقلة نوعية جعلت الويب أكثر فائدة ونجاحًا. سنناقش في بقية المقال الأنواع المختلفة للروابط وفائدتها في التصميم الحديث للويب. سنطلع في هذا المقال على الروابط التشعبية Hyperlinks، وسنتعرف على عملها وأهميتها في تقانة الويب. ننصحك قبل قراءة المقال بأن تطلع على مقال كيف تعمل شبكة الإنترنت؟ وأن يكون الفرق بين صفحة الويب وموقع الويب وخادم الويب ومحرك البحث واضحًا بالنسبة لك. أنواع الروابط الرابط، كما أشرنا سابقًا، هو سلسلة نصية مرتبطة بعنوان URL، يستخدم لتسهيل الانتقال من مستند إلى آخر. لكن هناك بعض الفوارق البسيطة التي لا بدّ من عرضها. رابط داخلي Internal Link: وهو رابط بين صفحتي ويب تنتميان إلى نفس الموقع. وبالطبع لن تجد موقع ويب ليس فيه هذا النوع من الروابط (ما عدا الموقع وحيد الصفحة). رابط خارجي External link: وهو رابط بين صفحة ويب على موقعك وصفحة ويب على موقع آخر. بدون هذا النوع من الروابط ليس هناك ويب على الإطلاق لأنها في الواقع شبكة من صفحات الويب المترابطة. يستخدم هذا النوع لتزويد الزائر بمعلومات إضافية إلى جانب المحتوى الذي تقدمه صفحة الويب. رابط وارد Incoming Link: وهو رابط من صفحة خارج موقعك إلى صفحة في موقعك، وهي الحالة المعاكسة للرابط الخارجي. وليس ضروريًا بالطبع ربط صفحتك بكل صفحة خارجية تضع رابطًا لموقعك. ركّز على الروابط الداخلية عندما تبني موقع ويب لأنها تسهّل استخدام الموقع، وحاول أن توازن في عدد الروابط المستخدمة، فلا تكثر من الروابط ولا تجعلها قليلة في نفس الوقت. سنتحدث لاحقًا عن تصميم آليات التنقل داخل مواقع الويب، ولكن وكقاعدة عامة يمكن اعتمادها، حيثما تنشئ صفحة ويب في موقعك لا بدّ من وجود رابط واحد على الأقل بين الصفحة الجديدة وإحدى الصفحات الموجودة مسبقًا. لكن بالمقابل ستأتي هذه القاعدة بنتائج عكسية عندما يزيد عدد الصفحات في الموقع عن العشرة. لأنه لا يمكن ربط كل الصفحات مع بعضها بعضًا. لا تعر اهتمامًا كبيرًا للروابط الداخلية والخارجية إن كنت في بداية طريقك في تصميم المواقع، لكن سترى أن وجودها لاحقًا هام جدًا إن أردت من محركات البحث العثور على صفحات موقعك. المرابط تربط معظم الروابط بين صفحتي ويب، بينما تربط المرابط Anchors (وتدعى مراسي أيضًا) بين قسمين من مستند واحد. عندما تفتح مربطًا ما سينتقل المتصفح إلى جزء آخر من المستند الحالي بدلًا من تحميل مستند جديد أي سيُشير إلى مكان معين ضمن نفس المستند. ولا تختلف طريقة استخدام المربط عن الروابط الأخرى. الروابط ومحركات البحث للروابط أهمية كبيرة للمستخدم ولمحركات البحث، فكلما وصل محرك بحث إلى صفحة جديدة سيفهرس الموقع الذي يحتويها بالتنقل عبر الروابط الموجودة ضمن هذه الصفحة. لا تلاحق محركات البحث الروابط لتكتشف فقط الصفحات المختلفة للموقع، بل لتستخدم العبارات النصية للرابط في تحديد معايير البحث الملائمة للوصول إلى هذه الصفحة. تؤثر الروابط على سهولة الوصول إلى صفحتك عبر محركات البحث، لكن المشكلة تكمن في صعوبة تحديد ما يفعله محرك البحث (لأن معظم محركات البحث تخفي طريقة تصنيفها الدقيقة لكي لا يساء استخدامها للاحتيال على هذه المحرك). تحاول معظم الشركات أن تتصدر مواقعها نتائج محركات البحث، وسنطلعك على بعض ما نعرفه عن الآلية تقييم محرك البحث لموقع الويب: يؤثر النص المرئي للرابط على معايير البحث التي تتطابق مع عنوان URL. يرفع ترتيب ظهور موقعك في نتائج محركات البحث عند وجود عدد كبير من الروابط الواردة إلى موقعك. تؤثر الروابط الخارجية على ترتيب كلٍ من الصفحتين المصدر والهدف، ولكن لا نعرف تحديدًا مقدار هذا التأثير. قد ترغب الآن بإعداد بعض صفحات الويب وتزويدها بالروابط، لذلك لا بد من زيادة خلفيتك المعرفية النظرية بالروابط أولًا، ولذا ننصحك بمعرفة ما هي عناوين URL. ترجمة -وبتصرف- للمقال What are hyperlinks اقرأ أيضًا تطبيقات الشبكات الحاسوبية: شبكة الويب العالمية تطبيقات الشبكات الحاسوبية: خدمات الويب ما هو خادم الويب؟ ما هي الأدوات المستخدمة في بناء مواقع ويب؟
  16. يأتي مجال الويب كغيره من المجالات المعرفية بالكثير من المصطلحات التي لن يسعنا الحديث عنها جميعًا في مقالنا، لكن لا بدّ من معرفة بعض المصطلحات الأساسية في نهاية الأمر، لأنك ستصادفها دائمًا عندما تكمل قراءة هذه السلسلة. ويمكن أن تختلط عليك هذه المصطلحات أحيانًا لأنها تشير إلى نواح وظيفية مترابطة ولكن ستتوضح لك الفكرة أكثر وأكثر مع قراءتك للمقالات التي نشير إليها. كما أن الاستخدام الخاطئ لهذه المصطلحات في نشرات الأخبار يجعلها مبهمة أكثر وغير مفهومة. سنشرح لاحقًا هذه المصطلحات والتقانات بتفاصيل أكثر مع تقدمنا في السلسلة، وستكون التعريفات التالية بداية جيدة للانطلاق: صفحة ويب Web Page: هي مستند يمكن استعراض محتوياته من خلال المتصفحات مثل فايرفوكس وغوغل كروم وأوبِرا ومايكروسوفت إكسبلورير وإيدج أو متصفح سفاري من آبل. تدعى هذه المستندات أحيانًا "صفحات" فقط. موقع ويب Website: وهو مجموعة من صفحات الويب تُجمَّع مع بعضها، وترتبط عادة بطرق مختلفة. تدعى أحيانًا "موقع ويب" وأحيانا "موقع" فقط. خادم ويب Web Server: وهو حاسوب يستضيف موقع ويب على الإنترنت. محرك البحث Search Engine: وهو خدمة ويب تساعدك في العثور على صفحات الويب الأخرى. نذكر من هذه المحركات غوغل Google وبينغ Bing وياهو Yahoo ودك-دك-غو DuckDuckGo. تُستخدم هذه المحركات عادةً مباشرة عبر متصفحات الويب (أي بكتابة ما تريد إيجاده مباشرة في شريط عنوان المتصفح في فايرفوكس أو كروم أو غيره وسيبحث مباشرة في أحد محركات البحث)، كما يمكن الدخول إلى صفحة الويب الخاصة بمحرك البحث ثم كتابة العبارة المراد البحث عنها. لتوضيح مفهوم خادم الويب سنأخذ مثالًا بسيطًا وهو المكتبة فما تفعله عادة عند زيارة المكتبة يتلخص بالتالي: إيجاد فهرس لأسماء الكتب الموجودة في المكتبة والبحث فيها عن عنوان الكتاب المطلوب. تسجيل رقم التصنيف الخاص بالكتاب. الانتقال إلى القسم الذي يضم الكتاب والبحث عن رقم التصنيف الذي دوّنته ثم إحضار الكتاب. لنوازن الآن بين المكتبة وخادم الويب: تتشابه المكتبة مع خادم الويب، إذ تتضمن عدة أقسام يمكن تشبيهها بمواقع الويب المتعددة التي يستضيفها الخادم. تتشابه الأقسام المختلفة للمكتبة (علوم، رياضيات، تاريخ،..) مع مواقع الويب. وسيكون كل قسم من أقسام المكتبة بمثابة موقع ويب فريد (فلا يمكن أن يضم قسمان مختلفان الكتب نفسها). تتشابه الكتب وفق هذا المنظور مع صفحات الويب، إذ يضم كل موقع ويب عدة صفحات ويب، سيضم قسم العلوم مثلًا (الذي يمثل موقع الويب) كتبًا عن الحرارة والصوت الترموديناميك والإحصاء وغيرها (والتي تمثل صفحات ويب)، يمكن الوصول إلى أي صفحة ويب من خلال عنوان فريد URL. يتشابه فهرس أسماء الكتب مع محرك البحث، لكل كتاب موقعه الخاص في المكتبة، فلا يمكن وضع كتابين متطابقين في المكان ذاته والذي يحدده رقم التصنيف الخاص بالكتاب. سنشرح في هذا المقال بعض المفاهيم المتعلقة بالويب مثل: صفحات الويب ومواقع الويب وخوادم الويب ومحركات البحث لأنها يمكن أن تُربك المستخدمين الجدد للويب أو يمكن أن يستخدموها بطريقة غير صحيحة، وسنتحدث عن معنى كلٍّ منها. وبالتالي سيصبح القارئ على دراية تامة بالفوارق بين تلك المصطلحات. ننصحك بالاطلاع على مقال كيف تعمل شبكة الإنترنت؟ قبل إكمال قراءة المقال. إذًا، سنبحث بشيء من التفصيل عن الترابط بين المصطلحات السابقة وعن الالتباسات التي تحدث عند استخدامها. دورة تطوير واجهات المستخدم ابدأ عملك الحر بتطوير واجهات المواقع والمتاجر الإلكترونية فور انتهائك من الدورة اشترك الآن صفحة الويب صفحة الويب هي مستند يمكن استعراضه من خلال المتصفح. تكتب هذه المستندات بلغة HTML (سنتحدث عنها بتفاصيل أكثر لاحقًا. يمكن أن تتضمن صفحات الويب أنواعًا مختلفة من الموارد مثل: معلومات عن تنسيق الصفحة Style Information: وتتحكم بمظهر الصفحة وطريقة عرضها. سكربتات Scripts: تجعل الصفحة أكثر تفاعلًا مع مستخدمها. وسائط Media: وهي الصور أو الأصوات أو الفيديوهات. يمكن الوصول إلى أي صفحة ويب موجودة على الويب من خلال عنوان فريد يمكن كتابته في شريط عنوان المتصفح: موقع الويب موقع الويب هو مجموعة من صفحات الويب المترابطة (بالإضافة إلى الموارد التي تستخدمها) التي تشترك باسم نطاق Domain name فريد. يمكن الوصول إلى أي صفحة ضمن موقع ما من خلال روابط محددة عادة ما تكون جزء قابل للنقر من نص يسمح للمستخدم عند نقره بالانتقال من صفحة إلى أخرى ضمن الموقع. للوصول إلى موقع معين، ما عليك سوى كتابة اسم النطاق في شريط عنوان المتصفح الذي سيقودك مباشرة إلى الصفحة الرئيسية للموقع Homepage ويشار إليها أحيانًا بالرئيسية Home. يمكن الخلط بين مفهومي "صفحة ويب" و"موقع ويب" على وجه الخصوص في المواقع المكوّنة من صفحة واحدة والتي تُدعى عادة بالمواقع وحيدة الصفحة Single-Page Website ويرمز لها اختصارًا SPW. احصل على موقع إلكتروني مخصص لأعمالك أبهر زوارك بموقع احترافي ومميز بالاستعانة بأفضل خدمات تطوير وتحسين المواقع على خمسات أنشئ موقعك الآن خادم الويب خادم الويب هو حاسوب يستضيف موقع ويب أو أكثر. تعني كلمة "استضافة Hosting" أنّ جميع صفحات الويب والملفات التي تدعمها متاحة على هذا الحاسوب. عندما يطلب المستخدم صفحة ويب معينة يرسل خادم الويب هذه الصفحة من موقع ويب إلى متصفح المستخدم. لا تخلط بين مواقع الويب وخوادم الويب، فعندما تسمع مثلًا عبارة "موقع الويب الخاص بي لا يستجيب"، فهي تعني في الواقع أن خادم الويب الذي يستضيف الصفحة لا يستجيب وبالتالي لن يكون الموقع متاحًا. والناحية الأهم في معرض حديثنا أنّ خادم الويب لا يتحدد بموقع ويب، الأمر الذي يُحدثُ اختلاطًا في المفاهيم. فلو قلنا في مثالنا السابق أنّ "خادم الويب الخاص بي لا يستجيب"، يعني ذلك أن عدة مواقع ويب على ذلك الخادم لا تستجيب لأن غالبية المخدمات تستضيف عدة مواقع. محرك البحث تُسبب محركات البحث إرباكًا من ناحية الاصطلاح في عالم الويب، فهي نوع خاص من مواقع الويب، تساعد المستخدمين في العثور على صفحات ويب موجودة في مواقع ويب أخرى. ستجد على الويب العديد من محركات البحث مثل غوغل Google وبينغ Bing وياهو Yahoo ودك-دك-غو DuckDuckGo وغيرها. بعضها محركات بحث عامة والأخرى متخصصة بمواضيع محددة، لذلك فالخيار يعود لك في استخدام ما يناسبك. يخلط العديد من المستخدمين الجدد للويب بين محركات البحث والمتصفحات، لذلك سنوضح الأمر قليلًا. المتصفح Browser هو برنامج يحضر صفحة الويب ويعرضها، بينما يُعد محرك البحث موقع ويب يساعد المستخدمين في إيجاد صفحات ويب ضمن مواقع أخرى، ويأتي مصدر اختلاط المفهومين عندما يفتح مستخدم جديد متصفحًا لأول مرة، سيعرضُ المتصفح غالبًا محرك بحث في الصفحة الرئيسية للمتصفح، وهذا أمر منطقي لأن أول ما تفكر به عند استخدام المتصفح هو البحث عن صفحات ويب معينة وعرضها، لذلك لا تخلط بين البنية التحتية (التي يمثلها المتصفح) والخدمة (التي يمثلها محرك البحث). سيكون التمييز بين المفهومين مفيدًا لك، ولكن لا تقلق فبعض المحترفين أيضًا يرتكبون هفوات كهذه عندما يتحدثون في هذه المواضيع. تعرض الصورة التالية متصفح فايرفوكس وضمنه صندوق محرك البحث غوغل كصفحة بداية افتراضية: ترجمة -وبتصرف- للمقال What is the difference between webpage, website, web server, and search engine اقرأ أيضًا دورة تطوير واجهة المستخدم ما هو عنوان URL في الويب؟ ما هو خادم الويب؟ مفهوم الروابط التشعبية في مواقع الويب.
  17. المجموعة الملتقطة capturing group هي الجزء الذي يضم محارف بين قوسين (...) في أي تعبيير نمطي RegEx، ولها تأثيران اثنان: تسمح بالحصول على جزء من التطابق مثل عنصر مستقل ضمن مصفوفة النتائج. يُطبق المحدد الكمي quantifier على مجموعة الالتقاط كلها إذا وضع بعد القوسين مباشرةً. أمثلة عن مطابقة عدة مجموعات لنتعرف كيفية عمل الأقواس من خلال الأمثلة. مثال gogogo يفيد النمط +go دون أقواس في إيجاد المحرف g يليه المحرف o مكررًا مرةً أو أكثر، مثل goooo أو goooooo، وإذا وضعنا محارف النمط السابق بين قوسين +(go)، فسيعني ذلك go أو gogo أو gogogo وهكذا. alert( 'Gogogo now!'.match(/(go)+/ig) ); // "Gogogo" مثال نطاق موقع ويب نحتاج إلى تعبير نمطي للبحث عن نطاق موقع ويب، مثل النطاقات التالية: mail.com users.mail.com smith.users.mail.com يتألف النطاق من كلمات متتالية تفصل بينها نقاط، ويقابل ذلك التعبير النمطي +w+\.)+\w\): let regexp = /(\w+\.)+\w+/g; alert( "site.com my.site.com".match(regexp) ); // site.com,my.site.com سيعمل النمط السابق، لكنه سيواجه مشكلةً عندما تحتوي الكلمات على شرطة قصيرة -، مثل my-site.com، فلا يعتبر هذا المحرف من محارف الصنف w\، وسنحل هذه المشكلة باستبدال التعبير w\ بالمجموعة [-w\]، في كل كلمة عدا الأخيرة، وسيصبح النمط بالشكل +w-]+\.)+\w\]). مثال البريد الإلكتروني يمكن توسيع المثال السابق لإنشاء تعبير نمطي لبريد إلكتروني اعتمادًا على النمط السابق، وما دام للبريد الإلكتروني الشكل name@domain، فيمكن أن تكون أي كلمة هي الاسم، حيث يُسمح ضمنها بالشرطة القصيرة أو النقاط، وبلغة التعبير النمطي ستكون [.-w\]، وسيكون التعبير النمطي للبريد الإلكتروني /+[-w.-]+@([\w-]+\.)+[\w\]/ let regexp = /[-.\w]+@([\w-]+\.)+[\w-]+/g; alert("my@mail.com @ his@site.com.uk".match(regexp)); // my@mail.com, his@site.com.uk ليس هذا التعبير مثاليًا، لكنه سيعمل في معظم الأحيان، وسيساعدك في التخلص من الأخطاء الكتابية، وتأكد أن الطريقة الحقيقية الوحيدة للتحقق من بريد هو استلامه للرسالة التي أرسلتها! المحتوى الموجود بين قوسين عند البحث عن تطابق تُرقّم الأقواس من اليسار إلى اليمين، وسيتذكر المحرك المحتوى الذي يتطابق مع كل قوس، ويسمح بالحصول على هذه التطابقات ضمن النتيجة، ويبحث التابع (str.match(regexp عن التطابق الأول، ويعيد النتيجة في مصفوفة عندما لا تُستخدم الراية g ضمن التعبير regexp، حيث ستجد ضمن المصفوفة: التطابق بشكله الكامل في الموقع 0. محتوى القوس الأول في الموقع 1. محتوى القوس الثاني في الموقع 2. وهكذا… فلو أردنا مثلًا البحث عن وسوم HTML من النمط <?*.>، ثم معالجة النتائج، فمن المناسب أن نحصل على محتوى كل وسم ضمن متغير خاص به، وعندما نغلّف المحتوى الداخلي للوسم ضمن قوسين، بالشكل التالي <(?*.)>، فسنحصل على الوسم كاملًا، وليكن <h1>، وعلى محتوى هذا الوسم (أي النص h1) ضمن النتيجة: let str = '<h1>Hello, world!</h1>'; let tag = str.match(/<(.*?)>/); alert( tag[0] ); // <h1> alert( tag[1] ); // h1 المجموعات المتداخلة يمكن أن تتداخل الأقواس، وعندها ستُرقَّم أيضًا من اليسار إلى اليمين، فعندما نبحث عن وسم ضمن الوسم <span class="my"> مثلًا، فلربما نريد الحصول على: محتوى الوسم كاملًا "span class="my. اسم الوسم: span. سمات الوسم: "class="my. لنضف الأقواس إلى النمط <(([a-z]+)\s*([^>]*))>، لاحظ كيف تُرقَّم الأقواس من اليسار إلى اليمين: let str = '<span class="my">'; let regexp = /<(([a-z]+)\s*([^>]*))>/; let result = str.match(regexp); alert(result[0]); // <span class="my"> alert(result[1]); // span class="my" alert(result[2]); // span alert(result[3]); // class="my" سنجد دائمًا التطابق الكامل في الموقع صفر من المصفوفة، ثم المجموعات مرقمةً من اليسار إلى اليمين بواسطة القوس المفتوح، حيث تُعاد المجموعة الأولى في الموقع الأول [result[1، تليها الثانية الناتجة عن القوس المفتوح الثاني (+[a-z]) ضمن [result[2، ثم نتيجة التطابق مع النمط (‎[^>]*‎) ضمن [result[3، وستكون نتيجة كل مجموعة بصيغة نص. المجموعات الاختيارية حتى لو كانت المجموعة اختياريةً وغير موجودة ضمن التطابق، كأن يكون لها المحدد الكمي ?(...)، فسيبقى مكانها محجوزًا ضمن المصفوفة، وقيمته هي undefined، فلو تأملنا مثلًا التعبير ?(a(z)?(c، فسنجد أنه يبحث عن "a" متبوعًا -اختياريًا- بالحرف "z"، ومتبوعًا -اختياريًا أيضًا- بالحرف "c"، لأن المحدد الكمي ? يعني محرفًا أو لا شيء، فلو طبّقنا التعبير السابق على نص مكون من الحرف a فقط، فستكون النتيجة: let match = 'a'.match(/a(z)?(c)?/); alert( match.length ); // 3 alert( match[0] ); // a (whole match) alert( match[1] ); // undefined alert( match[2] ); // undefined سيكون طول المصفوفة 3 علمًا أن كل المجموعات فارغة! لكن لو كان النص هو ac: let match = 'ac'.match(/a(z)?(c)?/) alert( match.length ); // 3 alert( match[0] ); // ac (whole match) alert( match[1] ); // undefined, because there's nothing for (z)? alert( match[2] ); // c سيبقى طول المصفوفة 3، لكنك لن تجد تطابقًا يقابل المجموعة (z)?، وستكون النتيجة ["ac", undefined, "c"]. البحث عن كل التطابقات ضمن المجموعات: التابع matchAll لن يعيد التابع match محتوى المجموعات إذا استخدم للبحث بوجود الراية g، والتي تعني إيجاد كل التطابقات، وسنحاول في المثال التالي إيجاد كل الوسوم في النص: let str = '<h1> <h2>'; let tags = str.match(/<(.*?)>/g); alert( tags ); // <h1>,<h2> لاحظ أن النتيجة هي مصفوفة تحتوي على التطابقات كاملةً لكن دون تفاصيل، أي دون محتوى كل تطابق، لكننا نحتاج عمليًا إلى ذلك المحتوى، وسيساعدنا البحث باستخدام التابع (str.matchAll(regexp على استخلاص ذلك المحتوى، فقد أضيف هذا التابع إلى JavaScript بعد فترة طويلة من إضافة match مثل نسخة جديدة ومحسنة منه. يشابه matchAll التابع match، مع وجود ثلاثة اختلافات، وهي: لا يعيد مصفوفةً، بل كائنًا قابلًا للتكرار iterable object. يعيد كل تطابق مثل مصفوفة تحتوي مجموعات عند استخدام الراية g. عندما لا يجد تطابقات فلن يعيد null، بل كائنًا فارغًا قابلًا للتكرار. إليك مثالًا: let results = '<h1> <h2>'.matchAll(/<(.*?)>/gi); // النتائج ليست مصفوفة بل كائن قابل للتعداد alert(results); // [object RegExp String Iterator] alert(results[0]); // undefined (*) results = Array.from(results); // تحويل النتيجة إلى مصفوفة عادية alert(results[0]); // <h1>,h1 (1st tag) alert(results[1]); // <h2>,h2 (2nd tag) إنّ الاختلاف الأول مهم جدًا كما يوضّحه السطر "(*)"، فلا يمكن الحصول على التطابق في الموقع [results[0، لأن الكائن لا يمثل مصفوفةً زائفةً pseudoarray، ويمكننا تحويلها إلى مصفوفة حقيقية باستخدام Array.from، وستجد العديد من التفاصيل عن المصفوفات الزائفة والكائنات القابلة للتكرار في المقال Iterables. لا حاجة لتحويل المصفوفة باستخدام Array.from إذا كنا سنشكل حلقةً من النتائج: let results = '<h1> <h2>'.matchAll(/<(.*?)>/gi); for(let result of results) { alert(result); // first alert: <h1>,h1 // second: <h2>,h2 } أو عند استخدام التفكيك destructuring: let [tag1, tag2] = '<h1> <h2>'.matchAll(/<(.*?)>/gi); يشابه تنسيق كل تطابق يعيده التابع matchAll التنسيق الذي يعيده match دون الراية g، وهذا التنسيق هو مصفوفة مع خصائص إضافية index التي تطابق الفهرس في النص، وinput الذي يعني النص الأصلي: let results = '<h1> <h2>'.matchAll(/<(.*?)>/gi); let [tag1, tag2] = results; alert( tag1[0] ); // <h1> alert( tag1[1] ); // h1 alert( tag1.index ); // 0 alert( tag1.input ); // <h1> <h2> انتبه، لماذا ستكون نتيجة التابع كائنًا قابلًا للتكرار وليس مصفوفةً؟ السبب بسيط وهو التحسين، فلن يُنفِّذ الاستدعاء عملية البحث، بل سيعيد كائنًا قابلًا للتكرار لا يحتوي على النتيجة مبدئيًا، ويُنفَّذ البحث في كل مرة نكرره (ضمن حلقة مثلًا)، وبالتالي سيجد العدد المطلوب من النتائج تمامًا، فإذا كان من المحتمل مثلًا وجود 100 تطابق، لكننا وجدنا في حلقة for..of خمسةً فقط، وقررنا أن هذا كاف وأوقفنا الحلقة، فلن يستهلك المحرك وقتًا إضافيًا في إيجاد التطابقات 95 الباقية. المجموعات المسماة يصعب تذكر المجموعات بأرقامها، على الرغم من بساطته في الأنماط البسيطة، لكن عند البحث عن أنماط أكثر تعقيدًا فلن يكون ترقيم الأقواس أمرًا مناسبًا، وسنجد أن خيار تسمية الأقواس هو الأفضل، ونسمي الأقواس بوضع الاسم بالشكل التالي <name>? مباشرةً بعد القوس، ولنبحث مثلًا عن تاريخ وفق التنسيق "يوم-شهر-سنة": let dateRegexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/; let str = "2019-04-30"; let groups = str.match(dateRegexp).groups; alert(groups.year); // 2019 alert(groups.month); // 04 alert(groups.day); // 30 حيث سنجد المجموعات عبر الخاصية groups. لكل تطابق، ويمكن إيجاد جميع التواريخ باستخدام الراية g، كما ينبغي استخدام التابع matchAll للحصول على التطابق كاملًا بالإضافة إلى المجموعات: let dateRegexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/g; let str = "2019-10-30 2020-01-01"; let results = str.matchAll(dateRegexp); for(let result of results) { let {year, month, day} = result.groups; alert(`${day}.${month}.${year}`); // first alert: 30.10.2019 // second: 01.01.2020 } مطابقة مجموعات ثم تنفيذ عملية استبدال يسمح التابع (str.replace(regexp, replacement الذي يستبدل محتوى الأقواس ضمن النص replacement، بكل التطابقات regexp التي يجدها في النص str، وينفذ ذلك باستخدام الرمز n$، حيث n هو رقم المجموعة، وإليك مثالًا: let str = "John Bull"; let regexp = /(\w+) (\w+)/; alert( str.replace(regexp, '$2, $1') ); // Bull, John ستتغير العملية باستخدام <name>$ في الأقواس المسماة، ولتغيير تنسيق التاريخ مثلًا من "يوم -شهر-سنة" إلى "سنة.شهر.يوم": let regexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/g; let str = "2019-10-30, 2020-01-01"; alert( str.replace(regexp, '$<day>.$<month>.$<year>') ); // 30.10.2019, 01.01.2020 استثناء التقاط المجموعات باستخدام :? نحتاج أحيانًا إلى الأقواس لتطبيق المحددات الكمية بطريقة صحيحة، لكننا لا نحتاج إلى محتواها ضمن النتائج، لذلك يمكن استثناء المجموعات باستخدام :? في البداية، فإذا أردنا مثلًا إيجاد النمط +(go)، لكننا لا نحتاج إلى محتوى الأقواس (go) في عنصر مصفوفة مستقل، فيمكننا صياغة النمط بالشكل `+(go?:)، وإليك مثالًا: let str = "Gogogo John!"; // ?: exludes 'go' from capturing let regexp = /(?:go)+ (\w+)/i; let result = str.match(regexp); alert( result[0] ); // Gogogo John (تطابق كامل) alert( result[1] ); // John alert( result.length ); // 2 (لا مزيد من العناصر ضمن المصفوفة) الخلاصة تُجمِّع الأقواس أجزاءً من التعبير النمطي ليُطبَّق المحدد الكمي عليها مثل زمرة واحدة. تُرقَّم أقواس المجموعات من اليسار إلى اليمين، كما يمُكن أن تُسمّى اختياريًا باستخدام النمط (...<name>?). يمكن الحصول على المحتوى الموجود داخل الأقواس -الذي يحقق التطابق- بصورة مستقلة ضمن النتيجة، حيث: يعيد التابع str.match المجموعة الملتقطة عند استخدام الراية فقط. يعيد التابع str.matchAll المجموعات الملتقطة دومًا. إذا لم تُسمَّ الأقواس فسنحصل على محتوياتها ضمن المصفوفة وفقًا لتسلسل ترقيمها، كما يمكن الحصول على محتويات الأقواس المسماة من خلال الخاصية groups.. يمكن استخدام محتويات الأقواس في النص البديل للتابع، إما عبر أرقامها من خلال n$، أو أسمائها من خلال <name>$. يمكن استثناء مجموعة من الترقيم باستخدام النمط :? قبلها، وذلك عندما نريد تطبيق مُحصٍ quantifier على كامل المجموعة، لكننا لا نريد أن تظهر محتويات المجموعة -الموجودة بين قوسين- في عنصر مستقل ضمن مصفوفة النتيجة، كما لا يمكن الإشارة إلى هذه الأقواس عند استخدام تابع الاستبدال. مهام لإنجازها تحقق من عنوان MAC يتكون عنوان MAC لواجهة اتصال مع الشبكات من 6 أرقام ست عشرية ذات خانتين تفصل بينها نقطتان ":"، مثل العنوان التالي '01:32:54:67:89:AB'، اكتب تعبيرًا نظاميًا يتحقق من أن النص هو عنوان MAC. let regexp = /your regexp/; alert( regexp.test('01:32:54:67:89:AB') ); // true alert( regexp.test('0132546789AB') ); // false (no colons) alert( regexp.test('01:32:54:67:89') ); // false (5 numbers, must be 6) alert( regexp.test('01:32:54:67:89:ZZ') ) // false (ZZ at the end) الحل: يُعطى التعبير النمطي الذي يبحث عن عدد ست عشري من خانتين بالشكل: {2}[‎0-9a-f] مفترضين استخدام الراية i. سنحتاج الآن إلى هذا النمط وخمسة أنماط أخرى مشابهة له، وبالتالي سيكون التعبير النمطي على الشكل: [0-9a-f]{2}(:[0-9a-f]{2}){5} ولكي نجبر التعبير على التقاط كامل النص الموافق، لابد من وضع محرفي ارتكاز البداية والنهاية $...^ إليك شيفرة الحل بشكلها الكامل: let regexp = /^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/i; alert( regexp.test('01:32:54:67:89:AB') ); // true alert( regexp.test('0132546789AB') ); // false (no colons) alert( regexp.test('01:32:54:67:89') ); // false (5 numbers, need 6) alert( regexp.test('01:32:54:67:89:ZZ') ) // false (ZZ in the end) أوجد الألوان التي تنسّق بالشكل abc# أو abcdef اكتب تعبيرًا نمطيًا يبحث عن الألوان المكتوبة وفق أحد التنسيقين abc# أو abcdef#، أي المحرف # يليه ثلاث أو ست أرقام ست عشرية. let regexp = /your regexp/g; let str = "color: #3f3; background-color: #AA00ef; and: #abcd"; alert( str.match(regexp) ); // #3f3 #AA00ef لاحظ أنه لا ينبغي الحصول على تطابقات تحوي أربع أو خمس أرقام ست عشرية، بل 3 أو 6 فقط. الحل: سيكون التعبير النمطي المناسب للبحث عن شيفرة لون ثلاثية الأرقام كالتالي: /#[a-f0-9]{3}/i يمكننا أيضًا إضافة ثلاث أرقام ست عشرية أخرى بالضبط فلن نحتاج أكثر أو أقل، لكون الشيفرة اللونية مزيج من ثلاث أو ستة أرقام. لنستخدم إذًا المكمم {1,2} بعد وضع الصيغة السابقة للتعبير النمطي بين قوسين: /#([a-f0-9]{3}){1,2}/i لاحظ الشيفرة: let regexp = /#([a-f0-9]{3}){1,2}/gi; let str = "color: #3f3; background-color: #AA00ef; and: #abcd"; alert( str.match(regexp) ); // #3f3 #AA00ef #abc تواجهنا مشكلة صغيرة هنا، فسيجد التعبير النمطي المحارف abc# ضمن abcd#. يمكن وضع النمط b\ في النهاية لحل المشكلة: let regexp = /#([a-f0-9]{3}){1,2}\b/gi; let str = "color: #3f3; background-color: #AA00ef; and: #abcd"; alert( str.match(regexp) ); // #3f3 #AA00ef أوجد كل الأرقام اكتب تعبيرًا نمطيًا يبحث عن كل الأعداد العشرية، بما فيها الصحيحة والعشرية ذات الفاصلة العائمة أو السالبة. let regexp = /your regexp/g; let str = "-1.5 0 2 -123.4."; alert( str.match(regexp) ); // -1.5, 0, 2, -123.4 الحل: يُعطى نمط العدد العشري الموجب بوجود القسم العشري منه على الشكل: \d+(\.\d+)? لنضع الإشارة السالبة - لتكون اختيارية في بداية النمط: let regexp = /-?\d+(\.\d+)?/g; let str = "-1.5 0 2 -123.4."; alert( str.match(regexp) ); // -1.5, 0, 2, -123.4 فسر العبارات الرياضية تتكون العملية الحسابية من عددين بينهما إشارة عمليات، مثل: 1 + 2 1.2 * 3.4 -3 / -6 -2 - 2 قد تكون العملية "+"أو "-" أو "*" أو "/"، وقد توجد مساحات فارغة قبل أو بعد أو بين الأجزاء. أنشئ تابعًا (parse(expr يقبل العبارة معاملًا، ويعيد مصفوفةً من ثلاثة عناصر، وهي: العدد الأول. العامل الرياضي (إشارة العملية). العدد الثاني. let [a, op, b] = parse("1.2 * 3.4"); alert(a); // 1.2 alert(op); // * alert(b); // 3.4 الحل: يُعطى التعبير النمطي لإيجاد عدد كما رأينا في المهمة السابقة كالتالي: -?\d+(\.\d+)? تُعطى العملية الرياضية وفق النمط التالي [/*+-] ولابد من وضع المحرف - في بداية الأقواس المربعة لأنها ستعنى مجالًا من المحارف إن وضعت في المنتصف ونحن نريد فقط المحرف - بحد ذاته. لايد أيضًا من تجاوز المحرف /في التعبير النمطي كالتالي /.../ وهذا ما سنفعله لاحقًا. نحتاج إلى عدد ثم عملية ثم عدد آخر وقد تكون هناك مساحات فارغة اختيارية بينهم وبالتالي سيكون التعبير النمطي كاملًا: -?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)? يتكون التعبير النمطي من ثلاثة أقسام يفصل بينها ‎s*‎\: /-?\d+(\.\d+)?/ // العدد الأول /[-+*/],/ // رمز العملية /-?\d+(\.\d+)?/ // العدد الثاني يمثل القسم الأول العدد الأول والقسم الثاني العملية الحسابية والثالث العدد الثاني، ولكي يظهر كل قسم كنتيجة مستقلة ضمن مصفوفة النتيجة، سنضع كل قسم ضمن قوسين: /(-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?)/ إليك الشيفرة: let regexp = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/; alert( "1.2 + 12".match(regexp) ); تتضمن النتائج: التطابق كاملًا : "result[0] == "1.2 + 12 المجموعة الأولى (‎-?\d+(\.\d+)?‎) وتمثل العدد الأول مع أجزائه العشرية: "1.2" المجموعة الثانية ‎(\.\d+)?‎ وتمثل الجزء العشري الأول: "‎.2" المجموعة الثالثة ‎([-+*\/])‎ وتمثل العملية الحسابية: "+" المجموعة الرابعة ‎(-?\d+(\.\d+)?)‎ وتمثل العدد الثاني: "12" المجموعة الخامسة ‎(\.\d+)?‎ والتي تمثل الجزء العشري من العدد الثاني وهو في الواقع غير موجود undefined نحتاج في الواقع إلى العددين والعملية الحسابية دون الأجزاء العشرية لذلك سنجعل التعبير أكثر وضوحًا ليلائم ما نريده. سنزيل العنصر الأول من المصفوفة والذي يمثل التطابق الكامل بإجراء انزياح لمصفوفة النتيجة array.shift. يمكن التخلص من الأجزاء العشرية (‎.\d+‎) في المجموعة الثانية والرابعة (أي النقط 3 و 4) من المصفوفة بوضع المحرف ? في بداية كل مجموعة. إليك الحل النهائي: function parse(expr) { let regexp = /(-?\d+(?:\.\d+)?)\s*([-+*\/])\s*(-?\d+(?:\.\d+)?)/; let result = expr.match(regexp); if (!result) return []; result.shift(); return result; } alert( parse("-1.23 * 3.45") ); // -1.23, *, 3.45 ترجمة -وبتصرف- للفصل Capturing Groups من سلسلة The Modern JavaScript Tutorial. اقرأ أيضًا المقال السابق: المحددات الكمية وأنماط استخدامها في التعابير النمطية مقدمة في التعابير النمطية Regular Expressions التعبيرات النمطية Regular expressions في Cpp التعابير النمطية في البرمجة
  18. تُعد شبكة الإنترنت العمود الفقري للويب والبنية التحتية التقنية التي جعلت الويب واقعًا معاشًا. ببساطة شديدة يمكن أن نعرّف الإنترنت بأنها شبكة ضخمة من الحواسيب التي تتواصل مع بعضها. يلف الغموض نوعًا ما تاريخ الإنترنت نظرًا لبدايته كمشروع بحثي مولَه الجيش الأمريكي في ستينات القرن الماضي، ثم تحوّل إلى بنية تحتية عمومية في ثمانينات القرن ذاته بدعم من عدة جامعات حكومية وشركات خاصة. تطورت مع الوقت تقنيات متنوعة تدعم الإنترنت، لكن آلية عملها لم تتغير كثيرًا: فالإنترنت وسيلة لربط الحواسيب مع بعضها بعضًا وتضمن بقاء هذه الحواسب متصلة ببعضها مهما حدث. سنناقش في هذا المقال ماهية الإنترنت وآلية عمله. لفهم مبادئ البنية التحتية التقنية للويب ولمعرفة الفرق الدقيق بينها وبين الإنترنت. الشبكة البسيطة عندما تريد من حاسوبين التواصل، لابد من وصلهما سلكيًا عبر كابل شبكة (أو كما يُعرف باسم كابل إيثرنت) أو لاسلكيًا عبر أنظمة اتصالات لاسلكية مثل تقنية الواي-فاي أو البلوتوث. وستجد أن معظم الحواسب الحديثة تدعم كل وسائل الاتصال التي ذكرناها. يمكن لهذه الشبكة أن تربط حاسوبين مع أي عدد تريده من الحواسب، لكن الوضع سيتعقد بسرعة. فلو حاولت أن تربط 10 حواسب مثلًا ستحتاج إلى 45 كابلًا وتسعة مقابس لوصلها لكل حاسوب. لحل هذه المشكلة يتصل كل حاسوب على الشبكة بجهاز حاسوبي صغير خاص يُدعى الموجّه Router، وهذا الجهاز له وظيفة واحدة: وهي التأكد أنّ الرسالة التي يرسلها حاسوب معين ستصل إلى وجهتها الصحيحة؛ أي إلى الحاسوب الصحيح. فعند ارسال رسالة من الحاسوب A إلى الحاسوب B ستخرج الرسالة من الحاسوب A إلى الموجّه الذي سيحوّل الرسالة بدوره إلى الحاسوب B ويتأكد أن الرسالة لن تحوّل إلى حاسوب آخر مثل C. عند إضافة موجّه إلى الشبكة المكونة من عشرة حواسب، سينخفض عدد الكابلات المطلوبة إلى 10 ومقبس واحد لكل حاسوب، كما سنحتاج إلى موجّه بعشرة مقابس. شبكة مكونة من عدة شبكات نلاحظ أن الأمر بسيط مع عشرة حواسيب، ولكن ماذا عن وصل مئات أو آلاف أو ملايين الحواسيب؟ لن يكفي موّجه واحد بالطبع، وطالما أن الموجّه هو حاسوب كبقية الحواسيب، فما المانع من وصل موجّهين معًا؟ لا شيء. عندما نوصل الحواسيب إلى موجهات ونوصل الموجهات ببعضها يمكننا توسيع الشبكة إلى ما لانهاية نظريًا. تتشابه هذه الشبكة التي بنيناها لشبكة الإنترنت، لكن ينقصها شيء ما. فعندما بنينا شبكتنا الخاصة التي تخدم أغراضنا، نسينا الشبكات الأخرى التي سيبنيها الآخرون لأن كل شخص قادر على بناء شبكته الخاصة ومن غير الممكن مثلًا توصيل كابلات بين منزلك وكل الشبكات المحيطة، فكيف سنحل الأمر إذًا؟ في الحقيقة هناك كابلات متعددة تصل بالفعل إلى منزلك مثل كابل الطاقة الكهربائية وكابل الهاتف. فالبنية التحتية للاتصالات الهاتفية تربط منزلك بالفعل مع أي شخص في العالم وبالتالي سيكون كابل الهاتف الخيار المثالي الذي نحتاج إليه. ولوصل شبكتنا بالبنية التحتية الهاتفية نحتاج إلى جهاز يدعى المودم Modem وهو يحول المعلومات التي توّلدها شبكتنا إلى معلومات تستطيع البنية التحتية الهاتفية فهمها وإدارتها والعكس بالعكس. بعد اتصالنا بالبنية التحتية الهاتفية ستكون الخطوة التالية هي توصيل الرسائل من شبكتنا إلى الشبكة التي نريدها. ولإتمام هذا الأمر سنصل شبكتنا أولًا بما يسمى مزود خدمة الإنترنت Internet Service Provider واختصارًا ISP. ومزود خدمة الإنترنت هي شركة تدير مجموعة خاصة من الموجهات المرتبطة ببعضها ولديها القدرة على الولوج إلى الموجهات الموجودة في مزودات خدمة أخرى. وهكذا تنتقل الرسائل من شبكتنا إلى الشبكة التي نريدها عبر شبكات مزود خدمة الإنترنت. تتكون الإنترنت من هذه البنية التحتية من الشبكات. إيجاد حاسوب معين إذا أردنا إرسال رسالة إلى حاسوب ما، علينا أن تحدد تمامًا من هو مستقبل الرسالة. لهذا السبب يمتلك كل حاسوب متصل إلى الشبكة عنوانًا فريدًا يميزه عن غيره من الحواسيب يدعى عنوان آي بي IP address (وهو اختصار للعبارة Internet Protocol أي بروتوكول إنترنت). يتكون عنوان آي بي من مجموعات مكونة من أربع أرقام تفصل بينها نقاط كالعنوان التالي: 192.168.2.10. تتذكر الحواسيب هذه العناوين جيدًا لكن يصعب على البشر تذكرها. ولتسهيل هذا الأمر يمكن تحويل هذه العناوين المؤلفة من أرقام إلى أسماء يفهمها البشر تُدعى أسماء النطاقات Domain names. فمثلًا (حتى لحظة كتابة هذه السطور ولأن عناوين آي بي تتغير) يرتبط اسم النطاق google.com بعنوان آي بي 142.250.190.78. وهكذا يُسهل اسم النطاق الوصول إلى حاسوب عبر الإنترنت. ما الفرق بين الإنترنت والويب؟ لا بدّ وأنك لاحظت أننا نستخدم أسماء النطاقات عادة عندما نتصفح الويب من خلال المتصفحات، فهل يعني ذلك أنّ الإنترنت والويب هو الشيء ذاته؟ في الحقيقة الأمر ليس بهذه البساطة. يعد الإنترنت كما رأيناه كبنية تحتية تقنية تسمح لمليارات الحواسيب بأن تتواصل مع بعضها، ويمكن لبعض هذه الحواسب والتي تدعى خوادم ويب Web servers أن توصل رسائل مفهومة بالنسبة لمتصفحات الويب، وبالتالي فالإنترنت هي البنية التحتية الأساسية بينما الويب هي خدمات مبنية على هذه البنية. ومن المفيد الإشارة إلى وجود خدمات أخرى مبنية على الإنترنت مثل خدمة البريد الإلكتروني وخدمة المحادثة المبنية على إنترنت Internet Relay Chat واختصارًا IRC. الشبكات الداخلية (إنترانيت) والخارجية (إكسترانت) الإنترانت Intranet هي شبكات خاصة تسمح لأشخاص محددين فقط من منظمة محددة الوصول إليها. تشكل هذه الشبكات بوابة خاصة تساعد الأعضاء على الوصول إلى موارد مشتركة بطريقة آمنة وتسمح لهم التعاون والتواصل فيما بينهم، فيمكن أن تستضيف منظمات شبكة إنترانت خاصة بها لمشاركة صفحات ومعلومات ضمن القسم أو الفريق ومشاركة السواقات لإدارة المستندات الهامة وبوابات لإدارة مهام تتعلق بالأعمال وأدوات للتعاون مثل المنشورات التعاونية wikis ومنصات النقاش ومنظومات الرسائل. تشبه الإكسترانت Extranet الإنترانت إلا أن الإكسترانت تتيح الوصول إلى شبكتها الخاصة كليًا أو جزئيًا للتعاون مع منظمات أخرى وتُستخدم بصورة أساسية لمشاركة المعلومات بأمان وسرية مع العملاء والمضاربين، وتتشابه وظيفيًا في الكثير من الأحيان مع الإنترانت فيما يتعلق بمشاركة الملفات والمعلومات وأدوات التعاون ومنصات النقاش وغيرها. تعمل كلتا الشبكتين على البنية التحتية نفسها التي تعمل عليها الإنترنت كما تستخدم البروتوكولات ذاتها، وبالتالي يمكن الوصول إليها من قبل الأعضاء المفوضين بذلك ومن مواقع فيزيائية مختلفة. ترجمة -وبتصرف- للمقال How does Internet work اقرأ أيضًا ما هو عنوان URL في الويب؟ الفرق بين صفحة الويب وموقع الويب وخادم الويب ومحرك البحث؟ ما هي أسماء النطاقات في شبكة الإنترنت؟
  19. لنفترض أنّ لدينا النص التالي 67-45-123-(903)7+، وأننا نريد إيجاد كل الأعداد الموجودة ضمنه، سنحتاج هنا إلى أعداد كاملة، مثل 7 و903 و123 و45 و67، لا إلى كل رقم بمفرده، حيث يتألف العدد من رقم واحد أو تتابعٍ لأرقام d\، ولتحديد عدد الأرقام التي نحتاجها سنستخدم محددًا كميًا أو مكممًا quantifier. محدد الكمية {n} إنّ أبسط المحددات الكمية هو رقم ضمن أقواس معقوصة {n}، حيث يضاف المكمم إلى المحرف أو صنف المحرف أو الأقواس المربعة وغيرها؛ ليحدد العدد الذي نحتاجه منها، وللمكممات بعض الأشكال المتقدمة التي سنستعرض أمثلةً عنها: العدد الدقيق: مثل {5}، والذي يحدد العدد الدقيق من المحارف التي نحتاجها، فمثلًا يحدد {5}d خمسة أرقام تمامًا، كما لو كتبنا d\d\d\d\d\، ويعرض المثال التالي كيف نبحث عن خمسة أرقام متتالية: alert( "I'm 12345 years old".match(/\d{5}/) ); // "12345" ويمكن إضافة محرف حد الكلمة b\ لنستثني الأرقام الأطول. المجال: مثل {3,5}، ويحدد الأعداد التي تضم من 3 إلى 5 أرقام، ولإيجاد ذلك توضع حدود المجال ضمن أقواس معقوصة: alert( "I'm not 12, but 1234 years old".match(/\d{3,5}/) ); // "1234"` يمكننا تجاهل الحد الأعلى ليصبح التعبير على الشكل {,d{3\، وسيبحث عن أعداد مؤلفة من ثلاثة أرقام أو أكثر: alert( "I'm not 12, but 345678 years old".match(/\d{3,}/) );// "345678"` لنعد الآن إلى النص 67-45-123-(903)7+، حيث يتألف العدد من رقم واحد أو من تتابعٍ لأرقام في صف، فالتعبير النمطي المناسب هو {,d{1\: let str = "+7(903)-123-45-67"; let numbers = str.match(/\d{1,}/g); alert(numbers); // 7,903,123,45,67 اختصارات المحددات الكمية لمعظم المكممات اختصارات، وهي: +: يعني "واحد أو أكثر" مرة، تمامًا مثل النمط {,1}، إذ يبحث النمط +d\ عن الأعداد: let str = "+7(903)-123-45-67"; alert( str.match(/\d+/g) ); // 7,903,123,45,67` ?: يعني "صفر أو واحد" مرة، تمامًا مثل النمط {0,1}، أي يجعل الرمز اختياريًا، إذ يبحث النمط ou?r مثلًا عن المحرف o متبوعًا بمحرف u واحد أو غير متبوع به، ومن ثم المحرف r، لنبحث عن الكلمتين color أو colour: let str = "Should I write color or colour?"; alert( str.match(/colou?r/g) ); // color, colour *: يعني "صفر أو أكثر"، تمامًا مثل النمط {,0}، أي يبحث عن عدم وجود محرف أو تكراره مرةً واحدةً أو أكثر، إذ يبحث النمط *d0\ مثلًا عن رقم متبوع بأي تكرار للمحرف 0 (عدم وجوده أو تكراره مرةً أو عدة مرات): alert( "100 10 1".match(/\d0*/g) ); // 100, 10, 1` alert( "100 10 1".match(/\d0+/g) ); // 100, 10 // لا تطابق مع 1 لأن النمط 0+ سيتطلب أكثر من صفر أمثلة أكثر تستخدم المكممات كثيرًا، وتُعدّ البنية الرئيسية للتعابير النمطية المعقدة، وسنطلع على بعض الأمثلة. التعبير النمطي للكسور العشرية (عدد بفاصلة عشرية) ويعطى بالشكل +d+\.\d\، إليك مثالًا: alert( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // 12.345 التعبير النمطي لفتح وسم HTML لا يحوي سمات مثل أو الطريقة الأبسط: a-z]+>/i]>/ alert( "<body> ... </body>".match(/<[a-z]+>/gi) ); // <body> يبحث التعبير عن المحرف '>' يتبعه حرف لاتيني أو أكثر، ثم المحرف '<'. الطريق المحسنة: a-z][a-z0-9]*>/i]>/: إذ يمكن أن يحتوي وسم HTML -مثلما تنص المعايير- على رقم في أي موقع من الاسم، عدا بدايته مثل <h1>. alert( "<h1>Hi!</h1>".match(/<[a-z][a-z0-9]*>/gi) ); // <h1> التعبير النمطي لفتح أو إغلاق وسم HTML لا يحوي سمات استخدم التعبير التالي: a-z][a-z0-9]\*>/i]?/\>/، حيث وضعنا شرطةً مائلةً اختياريةً ?/ قرب بداية النمط، وكان لابد من تجاوزها بشرطة معكوسة، وإلا فستعتقد JavaScript أنها نهاية النمط. alert( "<h1>Hi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1> لاحظ أنه لكتابة تعابير نمطية أكثر دقةً لا بدّ من تعقيد التعبير أكثر، فيمكن أن ترى بأن القاعدة المشتركة بين تلك الأمثلة هي أنّ الدقة تأتي من تعقيد التعبير وطوله، ففي وسوم HTML كان يمكننا استخدام التعبير <+w\>، لكن التعبير الذي استخدمناه هو الأصلح؛ بما يتوافق مع تقييدات التسمية وقواعدها في HTML. هل يمكن استخدام <+w\> أم يجب استخدام النمط <‎[a-z][a-z0-9]*‎>؟ يُقبَل استخدام كلا النمطين في الواقع العملي، ويعتمد اختيارنا على قدرتنا على التعامل مع التطابقات الناتجة عن البحث، وصعوبة استخلاصها بطرق أخرى. مكممات البحث الجشعة والكسولة تبدو المكممات Quantifiers بسيطة الاستخدام للوهلة الأولى، لكنها قد تغدو مربكةً عند استخدامها، لذلك لا بدّ من فهم آلية البحث جيدًا إذا خططنا للبحث عن أشياء أكثر تعقيدًا من /+d\/، لنلق نظرةً على المهمة التالية مثلًا: لدينا نص ما ونريد استبدال الإشارتين «...» بإشارتي التنصيص "..."، لأنها مفضلة في تنسيقات الطباعة والكتابة في بلدان عدة، أي يجب أن يصبح النص "مرحبًا أحمد" مثلًا بالشكل «مرحبًا أحمد»، وسنجد أيضًا إشارتي التنصيص „!Witam, świat” في اللغة البولندية، أو الإشارتين 「你好,世界」 في اللغة الصينية، لكننا سنختار الإشارتين «...» فقط في مهمتنا. ستكون الخطوة الأولى تحديد النصوص الموضوعة ضمن إشارتي التنصيص، ثم استبدالهما، وقد يبدو التعبير النمطي التالي g/"+."/، والذي يعني (إشارة تنصيص ثم شيء ما مكرر ثم إشارة تنصيص أخرى) مناسبًا، لكنه ليس كذلك. انظر إلى المثال التالي: let regexp = /".+"/g; let str = 'a "witch" and her "broom" is one'; alert( str.match(regexp) ); // "witch" and her "broom" لم يعمل النمط كما هو مطلوب! فبدلًا من إيجاد الكلمتين "witch" و"broom"، وجد العبارة التالية:"witch" and her "broom". البحث الجشع Greedy search يتبع محرك التعابير النمطية الخوارزمية التالية في إيجاد التطابقات: من أجل كل موقع في النص: يحاول إيجاد التطابق عند هذا الموقع. إذا لم يجد تطابقًا فسينتقل إلى الموقع التالي. لكن هذه الكلمات غير قادرة على وصف سبب فشل التعبير بدقة، لذلك سنفصل آلية البحث عن النمط "+.": الخطوة الأولى، يحاول المحرك إيجاد المحرف الأول من النمط "عند الموقع 0 من النص a "witch" and her "broom" is one، لكنه بدلًا من ذلك سيجد المحرف a، لذلك سيتابع إلى الموقع التالي ويحاول إيجاد أول محارف النمط وسيخفق ثانيةً، وأخيرًا سيجد تطابقًا في الموقع الثالث (الموقع 2). الخطوة الثانية، يجد المحرك المحرف الأول ويتابع لإيجاد بقية محارف النمط، ويحاول أن يكتشف فيما لو تطابق بقية النص مع المحارف الباقية من النمط "+.، وسيكون المحرف التالي في النمط هو النقطة .، التي تشير إلى أي محرف عدا محرف السطر الجديد، لذلك ستجد التطابق مع الحرف 'w'. الخطوة الثالثة، سيتابع المحرك المطابقة مع النقطة نظرًا لوجود المكمم + بعدها، وسيطابق كل المحارف الأخرى ويضيفها إلى النتيجة حتى يصل إلى نهاية النص، لأن كل المحارف عدا محرف السطر الجديد ستمثل تطابقًا. الخطوة الرابعة، سينتهي المحرك من تكرار المحرف . ويحاول إيجاد المحرف التالي من النمط -وهي إشارة التنصيص "-، وهنا تظهر المشكلة فقد انتهى النص ولم يعد هناك المزيد من المحارف للبحث ضمنها، عندها سيفهم المحرك أنه ضم الكثير من المحارف .+، وسيبدأ بالتراجع، حيث يختصر نتيجة التطابق التي ولّدها المكمم بمقدار محرف إلى الخلف؛ مفترضًا أن المحارف ستنتهي قبل انتهاء النص بمحرف واحد، ثم يحاول إيجاد بقية محارف النمط انطلاقًا من هذا الموقع، وسينهي المحرك البحث إذا وجد المحرف، لكنه سيجد المحرف 'e'، وبالتالي لن تنتهي العملية. الخطوة الخامسة، سيقلل المحرك عدد المحارف الناتجة عن تكرار النقطة بمحرف واحد أيضًا، إلى أن يجد التطابق مع آخر محارف النمط '"' حتى يجده. الخطوة السادسة، سيكتمل البحث عند إيجاد التطابق. الخطوة السابعة، وهكذا ستكون النتيجة هي "witch" and her "broom". الخطوة الثامنة، مع وجود الراية g سيتابع البحث عن النمط ابتداءً من الموقع الذي انتهى فيه التطابق الأول، ولن يحصل على نتيجة طبعًا، فلن يجد إشارة تنصيص أخرى، طبعًا لم نتوقع ذلك، لكن الأمور تسير هكذا! يكرَّر المكمم في النمط الموسَّع -افتراضيًا- أكبر عدد ممكن من المرات، حيث يضيف المحرك القدر الأكبر من المحارف التي تتطابق مع +.، ثم يختصر النتيجة محرفًا تلو الآخر. النمط الكسول Lazy mode النمط الكسول أو المحدود هو نمط معاكس للنمط الموَّسع أو الجشع، ويعني أقل تكرار للمحارف، ويمكن أن نختار هذا النمط بوضع إشارة الاستفهام ? بعد المكمم حيث يصبح بالشكل ?* أو ?+ أو حتى ?? لــ?، ولنوضح الأمر علينا معرفة أن إشارة الاستفهام ? هي مكمم بحد ذاتها (صفر أو واحد)، وعندما تُضاف بعد مكمم آخر فسيصبح لها معنىً آخر، وهو تحويل نمط البحث إلى النمط المحدود الكسول، وسيعمل النمط g/"?+."/ في مهمتنا السابقة بالشكل الصحيح: let regexp = /".+?"/g; let str = 'a "witch" and her "broom" is one'; alert( str.match(regexp) ); // "witch", "broom" ولفهم التغيّر بوضوح سنتعقب عملية البحث خطوةً خطوةَ: الخطوة الأولى، تبقى الخطوة الأولى نفسها، وهي إيجاد المحرف '"' في الموقع الثالث من النص. الخطوة الثانية، وسيجد المحرك في الخطوة الثانية ما يطابق المحرف '.'. الخطوة الثالثة، سيظهر الاختلاف الآن، حيث لا يحاول المحرك في النمط المحدود إيجاد تطابق مع ما تمثله النقطة مرةً أخرى، بل يتوقف ويحاول إيجاد تطابقات مع بقية محارف النمط (أي '"') مباشرةً، وسيتوقف البحث عن النمط إذا وجد تطابقًا، لكنه سيجد الحرف i بدلًا منه. الخطوة الرابعة، سيزيد بعد ذلك محرك التعبير النمطي عدد التكرارات لمحرف النقطة مرةً واحدةً، ثم يحاول مطابقة بقية النمط، لكنه سيفشل ثانيةً، وسيزيد عدد مرات التكرار مرةً أخرى وأخرى… الخطوة الخامسة، سيتوقف البحث عندما يجد التطابق مع المحرف '"'. الخطوة السادسة، يبدأ البحث الجديد، نظرًا لوجود الراية g، من الموقع الذي انتهى عنده البحث السابق، وسيجد النتيجة الثانية. يعمل النمط الكسول بشكل مشابه للمكممات ?* و??، حيث يزيد محرك التعبير النمطي عدد التكرارات إذا لم يجد تطابقًا مع بقية محارف النمط في الموقع المُعطى. يُفعّل النمط الكسول للمكممات إذا تبعها المحرف ?، وإلا فستبقى في النمط الموّسع الجشع، إليك مثالًا: alert( "123 456".match(/\d+ \d+?/) ); // 123 4 يحاول النمط +d\ إيجاد أكبر عدد ممكن من الأعداد (نمط موسّع)، لذلك سيجد 123 ويتوقف، لأن المحرف التالي سيكون الفراغ ' '. سيجد المحرك المحرف التالي في النمط وهو الفراغ ' '. يحاول إيجاد الأعداد التالية وفقًا للنمط ?+d\ حيث يكون المكمم محدودًا، وسيجد العدد 4 ثم يتحقق من وجود بقية محارف النمط بعده، لكن محارف النمط قد انتهت. لا يكرر النمط الكسول أي شيء دون حاجة إلى ذلك، لذا سينتهي البحث بالنتيجة 4 123. لاحظ، تحسن محركات التعابير النمطية الحديثة خوارزميات البحث الداخلية لتعمل بسرعة أكبر، لذلك قد تعمل بطريقة مختلفة قليلًا عما وصفناه سابقًا، ولن نحتاج إلى معرفة تفاصيل الخوارزمية المحسَّنة عند كتابة التعابير النمطية وفهمها، لأنها تعمل داخليًا، وبما أن التعابير المعقدة صعبة التحسين، فسيجري البحث وفق الخطوات التي وصفناها سابقًا تمامًا. مقاربة بديلة نجد عادةً عند استخدام التعابير النمطية عدة طرق لتنفيذ الشيء نفسه، إذ يمكن في حالتنا السابقة إيجاد إشارات التنصيص دون الحاجة إلى البحث المحدود، بل من خلال النمط "+[^"]" let regexp = /"[^"]+"/g; let str = 'a "witch" and her "broom" is one'; alert( str.match(regexp) ); // "witch", "broom" سينجح هذا النمط لأنه يبحث عن إشارة تنصيص يتبعها تكرار لمحرف أو أكثر لا يمثل إشارة تنصيص، ثم يبحث عن إشارة تنصيص أخرى لإغلاق النص، وتجدر الملاحظة أن هذا المنطق في البحث لا يشكل بديلًا عن البحث المحدود، فهنالك حالات نحتاجه فيها. مثال عن إخفاق المكمم الكسول ونجاح الأسلوب البديل لنحاول مثلًا إيجاد رابط من الشكل <a href="..." class="doc"‎> بحيث يصلح لأي عنوان href، فما هو التعبير النمطي الذي سنستخدمه؟ قد تكون الفكرة الأولى هي: a href=".*" class="doc">/g>/، وسنتحقق منها: let str = '...<a href="link" class="doc">...'; let regexp = /<a href=".*" class="doc">/g; // !عملت alert( str.match(regexp) ); // <a href="link" class="doc"> ستعمل هذه الفكرة، لكن دعونا نتحقق منها عند وجود عدة روابط في النص: let str = '...<a href="link1" class="doc">... <a href="link2" class="doc">...'; let regexp = /<a href=".*" class="doc">/g; // حصلنا على رابطين في نتيجة واحدة alert( str.match(regexp) ); // <a href="link1" class="doc">... <a href="link2" class="doc"> النتيجة خاطئة، لأنّ المكمم *. ضمّ الكثير من المحارف، وسيكون التطابق مشابهًا للوصف التالي: <a href="....................................." class="doc"> <a href="link1" class="doc">... <a href="link2" class="doc"> لنُعدِّل النمط بجعل المكمم كسولًا ( ?*.): let str = '...<a href="link1" class="doc">... <a href="link2" class="doc">...'; let regexp = /<a href=".*?" class="doc">/g; // Works! alert( str.match(regexp) ); // <a href="link1" class="doc">, <a href="link2" class="doc"> سينجح الأمر وسيجد الرابطين: <a href="....." class="doc"> <a href="....." class="doc"> <a href="link1" class="doc">... <a href="link2" class="doc"> لنختبر ذلك مع نص آخر: let str = '...<a href="link1" class="wrong">... <p style="" class="doc">...'; let regexp = /<a href=".*?" class="doc">/g; // أخفق أيضًا alert( str.match(regexp) ); // <a href="link1" class="wrong">... <p style="" class="doc"> لقد أخفق البحث مجددًا، فقد طابق البحث الكثير من محارف النص بما فيها <p>، فما السبب؟ إليك ما حدث: يجد محرك التعبير النمطي المحارف <"=a href> بدايةً. ثم يبحث عن المكمم المحدود ?*.، الذي يأخذ محرفًا ويتحقق من وجود تطابق مع بقية أحرف النمط "class="doc "، فلا يجد شيئًا. ثم يضيف محرفًا إلى نتيجة النمط ?*. ويستمر بالإضافة إلى أن يصل إلى "class="doc "، لكن المشكلة أن ما وجده سيكون خارج حدود الرابط <...a> وضمن وسم مختلف <P>. إليك وصفًا لما حدث: <a href="..................................." class="doc"> <a href="link1" class="wrong">... <p style="" class="doc"> لاحظ إخفاق كل من البحث الجشع والكسول في المهمة، لكن سيُنفذ النمط "*[^"]"=href المطلوب في حالتنا، لأنه سيبحث عن المحارف ضمن السمة href إلى أن يجد أقرب إشارة تنصيص، وهذا ما نريده. إليك مثالًا: let str1 = '...<a href="link1" class="wrong">... <p style="" class="doc">...'; let str2 = '...<a href="link1" class="doc">... <a href="link2" class="doc">...'; let regexp = /<a href="[^"]*" class="doc">/g; // Works! alert( str1.match(regexp) ); // null, لا تطابق وهذا صحيح alert( str2.match(regexp) ); // <a href="link1" class="doc">, <a href="link2" class="doc"> الخلاصة للمكممات Quantifiers نمطان للعمل: الواسع الجشع Greedy: وهو الخيار الافتراضي الذي يحاول فيه محرك التعبير النمطي تكرار المحرف المُحصى أكبر عدد ممكن من المرات، فالنمط +d\ مثلًا سيستهلك كل الأرقام الممكنة، وعندما لا يعود قادرًا على إضافة المزيد من المحارف سيتابع مطابقة بقية أحرف النمط، فإذا لم يجد تطابقًا فسيقلل عدد مرات التكرار مرةً واحدةً -يتراجع- ويحاول مجددًا. المحدود الكسول Lazy: ويُمكَّن بإضافة إشارة الاستفهام بعد المكمم، حيث يحاول المحرك إيجاد تطابق مع بقية محارف النمط قبل تكرار البحث عن المحرف المُحصى. ويمكن استخدام بحث موّسع ومعدّل بدقة وفق النمط "[^"]+" بديلًا عن الأسلوبين. مهام لإنجازها إيجاد ثلاث نقاط متتابعة أو أكثر اكتب نمطًا للبحث عن ثلاث نقاط متتابعة أو أكثر let regexp = /your regexp/g; alert( "Hello!... How goes?.....".match(regexp) ); // ..., ..... الحل: let regexp = /\.{3,}/g; alert( "Hello!... How goes?.....".match(regexp) ); // ..., ..... تذكر أن النقطة . محرف خاص ولابد من تجاوزه وحشر النمط .\. تحديد الألوان في HTML أنشئ تعبيرًا نمطيًا للبحث عن ألوان HTML المكتوبة على الشكل ABCDEF#، ابحث أولًا عن المحرف # تليه 6 محارف لأرقام ستة عشرية، إليك مثالًا: let regexp = /...your regexp.../ let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2 #12345678"; alert( str.match(regexp) ) // #121212,#AA00ef الحل: علينا أن نبحث عن المحرف # متبوعًا بستة محارف ست عشرية. يمكن وصف المحرف الست عشري وفق النمط [0‎-9a-fA-F]، أو وفق النمط [‎0-9a-f] عند استخدام الراية i. يمكننا عندئذ البحث عن ستة محارف ست عشرية باستخدام المكمم {6}. بالنتيجة سيكون التعبير النمطي المناسب من الشكل: /#[a-f0-9]{6}/gi إليك شيفرة الحل: let regexp = /#[a-f0-9]{6}/gi; let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2" alert( str.match(regexp) ); // #121212,#AA00ef المشكلة في هذا الحل أن التعبير يطابق سلسلة طويلة أكثر حتى لو كانت أكثر من 6 محارف مثل: alert( "#12345678".match( /#[a-f0-9]{6}/gi ) ) // #123456 يمكن حل هذه المشكلة بإضافة ‎\b لنهاية التعبير: // لون alert( "#123456".match( /#[a-f0-9]{6}\b/gi ) ); // #123456 // ليس لون alert( "#12345678".match( /#[a-f0-9]{6}\b/gi ) ); // null إيجاد تطابق مع النمط /?+d+? d/ ما نتيجة التطابق في المثال الآتي: alert( "123 456".match(/\d+? \d+?/g) ); // ? الحل: النتيجة هي 4 123. يحاول النمط الكسول ‎d+?‎\ أقل عدد ممكن من الأرقام لكنه سيصل إلى محرف المسافة الفارغة وبالتالي سيأخذ فقط 123، ثم يأخذ النمط الثاني ‎d+?‎\ رقمًا واحدًا فقط ويكتفي. إيجاد تعليقات HTML أوجد كل التعليقات في النص التالي: let regexp = /your regexp/g; let str = `... <!-- My -- comment test --> .. <!----> .. `; alert( str.match(regexp) ); // '<!-- My -- comment \n test -->', '<!---->' الحل: علينا إيجاد نمط بداية التعليق --!> ثم نأخذ المحارف اللاحقة له حتى نصل إلى نمط نهاية التعليق <-- إذًا سيكون النمط من الشكل <--?*.--!> ، حيث يجبر المكمم الكسول المحرف . على التوقف قبل النمط <--. نحتاج أيضًا إلى الراية s مع النقطة لكي تستمر في ضم المحارف حتى لو انتقلنا إلى سطر جديد وإلا لن نتمكن من التقاط التعليقات الممتدة على أكثر من سطر. let regexp = /<!--.*?-->/gs; let str = `... <!-- My -- comment test --> .. <!----> ..`; alert( str.match(regexp) ); // '<!-- My -- comment \n test -->', '<!---->' إيجاد وسوم HTML أنشئ تعبيرًا نمطيًا لإيجاد كل وسوم HTML (للبداية والنهاية) مع سماتها. إليك مثالًا: let regexp = /your regexp/g; let str = '<> <a href="/"> <input type="radio" checked> <b>'; alert( str.match(regexp) ); // '<a href="/">', '<input type="radio" checked>', '<b>' نفترض هنا عدم وجود المحرفين < و> ضمن سمات الوسم، مما يسهل الأمر قليلًا. الحل سيكون التعبير النمطي الصحيح من الشكل: <[^<>]+> إليك شيفرة الحل: let regexp = /<[^<>]+>/g; let str = '<> <a href="/"> <input type="radio" checked> <b>'; alert( str.match(regexp) ); // '<a href="/">', '<input type="radio" checked>', '<b>' ترجمة -وبتصرف- للفصلين َQuntifiers +,*,? And {n} وَGreedy and Lazy Quantifiers من سلسلة The Moden JavaScript Tutorial. اقرأ أيضًا المقال السابق: المجموعات والمجالات في التعابير النمطية أساسيات البحث باستخدام التعابير النمطية في جافاسكربت المجموعات والمجالات في التعابير النمطية
  20. وجود عدة محارف أو أصناف محارف ضمن قوسين مربعين […] يعني البحث عن أي محرف بينها. سيكمل هذا المقال الغوص في التعابير النمطية بعد أن تطرقنا إلى مقدمة شاملة عنها في المقال السابق بعنوان أساسيات التعابير النمطية في جافاسكربت. المجموعات يعني النمط [eao] البحث عن أيٍّ من المحارف الثلاثة 'a' أو 'e' أو 'o'، ويُدعى هذا النمط بالمجموعة، ويمكن استخدام المجموعات ضمن التعابير النمطية ومع محارف نظامية: //"op" ثم [t أو m] جد alert( "Mop top".match(/[tm]op/gi) ); // "Mop", "top" لاحظ أنه وعلى الرغم من وجود عدة محارف ضمن المجموعة، فإنها سترتبط بمحرف واحد تمامًا عند إعادة النتيجة، فمثلًا لن يعيد البحث التالي أي نتيجة: //"la" ثم [o أو i] ثم "V" جد alert( "Voila".match(/V[oi]la/) ); // null, no matches سيبحث النمط عن: V ثم أحد الحرفين [oi]. ثم la. لذا ستكون النتيجة إما Vola أو Vila، والنصان غير موجودين. المجالات يمكن أن تضم الأقواس المربعة مجالات من المحارف، مثل المجال [a-z]، الذي يحدد المحارف بين a وz، أو المجال [0-5] الذي يحدد الأرقام بين 0 و5، وسنبحث في المثال التالي عن "x" متبوعًا برقمين أو حرفين من A إلى F: alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) ); // xAF ستجد مجالين ضمن الأقواس المربعة [A-F0-9]، وسنبحث عن عدد من 0 إلى 9 أو حرف من A إلى F، ويمكن البحث عن أحرف بالحالة الصغيرة بإضافة المجال a-f، بحيث يصبح النمط [A-F0-9a-f] أو باستخدام الراية i، كما يمكن استخدام أصناف المحارف داخل الأقواس المربعة، فلو أردنا مثلًا البحث عن محرف كلمة أو شرطة قصيرة، فستكون المجموعة المناسبة هي [-w\]، ويمكن الجمع أيضًا بين أكثر من صنف محارف، مثل المجموعة [s\d\]، التي تعني البحث عن محرف فراغ أو رقم انتبه إلى أن أصناف المحارف هي اختصارات لمجموعات محددة من المحارف، فمثلًا: d\: هي نفسها المجموعة [9-0]. w\: هي نفسها المجموعة [a-zA-Z0-9]. s\: هي نفسها المجموعة [t\n\v\f\r\ ]، بالإضافة إلى بعض محارف فراغ Unicode الخاصة. مثال: محرف الكلمة w\ للغات متعددة يمكن لصنف المحارف w\، كونه اختصارًا للنمط [a-zA-Z0-9]، أن يجد المحارف العربية أو الصينية وغيرها، لذلك يمكننا كتابة أنماط من التعابير لإيجاد محارف في أي لغة باستخدام خصائص الترميز Unicode مثل التعبير النمطي التالي: [{p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C\] ولنفسر الآن هذا النمط، حيث ننشئ فيه مجموعةً خاصةً بنا تتضمن محارف لها خصائص Unicode التالية: Alpha: للأحرف. M: للعلامات فوق الأحرف. Nd: للأعداد بالنظام العشري. Pc: للشرطة السفلية (_) والمحارف المشابهة. Join_C: للمحارف الخاصة 200c و200d التي تستخدم في لغات غير لاتينية، مثل العربية. إليك مثالًا: let regexp = /[\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}]/gu; let str = `Hi 你好 12`; // جد كل الأحرف والأرقام: alert( str.match(regexp) ); // H,i,你,好,1,2 يمكن بالطبع تعديل هذه النمط بإضافة خصائص جديدة أو إزالتها، وسنفصّل في هذا الخصائص لاحقًا. انتبه إلى أن خصائص يونيكود Unicode أي p{...}‎ غير مدعومة في متصفح إنترنت إكسبلورر IE، فلا يدعم متصفح IE خصائص Unicode، فإذا احتجنا إليها فيمكننا استخدام المكتبة XRegExp، ومن الممكن أيضًا استخدام مجالات لأحرف اللغة المطلوبة، مثل المجال [ا-ي] في اللغة العربية. مجالات الاستثناء ستجد أيضًا مجالات لاستثناء محارف معينة تبدو بالشكل […^]، فهي معلّمة بالمحرف ^ في البداية، وتطابق أي محرف عدا المحارف المعطاة، وإليك بعض الأمثلة: [aeyo^]: أي محرف عدا المحارف 'a' أو 'e' أو 'y' أو 'o'. [0-9^]: أي محرف عدا الأرقام، لها وظيفة الصنف D\. [s\^]: أي محرف لا يمثل محرف فراغ. يبحث المثال التالي عن أي محارف عدا الأحرف أو الأرقام أو الفراغات: alert( "alice15@gmail.com".match(/[^\d\sA-Z]/gi) ); // @ and . التجاوز عند استخدام […] رأينا سابقًا أننا نتجاوز (نهرِّب) الوظيفة الخاصة لمحرف باستخدام الشرطة المعكوسة .\، وإذا أردنا البحث عن الشرطة المعكوسة بذاتها نكررها مرتين \\، ويمكن استخدام معظم المحارف الخاصة ضمن الأقواس المربعة دون الحاجة إلى تجاوزها: لاتحتاج الرموز . + ( ) إلى تجاوز. لا يحدث تجاوز للشرطة - في بداية ونهاية النص، أي عندما لا تحدد مجالًا. يحدث تجاوز للعلامة ^ في بداية النص فقط، عندما تعني الاستثناء. يحدث تجاوز دائم لقوس الإغلاق المربع [، إن أردنا البحث عنه بحد ذاته. وبعبارة أخرى يُسمح باستخدام المحارف الخاصة جميعها دون الحاجة للتجاوز؛ إلا عندما تعني شيئًا محددًا ضمن الأقواس المربعة، فالنقطة ضمن الأقواس المربعة تعني نقطة، فمثلًا سيبحث النمط [.,] مثلًا عن نقطة أو فاصلة. يبحث النمط [-().^+] في المثال التالي عن أي محرف من المحارف +().^-: // لا حاجة للتجاوز let regexp = /[-().^+]/g; alert( "1 + 2 - 3".match(regexp) ); // تطابق +, - لكن إذا قررت تجاوز هذه المحارف للاحتياط، فلا مشكلة في ذلك: // تجاوز كل شيء let regexp = /[\-\(\)\.\^\+]/g; alert( "1 + 2 - 3".match(regexp) ); // سينجح أيضًا +, - المجالات واستعمال الراية "u" إذا وجد محرف بصيغة زوج بديل surrogate pair، وهو تفسير بعض الخصائص للمحرف ذي البايتات الأربع، فلا بدّ من استخدام الراية u للتعامل مع هذه المحارف. لنبحث مثلًا عن النمط [‎??‎] ضمن النص "?": alert( '?'.match(/[??]/) ); // [?] سيظهر محرف غريب مثل // جرى البحث بطريقة غير صحيحة وأعاد نصف المحرف فقط ستكون النتيجة خاطئةً، لأن التعبير النمطي لا يعلم بوجود زوج بديل افتراضيًا، إذ يعتقد محرك التعبير النمطي أن النمط [‎??‎] مكون من أربعة محارف، وليس محرفين: الأول هو النصف اليساري من ?. الثاني هو النصف اليميني من ?. ,الثالث هو النصف اليساري من ?. الرابع هو النصف اليميني من ?. ويمكننا الاطلاع على ترميزها بالشكل التالي: for(let i=0; i<'??'.length; i++) { alert('??'.charCodeAt(i)); // 55349, 56499, 55349, 56500 }; إذًا سيجد المثال السابق النصف الأيسر فقط من ? ويعرضه، لكن سنحل المشكلة عند إضافة الراية u: alert( '?'.match(/[??]/u) ); // ? ونستخدم الحل نفسه عندما نبحث عن مجال يحوي محارف بأزواج بديلة، مثل [‎?-?‎]، وسينتج خطأً إذا لم نستخدم الراية u. '?'.match(/[?-?]/); // خطأ: تعبير نظامي غير صحيح والسبب أنّ الزوج البديل سيعامل مثل محرفين دون الراية u، وهكذا سيُفسَّر النمط [‎?-?‎] على الشكل التالي: [<56500><55349>-<56499><55349>] حيث يُبدَّل كل زوج بترميزه، وهكذا سيكون المجال 56499-55349 خاطئًا، لأن الرمز النصي 56499 لبداية المجال أكبر من الرمز النصي 55349 لنهايته، وهذا هو سبب الخطأ، وسيعمل النمط بشكل صحيح بوجود الراية u: // ? إلى ? البحث عن محارف من alert( '?'.match(/[?-?]/u) ); // ? ترجمة -وبتصرف- للفصل Sets and Ranges من سلسلة The Moden JavaScript Tutorial. اقرأ أيضًا التعابير النمطية (regexp/PCRE) في PHP مقدمة في التعابير النمطية Regular Expressions كيفية التعامل مع النصوص في البرمجة
  21. التعابير النمطية Regular expressions هي أنماط تزودنا بأسلوب فعّال للبحث عن النصوص التي تطابق نمطًا محددًا واستبدالها في JavaScript، يتيح الكائن RegExp استخدام هذه التعابير، وتُدمج مع التوابع التي تتعامل مع النصوص. مقدمة إلى التعابير النمطية تتألف التعابير النمطية من نمط pattern، ورايات flags اختيارية، ولإنشاء كائن تعبير نمطي يمكن استخدام صيغتين، صيغة طويلة وصيغة قصيرة، أما الصيغة الطويلة فتكتب بالشكل: regexp = new RegExp("pattern", "flags"); وأما الصيغة القصيرة فتكتب باستخدام المحرف "/" بالشكل: regexp = /pattern/; // لا رايات regexp = /pattern/gmi; // g و m و i باستخدام الرايات تخبر الخطوط المائلة JavaScript بأننا ننشئ تعبيرًا نمطيًا، فهي تلعب دورًا مماثلًا لعلامة الاقتباس في النصوص، وفي كلتا الصيغتين سيصبح الكائن regexp نسخةً عن الصنف المدمج RegExp. لا يُسمح بإدخال متغيرات تمثل الأنماط ضمن صيغة الخطوط المائلة /.../ باستخدام القوالب {...}$ الديناميكية مثلًا كما نفعل في النصوص، فهي ثابتة بشكل كامل، وهذا هو الاختلاف الرئيسي بين الصيغتين، إذ نستخدم الخطوط المائلة عندما نريد استخدام تعابير نمطية محددة ومعروفة بالنسبة لنا عند كتابة الشيفرة، وهذه هي الحالة الأكثر شيوعًا، بينما نستخدم الصيغة new RegExp عادةً عندما نحتاج إلى إنشاء تعابير نمطية أثناء التنفيذ انطلاقًا من نص أُنشئ ديناميكيًا. let tag = prompt("What tag do you want to find?", "h2"); let regexp = new RegExp(`<${tag}>`); // "h2" إن كان الجواب /<h2>/ نفس نتيجة الرايات للتعابير النمطية رايات تؤثر على نتيجة البحث، وتستخدم JavaScript ستةً منها، وهي: i: سيكون البحث غير حساس لحالة الأحرف مع هذه الراية، أي لن يكون هناك فرق بين "a" و"A". g: سيعيد البحث جميع النتائج المتطابقة مع هذه الراية، وإلا فسيعيد النتيجة الأولى. m: سيعمل البحث في نمط الأسطر المتعددة، وسنغطي ذلك لاحقًا. s: ستمكّن نمط "dotall" الذي يسمح بأن نعدَّ النقطة . هي محرف نهاية السطر n\، وسنغطيه لاحقًا. u: سيمكّن الدعم الكامل لترميز Unicode، وبالتالي المعالجة الصحيحة لمحتويات الأقواس المعقوصة {..}، وسنغطيه لاحقًا. y: سيمكّن النمط اللاصق "Sticky"، حيث يبحث في المكان المحدد تمامًا من النص، وسنغطيه لاحقًا. البحث باستخدام التابع str.match تتكامل التعابير النمطية مع توابع النصوص، إذ يبحث التابع (str.match(regexp عن كل ما يطابق التعبير regexp في النص str، ويعمل وفق ثلاثة أنماط: النمط الأول، التعبير النمطي مع الراية g، ويعيد مصفوفةً تضم النتائج المطابقة: let str = "We will, we will rock you"; alert( str.match(/we/gi) ); // سيعيد مصفوفة من الحالتين المتطابقتين للبحث وانتبه إلى أنّ البحث سيعيد النتيجتين "we" و"We" لأن راية حالة الأحرف i مفعّلة. النمط الثاني، إذا لم نفعّل الراية g، فسيعيد البحث النتيجة الأولى فقط ضمن مصفوفة، مع وضع التطابق في الدليل 0، بالإضافة إلى تفاصيل أخرى في الخصائص: let str = "We will, we will rock you"; let result = str.match(/we/i); // g دون الراية alert( result[0] ); // We (التطابق الأول) alert( result.length ); // 1 // Details: alert( result.index ); // 0 (موقع التطابق) alert( result.input ); // We will, we will rock you (النص الأصلي) قد تحتوي المصفوفة على عناصر أخرى بالإضافة إلى العنصر ذي الدليل 0؛ إذا كان جزء من التعبير النمطي ضمن قوسين مغلقين وسنغطي ذلك في المقالات القادمة. النمط الثالث، إذا لم توجد أي تطابقات، فسيعيد التابع القيمة null، بوجود الراية g أو عدم وجودها، لذا انتبه أننا لن نحصل في هذه الحالة على مصفوفة فارغة، بل على القيمة null، وسيؤدي نسيان هذه الحقيقة إلى مشاكل عدة: let matches = "JavaScript".match(/HTML/); // = null if (!matches.length) { //length خطأ لا يمكن قراءة الخاصية alert("Error in the line above"); } إذا أردنا أن نحصل دائمًا على مصفوفة، فيمكننا أن ننفذ الأمر بالشكل التالي: let matches = "JavaScript".match(/HTML/) || []; if (!matches.length) { alert("No matches"); // ستعمل الآن } الاستبدال باستخدام التابع str.replace يستبدل التابع (str.replace(regexp, replacement التطابقات الموافقة للكائن regexp في النص str بقيمة replacement، وستستبدل كل التطابقات عند استخدام الراية g، وإلا فسيستبدل أول تطابق فقط، وإليك مثالًا: // g دون الراية alert( "We will, we will".replace(/we/i, "I") ); // I will, we will // مع الراية alert( "We will, we will".replace(/we/ig, "I") ); // I will, I will يمكن استخدام محارف خاصة ضمن الوسيط الثاني replacement للبحث عن أجزاء من معيار التطابق: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } الرمز ما يفعله ضمن النص replacment &$ يمثل نص التطابق `$ يمثل النص الواقع قبل نص التطابق. '$ يمثل النص الواقع بعد نص التطابق. n$ يمثل التطابق ذا الرقم n من مجموعة التطابق (الموجود ضمن قوسي تجميع"()" ) . ‎$<name>‎ يمثل التطابق ذا الاسم name من مجموعة التطابق (الموجود ضمن قوسي تجميع"()" ). $$ يمثل المحرف $ مثال باستخدام &$: alert( "I love HTML".replace(/HTML/, "$& and JavaScript") ); // I love HTML and JavaScript الاختبار باستخدام التابع regexp.test يبحث التابع (regexp.test(str عن تطابق واحد على الأقل -إن وُجد- ويعيد القيمة true، وإن لم يجد تطابقًا فسيعيد القيمة false. let str = "I love JavaScript"; let regexp = /LOVE/i; alert( regexp.test(str) ); // true سندرس لاحقًا في هذا القسم تعابير نمطيةً أكثر، وسنتعرف على توابع أخرى لاحقًا. أصناف المحارف لنتأمل مهمةً تتطلب تحويل رقم هاتف، مثل "67-45-123-(903)7+"، إلى رقم صرف، أي 79031234567، لتنفيذ ذلك يمكننا تتبع وحذف أي محرف لا يمثل رقمًا، وستساعدنا أصناف المحارف في ذلك، حيث تمثل إشارات خاصةً تطابق أي رمز ضمن مجموعة معينة، وسنتعرف بدايةً على الصنف "digit"، الذي يُعبَّر عنه بالشكل d\، ويرتبط بأي رقم مفرد، فمثلًا لنجد الرقم الأول في رقم الهاتف: let str = "+7(903)-123-45-67"; let regexp = /\d/; alert( str.match(regexp) ); // 7 سيبحث التابع عن كل الأرقام التي سيجدها في النص بإضافة الراية g، وسيعيدها ضمن مصفوفة: let str = "+7(903)-123-45-67"; let regexp = /\d/g; alert( str.match(regexp) ); // 7,9,0,3,1,2,3,4,5,6,7 // لنشكل عددًا من أرقام المصفوفة: alert( str.match(regexp).join('') ); // 79031234567 سنستعرض الآن بعض الأصناف الأكثر استعمالًا، وهي: d\: من كلمة digit رقم، ويعيد أي رقم بين 0 و9. ‎\s: من كلمة space فراغ، وتضم محارف الفراغ، مثل: مسافة الجدولة t\، والسطر الجديد n\، وغيرها من الرموز النادرة الاستخدام مثل r\ وv\ وf\. w\: من كلمة word كلمة، وتعيد محارف قد تشكل كلمةً، مثل الأحرف اللاتينية أو الأرقام أو الشرطة السفلية _، ولا تنتمي الأحرف غير اللاتينية، مثل العربية، إلى هذا الصنف، إذ تشير الرموز d\s\w\ مثلًا إلى رقم متبوع بمحرف فراغ، ويليه محرف كلمة مثل 1 a. يمكن أن يضم الكائن محارف تعابير نمطية بالإضافة إلى الأصناف، فمثلًا سيبحث التعبير CSS\d عن الكلمة CSS متبوعةً برقم: let str = "Is there CSS4?"; let regexp = /CSS\d/ alert( str.match(regexp) ); // CSS4 كما يمكن استخدام أصناف محارف عدة: alert( "I love HTML5!".match(/\s\w\w\w\w\d/) ); // ' HTML5' الأصناف المعكوسة لكل صنف من أصناف المحارف صنف معكوس inverse class، يرمز له بالحرف نفسه لكن بحالة حرف كبير uppercase، ويعني ذلك الحصول على أي محرف عدا المحرف الذي يعيده الصنف عادةً، أي: D\: لا يعيد رقمًا، وإنما يعيد أي محرف عدا المحارف التي يعيدها d\، مثل الأحرف اللاتينية. S\: لا يعيد محرف فراغ، وإنما يعيد أي محرف عدا المحارف التي يعيدها s\، مثل الأحرف اللاتينية. W\: لا يعيد محرف كلمة، وإنما يعيد أي محرف عدا المحارف التي يعيدها w\، مثل الأحرف غير اللاتينية أو الفراغات. لاحظ كيف سنستخدَم هذه الأصناف في تحويل رقم الهاتف في المثال السابق إلى رقم صرف وبطريقة أقصر، وذلك بإزالة المحارف التي لا تمثل أرقامًا D\: let str = "+7(903)-123-45-67"; alert( str.replace(/\D/g, "") ); // 79031234567 يمثل المحرف نقطة أي محرف يمثل المحرف . صنفًا مميزًا من المحارف، ويطابق أي محرف عدا محرف السطر الجديد، إليك مثالًا: alert( "Z".match(/./) ); // Z كما يمكن إدراجه وسط التعبير regexp: let regexp = /CS.4/; alert( "CSS4".match(regexp) ); // CSS4 alert( "CS-4".match(regexp) ); // CS-4 alert( "CS 4".match(regexp) ); // CS 4 (الفراغ هو محرف أيضًا) لاحظ أن النقطة تطابق أي محرف، لكنها لن تبحث عن محرف غير موجود، فلا بدّ من وجود محرف حتى يعيده هذا الصنف: alert( "CS4".match(/CS.4/) ); // null, لن يعيد الصنف شيئًا لعدم وجود محرف لاحظ أن محرف النقطة يمثل أي محرف بالفعل بوجود الراية "s"، فلا تعيد النقطة عادةً محرف السطر الجديد، إذ يعيد التعبير A.B الحرفين A وB وأي محارف بينهما عدا محرف السطر الجديد n\: alert( "A\nB".match(/A.B/) ); // null (لا تطابقات) لكننا في عدة حالات نريد للنقطة أن تعني أي محارف فعلًا، بما في ذلك السطر الجديد، لذلك سنستخدم الراية s وسنحصل على المطلوب: alert( "A\nB".match(/A.B/s) ); // A\nB (match!) انتبه إلى أن المتصفح IE لا يدعم الراية s، لكن يمكن استخدام التعبير النمطي [‎\s\S] الذي يعيد أي محرف في أي مكان، وسنغطي ذلك لاحقًا. alert( "A\nB".match(/A[\s\S]B/) ); // A\nB (match!) ويعني التعبير [‎\s\S] البحث عن (محرف فراغ أو محرف لا يمثل فراغًا)، وهذا يمثل عمليًا أي محارف، ويمكن استخدام أي أزواج من الأصناف وعكسها، مثل [‎\d\D]، كما يمكن استخدام التعبير [^] الذي يعني البحث عن أي محرف عدا "لا شيء"، ويمكن استخدام الحيلة ذاتها إن أردنا أن يؤدي المحرف "نقطة" . كلا الوظيفتين، أي مطابقة أي محارف عدا السطر الجديد . أو مع السطر الجديد [‎\s\S]. انتبه أيضًا إلى الفراغات، إذ لا نكترث عادةً لوجود فراغات زائدة، وسنعتبر النص 1-5 مماثلًا للنص 1 - 5، لكن قد يخفق التعبير النمطي regexp إن لم يأخذ هذه الفراغات في الحسبان. لنحاول مثلًا أن نجد أرقامًا مفصولةً بشرطة صغيرة (-): alert( "1 - 5".match(/\d-\d/) ); // null, لا تطابق سنصلح ذلك بإضافة فراغات إلى التعبير النمطي d - \d\: alert( "1 - 5".match(/\d - \d/) ); // 1 - 5, سنجد الآن تطابقًا // \s أو يمكن استخدام الصنف: alert( "1 - 5".match(/\d\s-\s\d/) ); // 1 - 5, سيعمل أيًا فالفراغ هو محرف، ولا يمكننا إضافة أو إزالة الفراغات من تعبير نمطي، ثم نتوقع أن يعمل كما هو مطلوب، فكل المحارف التي ندخلها في التعبير النمطي ستُؤخذ في الحسبان عند البحث، بما فيها الفراغات. تعامل التعابير النمطية مع ترميز يونيكود Unicode تستخدم JavaScript ترميز يونيكود Unicode لتمثيل النصوص، حيث تُرمّز معظم المحارف باستخدام 2 بايت، وهذا ما يسمح بترميز 65536 محرف كحد أقصى، ولا يعتبر العدد السابق كافيًا لترميز كل المحارف الممكنة، لذلك ستجد أن بعض المحارف الخاصة رمِّزت باستخدام 4 بايت، مثل المحرف ? -التمثيل الرياضي للمحرف X- أو ? -الابتسامة- وبعض المحارف الهيروغليفية وغيرها، وإليك قيم Unicode لبعض المحارف الخاصة: المحرف ترميز Unicode عدد البايتات المستخدمة a 0x0061 2 ≈ 0x2248 2 ? 0x1d4b3 4 ? 0x1d4b4 4 ? 0x1f604 4 تشغل محارف -مثل a- بايتين اثنين، ومحارف -مثل ? و?- أربعة بايتات. كان ترميز Unicode في الأيام الأولى لظهور JavaScript أكثر بساطةً، حيث لم توجد محارف من أربعة بايتات، لذلك ستجد أن بعض ميزات اللغة ستتعامل معها بشكل غير صحيح، فتعتقد الخاصية length مثلًا أنها عبارة عن محرفين: alert('?'.length); // 2 alert('?'.length); // 2 والسبب في ذلك أنّ هذه الخاصية ستعامل المحرف ذا البايتات الأربعة على أنه محرفان لكل منهما بايتان فقط، وهذا أمر خاطئ، حيث ينبغي اعتبارها محرفًا واحدًا، وتُدعى "الزوج البديل" surrogate pair، وسنرى ذلك لاحقًا. تعامل التعابير النمطية regular expression المحارف الطويلة ذات البايتات الأربع مثل زوج من البايتات الثنائية، وقد يقود ذلك إلى أخطاء كما هو الحال في النصوص، لكن -وعلى خلاف النصوص- للتعابير النمطية الراية u التي تعالج هذه المشكلة، إذ يعالج التعبير المحارف ذات البايتات الأربع بشكل صحيح عند وجود هذه الراية، وسيصبح البحث متاحًا ضمن خصائص الترميز Unicode كما سنرى تاليًا. خصائص ترميز Unicode باستعمال {…}p\ لمحارف Unicode العديد من الخصائص التي تصف الفئة التي ينتمي إليها المحرف، كما تقدم معلومات متنوعةً عنها، فلو كان للمحرف الخاصية Letter فسيعني ذلك أنه ينتمي إلى أبجدية ما، كما يعني امتلاكه الخاصية Number أنه رقم، وقد يكون رقمًا عربيًا أو صينيًا وهكذا، ويمكن البحث عن محرف يمتلك خاصيةً معينةً باستخدام الصنف {...}p\، ولاستخدام هذا الصنف لا بد أن نفعّل الراية u في التعبير النمطي. يبحث التعبير {p{Letter\مثلًا عن حرف في أي لغة، كما يمكن كتابته بالشكل {p{L\، وهو اسم مستعار للخاصية Letter، ولمعظم الخصائص أسماء مستعارة قصيرة. سيجد البحث في المثال التالي ثلاثة أنواع من الأحرف: انكليزي وجورجي وكوري. let str = "A ბ ㄱ"; alert( str.match(/\p{L}/gu) ); // A,ბ,ㄱ alert( str.match(/\p{L}/g) ); // null (no matches, \p doesn't work without the flag "u") إليك الفئات الأساسية للمحارف، وفئاتها الفرعية: الحرف Letter: واسمها المستعار L. Ll: حرف صغير. Lm: حرف معدِّل modifier. Lt: عنوان. Lu: حرف كبير. Lo: غير ذلك. العدد Number: واسمها المستعار N. Nd: رقم بالصيغة العشرية. Nl: رقم حرف. No: غير ذلك. علامات الترقيم Punctuation: واسمها المستعار P. Pc: واصلة. Pd: خط فاصل dash. Pi: علامة اقتباس فاتحة. Pf: علامة اقتباس غالقة. Ps: مفتوح. Pe: مغلق. Po: غير ذلك. العلامة أو الحركة Mark: واسمها المستعار M، مثل العلامات أو الحركات فوق الأحرف وغيرها. Mc: علامة ضم مع فراغ spacing combining، وعلامة الضم هي محرف يعدّل محرفًا آخر بإضافة علامة أو حركة فوقه أو تحته وهكذا. Me: علامة ضم محيطة enclosing. Mn: علامة ضم دون فراغ non-spacing. الرمز Symbol: واسمه المستعار S. Sc: رموز عملة. Sk: رمز مُعدِّل. Sm: رمز رياضي. So: رمز آخر. الفواصل Separator: واسمها المستعار Z. Zl: خط. Zp: مقطع. Zs: فراغ. فئات أخرى: واسمها المستعار C. Cc: تحكم. Cf: تنسيق. Cn: لم يحدد بعد. Co: استخدام خاص. Cs: بديل. فلو أردنا مثلًا أحرفًا كبيرة فسنستخدم {p{Ll\، بينما نستخدم {p{p\ لعلامات الترقيم وهكذا. ستجد أيضًا بعض الفئات المشتقة، مثل: Alphabetic: واسمها المستعار Alpha، وتضم الأحرف L، والأرقام على شكل أحرف Nl، مثل Ⅻ وهو 12 بالرومانية. Hex_Digit: وتضم الأرقام الست عشرية: 0-9 وa-f. يدعم الترميز Unicode خصائص عديدةً، وسيزيد ذكرها من حجم المقالة بشكل كبير، لكن يمكنك الاطلاع على المراجع التالية: قائمة بكل الخصائص وفقًا للمحرف. قائمة بكل المحارف وفقًا للخاصية. قائمة بالاسماء المستعارة القصيرة للخصائص. قاعدة كاملة بمحارف Unicode بتنسيق نصي مع كامل خصائصها. مثال: الأعداد الست عشرية لننظر مثلًا إلى الأعداد الست عشرية المكتوبة بالشكل xFF، حيث F هو رقم ست عشري (0-1 أو A-F)، ويمكن الإشارة إلى الرقم الست عشري بالشكل {p{Hex_Digit\: let regexp = /x\p{Hex_Digit}\p{Hex_Digit}/u; alert("number: xAF".match(regexp)); // xAF مثال: الكتابة التصويرية الصينية في ترميز Unicode خاصية تحدد نظام الكتابة، ويمكن أن تأخذ قيمًا مثل: Cyrillic وGreek وArabic وHan (الصينية) وغيرها من القيم المشابهة، وللبحث عن محرف في نظام كتابة محدد علينا استخدام الخاصية <Script=<value، فللعربية مثلًا نستخدم {p{sc=Arabic\، وللصينية نستخدم {p{sc=Han\ وهكذا. let regexpHan = /\p{sc=Han}/gu; // يعيد التصويرية الصينية let regexpArab = /\p{sc=Arabic}/gu; // يعيد العربية let str = `Hello Привет 你好 جميل 123_456`; alert( str.match(regexpHan) ); // 你,好 alert( str.match(regexpArab) ); // ج,م,ي,ل مثال: رموز العملة للمحارف التي ترمز إلى العملات -مثل $ و€ و¥- خاصية في ترميز Unicode، هي {p{Currency_Symbol\، واسمها المختصر {p{Sc\، لنستخدم هذه الخاصية في الحصول على سعر منتج ضمن تنسيق يحوي رمز عملة يليه رقم: let regexp = /\p{Sc}\d/gu; let str = `Prices: $2, €1, ¥9`; alert( str.match(regexp) ); // $2,€1,¥9 وسنتعرف لاحقًا في مقالات قادمة على آلية البحث عن أعداد تحتوي عدة أرقام. محارف الارتكاز: محرفا بداية النص ^ ونهايته $ يحمل المحرفان ^ و$ معانٍ خاصةً في التعابير النمطية regular expression، وتسمى بالمرتكزات أو المرابط Anchors، حيث تبحث العلامة ^ عن تطابق في بداية النص، بينما تبحث $ عن تطابق في نهايته، لنر مثلًا إن بدأ نص ما بالكلمة "Mary": let str1 = "Mary had a little lamb"; alert( /^Mary/.test(str1) ); // true يعني النمط أن نبحث عن الكلمة "Mary" في بداية السطر حصرًا، وبشكل مشابه يمكن أن نستخدم $ للتحقق من وجود الكلمة "snow" مثلًا في نهاية نص: let str1 = "it's fleece was white as snow"; alert( /snow$/.test(str1) ); // true يمكن استخدام توابع التعامل مع النصوص startsWith/endsWith في هذه الحالات بالتحديد، لكن ينبغي استخدام التعابير النمطية في الحالات الأكثر تعقيدًا. اختبار التطابق الكامل يستخدم المرتكزان السابقان معًا $...^ لاختبار تطابق نص بشكل كامل مع النمط، مثل التحقق من مطابقة ما يدخله المستخدم للتنسيق المطلوب، لنتحقق مثلًا أن نصًا له التنسيق الزمني التالي 12:34، وهو عدد من رقمين، تليه نقطتان ":"، ثم عدد من رقمين، لذا سنستخدم التعبير d\d:\d\d\ في عالم التعابير النمطية: let goodInput = "12:34"; let badInput = "12:345"; let regexp = /^\d\d:\d\d$/; alert( regexp.test(goodInput) ); // true alert( regexp.test(badInput) ); // false يجب أن يبدأ التطابق مباشرة ًعند بداية النص ^، وينتهي بنهايته $، ويجب أن يطابق تنسيق النص تنسيق التعبير النمطي، فإذا وجدَت أي اختلافات أو محارف زائدة فستكون النتيجة "false"، وتسلك المرتكزات سلوكًا مختلفًا بوجود الراية m، وسنطلع على ذلك لاحقًا. انتبه إلى أن ليس للمرتكزات عرض، فالمرتكزات محارف اختبار، وليس لها عرض، فهي لا تطابق محارف محددةً، بل تجبر محرك التعبير النمطي للتحقق من الشرط (بداية ونهاية نص). نمط الأسطر المتعددة: تأثير الراية "m" على المرتكزان ^ و $ يُفعّل نمط الأسطر المتعددة باستخدام الراية m، التي تؤثر على سلوك المرتكزين $ و^ فقط، فلا تطابق المرتكزات في نمط الأسطر المتعددة بداية ونهاية النص فقط، بل بداية ونهاية السطر. البحث عند بداية سطر ^ يحتوي النص في المثال التالي على عدة أسطر، وسيأخذ النمط d/gm\^/ رقمًا من بداية كل سطر: let str = `1st place: Winnie 2nd place: Piglet 3rd place: Eeyore`; alert( str.match(/^\d/gm) ); // 1, 2, 3 سنحصل دون الراية m على الرقم الموجود في أول سطر فقط يطابق النمط: let str = `1st place: Winnie 2nd place: Piglet 3rd place: Eeyore`; alert( str.match(/^\d/g) ); // 1 والسبب أنّ العلامة ^ ستطابق افتراضيًا بداية النص فقط، بينما ستطابق في نمط الأسطر المتعددة بداية أي سطر. انتبه، فتعني بداية السطر رسميًا المحرف الذي يأتي بعد محرف السطر الجديد، وهكذا ستطابق العلامة ^ في نمط الأسطر المتعددة كل المحارف التي يسبقها محرف السطر الجديد n\. البحث عند نهاية سطر $ يسلك المرتكز $ السلوك السابق نفسه، إذ يجد التعبير النمطي $d\ مثلًا آخر رقم في كل سطر: let str = `Winnie: 1 Piglet: 2 Eeyore: 3`; alert( str.match(/\d$/gm) ); // 1,2,3 سيطابق المرتكز $ نهاية النص ككل دون استخدام الراية m، وبالتالي سنحصل فقط على آخر رقم. انتبه، فتعني نهاية السطر رسميًا المحرف الذي يأتي قبل محرف السطر الجديد، وهكذا ستطابق العلامة $ في نمط الأسطر المتعددة كل المحارف التي تسبق محرف السطر الجديد n\ مباشرةً. البحث عن محرف السطر الجديد n\ بدل المرتكز $ يمكن البحث عن سطر جديد باستخدام المحرف n\ بدلًا من البحث عن المرتكزين ^ و$، لكن ما الفرق؟ سنبحث في المثال التالي عن d\n\بدلًا من $d\: let str = `Winnie: 1 Piglet: 2 Eeyore: 3`; alert( str.match(/\d\n/gm) ); // 1\n,2\n ستجد الشيفرة تطابقين بدلًا من ثلاث، وذلك لعدم وجود سطر جديد بعد الرقم 3، على الرغم من وجود مرتكز نهاية النص الذي يطابق $، أما الاختلاف الآخر فهو أنّ n\محرف، وسيظهر ضمن النتيجة، وليس مثل المرتكزين ^ و$ اللذين يحددان شرط البحث في بداية ونهاية النص، وبالتالي سنستخدم n\ إذا أردنا ظهور محرف السطر الجديد في النتيجة، وإلا استخدمنا ^ و$. حدود الكلمة: b\ حدود الكلمة اختبار، مثل ^ و$، حيث يشير وجود العلامة b\ بأنّ الموقع الذي وصل إليه محرك بحث التعابير النمطية هو حد لكلمة، وتوجد ثلاثة مواقع مختلفة يمكن اعتبارها حدودًا لكلمة، وهي: في بداية نص، إذا كان أول محرف نصي فيه هو محرف كلمة w\. بين محرفين في نص، إذا كان أحدهما محرف كلمة w\ والآخر ليس كذلك. في نهاية نص، إذا كان آخر محرف فيه هو محرف الكلمة w\. يمكن أن تجد التعبير bJava\b\ مثلًا في النص !Hello, Java عندما تكون الكلمة Java منفصلةً عن غيرها، لكنك لن تحصل على نفس النتيجة في النص !Hello, JavaScript alert( "Hello, Java!".match(/\bJava\b/) ); // Java alert( "Hello, JavaScript!".match(/\bJava\b/) ); // null في الشكل التالي ستمثل المواقع المشار إليها العلامة b\ في النص !Hello, Java: لذلك فهي تطابق النمط bHello\b\ لأن: بداية النص تتطابق مع العلامة b\. ثم تتطابق مع الكلمة Hello. ثم تتطابق مع العلامة b\ مرةً أخرى، كما لو أنها بين المحرف o والفاصلة. إذًا سنعثر على النمط bHello\b\، لكن ليس النمط bHell\b\، لعدم وجود علامة حد الكلمة b\ بعد المحرف l، كما لن نحصل على النمط Java!\b لأن علامة التعجب ليست محرف كلمة w\، وبالتالي لا وجود لعلامة حد الكلمة b\ بعده. alert( "Hello, Java!".match(/\bHello\b/) ); // Hello alert( "Hello, Java!".match(/\bJava\b/) ); // Java alert( "Hello, Java!".match(/\bHell\b/) ); // null (no match) alert( "Hello, Java!".match(/\bJava!\b/) ); // null (no match) يمكن استخدام b\ مع الأرقام أيضًا، إذ يبحث النمط b\d\d\b\ مثلًا عن عدد من رقمين -عدد بخانتين- منفصل عن غيره، أي يبحث عن عدد بخانتين غير محاط بمحارف الكلمة w\، مثل محارف الفراغات أو علامات الترقيم أو مرتكزات بداية ونهاية نص. alert( "1 23 456 78".match(/\b\d\d\b/g) ); // 23,78 alert( "12,34,56".match(/\b\d\d\b/g) ); // 12,34,56 انتبه، لا تعمل العلامة b\ مع الأبجديات غير اللاتينية، إذ تتحقق العلامة b\ من وجود محرف كلمة w\ في طرف نص وعدم وجوده في الطرف الآخر، وبما أنّ محرف الكلمة w\ سيدل على الأحرف اللاتينية a-z أو الأرقام أو الشرطة السفلية فقط، فلن يعمل مع محارف اللغات الأخرى، مثل العربية أو الصينية. المحارف الخاصة وطريقة تجاوزها يُستخدم المحرف \ كما رأينا للإشارة إلى أصناف المحارف -مثل d\- فهو إذًا محرف خاص، وستجد محارف خاصةً أخرى تحمل معنىً خاصًا في التعابير النمطية، وتستخدم لتنفيذ عمليات بحث أكثر قدرةً، وهذه المحارف هي: [ ]\ ^ $ . | ? * + ( )، ولا حاجة طبعًا لتذكر هذه القائمة، فسنتعامل مع كل محرف منها بشكل منفصل وستحفظها تلقائيًا. التجاوز لنفترض أننا نريد البحث عن محرف النقطة بذاته، وليس أي محرف، في هذه الحالة -وبقية الحالات التي نريد فيها البحث عن محرف خاص بحد ذاته كما لو أنه محرف عادي- سنضع المحرف \ قبله، أي .\ في حالة النقطة، وتُدعى هذه العملية بالتجاوز أو تهريب محرف escaping a character، إليك مثالًا: alert( "Chapter 5.1".match(/\d\.\d/) ); // 5.1 (تطابق!) alert( "Chapter 511".match(/\d\.\d/) ); // null تعتبر الأقواس محارف خاصةً أيضًا، فلا بد من البحث عنها وفق النمط )\، ويبحث المثال التالي عن النص "()g": alert( "function g()".match(/g\(\)/) ); // "g()" إذا أردنا البحث عن المحرف الخاص \ فلا بدّ من مضاعفته \\: alert( "1\\2".match(/\\/) ); // '\' الشرطة المائلة "/" لا تعتبر الشرطة المائلة '/' من المحارف الخاصة، لكنها تستخدم في JavaScript لفتح وإغلاق التعابير النمطية /...pattern.../ فلا بد من تجاوزها أيضًا، إليك الطريقة التي نبحث فيها عن الشرطة المائلة: alert( "/".match(/\//) ); // '/' لا داعي لتجاوز الشرطة المائلة في الحالة التي لا نستخدم فيها النمط /.../، بل ننشئ كائن تعبير نمطي باستخدام new RegExp: alert( "/".match(new RegExp("/")) ); // / يجد الإنشاء باستخدام new RegExp عندما ننشئ تعبيرًا نمطيًا باستخدام new RegExp، فلا حاجة لتجاوز المحرف / لكن يتحتم علينا تجاوز غيره. تأمل الشيفرة التالية: let regexp = new RegExp("\d\.\d"); alert( "Chapter 5.1".match(regexp) ); // null لقد نجح البحث المشابه في أمثلة سابقة عندما استخدمنا /\d\.\d/، لكن لن يعمل البحث باستخدام ("new RegExp("\d\.\d فما السبب؟ السبب أن الشرطة المائلة ستُستهلك من قبل النص، وكما نتذكر فللنصوص العادية محارفها الخاصة -مثل n\- وقد استخدمت الشرطة المعكوسة backslash للتهريب. إليك مثالًا: alert("\d\.\d"); // d.d تستهلك إشارتا التنصيص الشرطة المعكوسة وتفسرها بطريقتها، فمثلًا: تتحول n\ إلى محرف السطر الجديد. تتحول u1234\ إلى محرف Unicode بهذا الرمز. وفي حال لم يوجد معنىً لوجود الشرطة المعكوسة -مثل d\ أو z\- فستُزال هذه الشرطة ببساطة. يحصل new RegExp على نص بلا شرطات معكوسة، لهذا لن يفلح البحث، ولحل المشكلة لا بدّ من مضاعفة الشرطة المعكوسة، لأن إشارتي التنصيص تحولان \\ إلى \. let regStr = "\\d\\.\\d"; alert(regStr); // \d\.\d (عملية صحيحة) let regexp = new RegExp(regStr); alert( "Chapter 5.1".match(regexp) ); // 5.1 خلاصة يتألف التعبير النمطي من نمط pattern، ورايات flags اختيارية هي: g وi وm وu وs وy. لا تختلف عملية البحث دون استخدام الرايات والرموز الخاصة عن أي عملية بحث اعتيادية ضمن نص. يبحث التابع (str.match(regexp عن كل حالات التطابق التي يحددها التعبير regexp بوجود الراية g، وإلا فسيبحث عن أول تطابق فقط. يستبدل التابع (str.replace(regexp, replacement التطابقات التي يحددها التعبير regexp بالنص replacement، حيث يستبدل التطابقات كلها عند وجود الراية g، وإلا فسيستبدل أولها فقط. يعيد التابع (regexp.test(str القيمة true إن وجد تطابقًا على الأقل مع التعبير المستخدم، وإلا فسيعيد false. هنالك أصناف محارف متعددة، هي: d\: للأرقام. D\: لغير الأرقام. s\: لمحارف الفراغات والجدولة والسطر الجديد. S\: لكل المحارف عدا محارف الفراغات والجدولة والسطر الجديد. w\: كل الأرقام والأحرف اللاتينية والشرطة السفلية (_). W\: كل المحارف عدا ما ذكرناه في السطر السابق. .: أي محرف عدا محرف السطر الجديد، وأي محرف تمامًا عند استخدام الراية "s". تؤمن مجموعة المحارف Unicode التي تستخدمها JavaScript العديد من الميزات المتعلقة بالمحارف، مثل تحديد اللغة التي ينتمي إليها محرف معين، وهل يمثل المحرف علامة ترقيم وغيرها، ويتطلب ذلك استخدام الراية u. تدعم الراية u استخدام رموز Unicode في التعابير النمطية، ويعني ذلك أمرين اثنين: ستتعامل الميزات والخصائص مع المحارف المكونة من أربع بايتات بشكل صحيح ومثل محرف واحد، وليس مثل محرفين يتكون كل منهما من بايتين. يمكن استخدام خصائص Unicode في عمليات البحث من خلال {...}\p. يمكن البحث عن كلمات في لغة محددة باستخدام خصائص Unicode، بالإضافة إلى البحث عن محارف خاصة مثل إشارات التنصيص، العملات،…. للبحث عن المحارف الخاصة [ \ ^ $ . | ? * + ( ) بذاتها، لا بدّ من وضع الشرطة المائلة \ قبلها لتجاوز الوظيفة الخاصة للمحرف. ينبغي تجاوز الشرطة المعكوسة \ أيضًا في النمط /.../، لكن ليس ضمن new RegExp. عند تمرير نص إلى new RegExp فلا بدّ من مضاعفة الشرطة المعكوسة، لأن إشارة التنصيص \\ تستهلك إحداهما. ترجمة -وبتصرف- للفصول: Patterns and flags character classes Unicode: flag "u" and class \p{…} Anchors: string start ^ and end $ Multiline mode of anchors ^ $, flag "m" Word boundary: \b Escaping special characters من سلسلة The Modern JavaScript Tutorial. اقرأ أيضًا المقال السابق: مكونات الويب: التعامل مع شجرة DOM الخفية التعابير النمطية (regexp/PCRE) في PHP مقدمة في التعابير النمطية Regular Expressions كيفية التعامل مع النصوص في البرمجة
  22. الآن وبعد أن تعرّفت على سكراتش Scratch في المقال السابق، البرمجة باستخدام سكراتش Scratch في راسبيري، ستكتشف في هذا المقال كيفية كتابة شيفرة نصية باستخدام لغة البرمجة بايثون Python. سُميت اللغة بايثون Python تيمنًا بالفرقة الكوميدية مونتي بايثون Monty Python، وتطورت هذه اللغة التي أنشأها غويدو فان روسوم Guido van Rossum من مشروع هواة أُطلق للمرة الأولى عام 1991 إلى لغة البرمجة المحبوبة التي تقف خلف الكثير من البرمجيات والمشاريع حاليًا. بايثون هي لغة برمجةٍ نصية على عكس اللغة البصرية سكراتش؛ حيث تُكتب التعليمات باستخدام لغةٍ مبسطةٍ وبتنسيقٍ محددٍ ينفذها الحاسوب لاحقًا. تُعد بايثون خطوةً ثانيةً رائعةً في طريق احتراف البرمجة بالنسبة للذين اكتسبوا خبرةً في استخدام سكراتش، حيث تمُدّهم بمرونةٍ أكبر وبيئة عملٍ برمجية تقليدية. وليس الغرض من هذا الكلام إيصال فكرةٍ أن اللغة صعبة التعلم، حيث يمكن لأي مهتم وبقليلٍ من التدريب كتابة برامج بايثون لأغراضٍ مختلفة انطلاقًا من آلة حاسبة بسيطة، وصولًا إلى ألعاب على درجة من التعقيد. بُني هذا المقال على المفاهيم والمصطلحات التي قدمناها في مقال البرمجة باستخدام لغة سكراتش، لذلك ستجد هذا المقال أسهل إدراكًا إذا نفذت التمارين التي شُرحت في المقال السابق، وننصح بالعودة والعمل عليها إذا لم تفعل ذلك بعد. ثوني Thonny: بيئة تطوير بايثون المتكاملة تتألف الواجهة الرئيسية للبيئة من الأجزاء التالية: A- شريط الأدوات: يقدم لك "النمط البسيط simple mode" للبيئة شريط أدواتٍ بأيقوناتٍ مريحةٍ للمستخدم، تساعدك في إنشاء وحفظ وتحميل وتشغيل برامج بايثون، كما تساعدك على اختبار برامجك بطرقٍ عدة. B- منطقة كتابة الشيفرة: وهي المنطقة التي تكتب فيها تعليمات بايثون، وتقسم إلى منطقةٍ رئيسية لكتابة الشيفرة، ومنطقةٍ جانبية طولانية تشكل هامشًا لإظهار أرقام الأسطر. C- منطقة مفسّر أوامر بايثون Python shell: ويسمح لك المُفسِّر في كتابة تعليماتٍ مستقلةٍ، ثم تنفيذها بضغط المفتاح Enter، كما تزوّدك بمعلوماتٍ عن البرامج الجاري تنفيذها. D- منطقة المتغيرات: ويظهر فيها أي متغيرٍ تنشئه في برنامجك، بالإضافة إلى قيمته الحالية، لسهولة المراجعة. انطلق مع بايثون ستجد ثوني مثل غيره من البرامج المثبتة مسبقًا على راسبيان ضمن قائمة راسبيري باي. انقر على الأيقونة ثم انقل مؤشر الفأرة إلى قسم البرمجة Programming، ثم انقر على Thonny Python IDE. ستظهر بعد ثوانٍ واجهة النمط البسيط لثوني والتي تُحمَّل افتراضيًا. يُعَد ثوني Thonny حزمة برمجياتٍ تُعرف باسم بيئة التطوير المتكاملة Integrated Development Environment -أو اختصارًا IDE-. إن التسمية معقدةً في الواقع لكنها سهلة الشرح؛ فهي تجمع أو تُكامل جميع الأدوات المختلفة التي تحتاجها لكتابة وتطوير برمجيات ضمن واجهة عمل أو بيئةٍ واحدة. هناك الكثير من بيئات التطوير التي يدعم بعضها عدة لغات برمجةٍ مختلفة، بينما يدعم البعض الآخر لغةً واحدةً مثل ثوني. وعلى خلاف سكراتش التي تقدم لك كتلًا برمجيةً بصريةً تبني من خلالها برنامجك، ستكتب تعليماتك مثل أي لغة برمجةٍ تقليدية عند استخدام بايثون. ابدأ برنامجك الأول بالنقر ضمن نافذة Python shell أسفل ويسار نافذة ثوني، واكتب التعليمات التالية، ثم اضغط المفتاح Enter. print("Hello, World!") سيعمل البرنامج مباشرةً ويُظهر لك العبارة "!Hello, World" ضمن نفس النافذة، كما هو موضحٌ في الشكل التالي، وهذا ما طلبته تمامًا. فما يفعله مفسر سطر الأوامر shell هو قراءة تعليماتك وتفسير معناها. يًدعى هذه الأسلوب الأسلوب التفاعلي والذي يشابه إلى درجةٍ ما الحوار وجهًا إلى وجه مع أحدهم؛ فعندما تنهي ما تقوله سيرد عليك الشخص الآخر وينتظر حتى تقول شيئًا ما من جديد. شكل 1-5 يطبع بايثون الرسالة Hello, World في نافذة مفسر الأوامر يمكنك كتابة التعليمات في منطقة الشيفرة إلى يسار نافذة ثوني أيضًا. انقر على النافذة واكتب الشيفرة السابقة تمامًا، ثم اضغط المفتاح Enter. لن يحدث شيء هذه المرة، بل سينتقل المؤشر إلى سطرٍ جديد في نافذة الشيفرة، ولا بدّ أن تنقر أيقونة التشغيل Run الموجودة في شريط أدوات ثوني من أجل تنفيذ تعليماتك، حيث سيُطلب منك حفظ برنامجك، لهذا اختر اسمًا مناسبًا، مثل "Hello World"، ثم انقر زر الحفظ Save. ستُطبع الآن هذه العبارة في نافذة المفسِّر بمجرد حفظ برنامجك. >>>> %Run 'Hello World.py' Hello, World! يمثّل السطر الأول توجيهًا للمفسر بتشغيل البرنامج الذي حفظته لتوّك، بينما يمثل الثاني نتيجة التنفيذ. تهانينا، لقد كتبت ونفذت أول برامج بايثون بالاسلوبين التفاعلي والتقليدي (الكتابة في نافذة الشيفرة). شكل2-5 تشغيل برنامجك البسيط الحلقات وإزاحة التعليمات تستخدم سكراتش كما رأينا كتلًا تمثّل شيفراتٍ محضرةً مسبقًا، ثم تربط بين هذه الكتل مثل قطع لعبة الأحجية؛ بينما تمتلك بايثون طريقتها الخاصة في التحكم بتسلسل التعليمات التي يُبنى عليها البرنامج وهي الإزاحة indentation. أنشئ برنامجًا جديدًا بالنقر على الأيقونة جديد New في شريط أدوات ثوني، حيث لن يغلق ثوني برنامجك القديم بل سيفتح إلى جواره نافذةً فرعيةً جديدة. اكتب في النافذة الجديدة التعليمات التالية: print("Loop starting!") for i in range (10): تطبع التعليمة في السطر الأول رسالةً بسيطةً ضمن المفسِّر تمامًا كما فعل البرنامج السابق، بينما يبدأ السطر الثاني تشكيل حلقةٍ محدودةٍ تعمل بنفس الطريقة التي عرفناها في سكراتش؛ حيث يُسنَد العداد i إلى الحلقة ويُعطى سلسلةً من الأعداد عبر التعليمة range والتي تحدد رقم البداية 0 صعودًا حتى 9 دون بلوغ العدد 10. يُخبر رمز النقطتين المتعامدتين ":" بايثون أن التعليمات التالية ستكون جزءًا من الحلقة؛ حيث نلاحظ وجود التعليمات التي ينبغي أن تكون ضمن الحلقة فعلًا داخل الكتلة التي تشبه شكل الحرف "C" في سكراتش؛ بينما يكون الأمر مختلف في بايثون، حيث يجب أن تُزاح بداية أسطر التعليمات الموجودة داخل الحلقة بمقدار أربع مسافاتٍ فارغة بالموازنة مع سطر تعريف الحلقة، وهذا ما يفعله ثوني تلقائيًا عند الضغط على مفتاح Enter بعد السطر الثاني وكتابة التعليمة التالية: print("Loop number", i) ستدفع المسافات الفارغة هذا السطر إلى اليمين موازنةً بالأسطر السابقة، وهذا هو الأسلوب الذي تعتمده بايثون للتمييز بين التعليمات داخل وخارج الحلقة، ونقول عندها أن التعليمات متداخلة Nested. لاحظ أنه بمجرد ضغط المفتاح Enter للانتقال إلى السطر التالي، سيستمر ثوني بإزاحة السطر آخذًا بالحسبان أن السطر الجديد لا يزال ضمن الحلقة، وللتراجع عن ذلك ضع المؤشر في بداية السطر واضغط الزر BACKSPACE مرةً واحدة. print("Loop finished!") وهكذا يكتمل برنامجك ذو الأسطر الأربعة، حيث سيُنفَّذ السطر الأول مرةً واحدةً كونه خارج الحلقة وكذلك السطر الرابع، بينما سيُنفّذ السطر الثالث عشرة مرات لوقوعه ضمن الحلقة التي يُعرّفها السطر الثاني: print("Loop starting!") for i in range (10): print("Loop number", i) print("Loop finished!") انقر على أيقونة التشغيل Run، احفظ البرنامج، وانظر إلى نافذة المفسّر لترى نتيجة التنفيذ: Loop starting! Loop number 0 Loop number 1 Loop number 2 Loop number 3 Loop number 4 Loop number 5 Loop number 6 Loop number 7 Loop number 8 Loop number 9 Loop finished! شكل 3-5 تنفيذ الحلقة إزاحة التعليمات أحد مصادر قوة بايثون، وفي نفس الوقت السبب الأكثر شيوعًا لكي لا يعمل البرنامج كما هو متوقع؛ فعندما تبحث عن أخطاء برنامج بالعملية التي تُدعى تنقيح الأخطاء Debugging، تحقق دومًا من الإزاحة وخاصةً عند ترتيب حلقاتٍ ضمن حلقات. يدعم بايثون أيضًا الحلقات اللامتناهية التي تُنفّذ ما بداخلها من تعليمات دون توقف. لتشاهد ذلك بدّل السطر الثاني من البرنامج ليصبح: while True نفِّذ البرنامج الآن وستحصل على رسالة خطأ: name 'i' is not defined لأنك حذفت السطر الذي أنشأ المتغير i وأسند قيمةً إليه. لإصلاح المشكلة اجعل السطر الثالث على النحو التالي: print("Loop running!") انقر على أيقونة التشغيل Run، وقد ترى العبارة "!Loop starting" إذا كنت سريعًا بما يكفي، لأن ما ستشاهده تاليًا تكرارُ لا ينتهي للعبارة "!Loop running"، ولن ترى بالطبع العبارة "!Loop finished" لعدم وجود نهاية للحلقة، ولدى الانتهاء من طباعة رسالة "!Loop running" يعود مجددّا إلى البداية من جديد، وبالتالي الحلقة لا متناهية. شكل 4-5 حلقة لا متناهية ستستمر حتى توقف البرنامج بنفسك انقر على أيقونة إيقاف Stop في شريط أدوات ثوني لإيقاف عمل برنامجك (مقاطعة عمل البرنامج)، فستظهر لك رسالةً في نافذة المفسِّر وسيتوقف البرنامج دون أن يصل حتى إلى السطر 4. العبارات الشرطية والمتغيرات المتغيرات أدواتٌ برمجيةٌ هامةٌ جدًا في جميع اللغات ولا تقتصر مهمتها على التحكم بالحلقات فقط. ابدأ برنامجًا جديدًا بالنقر على الأيقونة جديد New في شريط أدوات ثوني، ثم اكتب الشيفرة التالية في نافذة الشيفرة: userName = input ("what is your name? ") انقر على الأيقونة Run واحفظ برنامجك بالاسم "Name Test"، ثم راقب ما يحدث في نافذة المفسِّر. ستُسأل عن اسمك، لذلك اكتبه في نافذة المفسِّر واضغط المفتاح Enter. وبما أن برنامجك مكوّنٌ من تعليمةٍ واحدة، فلن يحدث أكثر من ذلك، لكن ستلاحظ ظهور المتغير وقيمته تلقائيًا في نافذة المتغيرات إلى يمين نافذة ثوني كما هو موضحٌ في الشكل التالي، وستبقى المتغيرات في نافذتها حتى عند توقف البرنامج، ليسهل عليك إدراك ما فعله البرنامج. شكل 5-5 تساعدك نافذة المتغيرات على تتبع المتغيرات وقيمها وحتى يقدّم البرنامج شيئًا مفيدًا، ضع عبارة شرطية ضمنه بكتابة التعليمات التالية: if userName == "Clark Kent": print("You are Superman!") else: print("You are not Superman!") لاحظ أن ثوني سيزيح الشيفرة تلقائيًا إذا وجد ذلك ضروريًا، لكنه لا يعرف متى يتوقف عن إزاحة الشيفرة؛ لذلك عليك حذف المسافات الفارغة بنفسك. انقر على الأيقونة "Run" واكتب اسمك في نافذة المفسِّر؛ فإذا صدف وكان اسمك Clark Kent، سترى الرسالة "You are Superman". شغل البرنامج من جديد واحرص أن يكون اسمك Clark Kent بحرفي C وK كبيرين كما هو في الشيفرة تمامًا، سيميّز البرنامج عندها أنك Superman فعلًا، كما هو موضحٌ في الشكل التالي. شكل 6-5 ألا يحب أن تكون في الخارج تحمي العالم يُستخدم الرمز "==" في بايثون للموازنة المباشرة؛ أي سيرى إذا كانت قيمة المتغير userName مطابقة للنص الموجود في برنامجك. يمكنك استخدام عوامل موازنة comparison operators أخرى إذا كنت تتعامل مع الأعداد، مثل العامل "<"، الذي يعني أكبر من، و">"، الذي يعني أصغر من، و"<=" الذي يعني أكبر من أو يساوي، و">="، الذي يعني أصغر من أو يساوي، كما يوجد العامل "=!" ويعني لا يساوي وهو المعاكس المباشر للعامل "==". يمكن استخدام عوامل الموازنة ضمن الحلقات أيضًا. احذف الأسطر من 2 إلى 5 واكتب الشيفرة التالية: while userName != "Clark Kent": print("You are not Superman - try again!") userName = input ("What is your name? ") print("You are Superman!") انقر على الأيقونة Run مرةً أخرى، ستلاحظ سؤال البرنامج عن اسمك مرارًا وتكرارًا حتى تؤكد له أنك "Superman"، كما هو موضحٌ في الشكل التالي، أي حتى تكتب الاسم "Clark Kent" كما لو أنه كلمة سر من نوعٍ ما. إذًا، عليك كتابة الاسم "Clark Kent" حتى تخرج من الحلقة، أو تنقر الأيقونة Stop في شريط أدوات ثوني. تهانينا، لقد تعلمت الآن استخدام العبارات الشرطية وعوامل الموازنة. شكل 7-5 سيستمر البرنامج بسؤالك عن اسمك حتى تكتب Clark Kent المشروع الأول: السلحفاة والثلج طالما أنك تعرّفت على الطريقة التي تعمل بها بايثون فقد حان الوقت للعمل مع الرسوميات وتصميم بلورات الثلج باستخدام أداة تُدعى turtle "سلحفاة". تُصنَّع الأشكال الفيزيائية للروبوتات وفقًا لأسماء الحيوانات التي تحاكيها، لهذا تُصنّع السلاحف على شكل قلمٍ يتحرك وفق خطٍ مستقيم ويلتف ويرتفع أو ينخفض؛ وهذا يعني برمجيًا أن تتحرك وتقف وترسم خطًا عندما تتحرك. لا تمتلك بايثون أداة سلحفاةٍ مدمجة مثل غيرها من اللغات، مثل لغة Logo وتوزيعاتها، لكنها تأتي ضمن مكتبةٍ ذات إضافاتٍ برمجية لتزيد قدرة بايثون. وتُعرف المكتبات Libraries بأنها تجميعاتٌ Bundles لشيفراتٍ تضيف تعليماتٍ جديدة لتوسيع إمكانيات بايثون، ويمكن أن تضمها إلى برامجك من خلال الأمر import. أنشئ برنامجًا جديدًا بالنقر على الأيقونة New، ثم اكتب الشيفرة التالية: import turtle عند استخدام التعليمات التي تتيحها مكتبةٌ ما، لا بُدّ من كتابة اسم المكتبة تليها نقطةٌ، ثم اسم التعليمة. قد يغدو هذا الأمر مزعجًا مع الوقت، لذلك يمكن إسناد هذا الأمر إلى متغيرٍ باسمٍ مختصر قد يكون حرفًا واحدًا مثلًا، لكننا سنختار اسم حيوانٍ أليفٍ لهذه السلحفاة على النحو التالي: pat = turtle.Turtle() ولاختبار السلحفاة لا بدّ أن نعطيها عملًا لتنفّذه، لذلك اكتب الشيفرة التالية: pat.forward(100) انقر الآن على أيقونة التشغيل Run، ثم احفظ برنامجك باسم "Turtle Snowflakes". ستظهر نافذةٌ رسوميةٌ جديدةٌ باسم Turtle Graphics، عندما يعمل البرنامج لتعرض نتيجة التنفيذ، وسترى تحرٌّك السلحفاة "pat" للأمام مقدار 100 وحدةٍ راسمةً خطًا مستقيمًا، كما هو وضحٌ في الشكل التالي. شكل 8-5 تتحرك السلحفاة إلى الأمام وترسم خطًا مستقيمًا عُد إلى نافذة ثوني الرئيسية إذا حجبتها النافذة الرسومية، وذلك بالنقر على نافذة ثوني أو تصغير النافذة الرسومية. انقر على أيقونة الإيقاف Stop لإغلاق النافذة الرسومية. نظرًا لمشقة كتابة كل تعليمة من تعليمات حركة السلحفاة، سنستعمل حلقةً Loop، لذلك احذف السطر الثالث واكتب الشيفرة التالية مكانه: for i in range(2): pat.forward(100) pat.right(60) pat.forward(100) pat.right(120) شغل البرنامج لتشاهد متوازي الأضلاع الذي ترسمه السلحفاة والموضح بالشكل التالي. شكل 9-5 بدمج الانعطافات والحركات يمكن رسم الأشكال ولتحويل الشكل إلى بلورة ثلج، أوقف البرنامج، ثم ضع الحلقة السابقة ضمن حلقةٍ جديدة بتعديل السطر 3 ليصبح على النحو التالي: for i in range(10): ووضع سطر الأوامر التالي في نهاية البرنامج: pat.right(36) لن يعمل البرنامج حاليًا لعدم إزاحة الحلقة الداخلية بصورةٍ صحيحة، لذلك أزح الأسطر من 4 إلى 8 إلى الأمام بإضافة أربع مسافاتٍ فارغة قبل كلٍ منها. إليك الشيفرة الصحيحة: import turtle pat = turtle.Turtle() for i in range(10): for i in range(2): pat.forward(100) pat.right(60) pat.forward(100) pat.right(120) pat.right(36) انقر على أيقونة التشغيل Run وشاهد كيف ترسم السلحفاة متوازي الأضلاع كما فعلت سابقًا، ثم تستدير بزاوية 36 درجة وترسم متوازي أضلاعٍ آخر وتستدير بنفس المقدار وترسم آخرًا وهكذا حتى ترسم 10 أشكالٍ متداخلة، كما هو موضحٌ في الشكل التالي. شكل 10-5 تداخل متوازيات الأضلاع على الشاشة تعطي شكلًا مشابهًا لبلورة الثلج يمكن رسم السلحفاة في بايثون بعدة ألوان. أضف الأسطر التالية قبل السطر الثالث لتدفع الأسطر إلى الأسفل: turtle.Screen().bgcolor("blue") pat.color("cyan") شغَّل برنامجك من جديد لترى تأثير الشيفرة، حيث سيتغير لون خلفية النافذة الرسومية إلى الأزرق ولون بلورة الثلج لتصبح رمادية، كما هو مبينٌ في الشكل التالي. تغيير لون الخلفية ولون شذرة الثلج يمكن اختيار الألوان عشوائيًا من قائمةٍ أيضًا وذلك باستخدام المكتبة random. عُد إلى بداية برنامجك واكتب الشيفرة التالية لتصبح في السطر الثاني: import random غيَّر لون الخلفية في السطر الرابع من اللون الأزرق "blue" إلى اللون الرمادي "grey"، ثم أنشئ متغيرًا جديدًا يُدعى "colours" بكتابة الشيفرة التالية لتحل مكان السطر الخامس: colours = ["cyan", "purple", "white", "blue"] يُعرف النوع السابق من المتغيرات بالقائمة list ويُحدَّد بقوسين مربعين. وضعنا في القائمة بعض الألوان المحتملة لبلورة الثلج وعليك الآن أن تخبر بايثون باختيار لونٍ منها في كل مرةٍ تُكرر فيها الحلقة. أضف في آخر البرنامج الشيفرة التالية وانتبه أن تبتعد عن بداية السطر أربع مسافاتٍ فارغة لتكون ضمن الحلقة الخارجية: pat.color(random.choice(colours)) انقر الآن على أيقونة التشغيل Run وسيرسم البرنامج بلورة الثلج التي تشبه نجمة النينجا من جديد، ولكن ستختار بايثون هذه المرة لونًا مختلفًا لكل متوازي أضلاعٍ من قائمة الألوان السابقة، وهذا يعطي البلورة ألوانًا مبهجة، كما هو موضحٌ في الشكل التالي. شكل12-5 استخدام ألوان عشوائية لرسم بتلات شذرة الثلج ولتظهر البلورة أقرب إلى بلورة الثلج الحقيقية وليس إلى نجمة النينجا، أضف الشيفرة التالية ابتداءً من السطر السادس وتحت قائمة الألوان: pat.penup() pat.forward(90) pat.left(45) pat.pendown() ستدفع التعليمتان penup وpendown بالقلم نحو الورقة وخارجها في روبوت سلحفاة واقعي، لكنهما تخبران السلحفاة في بايثون بالبدء برسم الخط أو التوقف. سنستخدم الآن دالةً بدلًا من الحلقة؛ والدالة function هي مجموعةٌ من التعليمات الممكن استدعائها سويةً في أي وقت كما لو أنك تصمم تعليمة بايثون خاصةٍ بك. ابدأ بحذف شيفرة رسم بلورات الثلج المبنية على متوازي الأضلاع وهي الشيفرة الموجودة بين الأمر: pat.color("cyan") في السطر 10 ضمنًا وحتى الأمر: pat.right(36) في السطر 17. اترك الأمر: pat.color(random.choice(colours)) بعد أن تضع الرمز "#" في بداية السطر، ويُعرف ذلك بتعليق السطر؛ أي أن بايثون سيتجاهل تنفيذه. يمكن أيضًا استخدام "#" لإضافة ملاحظاتٍ عن شيفرتك، لجعلها سهلة الفهم وخاصةً عندما تعود لقرائتها بعد عدة أشهرٍ، أو إذا أردت إرسالها إلى شخصٍ آخر. أنشئ دالتك التي سنسميها ()branch، وذلك بكتابة الشيفرة التالية في السطر العاشر تحت تعليمة ()pat.pendown مباشرةً: def branch(): ستعرف التعليمة السابقة الدالة ()branch، وسيضيف ثوني تلقائيًا إنزياحًا للتعليمات التي ستأتي ضمن الدالة. اكتب الشيفرة التالية وانتبه جيدًا إلى الإزاحة، لأنك سترتّب شيفراتٍ متداخلة وفق ثلاث سوياتٍ من الإزاحة: for i in range(3): for i in range(3): pat.forward(30) pat.backward(30) pat.right(45) pat.left(90) pat.backward(30) pat.left(45) pat.right(90) pat.forward(90) أخيرًا، أضف حلقةً إلى نهاية برنامجك لكن قبل سطر الاختيار العشوائي للون، والذي وضعت الرمز "#" قبله، وذلك لاستدعاء الدالة التي أنشأتها: for i in range(8): branch() pat.left(45) ستبدو الشيفرة الكاملة للمشروع على النحو التالي: import turtle import random pat = turtle.Turtle() turtle.Screen().bgcolor("grey") colours = ["cyan", "purple", "white", "blue"] pat.penup() pat.forward(90) pat.left(45) pat.pendown() def branch(): for i in range(3): for i in range(3): pat.forward(30) pat.backward(30) pat.right(45) pat.left(90) pat.backward(30) pat.left(45) pat.right(90) pat.forward(90) for i in range(8): branch() pat.left(45) # pat.color(random.choice(colours)) انقر على أيقونة التشغيل Run وراقب السلحفاة وهي ترسم بلورة الثلج وفقًا لتعليماتك. تهانينا، تبدو بلورة الثلج الآن أكثر واقعية، وهذا موضحٌ في الشكل التالي. شكل 13-5 تمنح التفرعات الإضافية شذرة الثلج شكلًا أكثر واقعية المشروع الثاني: إيجاد الاختلافات المخيفة يمكن لبايثون التعامل أيضًا مع الصور والأصوات، وسنستخدم ذلك في تصميم لعبة إيجاد الاختلاف بين صورتين لكن مع نكهةٍ مرعبةٍ لتفاجئ اللاعب. يحتاج المشروع إلى صورتين، الأولى هي الصورة الرئيسية وتتكون من قسمين متناظرين مع اختلافاتٍ محدودةٍ جدًا، والثانية هي الصورة المرعبة التي ستظهر فجأة. كما نحتاج أيضًا إلى ملفٍ صوتي لتعزيز التأثير المرعب. انقر على أيقونة راسبيري باي وانتقل إلى المتصفح كروميوم، ثم اكتب في شريط الأدوات العنوان rpf.io/spot-pic وبعدها اضغط المفتاح Enter. بعد ان يحمل المتصفح الصور، انقر عليها بالزر اليميني للفأرة واختر "حفظ الصورة باسم Save image as"، ثم خزنها في المجلد home/pi/، وكرّر نفس الأمر لتنزيل الصورة الأخرى من العنوان rpf.io/scary-pic. يختلف الأمر بالنسبة للملف الصوتي الموجود على العنوان rpf.io/scream، حيث سيبدأ المتصفح كروميوم بتنزيل الملف تلقائيًا إلى مجلد "التنزيلات Downloads"، لذلك لا بُدّ من نقله إلى المجلد home/pi/. لنقل الملف، انقر على أيقونة راسبيري باي مرورًا بفئة البرامج الملحقة Accessories، ثم انقر على برنامج مدير الملفات File Manager، وافتح مجلد التنزيلات Downloads وابحث عن ملفٍ باسم "scream.wav". انقر على الملف بالزر اليميني، ثم اختر قص Cut، ثم انتقل إلى المجلد home/pi/ وانقر على أيّ مكانٍ فارغٍ من نافذته بالزر اليميني، ثم اختر لصق Paste. يمكنك الآن إغلاق كروميوم ومدير الملفات. انقر على الأيقونة جديد New في شريط أدوات ثوني لإنشاء مشروعٍ جديد، حيث سنستخدم هنا أيضًا مكتبةً جديدةً تدعى "Pygame" لتوسيع إمكانيات بايثون، ويُلمِّح اسم هذه المكتبة كما نرى إلى علاقتها بالألعاب. اكتب الشيفرة التالية: import pygame سنحتاج في هذا المشروع إلى إدراج أجزاءٍ محددةٍ من المكتبة Pygame بالإضافة إلى أجزاءٍ من مكتباتٍ أخرى، ولتنفيذ ذلك اكتب الشيفرة التالية: from pygame.locals import * from time import sleep from random import randrange تختلف التعليمة from عن التعليمة import بأنها تدرج جزءًا محددًا من المكتبة بدلًا من إدراجها بالكامل. أما الآن فعلينا إعداد المكتبة Pygame، وتدعى هذه العملية التهيئة initialisation، حيث تحتاج Pygame معرفة ارتفاع وعرض جهاز العرض الذي تستخدمه أو ما يُسمى دقة جهاز العرض، لذلك اكتب الشيفرة التالية: pygame.init() width = pygame.display.Info().current_w height = pygame.display.Info().current_h أما الخطوة النهائية في تهيئة Pygame فهي إنشاء نافذة العرض التي تُدعى شاشة وفق مصطلحات المكتبة. اكتب الشيفرة التالية لإنجاز ذلك: screen = pygame.display.set_mode((width, height)) pygame.quit() يشير الفراغ بين السطرين السابقين إلى أن شيفرة برنامجك ستكون بينهما. انقر على أيقونة التشغيل Run واحفظ برنامجك باسم"Spot the difference" ثم راقب التنفيذ. ستُنشئ المكتبة نافذةً بخلفيةٍ سوداء لا تلبث أن تختفي مباشرةً نظرًا لتنفيذ تعليمة الخروج **()quit**، كما ستلاحظ امتلاء نافذة المتغيرات بعددٍ كبيرٍ من المتغيرات الجديدة التي ولّدتها Pygame تلقائيًا، كما هو موضحٌ في الشكل التالي. لا تلقِ بالًا لهذا الآن. شكل 14-5 لا تلق بالًا للمتغيرات الجديدة التي ستظهر في نافذة المتغيرات لعرض الصورة الأولى من أجل إيجاد الاختلاف بين قسميها، اكتب في الفراغ بين سطري الشيفرة السابقين السطر الجديد التالي: difference = pygame.image.load('spot_the_diff.png') ولتملأ الصورة شاشة العرض، لا بدّ من تغيير أبعاد الصورة لتتناسب مع دقة جهاز العرض الذي تستخدمه، لهذا اكتب الشيفرة التالية: difference = pygame.transform.scale(difference, (width, height)) أصبحت الصورة جاهزةً الآن في الذاكرة وعليك عرضها على الشاشة بعملية تُعرف باسم نقل البتات blitting، لذلك اكتب الشيفرة التالية: screen.blit(difference, (0, 0)) pygame.display.update() ينقل السطر الأول الصورة إلى الشاشة، بينما يطلب السطر الثاني من Pygame تحديث الشاشة، وستبقى الصورة دون السطر الثاني في مكانها الصحيح، لكنها في الذاكرة ولن تتمكن من رؤيتها. انقر على أيقونة Run، ستظهر الصورة على الشاشة لبرهة وتختفي، كما هو موضحٌ في الصورة التالية. الشكل 15-5 الصورة الأساسية للعبة "جد الاختلافات" لعرض الصورة مدةً أطول، اكتب الشيفرة التالية: sleep(3) في السطر الذي يسبق التعليمة: pygame.quit() انقر على أيقونة التشغيل Run وسترى أن الصورة ستُعرض لفترةٍ أطول على الشاشة. أضف الآن الصورة المفاجِئة إلى برنامجك بكتابة الشيفرة التالية: zombie = pygame.image.load('scary_face.png') zombie = pygame.transform.scale(zombie, (width, height)) تمامًا قبل السطر: pygame.display.update() أضف تأخيرًا زمنيًا لتبقى صورة الزومبي المخيفة فترةً أطول بكتابة الشيفرة التالية: sleep(3) وانقل أخيرًا بتات صورتك إلى الشاشة وحدّثها ليرى اللاعب الصورة المخيفة. لتنفيذ ذلك، اكتب الشيفرة التالية: screen.blit(zombie, (0,0)) pygame.display.update() انقر على أيقونة التشغيل Run وراقب ما يحدث. ستظهر الصورة الأساسية للعبة لكن ستحل محلها صورة الزومبي المخيفة بعد ثلاث ثوان، كما هو موضحٌ في الشكل التالي. شكل 16-5 سترعب أحدهم بالتأكيد لكن ظهور الصورة المرعبة بعد ثلاث ثوانٍ سيجعل الأمر متوقعًا، ولتفادي ذلك بدّل السطر: sleep(3) الذي يقع قبل تعليمة نقل بتات الصورة المخيفة بالسطر التالي: sleep(randrange(5, 15)) تختار التعليمة السابقة عددًا عشوائيًا بين 5 و 15 وتؤخر البرنامج هذه المدة. سنحمّل الآن الملف الصوتي وذلك بإضافة السطر التالي: scream = pygame.mixer.Sound('scream.wav') فوق تعليمة التأخير الزمني الأخيرة مباشرةً. سنشغل الملف الصوتي بعد عرض الصورة المخيفة فورًا بكتابة التعليمة: scream.play() ثم ضع تعليمة إيقاف الصوت: scream.stop() قبل التعليمة الأخيرة في البرنامج: pygame.quit() انقر على أيقونة التشغيل Run واستمتع بإنجازك؛ فبعد عرض الصورة البريئة التي سيجد اللاعب الاختلافات بين قسميها، ستظهر فجأة صورة الزومبي المخيفة مع صوتٍ دمويٍ مخيف. إذا ظهرت صورة الزومبي قبل أن يبدأ الصوت، يمكنك تعديل ذلك بإضافة تأخيرٍ زمني بسيط وفق التعليمة: sleep(0.4) قبل السطر: screen.blit(zombie, (0,0)) ستبدو الشيفرة الكاملة للمشروع على النحو التالي: import pygame from pygame.locals import * from time import sleep from random import randrange pygame.init() width = pygame.display.Info().current_w height = pygame.display.Info().current_h screen = pygame.display.set_mode((width, height)) difference = pygame.image.load('spot_the_diff.png') difference = pygame.transform.scale(difference, (width, height)) screen.blit(difference, (0, 0)) pygame.display.update() zombie = pygame.image.load('scary_face.png') zombie = pygame.transform.scale (zombie, (width, height)) scream = pygame.mixer.Sound('scream.wav') sleep(randrange(5, 15)) scream.play() screen.blit(zombie, (0,0)) pygame.display.update() sleep(3) scream.stop() pygame.quit() كل ما عليك فعله الآن هو دعوة أصدقائك للعب، وتأكد من توصيل مكبرات الصوت. المشروع الثالث: المتاهة بعد أن تعرّفت أكثر على بايثون، حان الوقت لاستخدام مكتبة Pygame في إنجاز مشروعٍ أكثر تعقيدًا، وهو لعبة متاهة ووحشٌ يلاحق اللاعب، مبنيةٌ على تعليماتٍ نصية، حيث تُعرف هذه الألعاب بالمغامرات ذات الأوامر الكتابية أو الخيال التفاعلي، وتعود إلى الزمن الذي لم تتمكن فيه الحواسب من التعامل مع الرسوميات وأصرَّ حينها معجبوا هذه الأجهزة بأن الرسوميات الأكثر وضوحًا هي تلك التي نرسمها في مخيلتنا. يُعدُّ هذا البرنامج أكثر تعقيدًا من البرامج السابقة في هذا المقال، لذلك كُتبت شيفرته جزئيًا لتسهيل الأمر. نزّل شيفرة المشروع بفتح متصفح كروميوم وكتابة العنوان التالي rpf.io/rpg-code في شريط العناوين ثم الضغط على المفتاح Enter، حيث ستجد الشيفرة عند اكتمال التنزيل التلقائي في مجلد التنزيلات Downloads. عُد الآن إلى ثوني وانقر أيقونة التحميل Load، ثم ابحث عن الملف rpg-rpg.py في مجلد التنزيلات Downloads وانقر على زر التحميل Load. انقر الآن على أيقونة التشغيل Run لتتعرف على الطريقة التي تُنفَّذ فيها المغامرات الكتابية، وسيظهر الخرج في نافذة المُفسِّر أسفل نافذة ثوني. كبِّر نافذة ثوني لتسهل عليك القراءة. اللعبة بسيطةٌ جدًا كما تبدو الآن. هناك غرفتان دون أغراض، ويبدأ اللاعب في الصالة، وهي أولى الغرفتين. اكتب 'go south' للذهاب نحو المطبخ، ثم اضغط المفتاح Enter، كما هو موضحٌ في الشكل التالي؛ واكتب 'go north' للعودة من المطبخ إلى الصالة. يمكنك أيضًا كتابة أوامر، مثل 'go west' أو 'go east'، ولكن ستظهر لك رسالة خطأ لعدم وجود غرفٍ في هذه الاتجاهات. شكل17-5 هنالك غرفتان فقط حتى الآن انقر على أيقونة الإيقاف Stop لإيقاف البرنامج، وانظر إلى المتغير rooms ضمن نافذة المتغيرات، ويُدعى هذا النوع من المتغيرات القاموس، واسُتخدِم من أجل إخبار اللعبة بالغرف المتوفرة وإلى أيِّ غرفةٍ يقود طريقٌ معين. يمكنك الانتقال إلى السطر 29 من الشيفرة لرؤية النقطة التي أُنشئ فيها هذا المتغير وكيف استُعمل. لجعل اللعبة أكثر متعةً، أضِف غرفةً جديدةً هي غرفة الطعام شرق الصالة. لتنفيذ ذلك، ابحث عن المتغير rooms في الشيفرة ووسِّعه بوضع فاصلة "," بعد القوس "{" في السطر 38، وأضِف الشيفرة التالية، دون التدقيق كثيرًا على الإزاحة في القاموس: 'Dining Room' : { 'west' : 'Hall' } ستحتاج أيضًا إلى مخرج للغرفة فلن تولّده الشيفرة تلقائيًا؛ لذلك انتقل إلى بداية السطر 33 وأضِف فاصلة "," ثم أضِف السطر التالي: 'east' : 'Dining Room' انقر الآن على أيقونة التشغيل Run، واختبر الغرفة الجديدة من خلال كتابة الأمر 'go east' لتنتقل من الصالة إلى غرفة الطعام، واكتب الأمر 'go west' للعودة من غرفة الطعام إلى الصالة. تهانينا، صنعت غرفةً بنفسك. شكل 18-5 لقد صنعت غرفة بنفسك لن يكون الأمر ممتعًا إذا لم يكن في الغرفة أغراض؛ لذلك سنضيف شيئًا إلى الغرفة بتعديل قاموس الغرفة. أوقف البرنامج وابحث عن القاموس Hall في نافذة الشيفرة، ثم أضف فاصلةً "," في نهاية السطر: 'east' : 'Dining Room' ثم اضغط المفتاح ENTER واكتب مايلي: 'item' : 'key' انقر على أيقونة التشغيل Run مجددًا، حيث ستخبرك اللعبة بوجود غرضٍ جديدٍ، وهو المفتاح 'key'. يمكنك كتابة الأمر 'get key' لتتمكن من التقاطه وإضافته إلى قائمة الأغراض التي تحملها، ويُطلق على هذه القائمة اسم المقتنيات inventory، وهي تبقى معك أثناء تنقلك بين الغرف. شكل 19-5 سيضاف المفتاح إلى مقتنياتك انقر على أيقونة Stop لإيقاف اللعبة. علينا الآن جعل اللعبة أكثر تشويقًا من خلال إضافة وحشٍ إليها ينبغي تفاديه؛ ولهذا ابحث عن القاموس 'Kitchen'، وأضف إليه الغرض 'monster' الذي سيمثل الوحش كما أضفت الغرض السابق 'key'، وتأكد من وضع فاصلةٍ "," في نهاية السطر الذي يسبق السطر الجديد الذي ستضيفه: 'item' : 'monster' حتى يكون الوحش قادرًا على مهاجمة اللاعب، لا بدّ من إضافة منطقٍ لهذه العملية؛ لذلك انتقل إلى آخر سطرٍ في البرنامج، وأضِف الأسطر التالية بما فيها السطر الذي يبدأ بالرمز "#". ستساعدك أسطر التعليقات على فهم برنامجك عندما تعود إليه بعد فترةٍ من الزمن، ولا تنسى إزاحة الأسطر بصورةٍ مناسبة: # player loses if they enter a room with a monster if 'item' in rooms[currentRoom] and 'monster' in rooms[currentRoom]['item']: print('A monster has got you... GAME OVER!') break انقر على أيقونة Run مجددًا، ثم حاول الدخول إلى المطبخ، ستكون نهايتك. شكل 20-5 وحش في المطبخ لجعل اللعبة ذات معنىً، سنضيف أغراضًا جديدةً وغرفةً أخرى ووسيلةً للفوز تقتضي بمغادرة المنزل بسلام وبحوزتك كل الأغراض. ابدأ بإضافة غرفةٍ أخرى إلى المتغير rooms كما أضفت غرفة الطعام 'Dining Room' وسمِّها هذه المرة 'Garden'، وأضف مخرجًا إليها من غرفة الطعام 'Dining Room'؛ لهذا عليك أولًا وضع فاصلةٍ "," في نهاية السطر الأخير من القاموس 'Dining Room' ثم إضافة السطر التالي: 'south' : 'Garden' قبل القوس "{" في نهاية 'Dining Room' وأضف فاصلةً "," بعده. بعد أن وضعت مخرجًا إلى الغرفة 'Garden'، أضف هذه الغرفة بعد 'Dining Room' بكتابة الشيفرة التالية: 'Garden' : { 'north' : 'Dining Room' } أضف الغرض 'potion' إلى القاموس 'Dining Room' ولا تنسى الفاصلة "," في نهاية السطر الذي يسبقه: 'item' : 'potion' انتقل أخيرًا إلى نهاية البرنامج وأضف الشيفرة التي تتحقق من امتلاك اللاعب كل الأغراض لإبلاغه بالفوز. # player wins if they get to the garden with a key and a potion if currentRoom == 'Garden' and 'key' in inventory and 'potion' in inventory: print('You escaped the house... YOU WIN!') انقر أيقونة Run وحاول إنهاء اللعبة بالتقاط الغرضين 'key' و'potion' قبل التوجه إلى الحديقة. لا تدخل إلى المطبخ فالوحش موجودٌ هناك. ولإضفاء نكهةٍ إلى اللعبة، يمكنك إضافة إرشاداتٍ تساعد اللاعب على إنهاء اللعبة؛ ولتنفيذ الأمر انتقل إلى بداية البرنامج، وابحث عن الدالة ()showInstructions وأضف النص التالي ضمنها: Get to the Garden with a key and a potion Avoid the monsters! ستظهر الإرشادات السابقة في بداية برنامجك بمجرد تشغيل اللعبة. تهانينا، لقد أنجزت لعبة متاهةٍ مبنيةٍ على أوامر نصية. شكل 21-5 يعرف اللاعب الآن ما عليه فعله ترجمة -وبتصرف- للفصل الخامس Programming with python من كتاب THE OFFICIAL Raspberry Pi Beginner’s Guide. اقرأ أيضًا جولة في راسبيان: نظام تشغيل راسبيري باي تجميع راسبيري باي والتحضير لاستعماله تعرف على جهاز راسبيري باي Raspberry Pi
  23. لا يقتصر استخدام راسبيري باي على التعامل مع البرامج التي صممها آخرون، بل بناء برمجياتٍ خاصةٍ بك لتلبية أية احتياجات. سواءٌ امتلكت خبرةً في إنشاء البرامج بكتابة الأوامر والتعليمات أم لا، فستجد منصة راسبيري باي ممتازةً لبناء البرامج واختبارها. تعد لغة سكراتش مفتاحًا إلى كتابة البرامج على باي بأسلوبٍ سهل، وهي لغةٌ برمجةٌ بصرية طوّرها معهد ماساشوسيتس للتكنولوجيا MIT. تعتمد لغات البرمجة التقليدية على كتابة تعليماتٍ نصية ينفّذها الحاسوب كما لو أنك تكتب وصفةً لتحضير كعكة، بينما تساعدك سكراتش scratch على كتابة برنامجك خطوةً بخطوة باستخدام الكتل البرمجية؛ وهي قطعٌ برمجية مكتوبة مسبقًا تُعرَض على شكل قطعٍ مشابهةٍ لقطع الأحجية الملوّنة، كما أن سكراتش scratch لغةٌ ممتازةٌ في بداية مسيرتك في البرمجة سواء كنت صغيرًا أو متقدمًا في السن، ولكن لا تنخدع بمظهرها الودود والملوّن؛ فهي بيئةٌ برمجيةٌ قويةٌ ومتكاملةٌ وظيفيًا وقادرةٌ على كتابة كل ما تتخيله من برمجيات، ابتداءً بالألعاب البسيطة والرسوميات المتحركة وانتهاءً بالبرمجيات التفاعلية المعقدة لمشاريع الروبوتات. ستتعلم في هذا المقال خطواتك الأولى في تعلم البرمجة باستخدام لغة سكراتش التي تعتمد على الكتل البرمجية. تعرف على سكراتش تمثّل المناطق التالية الواجهة الرئيسية للبرنامج بإصداره الثاني: A- المسرح: تتحرك شخصية البرنامج Sprite فيه وفقًا للبرنامج الذي تكتبه. B- الشخصية التفاعلية Sprite: وهي الشخصيات أو الكائنات التي تتحكم بها من خلال برنامج سكراتش وتظهر على المسرح. C- منطقة التحكم بالمسرح: وتُستخدم لتغيير المسرح مثل إضافة الصور والخلفيات. D- قائمة الشخصيات: وتظهر فيها كل الشخصيات التي أنشأتها أو حمّلتها في سكراتش. E- لوحة الكتل البرمجية: وتضم كل القطع البرمجية المتاحة لبرامجك، وتُرتب على شكل فئاتٍ ملونة وفقًا لوظائفها. F- الكتل البرمجية: تضم أسطرًا برمجيةً مكتوبةً مسبقًا ولها وظيفةُ محددة تسمح لك ببناء برنامجك خطوةً بخطوة. G- منطقة بناء البرنامج: حيث تسحب وتفلت الكتل البرمجية ضمنها لتكوين برنامجك. إصدارات سكراتش يأتي راسبيان حتى لحظة إعداد السلسلة بنسختي سكراتش، هما النسخة الأصلية والنسخة المحدّثة 2 وكلاهما ضمن قسم البرامج في قائمة راسبيان. كُتب هذا المقال باستخدام سكراتش 2، فلا تخطئ وتفتح نسخة سكراتش الأصلية، حيث من الممكن أن تختلط عليك الأمور جديًا، ولسوء الحظ لن يعمل سكراتش 2 على Pi Zero نموذج A أو +A أو B أو +B. وتجدر الإشارة أن أحدث الإصدارات هي سكراتش 3. اكتب برنامجك الأول باستخدام سكراتش لفتح سكراتش 2، انقر على أيقونة القائمة، ثم انقل المؤشر إلى فئة البرمجة وانقر على Scratch 2 وستظهر واجهة البرنامج خلال ثوانٍ. يختلف سكراتش عن غيره من لغات البرمجة بأنك لن تصيغ أوامرك للحاسوب على هيئة تعليماتٍ نصية تكتبها بنفسك، بل عن طريق اختيار كتلةٍ برمجيةٍ مناسبة من لوحة الكتل البرمجية. ابدأ رحلتك بالنقر على فئة المظهر Looks ضمن لوحة الكتل البرمجية وسط نافذة البرنامج، حيث ستُظهر لك هذه الفئة كتلًا باللون الأرجواني. ابحث عن الكتلة ، ثم اسحبها إلى منطقة بناء البرنامج إلى يمين النافذة، كما هو موضح في الشكل التالي. شكل 1-4 جر وإفلات كتلة برمجية ألقِ نظرةً على شكل الكتلة التي نقلتها، ستجد فتحةً في أعلاها، وجزءًا بارزًا لوصل الكتلة مع غيرها في الأسفل تمامًا مثل قطعةٍ من لعبة تركيب الأحجيات، وهذا ما يدفعك للتفكير بوجود كتلةٍ قد ترتبط بها من الأعلى وكتلةٍ من الأسفل. ويوجد أعلى الكتلة التي نقلتها للتو في برنامجنا بادئ البرنامج Trigger. انقر على فئة الأحداث Events ضمن لوحة الكتل البرمجية والتي تضم كتلًا ملونةً باللون البني الفاتح، ثم اسحب الكتلة المُسماة بكتلة القبعة إلى منطقة البناء بحيث يلتصق تقريبًا الجزء البارز منها بالفتحة أعلى كتلة ، حيث ستلاحظ ظهور إطارٍ أبيض عند تقريب كتلة القبعة، أفلتها عندئذ. ليس ضروريًا أن تكون دقيقًا في وضع كتلة فوق أخرى، فعندما تقترب كفاية من بعضها ستنزلق في مكانها تمامًا مثل قطعةٍ من قطع أحجية. كرر العملية إذا لم تنجح في المحاولة الأولى. لقد اكتمل برنامجك الآن، انقر على أيقونة الراية الخضراء لتشغيله. إذا سار كل شيءٍ على ما يرام، ستحييك شخصية القط من على المسرح بالعبارة '!Hello'، كما هو موضحٌ في الشكل التالي، وسينتهي برنامجك بنجاح. شكل 2-4 نجاح برنامجك الأول قبل المضي للأمام، اختر اسمًا لبرنامجك واحفظه من خلال النقر على قائمة ملف File، ثم حفظ Save. لدى ظهور نافذة الحفظ، اكتب اسم البرنامج ثم انقر زر حفظ Save، كما هو موضح في الشكل التالي. شكل 3-4 احفظ البرنامج باسم يمكنك تذكره. الخطوة التالية: تتابع الكتل البرمجية يمتلك برنامجك كتلتين فقط وتعليمةً واحدةً تجعل القط يقول '!Hello' في كل مرةٍ يعمل فيها البرنامج بنقر الراية الخضراء. لتطوير برنامجك أكثر، لا بدّ أن تتعلم المزيد عن سَلسَلة الكتل البرمجية Sequencing. تُعد برامج الحاسوب بأبسط وصف لها سلسلةً من التعليمات مثل وصفةٍ لتحضير طبقٍ ما، حيث تُنفَّذ كل تعليمةٍ بعد الأخرى بطريقةٍ منطقية تُدعى السلسلة الخطية. احذف الكتلة بالنقر عليها في منطقة بناء البرنامج، ثم اسحبها إلى لوحة الكتل البرمجية، وبذلك ستبقى فقط كتلة بادئ البرنامج ، كما هو موضحٌ في الشكل التالي. شكل 4-4 لحذف كتلة جرها خارج منطقة البناء ببساطة انقر على فئة الحركة Motion، التي تضم كتلًا باللون الكحلي، ثم اسحب الكتلة وضعها تحت كتلة القبعة (بادئ البرنامج) في منطقة بناء البرنامج، وكما يدل اسمها، فإنها ستُعطي أمرًا لشخصية القط بالتحرك عددًا من الخطوات بالاتجاه الذي يأخذه. سنضيف مزيدًا من التعليمات لتشكل سلسلة. انقر على فئة الصوت Sound، والتي تضم كتلًا باللون الزهري الغامق، ثم انقر على الكتلة واسحبها لتستقر تحت الكتلة ، وأعد النقر مجددًا على فئة الحركة Motion واسحب الكتلة وضعها أسفل كتلة الصوت، ثم انقر على العدد '10' واستبدله بالعدد '-10' لتصبح الكتلة على النحو التالي . انقر الآن على أيقونة الراية الخضراء لتنفيذ البرنامج. سيتحرك القط 10 خطواتٍ إلى اليمين ويصدر الصوت "مياو Meow" (تأكد من وجود مكبر صوت أو سماعة رأس)، ثم يعود إلى نقطة البداية، وسيكرّر القط ما فعله تمامًا عند النقر مجددًا على الراية. تهانينا! لقد أنجزت سلسلةً من التعليمات المتتابعة التي ينفذها سكراتش واحدةً تلو الأخرى من الأعلى إلى الأسفل. نظرًا لتنفيذ سكراتش تعليمةً واحدةً في كل مرة من السلسلة، سيكون التنفيذ سريع جدًا، لذلك حاول أن تحذف الكتلة بإبعاد الكتلة لتنفصل عنها، ثم انقلها خارج منطقة البناء واستبدلها بالكتلة الصوتية الأبسط ، ثم أعد الكتلة لتتصل بها من الأسفل. انقر الراية الخضراء لتشغيل البرنامج من جديد ولن تلاحظ حركة القط. في واقع الأمر، تحرك القط وعاد إلى مكانه دون أن تلاحظ ذلك لأن العملية حدثت بسرعةٍ كبيرة؛ والسبب في ذلك الكتلة التي لا تنتظر الصوت حتى ينتهي قبل أن ينتقل التنفيذ إلى الكتلة التالية، ونظرًا لسرعة راسبيري باي، ستُنفَّذ التعليمة التالية قبل أن تدرك ذلك. سنستخدم طريقةً أخرى للالتفاف على الموضوع دون الحاجة إلى الكتلة ، لذلك سننفِّذ التالي: انقر على فئة التحكم Control، التي تضم كتلًا باللون الذهبي، ثم اسحب الكتلة وضعها بين الكتلة والكتلة . انقر على الراية الخضراء مجددًا وسترى أن القط سينتظر بعد أن يتحرك إلى اليمين ثانيةً واحدةً ثم يعود للخلف، وتُعرف هذه التعليمة بتعليمة التأخير الزمني Delay، وهي الأساس في التحكم بالمدة الزمنية التي سيستغرقها تنفيذ سلسلة التعليمات. تنفيذ حلقة من التعليمات من المؤكد أنك لاحظت تنفيذ سلسلة التعليمات السابقة مرةً واحدةً فقط، حيث يتحرك القط بعد نقر الراية الخضراء، ثم يصدر صوتًا ويعود إلى مكانه، ثم يتوقف البرنامج حتى تنقر الراية مرةً أخرى، ولكن ليس بالضرورة أن تجري الأمور هكذا؛ حيث يقدم سكراتش نوعًا من الكتل البرمجية تُدعى الحلقة Loop. انقر على فئة التحكم Control وابحث عن الكتلة البرمجية ، ثم اسحبها إلى منطقة بناء البرنامج واحشر عارضتها العليا بين الكتلة والكتلة لتضم ضمن عارضتيها بقية الكتل. تتوسع الكتلة التي تأخذ شكل حرف C لتُحيط بمجموعة الكتل البرمجية التي ينبغي تنفيذها بصورةٍ متسلسلةٍ وباستمرار. انقر على الراية الخضراء وستدرك ما تفعله الكتلة ؛ فبدلًا من تنفيذ برنامجك مرةً واحدةً، سيعمل مرةً تلو المرة دون نهاية. تُعرف هذه الفكرة في عالم البرمجة باسم الحلقة اللامتناهية infinite loop؛ أي الحلقة التي لا تنتهي. إذا شعرت بالإزعاج من صوت القط المتكرر، انقر على المثمّن الأحمر بجانب الراية الخضراء لإيقاف البرنامج. اسحب الكتلة والكتل الواقعة أسفلها خارج الكتلة وضعهم جميعًا تحت كتلة القبعة ، ثم اسحب الكتلة خارج منطقة بناء البرنامج لحذفها. انقر واسحب الكتلة وضعها تحت الكتلة لتحيط ببقية الكتل تمامًا كما فعلت سابقتها. انقر على الراية الخضراء لتنفيذ البرنامج. ستعتقد للوهلة الأولى أنه يعيد تنفيذ البرنامج السابق بتكرير التعليمات مرارًا، لكن ما سيحدث أنه سيتوقف عن التنفيذ بعد تكرار التعليمات عشر مرات، وتُعرف هذه الفكرة باسم الحلقة المنتهية definite loop والتي يمكنك فيها تحديد نهاية الحلقة. تُعدّ الحلقات أدواتٍ قويةً برمجيًا، حيث تُستخدم بكثرة خاصةً عند برمجة الألعاب وبرامج تحسس المحيط. استخدام المتغيرات والعبارات الشرطية لا بدّ من المرور أخيرًا على مفهومين هامين قبل البدء بكتابة برامج سكراتش، هما المتغيرات والعبارات الشرطية؛ حيث تُعرّف المتغيرات Variables كما يوحي اسمها، بأنها قيمٌ قابلةٌ للتغيير مع الوقت وبتوجيهٍ من البرنامج. وللمتغيّر خاصيتين رئيسيتين، هما الاسم Name والقيمة Value التي يُخزّنها، وليس بالضرورة أن تكون قيمة المتغير أعدادًا، بل قد تكون كلماتٍ أو نصوصًا أو قيمًا منطقية (صحيح أو خاطئ)، أو أن تكون فارغةً تمامًا وتدعى عندها لا شيء null. المتغيرات أدواتٌ برمجيةٌ فعّالةٌ جدًا، فكّر مثلًا بطريقة تتبع بعض مؤشرات لعبة، مثل سلامة الشخصيات، أو سرعة حركة الأشياء، أو المستوى الحالي للعبة، أو النتيجة فجميعها قيمٌ نتعقبها من خلال متغيرات. انقر على قائمة ملف File واحفظ برنامجك الحالي بالنقر على حفظ المشروع Save Project، ثم ابدأ مشروعًا جديدًا فارغًا بالنقر على جديد New. انقر على فئة البيانات Data التي تضم كتلًا باللون البرتقالي، ثم انقر على الزر 'أنشئ متغيرًا Make a Variable' وسمِّ المتغير بالاسم'loops' كما هو موضحٌ في الشكل التالي، ثم انقر زر OK. ستكون النتيجة سلسلةً من الكتل ضمن لوحة الكتل البرمجية. شكل 5-4 تسمية المتغير انقر ثم اسحب الكتلة إلى منطقة بناء البرنامج، حيث تخبر هذه التعليمة برنامجك أن يجعل قيمة المتغّير صفرًا. انقر بعد ذلك على فئة المظهر Looks واسحب الكتلة إلى أسفل . سيقول القط ما هو مكتوب في الكتلة كما رأينا سابقًا، لكن وبدلًا من ذلك يمكنك استخدام متغيّر. انقر مجددًا على فئة البيانات Data ضمن لوحة الكتل البرمجية، ثم اختر الكتلة التي تُدعى كتلة المُخبر Reporter block، حيث ستجدها في أعلى القائمة وبجوارها مربع تحقق. ضع هذه الكتلة فوق الكلمة '!Hello' ضمن الكتلة . ستكون النتيجة كتلةً برمجيةً مركبةً هي . انقر على فئة أحداث Events ضمن لوحة الكتل البرمجية واسحب الكتلة إلى قمة سلسلة الكتل في منطقة بناء البرنامج. انقر الراية الخضراء وسترى القط يقول '0'، وهي القيمة التي أسندتها للمتغير 'loops'، كما هو موضحٌ في الشكل التالي. شكل 6-4 سيقول القط هذه المرة قيمة المتغيّر يمكن أن تتغير قيم المتغيرات. انقر على فئة البيانات Data في لوحة الكتل البرمجية، ثم انقر واسحب الكتلة إلى أسفل سلسلة الكتل، ثم انقر بعد ذلك على فئة التحكم Control، بعدها انقر واسحب الكتلة وضعها مباشرةً تحت الكتلة بحيث تحيط بقية الكتل في السلسلة. انقر على الراية الخضراء مجددًا، وسترى القط يعد من '0' إلى '9'؛ ويحدث هذا لأن برنامجك يغيّر أو يعدّل قيمة المتغير نفسه، وفي كل مرةٍ تُنفَّذ فيها الحلقة، يضيف البرنامج '1' إلى قيمة المتغيّر 'loops'، كما هو موضحٌ في الشكل التالي. الشكل 7-4 بتعديل قيمة المتغير، يعد القط تصاعديًا الآن يمكن الاستفادة من المتغيرات بما هو أكثر من مجرد تعديل قيمتها. انقر واسحب الكتلة خارج إطار الكتلة وضعها أسفلها، انقر بعد ذلك على الكتلة واسحبها نحو لوحة الكتل البرمجية لحذفها، ثم استبدلها بالكتلة وتأكد بأنها متصلةٌ بأسفل الكتلة وتحيط بالكتلتين الباقيتين. انقر على فئة العوامل Operators التي تضم كتلًا باللون الأخضر، ثم انقر واسحب الكتلة وافلتها في الفتحة المماثلة لها في كتلة . تمكّنك هذه الكتلة من موازنة قيمتين بما في ذلك المتغيّرات. انقر على فئة البيانات Data واسحب كتلة المُخبِر إلى الفراغ الأول للكتلة ثم انقر الفراغ الثاني واكتب العدد '10'. انقر على الراية الخضراء فوق منطقة المسرح وستلاحظ أن البرنامج يعمل مثل السابق، حيث يعد القط من '0' إلى '9' ثم يتوقف البرنامج. يعود السبب في ذلك إلى عمل الكتلة بنفس طريقة عمل الكتلة تمامًا، لكنها توازن قيمة المتغير 'loops' بالقيمة المقابلة في الكتلة وهي '10'، وسيتوقف البرنامج عندما تصل قيمة المتغير إلى '10'، كما هو موضح في الشكل التالي. الشكل 8-4 استخدام الكتلة 'repeat until' مع كتلة عامل الموازنة تُعرف هذه التعليمة باسم عامل الموازنة comparative operator، فهي توازن حرفيًا بين قيمتين. انقر على فئة العوامل Operators ضمن لوحة الكتل البرمجية واطلّع على الكتلتين الباقيتين أعلى وأسفل الكتلة التي تحتوي الرمز '=. لاحظ أنهما كتلتي موازنة أيضًا، حيث يوازن العامل '>' بين قيمتين ويعطي القيمة 'صحيح True' عندما تكون قيمة الطرف الأيسر أصغر تمامًا من قيمة الطرف الأيمن، بينما يحدث العكس عند استخدام العامل '<'. انقر على فئة التحكم Control ضمن لوحة الكتل البرمجية وابحث عن الكتلة ، ثم اسحبها إلى منطقة بناء البرنامج وضعها مباشرةً أسفل الكتلة . ستغلّف تلقائيًا الكتلة لذلك انقر واسحب هذه الأخيرة وضعها لتستقر أسفل الكتلة وليس ضمنها. انقر على فئة المظهر Looks، ثم انقر واسحب الكتلة إلى داخل الكتلة ، وانقر بعد ذلك على فئة العوامل Operators، ثم انقر واسحب الكتلة إلى الفتحة التي تطابقها في الكتلة . الكتلة هي كتلةٌ شرطية، أي أنّ تنفيذ الكتل التي تقع بداخلها مرتبطٌ بتحقق شرطٍ معين. انقر على فئة البيانات Data ثم اسحب الكتلة إلى المربع الفارغ الأول للكتلة ، وانقر بعدها على المربع الفارغ الثاني واكتب '5'، ثم انقر أخيرًا على الكلمة '!Hello' في الكتلة واكتب العبارة 'That’s high' مكانها. شغّل البرنامج بالنقر على الراية الخضراء وسيعمل البرنامج بدايةً كما سبق، حيث سيعُد القط تصاعديًا من الصفر، لكن عند وصول العد إلى الرقم '6' وهو الرقم الأكبر مباشرةً من '5'، ستُفعَّل الكتلة وسيعلّق comment القط على الرقم الأعلى الذي سيظهر، كما هو مبينٌ في الشكل التالي. تهانينا! ستكون قادرًا من الآن فصاعدًا على العمل مع المتغيرات والكتل الشرطية. شكل 9-4 سيُعلِّق القط عندما يصل العد إلى 6 تحدّي الأعلى والأدنى: كيف ستغيّر البرنامج حتى يعلّق القط على الأرقام الأصغر من '5' بدلًا من الأكبر؟ هل يمكنك تغيير البرنامج حتى يعلّق على القيم الأعلى والأدنى من '5'؟ لتبسيط العملية جرّب الكتلة . المشروع الأول: رائد الفضاء الخارق بعد فهم الطريقة التي يعمل بها سكراتش، حان الوقت لإنجاز مشروع تفاعلي أكثر؛ وهو مؤقتٌ يتحكم بأفعال رائد فضاء، حيث صُمم هذا المشروع لتكريم رائد وكالة الفضاء الأوروبية البريطاني "تيم بيك Tim Peake" وللوقت الذي قضاه في محطة الفضاء الدولية. احفظ مشروعك السابق إذا أردت ذلك، ثم افتح مشروعًا جديدًا بالنقر على قائمة ملف File، ثم جديد New، وسمِّ مشروعك قبل أن تبدأ العمل بالنقر على ملف File، ثم حفظ المشروع Save Project، وليكن اسمه 'Astronaut Reaction Timer'. يعتمد المشروع على صورتين، الأولى هي خلفية المسرح، والثانية هي الشخصية ولن تجدهما بالطبع ضمن موارد سكراتش المدمجة وعليك تنزيلها. انقر على أيقونة راسبيري باي، ثم انقل مؤشر الفأرة إلى إنترنت Internet وبعدها إلى متصفح الويب كروميوم Chromium Web Browser وانقر عليه، ثم اكتب العنوان 'rpf.io/astronaut-backdrop' ضمن شريط العنوان عندما يكتمل تحميل البرنامج واضغط على الزر Enter، انقر بعد ذلك بالزر اليميني للفأرة على صورة الفضاء لتظهر لك قائمةٌ اختر منها الأمر حفظ الصورة باسم 'Save image as'، ثم اختر مجلدًا لحفظها وانقر الزر حفظ Save، كما هو مبينٌ في الشكل التالي. الشكل 10-4 حفظ صورة الخلفية انقر على زر التراجع بجوار شريط العنوان ثم اكتب عنوان الصورة الأخرى 'rpf.io/astronaut-sprite' واضغط على الزر Enter. احفظ الصورة الموجودة بنفس الطريقة، وأغلق كروميوم إذا أردت أو استخدم شريط المهام للعودة إلى سكراتش 2. إذا كنت تتابع معنا هذا المقال منذ بدايته فمن المفترض أن تكون واجهة سكراتش 2 مألوفةً بالنسبة إليك. ستعتمد الشروحات في المشاريع القادمة على معرفتك بالأشياء ومواقعها ضمن الواجهة؛ فإذا نسيت أين تجد شيئًا ما، عُد إلى الخلف وانظر إلى الصورة التفصيلية للواجهة التي شرحناها بداية هذا الفصل. انقر بالزر الأيمن للفأرة على شخصية القط الموجودة على المسرح واحذفه، ثم ابحث عن أدوات التحكم بالمسرح الموجودة أسفل ويسار نافذة سكراتش 2 وانقر على أيقونة رفع الخلفيات، والتي ستكون على شكل مجلد مفتوح يخرج منه سهمٌ للأعلى. ابحث عن صورة باسم Space-background.png ضمن مجلد التنزيلات Downloads وانقر عليها، ثم اضغط الزر OK. ستتحول الآن خلفية المسرح البيضاء إلى صورةٍ للفضاء كما هو موضح في الشكل التالي، وستُستبدل منطقة بناء البرنامج بمنطقة الخلفيات التي يمكنك الرسم على الخلفية ضمنها. لإعادة منطقة بناء البرنامج، انقر على النافذة الفرعية Scripts أعلى نافذة سكراتش 2. شكل 11-4 تظهر خلفية الفضاء على المسرح حمّل الشخصية الجديدة بالنقر على أيقونة الشخصيات بجوار عبارة شخصية جديدة 'New sprite' أعلى منطقة الشخصيات. ابحث عن الصورة Astronaut-Tim.png ضمن مجلد تنزيلات Downloads، ثم انقر عليها واضغط الزر OK. ستظهر الشخصية الجديدة تلقائيًا على المسرح وقد لا تكون في المنتصف، انقر عليها واسحبها حتى تصبح أسفل منتصف المسرح بقليل ثم أفلتها، كما هو موضح في الشكل التالي. شكل 12-4 اسحب شخصية رائد الفضاء إلى أسفل منتصف المسرح ستتمكن الآن من إكمال مشروعك بعد أن وضعت الخلفية الجديدة والشخصية المطلوبة في المكان الصحيح. ابدأ الآن بإنشاء متغيرٍ جديد باسم 'time' وتأكد من تفعيل الخيار "جميع الشخصيات For all sprites" ثم اضغط الزر OK. انقر على الشخصية لاختيارها ثم أضف الكتلة إلى منطقة بناء البرنامج، وأضف بعد ذلك الكتلة ، ثم انقر على الكلمة '!Hello' واستبدلها بالعبارة '?Hello! British ESA Astronaut Tim Peake here. Are you ready'. أضِف الكتلة ثم الكتلة وغيّر هذه الأخيرة لتقول 'انقر على الفضاء !Hit Space'. اختر فئة الاستشعار Sensing والتي تضم كتلًا باللون الأزرق الفاتح، ثم أضف الكتلة التي تتحكم بمتغيرٍ خاصٍ مدمجٍ مع سكراتش لأغراض التوقيت وسنستخدمه لتقدير سرعة تفاعلك مع اللعبة. أضِف كتلة التحكم ، ثم ضع كتلة الاستشعار في الفراغ الأبيض ضمنها. سيوقف هذا الأمر البرنامج مؤقتًا حتى تضغط المفتاح SPACE في لوحة المفاتيح. إذًا، سيقيس المؤقت الآن الفترة الزمنية التي تبدأ بظهور الرسالة '!Hit Space' وحتى تضغط المفتاح SPACE. سنجعل رائد الفضاء تيم Tim يخبرك كم الزمن الذي استغرقته حتى ضغطت المفتاح SPACE وبطريقةٍ سهلة القراءة، حيث ستحتاج لتنفيذ الأمر إلى كتلة العوامل . تأخذ الكتلة قيمتين بما في ذلك المتغيرات، ثم تضمهما سويّةً الأول ثم الثاني وهذا ما يُعرف برمجيًا باسم الدمج Concatenation. ابدأ بالكتلة، ثم اسحب الكتلة وضعها فوق الكلمة '!Hello'، واكتب في الفراغ الأول لكتلة الضم العبارة ' Your reaction time was' وتأكد من ترك محرف مسافةٍ فارغةٍ في نهاية الجملة. اسحب كتلة ضمٍ أخرى وضعها في الصندوق الثاني لكتلة الضم السابقة. وأخيرًا اسحب الكتلة من فئة استشعار Sensing، وضعها في الصندوق الفارغ الأول لكتلة الضم الثانية، ثم اكتب كلمة 'seconds ' في الصندوق الفارغ الثاني لكتلة الضم الثانية، وتأكد من وجود مسافةٍ فارغةٍ قبلها. اسحب أخيرًا كتلة البيانات إلى نهاية سلسلة التعليمات، ثم استبدل الرقم '0' بكتلة الإخبار . أصبحت اللعبة الآن جاهزةً للاختبار، لذلك انقر على الراية الخضراء واستعد. اضغط المفتاح SPACE فور رؤيتك للرسالة '!Hit Space' وحاول أن تحطّم زمن اللعبة القياسي. شكل 13-4 حان وقت اللعب يمكنك توسيع المشروع أكثر بحسابك المسافة التقديرية التي ستقطعها محطة الفضاء الدولية وهي تدور حول الأرض خلال الفترة التي استغرقتها حتى تضغط المفتاح SPACE، وذلك بعد الأخذ بالحسبان أن سرعتها تصل إلى 7 كيلومترات في الثانية. أنشئ أولًا متغيرًا باسم 'distance'، ولاحظ كيف تتغير الكتل تلقائيًا في فئة البيانات Data لإظهار المتغير الجديد، وستبقى كتل المتغير السابق في البرنامج كما هي. أضف الكتلة ، ثم اسحب كتلة عامل الجداء وضعها فوق القيمة '0' للكتلة السابقة، ثم اسحب الكتلة وضعها فوق الفراغ الأول لكتلة عامل الجداء واكتب الرقم '7' في الفراغ الثاني لها. ستقرأ الكتلة المركبة التي أنشأتها أخيرًا قيمة المقدار الذي يمثِّل الزمن الذي استغرقته حتى ضغطت المفتاح SPACE مضروبًا بالرقم '7'، وهي المسافة التي ستقطعها محطة الفضاء الدولية خلال هذه الفترة. أضف الكتلة وغيّر الزمن من '1' إلى '4 ثوان'، ثم اسحب كتلةً أخرى وضعها في نهاية السلسلة، وضع ضمنها كتلتي ضم كما فعلت سابقًا. اكتب في الفراغ الأول للكتلة الأولى الجملة ' In that time the ISS travels around' واترك مسافةً فارغةً في نهايتها. ستملأ كتلة الضم الثانية الفراغ الثاني من كتلة الضم الأولى، اكتب في الفراغ الثاني لكتلة الضم الثانية الكلمة 'kilometres ' واترك مسافةً فارغةً قبلها. اسحب كتلة العوامل وضعها في الفراغ الأول لكتلة الضم الثانية، ثم اسحب الكتلة وضعها داخل الفراغ الوحيد للكتلة السابقة. تُدوِّر الكتلة العدد إلى أقرب عددٍ صحيح أكبر أو أصغر منه، وبالتالي ستظهر النتيجة عددًا صحيحًا سهل القراءة بدلًا من عددٍ فائق الدقة صعب القراءة بسبب وجود عددٍ كبيرٍ من الأرقام بعد الفاصلة. انقر على الراية الخضراء لتنفيذ البرنامج لتلاحظ المسافة التي ستقطعها محطة الفضاء الدولية خلال الوقت الذي تستغرقه في ضغط المفتاح SPACE، كما هو موضحٌ في الشكل التالي. تذكر أن تحفظ البرنامج عند الانتهاء لتتمكن من تشغيله مجددًا دون عناء كتابته من جديد. الشكل 14-4 سيخبرك تيم كم المسافة التي قطعتها محطة الفضاء الدولية المشروع الثاني: سباحة فنية متزامنة تستخدم معظم الألعاب أكثر من زر للتحكم بمجرياتها، وسنوضح هذه الفكرة في مشروعنا الحالي باستخدام زري لوحة المفاتيح ← و→. أنشئ مشروعًا جديدًا واحفظه باسم 'Synchronised Swimming'، ثم انقر على المسرح وبعدها على نافذة الخلفيات. انقر على اللون الأزرق المائي ضمن لوحة الألوان، ثم انقر على أيقونة الدلو التي تملأ الخلفية بلونٍ محدد، وانقر بعدها على الخلفية البيضاء للمسرح لتصبح باللون المطلوب، كما يبين الشكل التالي. شكل 15-4 املأ الخلفية باللون الأزرق انقر بالزر الأيمن على شخصية القط، ثم اختر الأمر "حذف delete". انقر على الأيقونة "اختر شخصية من المكتبة choose sprite from library" لتعرض لك مجموعة الشخصيات المدمجة مع سكراتش 2، وانقر على فئة الحيوانات Animals ثم اختر الشخصية 'Cat1 Flying'، وبعدها انقر الزر OK. ستفيدنا هذه الشخصية جيدًا في السباحة أيضًا! شكل 16-4 اختر شخصية من المكتبة انقر على الشخصية الجديدة، ثم اسحب كتلتي أحداث من النوع إلى منطقة بناء البرنامج. انقر في الكتلة الأولى على السهم الصغير المتجه للأسفل بجانب الكلمة 'space' واختر 'left arrow' من قائمة الخيارات، ثم اسحب كتلة الحركة وضعها أسفل كتلة الحدث when left arrow pressed (عند الضغط على السهم الأيسر)، وكرّر نفس العملية على كتلة الحدث الثانية لتغيّر زر 'space' بالزر 'right arrow'، وضع تحتها الكتلة . لاحظ أن مجموعتي الكتل السابقتين ستبقيان منفصلتين ولا تمثلان سلسلةً واحدة. اضغط الزرين ← و→ لاختبار برنامجك، حيث ستلاحظ أن القط سيدور بالجهة التي تريد وفقًا للزر الذي تضغط عليه. انتبه أنك لست بحاجةٍ إلى النقر على الراية الخضراء لتنفيذ البرنامج، لأن كتلة بادئ البرنامج التي استخدمتها سابقًا ستبقى فعّالة دومًا حتى لو لم يكن البرنامج في وضع 'التشغيل running' بالمعنى العام. كرّر الخطوات السابقة مرتين لكن اختر الزرين 'up arrow' و'down arrow' في كتلتي الأحداث وضع الكتلتين و بدلًا من كتلتي الدوران. اضغط الآن على الأسهم في لوحة المفاتيح لترى القط يدور ويسبح إلى الأمام والخلف. لجعل حركة القط أكثر واقعية، يمكنك تغيير مظهره، ويُعرف هذا الأمر في سكراتش بتغيير الزي costume. انقر على شخصية القط ثم على النافذة الفرعية المُسماة أزياء Costumes فوق لوحة الكتل البرمجية، وانقر على الزي 'cat1 flying-a'، ثم انقر على أيقونة 'X' الدائرية التي ستظهر على زاوية الزي اليسارية العليا لحذفه. اختر الزي 'cat1 flying-b' واستخدم الصندوق أعلاه لتغيير الاسم إلى 'right'، كما هو موضحٌ في الشكل التالي. شكل 17-4 إعادة تسمية الزي انقر بزر الفأرة الأيمن على الزي الجديد 'right' في النافذة الفرعية أزياء Costume، ثم انقر 'نسخة أخرى duplicate' لإنشاء نسخةٍ جديدةٍ، ثم انقر على هذه النسخة لاختيارها وسمِّها 'left'. انقر بعد ذلك على أيقونة عكس الاتجاه يمين- يسار وستجدها في شريط الأيقونات بجوار صندوق تغيير اسم الزي في النافذة الفرعية أزياء Costumes، وهكذا ستحصل على زيين، أحدهما 'right' ووجه القط فيه نحو اليمين، والآخر 'left' ووجه القط فيه نحو اليسار، كما هو موضحٌ في الشكل التالي. شكل 18-4 نسخ الزي ثم قلبه وتسميته 'left' انقر على النافذة الفرعية المُسماة منطقة بناء البرنامج Scripts، ثم اسحب إليها كتلتي مظهر من النوع و، وضَعهما أسفل كتلتي الحدث left arrow (عند الضغط على السهم الأيسر) و right arrow (عند الضغط على السهم الأيمن) بحيث يتوافق السهم اليميني مع الزي اليميني واليساري مع اليسار. جرب السهمين اليميني واليساري الآن في لوحة المفاتيح وستلاحظ أن القط يدير وجهه باتجاه الحركة. وللحصول على الطابع الأولمبي للسباحة المتزامنة، سنحتاج إلى المزيد من السباحين، كما سنحتاج إلى طريقةٍ لإعادة ضبط موقع الشخصية. أضِف الكتلة وضع تحتها كتلة الحركة ، وغيّر القيم الصفرية إذا كان ذلك ضروريًا، أضف بعد ذلك الكتلة . عند النقر على الراية الخضراء سيُوجّه القط إلى منتصف المسرح (النقطة (0,0)) وسيشير إلى اليمين. لإنشاء عددٍ أكبر من السباحين، أضف كتلة التحكم بعد تغيير قيمتها الافتراضية '10' إلى '6'، ثم ضع كتلة التحكم داخلها. ولجعل السباحين يتحركون بحيث لا يتوجهون جميعهم إلى نفس الوجهة، أضف الكتلة فوق الكتلة ضمن الكتلة . انقر على الراية الخضراء لترى أن السباحين قد ظهروا! ستحتاج إلى بعض الموسيقى لإكمال اللمسة الأولمبية، لذلك انقر على النافذة الفرعية المُسماة أصوات Sounds والموجودة فوق لوحة الكتل البرمجية، ثم انقر الأيقونة 'اختر صوتًا جديدًا من المكتبة choose new sound from library'. انقر على فئة أصوات موسيقية Music Loops واختار الصوت الذي يعجبك بعد تجريب الأصوات بالنقر على أيقونات التشغيل. اخترنا في برنامجنا الصوت 'dance around'، انقر OK لانتقاء الصوت، ثم انقر على واجهة بناء البرنامج Scripts لفتح منطقة البرنامج مجددًا. شكل 19-4 اختر الموسيقى من مكتبة الأصوات أضف كتلة أخرى إلى منطقة بناء البرنامج، ثم أضف كتلة التحكم . أضف داخل كتلة التحكم الكتلة ، وتذكر أن تضع اسم المقطوعة الموسيقية التي تختارها وليس بالضرورة 'dance around'. انقر على الراية الخضراء لاختبار البرنامج، وانقر على المثمَّن الأحمر لإيقاف البرنامج وإسكات الموسيقى إذا أردت. يمكنك محاكاة رقصةٍ كاملةٍ من خلال إضافة محرّض حدث جديد event trigger إلى برنامجك، ولهذا أضِف كتلة الأحداث ثم الكتلة وتحتها الكتلة ، وضع داخل كتلة التكرار الأخيرة الكتلتين و. انقر على الراية الخضراء، ثم انقر على المفتاح SPACE وشاهد الرقصة. لا تنس حفظ البرنامج عندما تنتهي. شكل 20-4 البرنامج الكامل للسباحة المتزامنة المشروع الثالث: لعبة القوس والسهم لقد بدأت بخط طريقك نحو احتراف سكراتش، لهذا لا بُدّ أن ترفع مستوى التحدي قليلًا بتصميم لعبة قوسٍ وسهم، والتي يُطلب فيها من اللاعب إصابة هدفٍ بقوسٍ مُتأرجحٍ وسهم. لنبدأ بتنزيل موارد اللعبة من ملف ArcheryResources.sb2 مستعينين بمتصفح كروم، حيث تستغرق العملية عدة ثوانٍ فقط. افتح بعدها برنامج سكراتش 2، ثم انقر على قائمة الملف File، ثم اختر تحميل مشروع Load Project. انقر على 'pi' في الجزء اليساري من النافذة وابحث عن المجلد 'تنزيلات Downloads'، وانقر على الملف ArcheryResources.sb2 ثم انقر الزر فتح Open. سيسألك البرنامج إذا كنت تريد استبدال محتوى البرنامج الذي تعمل عليه حاليًا، لذلك انقر إلغاء Cancel ثم احفظ برنامجك أولًا إذا أردت الاحتفاظ به، وإلا انقر الزر OK. شكل 21-4 موارد مشروع القوس والسهم يحتوي المشروع على خلفية وشخصية، ولكن دون أية شيفرات لتشغيل اللعبة، لذا عليك إضافتها بنفسك. ابدأ بإضافة الكتلة ثم الكتلة وانقر فيها على السهم المتجه للأسفل واختر 'رسالة جديدة New Message'، ثم اكتب فيها 'new arrow' قبل النقر على الزر OK. ستظهر الكتلة الآن على الشكل . رسالة البث broadcast هي رسالةٌ يصدرها جزءٌ من البرنامج ويتلقاها جزءٌ آخر؛ ولتستفيد حقيقةً من هذه الرسالة، أضف الكتلة ثم حوّلها لتصبحمن خلال النقر على السهم المتجه للأسفل واختيار 'new arrow'. أضف الكتلتين ثم أسفل الكتلة ، وغيّر القيمة الافتراضية في الكتلتين السابقتين كما يناسبك بعد سحبهما إلى منطقة بناء البرنامج. انقر على الراية الخضراء وراقب ما فعلته حتى اللحظة، حيث ستقفز شخصية السهم التي يستخدمها اللاعب للتصويب على الهدف إلى الزاوية اليمينية السفلى من المسرح ويتضاعف حجمها 4 مرات. لزيادة التحدي في اللعبة، أضف محاكاةً لحركة التأرجح عندما يُشدُّ القوس ويصوّب اللاعب. لفعل ذلك اسحب الكتلة وضع تحتها الكتلة، وغيّر القيمة '1' إلى '0.5'، ثم ضع كتلة العوامل مكان الفراغين اللذان يحملان الرقمين '150' و '-150' في الكتلة السابقة؛ وهذا يعني أنّ السهم سيغيّر اتجاهه على المسرح عشوائيًا وسيبتعد عن الهدف مسافةً عشوائيةً أيضًا، مما سيزيد صعوبة إصابة الهدف. انقر على الراية الخضراء وراقب ما يحدث؛ حيث سيتحرك السهم ضمن المسرح مغطيًا أجزاءًا مختلفةً من الهدف، لكن حتى هذه اللحظة لا توجد وسيلةٌ لإطلاق السهم؛ لذلك اسحب الكتلة وضع بعدها كتلة التحكم ، ثم انقر على السهم المتجه للأسفل في هذه الكتلة وغيّرها إلى كتلة . انقر الراية الخضراء إذا أوقفت برنامجك، ثم اضغط المفتاح SPACE وستلاحظ أن السهم سيتوقف عن الحركة. بداية جيدة، لكنك بحاجةٍ إلى تمثيل السهم متجهًا إلى الهدف؛ لذلك أضف الكتلة واتبعها بالكتلة ، ثم انقر زر الراية الخضراء لتشغيل البرنامج مجددًا، وسيبدو السهم الآن متحركًا نحو الهدف. لجعل اللعبة أكثر متعةً، لا بدّ من وسيلةٍ لإظهار النتيجة؛ لذلك أضف الكتلة وتأكد أنها تحت الكتلة وليس داخلها، ثم ضع داخل الفراغ المخصص في الكتلة كتلة الاستشعار . ولاختيار اللون الصحيح، انقر على المربع الملون داخل الكتلة، ثم انقر على البقعة الصفراء داخل الهدف الموجود على المسرح، وهكذا سيعرف اللاعب أنه حقق نتيجةً برميته. أضِف الكتلتين و داخل الكتلة ، ثم أضف أخيرًا الكتلة بعد الكتلة ، وذلك لتمنح اللاعب سهمًا جديدًا في كل مرةٍ يطلق فيها السهم. انقر على الراية الخضراء لتبدأ اللعبة، وحاول أن تصيب العين الصفراء منتصف الهدف، وإذا فعلتها ستسمع هتافًا تشجيعيًا وستُكافأ بمئتي نقطة. ستعمل اللعبة الآن، لكن حاول استخدام ما تعلمته في هذا الفصل في إضافة نقاطٍ لإصابة الأجزاء الأخرى من الهدف، كأن يحصل اللاعب على 100 نقطةٍ عند إصابة الدائرة الحمراء و50 عند إصابة اللون الأزرق. اطلع على الملحق D، الذي يحمل العنوان "اطلع أكثر" للمزيد من مشاريع سكراتش. ترجمة -وبتصرف- للفصل الرابع "Programming with scratch" من كتاب THE OFFICIAL Raspberry Pi Beginner’s Guide. اقرأ أيضًا المقال التالي: البرمجة باستخدام لغة بايثون في تطبيقات راسبيري باي المقال السابق: جولة في راسبيان: نظام تشغيل راسبيري باي إنشاء لعبة أضواء باستخدام برنامج سكراتش وحاسوب راسبيري باي لعبة تخفيف التوتر باستخدام سكراتش وحاسوب راسبيري باي
  24. يُميِّز عمل مجموعة الضوء الأساسية لرسام المدرسة التقليلية Minimalism جو باير ثلاثة مربعات ذات إطاراتٍ سوداء مع عصابة ملونة، وتبدو المربعات وكأنها تطفو بفضل طريقة الإدراك النفسية للبشر. يُظهر العمل السابق أنه لا حاجة لتغطية لوحة العمل الفني بالكامل لتحصل على انطباع ما، وتنطبق القاعدة نفسها على صفحة الويب الرئيسية، فقد لا ترغب في أن تملأ كامل صفحتك بالمحتوى. وفي بعض الأحيان تسود مقولة "الأقل هو الأكثر Less is more"، فوجود المساحات البيضاء أو الفارغة سيمنح صفحتك الرئيسية منافعًا عظيمةً تصب في صالح انسيابيتها وهيكلها وتأثيرها. هل تريد معرفة الطريقة التي تبني بها صفحة رئيسية مبهرة تستخدم طاقة المساحات البيضاء؟ ستنتقل بك هذه المقالة من مفهوم المساحات البيضاء وما الذي تقدمه لتحسين صفحتك الرئيسية إلى كيفية استغلال إمكانياتها. ماهي قصة المساحات البيضاء؟ تُعرف المساحات البيضاء أو الفراغ السلبي Negative space كما تُدعى أحيانًا في مجال تصميم صفحات الويب، على أنها الفراغات بين عناصر التصميم. وعلى خلاف التسمية، لا ينبغي أن تكون المساحات البيضاء بيضاءً أو فارغةً بالضرورة، فقد يكون لهذه المساحات لون مغاير للأبيض أو حتى صورة للخلفية. للصفحات الرئيسية نوعين من المساحات البيضاء، هي المساحات الدقيقة micro والواسعة macro كما يشير تصنيفها: الفراغات البيضاء الدقيقة: هي المساحات بين العناصر الصغيرة، مثل المساحات بين الأيقونات، أو الفراغات بين أسطر النص. الفراغات البيضاء الواسعة: هي المساحات بين العناصر الكبيرة مثل الرسوميات والأعمدة التي تضم نصوصًا. لنستخدم أحد أمثلتنا عن صفحات جذب العملاء ذات معدل التحول العالي لإظهار عمل المساحات البيضاء الدقيقة والواسعة. سترى في الناحية اليمنى عددًا كبيرًا من المساحات البيضاء الواسعة، والتي توجه العين مباشرةً إلى منطقة اتخاذ القرار الموجودة على يسار الصفحة، ثم توجهها نحو التطبيق الذي يعرضه الجهاز اللوحي في الأسفل. ستجد على يسار العنوان ثلاث مناطق تحوي مساحات بيضاء دقيقة تفصل بين العنوان الرئيسي والعناوين الفرعية وحقل النموذج وزر الإرسال. إذًا كما ترى، يمكن استخدام المساحات البيضاء الدقيقة والواسعة في تصميم الصفحات الرئيسية لفصل العناصر المختلفة عن بعضها وتمييزها. تزيد المساحات البيضاء القدرة على القراءة على الرغم من أن دور المساحات البيضاء في تسهيل القراءة لن يكون واضحًا عندما تكون موجودة، إلا أنك ستدرك بالطبع عملها عندما لا تكون موجودة. هل حاولت مثلًا قراءة نص تمتد كلماته لتغطي حواف الصفحة؟ أو هل حاولت قراءة نص ضخم من الكلمات المتتالية التي لا تفصل بينها أسطر؟ لن تكون هذه تجربةً مريحةً أبدًا. تزيد أهمية القراءة السهلة أكثر على الإنترنت، حيث يريد القارئ جوابًا سريعًا لتساؤلاته. وقد خلُصت آلاف الدراسات حول مستخدمي الإنترنت أن ما يقرأه العميل لا يتعدى 18% وسطيًا من محتوى صفحة ويب. لذلك عليك مساعدتهم في العثور على 18% التي يريدونها بسرعة وإلا سيغادرون موقعك. تساعد المساحات البيضاء على تصنيف صفحتك تُعد المساحات البيضاء هي العلامة الفارقة لتصاميم صفحات الويب العصرية، حيث تبدو الصفحات التي تستخدم مساحات بيضاء أكثر، أقل تكلّفًا وأوضح وذات جودة عالية. قد تشعر أنك تهدر مساحات بلا فائدة، إلا أن أهمية المساحات البيضاء بأهمية باقي عناصر التصميم. لنلق نظرةً على مثال عن استخدام المساحات البيضاء بطريقة استراتيجية وبحدها الأدنى: إن عشت في نيويورك أو زرتها في العقدين الماضيين، فلربما تكون قد رأيت إعلانات للدكتور جوناثان تسيزمور قبل أن يتقاعد سنة 2016. لقد عُرفت هذه الإعلانات بأنها من النوع المبالغ فيه، وأحد أسباب ذلك، أنها تحشر العديد من العناصر التصميمية في صفحة واحدة. لا تمتلك هذه الإعلانات الكثير من المساحات البيضاء الدقيقة أو الواسعة، فكل بقعة منها تقريبًا تحوي نصًا أو صورة. لقد استمرت هذه الإعلانات بالعمل لصالح تسيزمور طوال 25 عامًا مثل مادة أساسية في إعلانات مترو الأنفاق. لن تعمل مقاربة تسيزمور مع الأعمال التي تريد أن تتسم بطابع الحداثة والمعاصرة. عند موازنة إعلانات تسيزمور بالصورة التي نعرضها تاليًا لصفحة رئيسية لموقع كتب إلكترونية مصدرها Optimonk، ستُظهر بوضوح تصميمًا مفعمًا بالألوان تمامًا كما في الإعلان السابق، لكنه يستخدم كمًا أكبر بكثير من المساحات البيضاء. تتماشى المساحات الفارغة الكبيرة سواءً الدقيقة أو الواسعة منها مع المعايير الحالية للمارسة الصحيحة في استخدام المساحات البيضاء، وتمنح صفحات الويب الرئيسية مظهرًا أكثر عصرية. كيف تجعل صفحتك أكثر جاذبية باستخدام المساحات البيضاء تؤدي المساحات البيضاء عدة وظائف في صفحة الويب، وستتمكن من وضع هذه الوظائف موضع التنفيذ إن فهمت هذه الوظائف المختلفة. مسارات مستخدم مباشرة تمتلك كل صفحة ويب تراتبيةً مرئيةً لعناصرها تقود المستخدم عبر العناصر التي تكوّن الصفحة. يمكنك التحكم بهذه التراتبية (التي تُدعى مسار المستخدم) بإدخال مساحات بيضاء استراتيجية، فمن المرجح أن ينظر الزائر إلى عنصر محدد عندما تحيط به مساحة بيضاء أكبر. تعود هذه الممارسة إلى مبدأ هيكلية البناء building structure، وهو أحد المبادئ الأساسية لتصميم الصفحات المرتكز على نسبة التحول. ويمكن الوصول إلى بنية تراتبية من المعلومات بإحاطة التفاصيل الأكثر أهميةً بالمزيد من المساحة البيضاء موازنةً مع الأقل أهميةً. تحقق كيف بنى مسارًا مرئيًا باستخدام المساحات البيضاء الواسعة والدقيقة في الصورة التالية: لاحظ كيف أحيط العنوان الرئيسي والعناوين الفرعية وزر اتخاذ قرار الشراء بمساحات بيضاء واسعة أكبر لتجذب عينيك أولًا. وبعد أن تمرر الصفحة للأسفل ستجد عملية من ثلاث خطوات تفصلها عن بعضها مساحات بيضاء دقيقة. وهكذا يتجه نظرك إلى العناصر الأكثر أهميةً في الصفحة بفضل الحيز الفارغ الذي يحيط بها. جزء المحتوى الذي تعرضه يمكن أن تفصل المساحات البيضاء بين النصوص في صفحات الويب وبقية الأجزاء لوضع ما يتشابه من أفكار في حيز واحد، مما يزيد سهولة القراءة. تساعد المساحات البيضاء بين أسطر النصوص والعناوين والمقاطع على فهم النص بالترتيب الصحيح. كما تجعل المساحات البيضاء الانتقال من موضوع إلى آخر في صفحة الويب أكثر سلاسة. يشير المبدأ الخامس "لفت الانتباه drawing attention" من المبادئ الأساسية لتصميم الصفحات المرتكز على نسبة التحول إلى ضرورة جذب الانتباه إلى الأجزاء الأكثر أهميةً من الصفحة. وبالتالي عندما تجزئ المحتوى باستخدام المساحات البيضاء، ستساعد الزوار بمنح كل جزء العناية التي يستحقها. ألقِ نظرةً في الصورة التالية على الطريقة التي نفّذت بها منصة Sundae صفحة ويب واضحة للغاية باستخدام الفكرة السابقة: لقد أحاطت sundae كل نقطة رئيسية في كل قسم بمساحة بيضاء لجذب الانتباه، كما دمجت بين خلفيتين باللونين الأبيض والرمادي مع الكثير من المساحات الفارغة لفصل قسمي الصفحة عن بعضهما كما يظهر في الصورة حقق تأثيرا أكبر وفقًا لمبدأ لفت الانتباه السابق، ستسمح المساحات البيضاء بمنح أثر أكبر للمساحات غير البيضاء، فالعناصر الأساسية المُحاطة بمساحات بيضاء ستبرز بوضوح عندما لا تجاورها عناصر تشتت الانتباه عنها. لاحظ كيف مزجت صفحة أمازون المساحات البيضاء مع مبدأ لفت الانتباه لأي عنصر اتخاذ قرار: تحيط الصفحة الميزات وشهادات المستخدمين بكمية مناسبة من المساحات البيضاء، ثم تعرض عنصر اتخاذ القرار ("استعد Get started") محاطًا بمساحة بيضاء، ثم تكشف التفاصيل الإضافية في قسم الأسئلة الأكثر تكرارًا FAQ بأقل كمية ممكنة من الفراغات البيضاء. تدعوك أمازون إلى الاستعداد لرحلة الشراء بعد استعراضٍ لطيف لمنافع المنتج، فإن أردت التنقيب أكثر في التفاصيل، فعليك بقسم الأسئلة الأكثر تكرارًا. عزز تجاوب صفحتك بما يرضي المستخدم لا بد أنك تريد عرض ما حققته باستخدام المساحات البيضاء على كل منصة تعرض عليها صفحتك، لذلك ابقِ على المساحات البيضاء ثابتةً في كل التنسيقات التي تُعرض بها الصفحة بما في ذلك على الهواتف المحمولة، وتأكد بالإضافة إلى ذلك أنّ المساحات البيضاء لن تدفع بقية العناصر بعيدًا عن المشهد عند عرض الصفحة على الحواسب المكتبية، أو أن تتداخل على الأجهزة الأصغر. يشير المبدأ السابع "تخفيض التلامس reducing friction" من المبادئ الأساسية لتصميم الصفحات المرتكز على نسبة التحول، إلى هذا الأمر تمامًا. ووفقًا لمنصة Statcounter، فإن 49.97% من الحركة على الإنترنت مصدرها مستخدمي الحواسب المكتبية وترتفع النسبة إلى 55.31% في الهواتف المحمولة. إذًا، لا بد من تقديم تجربة مميزة لمستخدمي الهواتف المحمولة عند زيارة صفحتك أيضًا. لاحظ كيف وازنت صفحة ويب ClaimCompass المخصصة للعرض على الهواتف المحمولة بين المساحات البيضاء وسهولة الاستخدام. تلفت الصفحة في القسم الأول الانتباه إلى الخلفية بين العنوان الرئيسي والعناوين الفرعية، ثم تفصل بين علامات التحقق التي تصف الفوائد المقدّمة بمساحات بيضاء دقيقة لتجعلها أكثر قابليةً للقراءة. تظهر جميع العناصر وكأنها في المكان المناسب حتى المساحات البيضاء المستخدمة في تنسيق الهواتف المحمولة. ابدأ باستخدام المساحات البيضاء لا تستهن بقدرة المساحات البيضاء. عندما تمنح العناصر في صفحتك مساحةً كافية، فستخدم الغرض الذي وجدت من أجله بفعالية أكبر، مما يزيد من فرصة رفع نسبة تحول الزوار إلى عملاء أيضًا. ترجمة -وبتصرف- للمقال How White Space Can Boost Your Landing Page Conversions لكاتبه Josh Gallant. اقرأ أيضًا كيفية تحسين إعدادات تطبيق بناء على تجربة المستخدم تحليل تجربة المستخدم ونصائح لتحويل الزوار إلى عملاء التحقق من سهولة الوصول لصفحات الويب الدلالات المضمنة لعناصر صفحة الويب ودورها في تعزيز سهولة الوصول النسخة العربية الكاملة من كتاب مدخل إلى تجربة المستخدم (User Experience - UX)
  25. هناك الكثير من اﻷمور التي ستساعدك في العمل على أدوبي إليستريتور Adobe Illustrator. مثل محرر رسوميات شعاعية vector graphics editor، يُعد إليستريتور برنامجًا فعالًا يساعد المصممين على إنشاء وتعديل الرسوميات. لقد جاءت فكرة البرنامج من شركة آبل وصُمم ليعمل على ويندوز وماك أو إس، لكن ليس من السهل العمل على إليستريتور، لذلك يستخدم مصممي الرسوميات المتمرسين حيلًا تبسط العمل لا يعرفها الكثيرون. سيركز هذا المقال على بعض الحيل المستخدمة في إليستريتور عند العمل على رسومياتك، بحيث قد تصنع هذه الحيل الفرق وتسهل عملك، ملقيةً حملًا ثقيلًا عن كاهلك. استخدام القلم يُعَد القلم Pen أكثر أدوات إليستريتور قوةً وفعالية، حيث يساعدك في تحديد وتوزيع نقاط الارتكاز anchor points عند تعديل المنحني الذي يصل بينها. ويمكن إنجاز ذلك عن طريق التحكم بنقطتين ترتبطان بكل نقطة ارتكاز. قد يكون التعامل مع القلم مربكًا أحيانًا، لكنه فعّال جدًا عند متابعة الخطوط ورسم أشعة مخصصة. وفي الوقت ذاته، هي الأداة التي يفضلها معظم المصممين المتمرسين نظرًا للّمسة المتقنة التي تقدمها. وإن كنت مبتدئًا، فبإمكانك تعلم استخدامها عبر التمرينات؛ أما إذا كنت قد استخدمته سابقًا، فاكتسب خبرةً أكبر بالاستخدام المتكرر له. حول النص إلى صورة يمكنك في اليستريتور تحويل النصوص إلى صور أو رسومات، وذلك بتحويلها إلى كائنات Objects، وبالتالي لن تكون قادرًا بعدها على تعديل النصوص باستخدام الوظائف المخصصة لذلك، إذ لن تتمكن من تحرير النص بالكتابة فوقه، أو بالضغط على المفتاح Backspace عند تحويله إلى كائن. يريحك هذا الأمر من إرسال خطوط الكتابة Fonts إلى من يريد استخدام ملف التصميم، إذ ستواجهك مثلًا مشكلة الطباعة الخاطئة لتصميمك عندما تُرسله إلى المطبعة إن لم تكن لديها الخطوط نفسها التي استخدمتها. وهذا هو المبرر الرئيسي لتحويل النصوص إلى صور. سيكون بالإمكان معالجة النص الذي حولته إلى كائن مثل غيره من الرسوميات، وهذه حيلة ممتازة في إليستريتور. استخدم قناع الاقتطاع قناع الاقتطاع Clipping mask هو كائن يغطي العمل الفني لتظهر منه فقط المناطق التي تقع داخل القناع. ويمكن أن نقول بأنه أداة لاقتطاع أجزاء من العمل بما يتلاءم مع شكل القناع. تُعرَف المجموعة المقتطعة بأنها مجموعة من الكائنات المقنّعة (المغطاة)، بالإضافة إلى قناع الاقتطاع. لتسهيل مشاريع التصميم التي تُنفّذها، عليك التعرف على قناع الاقتطاع جيدًا وفهم طريقة عمله، إذ يمكِّنك القناع من إضافة عناصر أو إزالتها أو تعديلها ضمنه، وسيساعدك كثيرًا في إنجاز تصميمات رسومية وأعمال فنية مميزة. تعرف على لوحة التحكم بالمسارات والحدود لوحة التحكم بالمسارات Stroke panel هي لوحة تضم أدوات متنوعةً لإدارة خطوط الرسم وحدود الكائنات والمسارات التي ترسمها بعض الأدوات في تصميمك. تقع اللوحة في الناحية اليمنى من الشاشة وتتيح لك إمكانية ضبط لون وحجم المسار أو الخط المحدد. لا بدّ من الاطلاع على وظيفة كل أداة موجودة في اللوحة، وبإمكانك إظهار بقية الأدوات في اللوحة بالنقر على إظهار الخيارات show options. ركز على أدوات معينة، مثل أداة نهايات Cap وزوايا Corners ومحاذاة المسار Align stroke وتنسيق العرض Width Profile، واستغلها لصالحك. تساعدك هذه الأدوات على إضفاء لمستك الشخصية على عملك وتحسينه على أصعدة مختلفة. سيكون حجم المسار الذي ترسمه محددًا افتراضيًا، وبالطبع ستغير واجهة تصميمك إن تعلّمت كيف تتحكم وتعدل حجم هذه المسارات. استخدم اختصارات اللصق بطريقة مثالية إنّ معرفة اختصارات لوحة المفاتيح لإنجاز الوظائف في إليستريتور أمر مهم جدًا، خاصةً عندما يداهمك الوقت. فتنفيذ كل شيء باستخدام الفأرة سيستغرق وقتًا أطول. يستخدم المصممون تعليمتي النسخ واللصق في كل مشاريعهم، لذلك من الأجدى تنفيذ هاتين التعليمتين باستخدام الاختصارات لتوفير الوقت. يمكن إنجاز ذلك من خلال أشرطة القائمة Menu bars، لكننا سنقدم لك الاختصارات التي ستساعدك على تقليل الزمن اللازم لإنهاء مشروعك بالكامل. CTRL+F: ينسخ كامل الكائن الرسومي ويضعه فوق النسخة القديمة. يساعدك هذا الاختصار على إنجاز عملية محاذاة مثالية من ناحية تطابق اليكسلات مع النسخة القديمة. CTRL+B: ينسخ الكائن المحدد ويلصق النسخة خلف الأصل. الضغط على ALT أثناء سحب كائن: تؤدي هذه العملية إلى نسخ الكائن الذي تسحبه، ولا بدّ من أن تضغط باستمرار على ALT حتى ترفع إصبعك عن الفأرة، فإن رفعت يدك عن ALT قبل زر الفأرة، فستنفذ عملية سحب فقط. الضغط على SHIFT أثناء سحب كائن: ستظهر لك إرشادات إلى المكان الأنسب لنقل الكائن، وتفيدك هذه الحيلة في إيجاد التراصف المثالي للكائن عندما تنقله من مكان لآخر. فصل الأدوات التي تستعمل باستمرار عن شريط الأدوات يفضل المصممون أدوات بعينها أثناء العمل ويستخدمونها بكثرة، لذلك ننصح دائمًا بفصل هذه الأدوات عن شريط الأدوات، فبدلًا من أن تكون في مكان ثابت، فمن الأفضل أن تبقى حرةً تستطيع أن نقلها إلى المكان الذي يناسبك. انتبه إلى أنك لا تستطيع فصل أية أداة عن شريط الأدوات، فهناك أدوات لا يمكن فصلها. تسهّل هذه الإمكانية التي يقدمها شريط أدوات إليستريتور عمل المصممين، كما توفر الوقت المستغرق في البحث عن أداة محددة يستخدمونها باستمرار. وحتى لو استخدمت أداةً ما عدة مرات فقط في مشروعك، فمن الأفضل تركها تطفو حرة لتصل إليها بسهولة. أنشئ الصناديق مدورة الزوايا بطريقة أكثر مرونة يستخدم المصممون باستمرار هذه الأيام عناصرًا تُدعى بالصناديق مدورة الزوايا Rounded Boxes، وقد ترى هذه العناصر في أي مكان ضمن التصاميم التي يجري تطويرها حاليًا. يزوّدك إليستريتور بأداة خاصة لرسم هذه العناصر تُدعى المربع المدوّر Rounded-rectangle، لكنها تفتقد المرونة اللازمة في العمل، ويجد المصممون صعوبةً في استخدامها. فحالما تُنشئ هذا العنصر على الورقة، سيتوجب عليك الانتقال من نقطة ارتكاز إلى أخرى لضبط شكله وأبعاده، وقد يقودك ذلك إلى تفكيك الشكل، أو أن يغدو شكلًا غريبًا غير محدد المعالم. لتفادي هذه المشكلة، أنشئ مربعًا نمطيًا، ومن ثم انتقل بالفأرة إلى الخيار تأثيرات Effect، ثم أضف تنسيقًا Stylize، ثم زوايا مدورة Rounded Corners. يساعدك ذلك على إنشاء مربع مدوّر الزوايا انطلاقًا من مربع نمطي. ستكون النتيجة مربعًا مرن الاستخدام، بحيث يسهل تغيير حجمه بالمقدار الذي تريده. ولكي تغير قياس الزاوية، انتقل إلى لوحة المظهر appearance panel، وانقر نقرًا مزودجًا على زر تنسيق الزوايا المدورة rounded corner style. استخدم مكتبات الرموز من أهم ميزات إليستريتور هو قدرته على تخزين الكائنات الرسومية والرموز ضمن لوحة الرموز Symbols panel، ثم إعادة استخدامها. ستكون قادرًا بفضل هذه الميزة العظيمة على حفظ كائناتك الرسومية والرموز، ثم إعادة استخدامها في أي مكان تشاء ضمن مشروعك الحالي، أو أية مشاريع جديدة أخرى. توفّر لك لوحة الرموز مكتبةً جاهزةً للاستخدام تظهر فائدتها عند حاجتك إلى إعادة استخدام بعض الرموز أو الكائنات التي عملت عليها سابقًا. وتُضاف الرموز إلى اللوحة، من خلال تحديد هذه الرموز أولًا، ثم النقر على زر رمز جديد New Symbol في لوحة الرموز. بعد أن تضيف الرمز بنجاح إلى المكتبة، يمكنك استخدامه بسحبه بكل بساطة من لوحة الرموز إلى ورقة العمل. وأهم ما في الأمر، هو أنّ هذه الرموز قابلة للتعديل بالطريقة التي تشاء، لكن بمجرد أن تعدّل الرمز ستتغير جميع نسخه التي استخدمتها في ورقة العمل. ولتعديل الرمز، عليك النقر عليه ضمن ورقة العمل نقرًا مزدوجًا، وتذكر أنك حين تعدل الرمز، فكل ما تفعله سينسحب على أيقونة الرمز ضمن اللوحة، وعلى كل نسخه التي استخدمتها في ورقة العمل. أنشئ فراشيك الخاصة لا يعرف المبتدئون أنه بالإمكان إنشاء فرشاة خاصة بهم، لكن المصممين المتقدمين يدركون ذلك. فإن أدركت أن الفرشاة التي تعمل بها لا تلبي حاجاتك، فيمكن دائمًا إنشاء فرشاة جديدة خاصة بك. عليك أولًا اختيار الشكل الذي ستبني فرشاتك انطلاقًا منه، وبإمكانك إنشاء الفرشاة أيضًا من أداة المربع. انتقل بعد ذلك إلى لوحة الفراشي Brushes palette وانقر على السهم لاختيار فرشاة جديدة New Brush. عليك اختيار فرشاة فنية جديدة New Art Brush من بين الخيارات الأربعة الموجودة، ثم تخصيص، بعد ذلك اتجاه مسار الفرشاة brush stroke لكي يكون مسارها متقنًا. يُنصح دائمًا أن تنشئ عدة فراشي مخصصة لكي تختار ما يناسبك منها وتبدأ عملك. استفد من الدورات التعليمية التي تُرشدك إلى إنشاء الفراشي المخصصة إن كنت مبتدئًا. ينشئ المحترفون فراشي خاصة لتعزيز عملهم الفني، حيث تمكّنهم من العمل على مشاريع مختلفة وفقًا لما يحتاجه العملاء. وهذه أحد الحيل الرائعة التي ينبغي عليك استخدامها في إليستريتور. استخدام عدة لوحات فنية في نفس المستند يشتهر إليستريتور بكونه برنامج تصميم رسوميات قوي جدًا، وذلك نظرًا لامكانياته المتنوعة، فمن هذه الإمكانيات، نجد إنشاء عدة لوحات فنية artboards في المستند نفسه. تُعرّف اللوحة الفنية بأنها المنطقة القابلة للطباعة التي تطوّر فيها رسوماتك، ويساعدك ذلك عندما تحتاج لعمل عدة لوحات فنية في المستند التي تعمل عليه، مثل حالة تصميم عدة صفحات ويب في نفس الموقع. لكل لوحة فنية عالمها الخاص، لكنها تشترك جميعها بالطبقات layers. بإمكانك استخدام الاختصار CTRL+O لإنشاء لوحة فنية جديدة، كما يمكنك تغيير حجمها ونسخها أو حذفها كما تشاء، إذًا فاللوحات الفنية أمر مشابه لصفحات مرنة في المستند نفسه. استخدم قناع العتامة قناع العتامة opacity mask هو مزيج بين قناع الاقتطاع وقناع الطبقات، إذ يمكنك التحكم بمظهر الشكل أو الرمز باستخدام هذا القناع. يُستخدم قناع العتامة أيضًا في مزج ألوان مختلفة بانتظام لكي يبدو التصميم فريدًا وواضحًا. ولتُنشئ قناعًا ما، أنشئ أولًا شكلًا ثم انتقل إلى لوحة الشفافية transparency panel، حيث يمكنك ملاحظة صورة مصغرة لعرض الشكل. انقر نقرًا مزدوجًا على البقعة الموجودة على يمين هذه الصورة لتمكين القناع. يعمل قناع العتامة في الستريتور بالطريق ذاتها التي يعمل فيها في برنامج أدوبي فوتوشوب، حيث يمكنك استخدام اللون الأسود لإخفاء العناصر والأبيض لإظهارها. ولكي تجرب الأمر قليلًا، حاول أن تستخدم التدرجات اللونية gradients وأن تغير العتامة. سيعطيك ذلك تأثيرات رائعة على الرسوميات المختارة، وهكذا سيكون عمل قناع العتامة. ستكون قادرًا على تصميم أعمال فنية مميزة باستخدام قناع العتامة إن تعلّمت كيف تستخدمه بذكاء وفعالية. يُنصح المبتدئون بتعلم المزيد من خلال الدورات التعليمية على الإنترنت، ويمكن للمتمرسين تطبيق ذلك مباشرةً في مشاريعهم. فكلما استخدمت أداة أكثر، خطرت في بالك أفكار جديدة في استخدامها. خلاصة ركّزنا كثيرًا على استخدام عدة حيل تزيد من فعالية عملك على مشاريع تصميم الرسوميات، كما أشرنا إلى إعادة استخدام الرموز والعناصر التي ترغب في استخدامها مرارًا في مشاريعك. ستوفر الكثير من الوقت عند اتقانك لهذه الحيل، وستساعدك على تصميم أعمال فنية مذهلة بكل سهولة. يمكن للمبتدئين العودة إلى هذه النصائح والحيل بعد تعلم أساسيات العمل على الستريتور ليحثوا الخطى في تطوير أعمالهم. ترجمة -وبتصرف- للمقال 11 Amazing Illustrator Hacks to Boost Your Work لكاتبه Harsh Raval. اقرأ أيضًا رسم خلفية شاطئ صيفي ببرنامج الإليستريتور كيفية رسم طائر النحام الوردي باستخدام برنامج أدوبي إليستريتور كيفية إنشاء ميزان مطبخ واقعي باستخدام إليستريتور كيفية إنشاء عربة يدوية مليئة بالرمال باستخدام إليستريتور
×
×
  • أضف...