لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 01/14/16 في كل الموقع
-
يوجد برامج عديدة سهلة تحتوي على أدوات سهلة جدًّا لإضافة الجدران والأبواب والنوافذ كما تحوي على عدد ضخم من نماذج مفروشات المنازل والديكورات المختلفة نذكر منها على سبيل المثال وليس الحصر: HomeByMe Sweet Home 3D Easy Planner 3D وهناك الكثير غيرها. ولكنني لن أنسى في النهاية البرنامج القديم الذي لطالما عملنا به وصممنا منازل وتحركنا بداخلها بحرية وهو برنامج 3D Home Architect الرائع.2 نقاط
-
مقدمة من أهم أسباب انتشار ووردبريس وسيطرته على سوق أنظمة إدارة المحتوى هو الكم الهائل من إضافاته المجانية والمدفوعة والتي تقدم العديد من الخصائص والمميزات والتحسينات الإضافية التي لا تتوفر بصورة افتراضية في قلب ووردبريس WordPress Core. في هذا المقال سنتعرف سوّيًا على أساسيات إنشاء إضافة لووردبريس لكن قبل الدخول في لب الموضوع دعنا نجب على سؤال مُهمّ وكذلك تعريف إضافات ووردبريس. لماذا ننشئ إضافات ووردبريس هنالك قاعدة مهمة في تطوير ووردبريس، وهي: إياك أن تلمس الشيفرات Codes الأساسية لووردبريس أي لا تُعدّل على قلب ووردبريس WordPress Core وذلك لأنه عند التحديث سيتمّ استبدال بعض أو كل ملفات ووردبريس الأساسية، وبالتّالي ستفقد التعديلات التي قمت بها، ولهذا السبب نلجأ إلى تطوير إضافات عند الحاجة لإضافة التحسينات والخصائص الجديدة على النّظام. تعريف إضافات ووردبريس إضافة ووردبريس عبارة عن دالة أو مجموعة دوال (حزمة شيفرات code package) مكتوبة بلغة php تقوم بإضافة بعض الخصائص لنظام إدارة المُحتوى. وتندمج شيفرات الإضافة معه من خلال واجهة برمجية API يوفرها له. بالإضافة لملفات php يمكن أن تحتوي الإضافة على ملفات أخرى مثل ملفات JavaScript, CSS وبعض الصور. إنشاء إضافة ووردبريس هذه بعض الخطوات المهمة عند إنشاء أي إضافة ووردبريس وبعض الأمور التي يجب مراعاتها. اختيار اسم الإضافة في البدء عليك أن تقوم باختيار اسم فريد للإضافة التي تود إنشائها بحيث لا يكون الاسم مستخدما من قبل من إحدى إضافات ووردبريس حتى لا يحدث تعارض بين الإضافات مستقبلا. إنشاء مجلد الإضافة بعد اختيار اسم الإضافة تقوم بإنشاء مجلد لها بالاسم الذي اخترناه ويكون هذا المجلد داخل مجلد plugins الخاص بالإضافات والموجود داخل مجلد wp-content كما موضح بالصّورة. يمكنك إنشاء ملف php بنفس الاسم بدلًا عن إنشاء مُجلّد كامل لكن يُفضّل أن تنشئ مُجلّدًا خاصًّا حتى يستوعب بقية ملفات الإضافة، ما لم تكن الإضافة تحتوي على ملف php واحد فقط. إنشاء الملف الأساسي للإضافة بعد إنشائك للمُجلّد في الخطوة أعلاه عليك أن تقوم بإنشاء ملف php له نفس اسم المجلد السابق، وهذا الملف هو الملف الأساسي للإضافة والذي سيستخدمه ووردبريس للتّعرف على بعض الأمور المُتعلّقة بالإضافة مثل اسمها واسم المُبرمج ورخصة الإضافة وغيرها، وهذا يتم من خلال استخدام ترويسة للملف الأساسي للإضافة وهذه هي الصّيغة العامة لها: <?php /** * Plugin Name: هنا تكتب اسم الإضافة والذي يجب أن يكون فريدًا * Plugin URI: هنا تكتب رابط موقع الإضافة * Description: هنا نبذة مختصرة عن الإضافة * Version: رقم نسخة الإضافة، مثلا 1.0.0 * Author: اسم مطور الإضافة * Author URI: رابط موقع مطور الإضافة * License: اسم رخصة الإضافة */ السّطر الإجباري هو سطر اسم الإضافة فقط، ويتمّ استخدام بقية السطور (في حال ورودها) في إنشاء معلومات الإضافة التي تظهر في لوحة تحكم الإضافات عند استعراض الإضافة. برمجة الإضافة قبل أن تبدأ في برمجة الإضافة تحتاج لمعرفة بعض الأمور العامة في برمجة ووردبريس بالإضافة لبعض التسهيلات التي يقدمها ووردبريس للمبرمجين مثل الواجهات البرمجية الجاهزة WordPress API's. الخطافات في ووردبريس WordPress Hooks ( الدخول الى عمق ووردبريس) من أهم المفاهيم في ووردبريس مفهوم الخطافات hooks والتي تنقسم إلى قسمين: الأحداث actions والمُرشّحات filters. 1- الإجراءات في ووردبريس WordPress Actions فلنفترض أنه لدينا دالة معينة نريد أن يتم تنفيذها في لحظة معينة أثناء دورة حياة ووردبريس أو عند حدوث حدث معين، كيف يمكننا إنجاز هذا الأمر؟ أحد الخيارات أن نقوم بمناداة هذه الدالة بالطريقة العادية في المكان الذي نريدها أن تُنفّذ فيه، لكن هذا الأمر يتطلّب التّعديل على ملفات ووردبريس الأساسية. لك القاعدة التي ذكرناها مسبقا: إياك أن تلمس الشيفرات الأساسية لووردبريس تمنعنا من القيام بذلك. الحل الآخر هو أن نستخدم الإجراءات actions وهي عبارة عن آليّة رائعة يوفرها ووردبريس تمكّنك من إضافة الدّوال الخاصّة بك لتُنفّذ في وقت معين أثناء تنفيذ الشيفرات الخاصة بووردبريس إذًا، يمكننا أن نعرف الإجراءات بأنها طريقة تمكننا من إخبار ووردبريس بتنفيذ دالة معينة عند حصول حدث معين وبهذه الطريقة نستطيع الدخول إلى عمق ووردبريس من دون التعديل المباشر على ملفاته الأساسية Core files. يتم هذا كله من خلال ربط الدّوال التي تريدها مع الأحداث الجاهزة التي يوفرها ووردبريس والتي يقوم بتنفيذها أثناء دورة حياته وهذا ما يجعلك قادرا على تنفيذ الدّوال الخاصة بك في أي مكان تريده تقريبا. إذا كنّا نريد مثلا تنفيذ الدّالة my_function عندما ينفذ ووردبريس الحدث my_action علينا ببساطة أن نخبره بذلك من خلال إضافة هذه الدالة إلى هذا الحدث. ويتم ذلك من خلال الدالة add_actions بالطريقة التالية add_action('my_action', 'my_function'); 1-1مثال للإجراءات في ووردبريس فلنأخذ هذا المثال الذي يقوم بإرسال بريد إلى مدير الموقع (الدالة المراد تنفيذها) كلما نشر مقالًا جديدًا (الحدث الذي تنفذ عنده الدالة) add_action('publish_post', 'email_admin'); function email_admin(){ // هنا يتم إرسال البريد الإلكتروني إلى مدير الموقع } 2-المرشحات في ووردبريس WordPress Filters المُرشّحات هي النوع الثاني من الخطّافات التي يوفرها ووردبريس وهي مختصّة أكثر بالبيانات حيث أنها تتيح لنا إمكانية التعديل على قيم المتغيرات (اسم المقال مثلا) قبل حفظها في قاعدة البيانات أو قبل عرضها للمستخدم، وكما هو ظاهر من اسمها فهي تتيح لنا إمكانية ترشيح البيانات، بمعنى إدخالها إلى filter مُعيّن يُعدّل عليها قبل إخراجها من الجانب الآخر من هذا المُرشّح . بطبيعة الأمر وكما هو الحال بالنّسبة للأحداث فإن ووردبريس يُوفّر لك إمكانية إدخال أغلب مُتغيّراته في المُرشّحات التي تريدها من خلال اسم المتغير، ويمكنك الاطّلاع على المُتغيّرات التي يمكنك تمريرها عبر المُرشّحات بزيارة التوثيق الرسمي للمرشحات. يتم إضافة فلتر معين my_filter لبيانات معينة my_data من خلال الدّالة add_filter بالطريقة التالية add_filter( 'my_data', 'my_filter' ); حيث أن my_filter هي الدّالة التي ستقوم بالتعديل على البيانات ويتم تمرير البيانات لها من قبل ووردبريس أي أنها يجب أن تستقبل my_data كمعامل parameter. 2-1مثال للمرشحات في ووردبريس هذا المثال يقوم بتعديل محتوى المقال the_content حيث يقوم بإضافة التّوقيع لمُحتويات كل مقال في الموقع add_filter ( 'the_content', 'add_signiture' ); function add_signiture($the_content){ // هنا نقوم بإضافة الشيفرات التي تضيف التّوقيع لمحتويات المقال return $the_content; // بعد ذلك تقوم الدّالة بإرجاع القيم الجديدة لمحتويات المقال } هذه نظرة سريعة فقط على الخطافات في ووردبريس ولكن ما زال هنالك العديد من الأشياء المتعلقة بهذه الآلية الرّائعة التي يوفرها ووردبريس منها: إمكانية إضافة الـhooks الخاصة بك. تعديل أولوية تنفيذ الدّوال التابعة لنفس الـhook. ويمكنك التعرف على المزيد حول موضوع الخطافات في التّوثيق الرسمي لPlugin API وسوم القالب Template Tags قد تبدو الترجمة الحرفية مُضلّلة نوعًا ما خصوصا إذا علمت أن المقصود من وسوم القالب هو مجموعة من الدّوال الجاهزة التي يوفرها ووردبريس والتي تختصر لك الكثير من العمل، لذلك من الجيد أن تلقي نظرة عليها قبل البدء في برمجة الإضافة الخاصة بك. الجدير بالذّكر أن يتم استخدام كثير من هذه الدّوال داخل الحلقة الخاصّة بجلب المقالات في ووردبريس WordPress Loop والتي تستخدم بكثرة في القوالب، ولعل هذا هو سرّ تسميتها بوسوم القالب. حفظ بيانات/ الإضافة في قاعدة البيانات الكثير من إضافات ووردبريس إن لم يكن معظمها تحتاج لاستقبال بعض البيانات من مدير الموقع (خيارات الإضافة مثلا) وحفظها في قاعدة البيانات لاسترجاعها واستخدامها لاحقا، ولهذا السبب يتيح لنا ووردبريس عدّة طرق لحفظ البيانات في قاعدة بيانات الموقع واختيار الطريقة المناسبة يعتمد على نوع البيانات المراد حفظها. هذه الطرق هي: 1- استخدام آلية "الخيارات options" التي يوفرها ووردبريس وهذه الطريقة مناسبة في حالة كون البيانات المراد حفظها صغيرة نسبيا ولا تتغير كثيرا مثل البيانات التي تتوقع من مدير الموقع إدخالها بعد تنصيب الإضافة مباشرة (خيارات الإضافة) والتي نادرا ما تتغير. في هذه الطريقة يتم حفظ بيانات الإضافة في جدول wp_options والذي يستخدمه ووردبريس لحفظ خياراته الخاصة. 2-استخدام البيانات الوصفية الخاصة بالمقالات Post Meta وهذه الطريقة مناسبة في حالة البيانات المتعلقة بمقال أو صفحة مفردة (مثلا مزاج الكاتب عند كتابة المقال) 3-استخدام الفئات المخصّصة وهذه مناسبة لتصنيف البيانات مثل تصنيف المقالات أو المستخدمين أو التعليقات. 4- إنشاء جدول جديد في قاعدة البيانات هذه الطريقة مناسبة مع البيانات التي لا يصلح معها أي نوع من الأنواع الثلاثة السابقة والتي تتوقع أن تتزايد مع الزمن والتي لا يمكن حصرها في اسم محدد. الاستفادة من الواجهات البرمجية API's التي يوفرها ووردبريس يحتوي ووردبريس على مجموعة ضخمة من الدّوال والأصناف Classes المفيدة التي تمثل بوّابات تربطك بقلب ووردبريس WordPress Core بالإضافة إلى توفيرها لدوال مفيدة في كثيرا من الأمور البرمجية العامة في مجال الويب، وهذه أمثلة لبعض الواجهات البرمجية التي يوفرها ووربريس Plugin API: تتيح لك الدّوال المستخدمة في الاستفادة من ميكانيكية الخطافات وكذلك الدّوال المساعدة لإنشاء الخطافات الخاصة بك. Database API : واجهة برمجية تسهل التعامل مع قاعدة بيانات ووردبريس. Rewrite API: تتيح لك إمكانية تغير صيغة روابط المقالات والموقع عموما والتحكم فيها. Filesystem API: للتعامل مع نظام الملفات في نظام التشغيل. وغيرها الكثير من الواجهات البرمجية ويمكنك الإطلاع عليها من هنا أمور عامة عليك مراعاتها عند برمجة الإضافة 1- الاهتمام بأمن الشيفرة Code Security كما هو الحال عند برمجة أي سكربت من خلال لغة php عليك مراعاة أن يكون خاليا من الثغرات التي قد تعرض الموقع لخطر الاختراق، نفس الأمر ينطبق على إضافات ووردبريس فعليك الاهتمام بإغلاق الثّغرات المعروفة وحماية المدخلات وكذلك ملفات الإضافة بمنع الوصول المباشر لها عن طريق استخدام الشيفرة التالية مثلا defined( 'ABSPATH' ) or die( 'ممنوع الوصول المباشر' ); هنالك أشياء أخرى يجب مراعاتها خصوصا إذا أردت نشر إضافتك في مستودع إضافات ووردبريس، بعض هذه الأمور إجباري وتحتاج لعمله حتى يتم قبول إضافتك ونشرها في المستودع، من هذه الأمور: 2- ملف اقرأني Readme File هو ملف تقوم بتضمينه في مجلد الإضافة باسم readme.txt ويستخدمه مستودع الإضافات لأخذ بعض المعلومات بالإضافة للمعلومات التي تظهر في صفحة الإضافة في المستودع، يمكنك استخدام هذا المُوّلد لإنشائه 3- جعل الإضافة قابلة للترجمة من الأمور الأخرى التي عليك مراعاتها هو جعل الإضافة قابلة للترجمة لعدة لغات localized حيث يمكنك استخدام مكتبة gettext التي يوفرها ووردبريس والتي تجعل من عملية جعل الكلمات قابلة للترجمة أمر سهل، وبعد ذلك يتم إرفاق ملفات اللغة مع الإضافة، ويمكنك قراءة المزيد عن هذا الأمر من هنا 4- استخدام معايير تطوير وودبريس معايير التّطويرCoding Standard هي بعض القواعد العامة التي عليك مراعاتها عند كتابة الشيفرة لتجنب أخطاء التشفير Coding وتسهيل عملية كتابة الشيفرات ومراجعتها وقراءتها خصوصا في حالة تعاون أكثر من شخص في برمجة شيء ما. لووردبريس قواعده الخاصة أيضا والتي يحاول من خلالها المحافظة على قواعد ثابتة في شيفرات ووردبريس وكذلك شيفرات الإضافات والقوالب لذلك يفضل أن تلتزم بهذه القواعد عند كتابة شيفرات الإضافة الخاصة بك. يمكنك قراءة المزيد عن هذه القواعد من هنا. 5- تحديث الإضافة يستخدم مستودع إضافات ووردبريس نظام Subversion لتحديث ولمعرفة آلية القيام بذلك، زر هذه الصّفحة كانت هذه كانت مقدمة سريعة ونبذة مختصرة حاولنا أن نجعلها كمدخل لبرمجة إضافات ووردبريس وما زال هنالك المزيد لمعرفته عن برمجة إضافات ووردبريس في مقالات قادمة.1 نقطة
-
سنتعلم في هذا الدرس كيفية استخدام أدوات برنامج إنكسكيب الأساسية لرسم صندوق هدية ثلاثي الأبعاد عن طريق برنامج inkscape والذي سيكون بالشكل التالي: افتح ملفا جديدا ثم اختر المسار: File > Document properties وألغ علامة الصح عند عبارة إظهار إطار الصفحة (Show page border) من تبويب Page. ملاحظة: لتصغير وتكبير مساحة العمل، نختار من لوحة المفاتيح علامة الزائد (+) للتكبير وعلامة الناقص (-) للتصغير أو عن طريق المسار: View > Zoom نبدأ الآن برسم الصندوق ثلاثي الأبعاد. نرسم مربعا مع الضغط على زر ctrl أثناء الرسم لنحافظ على أبعاد المربع، ثم نضغط على زر التحديد والتحويل (select and transform) ثم بالضغط عليه مجددا تظهر أسهم التدوير. نختار سهم التدوير في الزاوية اليمنى أو اليسرى العلوية كما هو موضع في الصورة مع الضغط على ctrl أثناء التدوير إلى أن يصبح الشكل كما في الصورة التالية: ثم بالضغط مجددا تظهر أسهم التصغير والتكبير فنقوم بالضغط المستمر على السهم العلوي ونسحب إلى الأسفل إلى أن يصل للبعد المناسب الذي نرغب أن تكون عليه قاعدة الصندوق. نكرر الشكل الناتج عن طريق تحديد الشكل ثم الضغط على ctrl+d أو عن طريق اختيار الزر الأيمن ثم Duplicate. بعد ذلك نحرك النسخة الجديدة من الشكل للأسفل مع الضغط على ctrl ليبقى بموازاة الشكل الأصلي ونضعه حيث نرغب أن يكون ارتفاع الصندوق. نختار أداة الرسم (Bezier) ومن الشريط العلوي نحدد خيار (snap cusp nodes) ليساعدنا على اختيار نقاط التقاطع (العقد) (nodes) في زوايا الشكل بدقة. وبالأداة نرسم شكلا كالتالي: ثم نكرر الشكل (Duplicate) وبالضغط على خيار الانعكاس الأفقي (Flip horizontal) من الشريط العلوي في الصورة المحدد أو اختصاره (H): حصلنا على شكل الصندوق سنزيل الحدود عن الطريق تحديد جميع الأشكال ثم نختار خيار التعبئة والحدود الخارجية (fill and stroke) وذلك عن طريق المسار: Object > fill and stroke أو بالضغط على shift+ctrl+f. ثم نختار تبويب رسم الحدود (stroke paint) ونضغط على الخيار (x). نلون الصندوق بالألوان التالية التي اخترناها من قائمة الألوان بالأسفل: نحدد الأجزاء الثلاثة الظاهرة لنا عن طريق تحديدها قطعةً قطعة مع الضغط على زر shift أثناد التحديد، ثم بالضغط على زر ctrl نرفعها قليلا للأعلى؛ ليظهر لنا الجزء المختفي وسنتركه في مكانه إلى حين الحاجة إليه. بعد أن أتممنا عمل الصندوق سنعمل على إنشاء غطاء الصندوق وذلك بتحديد أجزائه التي لوناها بتدرجات الرمادي، ثم تكرار هذه الأجزاء عن طريق ctrl+d ورفعها لمساحة كافية أعلى الصندوق. نقوم بتحديد ارتفاع الغطاء (الشكلين المتقابلين) على جهة اليمين واليسار وتكرارهما مجددا عن طريق ctrl+d وتغيير لونهما لتمييزهما عن الشكل الأصلي ثم بالضغط على ctrl ننزلهما أسفل إلى القدر الذي نرغب أن يتوقف فيه ارتفاع الغطاء كما في الصورة: ثم بتحديد الارتفاع الأيمن مع نسخته المكررة منه نختار المسار التالي: Path > Difference أو بالضغط على ctrl+-: ونفعل الشيء نفسه مع الارتفاع جهة اليسار، ليظهر لنا الغطاء بهذا الشكل: نلغي خيار (snap cusp nodes) الذي سبق أن فعلناه ثم نكرر الارتفاع الذي كوناه لغطاء الصندوق (الشكلين المتقابلين) ونلونه باللون الأسود لنعمل ظلا للغطاء. وعن طريق خيار الإرسال للخلف (page down) المحدد في الصورة نرسل المستطيلين الأسودين للخلف لثلاثة مرات. ومن تبويب (fill and stroke) سنختار الشفافية (opacity) من 70-90 والضبابية blur 2.5 تقريبا. ملاحظة: حتى لا يظهر الظل على الحواف جهة اليمين واليسار نقوم بإزاحة الظل (المستطيل) الأيمن إلى اليسار خطوتين والظل (المستطيل) الأيسر إلى اليمين خطوتين . بالتحديد على جميع الأشكال المكونة لغطاء الصندوق نحركه لمكانه المناسب على الصندوق مع الضغط على زر ctrl لنحافظ على المحاذاة ليعطينا هذا الشكل: أنهينا عمل الصندوق وغطاءه وبقي أن نزينه بالشريطة لتكتمل هديتنا. نحدد الأجزاء اليمنى الظاهرة لنا من الصندوق مع سقف الصندوق العلوي ونقوم بتكرارها وسحبها بعيدا عن الصندوق ونلونه كما في الصورة: نكرر المربع العلوي المحدد في الصورة ونغير لونه لنميزه عن الأصل ونكبر حجمه ونحركه حيث يتكون عندها عرض الشريطة التي نرغب أن نزين الصندوق بها كما في الصورة: ثم نقوم بالضغط على: Path > difference أو بالضغط على ctrl+-. نفعل الشيء نفسه مع بقية الأشكال كما في الصور: نحدد القطع الثلاثة التي أنشأناها ثم نكررها ونضغط على خيار الانعكاس الأفقي (Flip horizontal): لتكون الشريطة في منتصف الصندوق نحاذيها عن طريق استخدام تبويب المحاذاة (Align and Distribute) وذلك عن طريق اتباع على المسار التالي: Object > Align and Distribute أو بالضغط على shift+ctrl+A. من القائمة الموجودة في التبويب نحدد (آخر تحديد) (last selected) ثم نختار قطعة الشريطة التي نرغب بمحاذاتها أولا ثم الشكل الذي سنجعلها في منتصفه ثم نضغط على الخيارات: التمركز على المحور العمودي (center on vertical axis)التمركز على المحور الأفقي (center on horizontal axis)المحددة في الصورة: ونكرر ذلك مع جميع قطع الشريطة التي أنشأناها لتظهر بهذه الطريقة: ملاحظة: نرسل قطع الشريطة الظاهرة على ارتفاع الصندوق مرتين إلى الخلف عن طريق page down المحدد في الصورة: بقي أن نرسم عقدة الشريطة لتكتمل شريطتنا. نختار أداة الرسم (Bezier) ثم نرسم شكل مثلث ثم نتبع الخطوات التالية: نختار أداة تحرير الشكل (node tool) المحددة في الصورة، ونحدد العقدة (node) في الطرف العلوي للمثلث. نختار من الشريط العلوي خيار جعل العقدة المختارة متساوية (make selected nodes symmetric) لنحصل على انحناءة مكان العقدة. نفعل الشيء نفسه مع العقدة السفلية ثم نحدد الطرف المنحني للعقدة. لنضيف لها (node) من علامة (+) في الشريط العلوي. نحدد النقطة الجديد التي أنشأناها ونختار من الشريط العلوي (object to path). نحرك النقطة لداخل الشكل يمينا. نلون الشكل ونزيل التحديد ونكرره ونعكسه أفقيا ونحركها كالتالي: نرسم شكلا مربعا ونجعل حوافه مستديرة وذلك عن طريق تحريك الدائرة في الزاوية العلوية للمربع إلى الأسفل: ثم نحركه لوسط العقدة ونزيد من قتامة لونه عن طريق ملف حوار التعبئة: بقيت الزوائد التي تمتد من عقدة الشريطة. نرسم مستطيلا ثم بالضغط على أداة (node tool) ثم (object to bath) نحدد ضلع المربع الأقل ارتفاعا ثم نضيف (node) كما فعلنا مسبقا مع العقدة وذلك بالضغط على خيار (insert new nodes) ثم نضغط على نقطة التقاطع الجديدة التي أنشأناها (node) ونحركها للداخل. نكرر الشكل مجددا، بعد ذلك باستخدام أسهم التدوير والتحجيم نصل للشكل التالي: نحدد أجزاء العقدة التي أنشأناها وبالضغط على ctrl+G نجعلها في مجموعة (group). لتكون العقدة متناسقة مع بعد الصندوق سنقوم بعمل الخطوات التالية: نختار سهام التدوير ونحدد السهم المتوسط الأيسر ونحركه للأعلى. نختار السهم العلوي المتوسط من أسهم التدوير ونحركه يمينا. نقوم بتصغير الشكل ليتناسب مع حجم الصندوق. يمكن التعديل على العقدة لنعطيها بعدا وبروزا حيث نغير اللون للون أفتح، ثم نقوم بتكرار العقدتين ونجعلها أكثر قتامة ثم بأداة (node tool) نعدل على الشكل لنصل لهذه الصورة عن طريق حذف العقد (nodes) الزائدة وتصغير الزوائد الممتدة من عقدة الشريطة إلى أن نصل لما يلي: نضيف ثنيتين صغيرتين في أطراف عقدة الشريطة بأداة (node tool). نقوم بتلوين الثنيتين بلون أقتم ونزيل الحدود، لتظهر بالشكل التالي: اكتملت الهدية ولله الحمد ولم يتبق لنا إلا أن نتلاعب بألوانها ونضيف بعض الظلال ليكون صندوقنا أكثر جمالا وأقرب للواقعية. نكرر كل جزء من شكل الشريطة مجددا بما فيها العقدة ونحوله للأسود أو الرمادي القاتم مع جعل الضبابية (blur) بمقدار 1.9 تقريبا والشفافية opacity 50 نرسل الأشكال المكررة من الشريطة للخلف بعد تحديدها. ولا ننس المربع الذي تركناه في البداية حيث نكبر حجمه بالضغط على ctrl+shift ثم نسحبه إلى أسفل الصندوق مع تحديد الخيارات كما في الصورة: هذه هي النتيجة النهائية لهذا الدرس: مع إمكانية إضافة أفكار جديدة وتغيير الألوان والأحجام:1 نقطة
-
كيفية زيادة المتتبعين لقناتك على يوتيوب وزيادة عدد المشاهدات1 نقطة
-
أبحث عن شهادة تطبيقية في مجال الهكر الأخلاقي فنصحني صديقي بهذه الشهادة، فهل من نبذة عنها؟ أي ما هذه الشهادة؟ وما تكلفتها؟1 نقطة
-
يعتمد نمط أو إطار عمل MVC على مبدأ فصل الطبقات وهي اختصار لـ Model View Controller: Model: يمثل جوهر التطبيق مثل (قائمة من سجلات قاعدة البيانات) ويلعب دور طبقة العمل business layer حيث يكون مسؤولًا عن استرجاع وتخزين البيانات من قاعدة البيانات. View: مسؤول عن عرض البيانات مثل (عرض سجلات قاعدة البيانات) ويقوم بدور طبقة العرض display layer غالبًا يكون محتواه ناتج من البيانات التي يجلبها الـ Modelـ. Controller: وحدة تحكم تعالج المدخلات مثل (معالجة سجلات قاعدة البيانات) وتعتبر مسؤولة عن معالجة تفاعلات المستخدم مع التطبيق حيث يقوم المتحكم بقراءة البيانات من الـ View (مدخلات المستخدم) وإرسال المدخلات إلى الـ Model. لماذا تعتبر MVC أفضل من Web Forms؟ يسهل MVC إدارة التطبيقات المعقدة عن طريق خاصية فصل الطبقات لتتمكن من التركيز على جانب واحد على سبيل المثال يمكنك التركيز على الـ View من دون أن تلقي بالًا لآلية سير الـ Business Logic. ميزة أخرى هامة جدًا في الـ MVC وهي سهولة اختبار التطبيق كذلك يبسط MVC عمل فريق التطوير يمكن لأكثر من مطور العمل على الـview، الـ controller و الـ business logic بشكل متوازٍ. يحوي MVC كافة الميزات الموجودة في ASP.Net Web Forms مثل الصفحات الرئيسية Master Pages، الأمن والمصادقة Authentication ولكن بنموذج أخف، أكثر مرونة وقابلية للتطوير والاختبار. كيف تعمل تقنية MVC في ASP.Net؟1 نقطة
-
أريد نيل شهادة SQL، وأستعمل SQLZOO من أجل ذلك، لكن يبقى العائق أمامي هو وجود قاعدة بيانات مع أسئلة مشابهة لتلك المطروحة أثناء نيل الشهادة، حتى أتأقلم وَ جوِ الأسئلة ونوعيتها، فهل من اقتراح؟1 نقطة
-
كلام الأخوة صحيح كلاهما ففي الحالة التي ذكرها الأخ E.Nourddine يمكن إنشاء وتعديل شكل الحدود أو الإطار Stroke للأشكال فقط Shaps مع بعض المزايا الخاصة كجعل هذا الإطار منقطًّا مع تغيير شكل الانحناء عند الزوايا وشكل نهايات الإطار بالإضافة إلى الاختيار ما بين جعل هذا الإطار بلون واحد أو تدرج لوني أو نقش وهذا الأمر الأخير المتعلق بتلوين الإطار ينطبق على طريقة الأخ Ziad Araman إلا أن الفارق في هذه الطريقة أنه لا يمكن التحكم بتنقيط الإطار أو أشكل الانحناءات والنهايات ولكن يمكن تطبيق هذا النوع من الحدود على الأشكال والعناصر أيًّا كانت على عكس الطريقة السابقة لتي لا تنطبق إلا على الأشكال فقط. هذه صورة توضح طريقة الأخ E.Nourddine وهذه صورة توضح طريقة الأخ Ziad Araman1 نقطة
-
طبعًا تأثير الجرونجي أخي هو تأثير الخشونة وهو غالبًا ما يكون عبارة عن خامة خشنة تطبّق بتداخل مُعيّن على الصورة الأصلية وهذا الأمر ذاته ينطبق على الهواتف المحمولة وهناك العديد من البرامج القادرة على أداء المهمة بل إن هناك برامج وتطبيقات مهمتها فقط تطبيق هذا التأثير على الصور مع التعديل على هذا التأثير ما يضمن الوصول إلى الشكل النهائي المطلوب وسأذكر هنا مثالًا بسيطًا عن أحد البرامج الذي يوفر تطبيق هذا التأثير وهو برنامج PowerDirector اختر موقع الصورة المراد تطبيق التأثير عليها. اخترت هذه الصورة على سبيل المثال ثم سحبت الشريط السفلي لجهة اليسار حتى وصلت إلى خيَار Overlays واخترت منها Grunge ثم اخترت أحد الخامات الموجودة لتطبيق التأثير بالتوفيق1 نقطة
-
منذ مدّة وأنا أرغب في أن أقوم بعمل تصميم يجمع بين الهندسة والتصوير الفوتوغرافي. وأخيرًا استخدمت برنامجي الإليستريتور وفوتوشوب لابتكار طريقة لتحويل صورة فوتوغرافية إلى صور مُجمّعة تجريدية في أشكال هندسية. سنبدأ مع الإليستريتور لرسم مجموعة من الخطوط الهندسية ثم نستخدم هذه الخطوط لتقطيع الصورة ببرنامج فوتوشوب لإنشاء تركيبة مثيرة للاهتمام. سلسلة الخامات وتعديلات المنحنيات ستساعد على إعطاء التصميم نمطًا تراثيًّا قديمًا مع الكثير من الألوان وتأثير Grain. إن العمل الفني الذي سيتم تصميمه في هذا الدرس عبارةٌ عن صور مُجمّعة بتأثير النمط القديم للصور مع جعله على شكل قصاصات صور تم قصّها وترتيبها بطريقة مثالية من الأشكال الهندسية المتناظرة. سنبدأ مع الإليستريتور وسنُنشئ قالبًا من أجل أشكالنا الهندسية. افتح ملفًا جديدًا واختر أداة القطع الناقص Ellipse tool لرسم دائرة. أزِل ألوان التعبئة واترك لون الحدود فقط ثم انقر على لوح الرسم وأدخل 500px للعرض والارتفاع. ارسم دائرة أخرى ولكن بأبعاد 250px لتكون دائرة أصغر بحجم نصف الدائرة الأولى. استخدم الأدلّة الذكية CMD+U لمحاذاة الدائرة بدقة إلى أعلى الدائرة الكبيرة. اضغط مفتاح ALT مع سحب نسخة عن الدائرة الصغيرة. حاذِها بدقة عموديًّا مع الدائرة الصغيرة الأولى لتقبع في أسفل الدائرة الكبيرة تمامًا. انسخ الدائرتين الصغيرتين CMD+C وألصقهما في المقدمة CMD+F. اضغط على مفتاح Shift مع تدوير هاتين النسختين بزاوية 90 درجة. اصنع نسخةً واحدةً عن دائرة صغيرة واستخدم الأدلّة الذكية لوضعها في مركز الدائرة الكبيرة. اختر أداة المضلعات Polygon tool وانقر على لوح الرسم لتظهر نافذة الخيارات. أدخل القيمة 250px وبدّل عدد الجوانب إلى 3 لتشكيل مثلّث. بوضع القيمة 250 يجب أن تلامس رؤوس المثلّث حدود محيط الدائرة الكبرى من الداخل بدقة عالية. حدّد الدائرة الكبرى والمثلث معًا باستخدام مفتاح Shift ثم أفلت مفتاح Shift وامنح الدائرة نقرةً إضافية لجعلها العنصر المفتاح. استخدم لوحة المحاذاة Align panel لجعل المثلث يصطفّ على طول المحور العمودي ثم حاذِه للأعلى. انسخ وألصق نسخة عن المثلث ثم دوّرها 180 درجة. استخدم لوحة المحاذاة ليصطفّ المثلث أسفل الدائرة حتى يشكّل مع المثلث الأول نجمةً سداسيّة. حدّد الجميع CMD+A وانسخ جميع الأشكال التي تُكَوّن النقش الهندسي. ألصق هذه الأشكال داخل ملف فوتوشوب فوق صورة فوتوغرافية رائعة. اضغط CMD+I لعكس الألوان وبذلك تصبح الخطوط بيضاء. اختر أداة العصا السحرية Magic Wand too مع تحديد طبقة الخطوط ثم انقر لصناعة تحديد لأول شكل هندسي. حدّد الآن طبقة الصورة الفوتوغرافية ثم اختر أداة التحديد المستطيل Marquee tool لتتمكن من تحريك التحديد إلى مكان آخر في المستند. انسخ وألصق التحديد من مكان عشوائي في طبقة الخلفية ثم حرّك هذا الجزء إلى موضعه الأصلي الذي تم إنشاء التحديد فيه. حدّد طبقة الخطوط مجددًا وحدّد شكلًا آخر باستخدام أداة العصا السحرية ثم اختر أداة التحديد المستطيل وحرّك التحديد إلى مكان عشوائي. انسخ وألصق هذا التحديد ثم أعده مجدّدًا إلى موقعه الأصلي. استمر بالعمل على هذا المنوال عبر التصميم لصناعة تحديدات جديدة. سَرِّع وتيرة عملك عبر استخدام الاختصارات W من أجل أداة العصا السحرية، M من أجل أداة التحديد المستطيل، CMD+C وCMD+V للنسخ واللصق وفعّل المطابقة Snap من قائمة View لتسهيل وضع أجزاء التصميم في مواقعها الصحيحة. اتّخذ التصميم بشكلٍ عام شكل صور مُجمّعة رائعة عبر التموضع العشوائي للقطع في المواقع غير الطبيعية ولكن تناظر الأشكال الهندسية يحافظ على بنية واتِّزان التركيب. لنُضِف بعض اللمسات الأخيرة عبر منح التصميم مظهرَ الصور القديمة. ألصق أحد خامات صور الجرونجي وغيّر خصائص المزج إلى Screen لجعل اللون الأسود شفافًا. استخدم أحد خامات الغبار والخدوش لإضافة علامات الاهتراء. ألصقها فوق الصورة وغيّر خصائص المزج إلى Screen لتركيب تأثير الخامة على الصورة. أضف طبقة تعديلات المنحنيات Curves Adjustment في أعلى لوحة الطبقات. يمكننا ضبط المنحنيات لإنتاج تأثير القِدَم والاهتراء على الصورة. بدّل القائمة السفلية إلى القناة الحمراء وعدّل المنحنيات لإضافة مزيدٍ من اللون الأحمر للظلال وتخفيفه على الإضاءات. قم بعكس العملية بالنسبة للونين الأخضر والأزرق مستعيًنا بالمعاينة الحيّة للحصول على التأثير المطلوب مباشرةَ. النتيجة النهائية هي عبارة عن قطع تجريدية فنية مع أجزاء الصورة المقصوصة والمرصوفة مجددًا بتأثير الصورة المُجمّعة المعروف. الخطوط الهندسية حافظت على توازن كل شيء بينما منحت الخامات وتعديلات الألوان مظهر الصور القديمة المهترئة. لمَ لا تحاول استخدام تقنيات أخرى لتصميم أشكال هندسية مختلفة لصناعة تصميم جديد؟ ترجمة -وبتصرّف- للمقال: How To Create Abstract Geometric Photo Collage Art لصاحبه: Chris Spooner.1 نقطة
-
مرحبا بك اخي الكريم : من خيارات الدمج للطبقة Blending options التي تريد تغيير الحد strok الخاص بها تذهب لخانة strok وفيها خصائصه من حجم ولون ... الخ بالتوفيق1 نقطة
-
أخي الكريم يوجد شركة بخصوص هذا الشأن فتحل جميع مشاكلك موقع الشركة syria2u.com ولكن المشكلة الوحيدة تتمثل بارتفاع أسعارها حيث تصل الفيزا كارد إلي 300$ ومن جهة اخرى يوجد محل في دمشق يدعى زووم تك لصاحبه معاذ حداد حيث يقوم باعطائك البطاقة مع حساب الباي بال تقريبا ب 50$ لا اكثر مع العلم ان ليس لدي اي مصلحة تجارية تجد الأستاذ معاذ بكتابة ( معاذ حداد) في مربع البحث في الفيس بوك وتواصل معه1 نقطة
-
شاهدت مؤخرًا العديد من التصاميم ثلاثية الأبعاد للافتات نيون إعلانية تم تصميمها باستخدام برامج التصميم ثلاثي الأبعاد. أميل أكثر للتّصاميم ثنائية الأبعاد لذلك أريد أن أنتج تأثير نيون مشابه باستخدام الإليستريتور وفوتوشوب ولكن مع إضافة الحركة بواسطة صيغة GIF المتحركة. اتبع هذا الدرس لتتعلم عملية تصميم لافتة إعلانية لكوكب البيتزا مُستخدمًا أدوات فكتور الإليستريتور لإنشاء التصميم الأوّلي للافتة ثم فوتوشوب لإضفاء الحيوية على التصميم عبر أنماط الطبقات المتنوعة وتشكيل الحركة للملف. تأثير لافتة النيون سيتم إنشاؤه في الفوتوشوب باستخدام أنماط الطبقات عبر إنشاء توهجات نيون ملوّنة كما سيكون هناك طبقة قاتمة تكون عند إطفاء الأنوار والتي ستُضاف في إطار أثناء سير الحركة للملف لإضفاء الشعور بالواقعية على التأثير. لافتات النيون تعتمد على الأنابيب المنحنية لتشكيل أشكال التصميم لذلك سنستخدم الإليستريتور لصياغة مسارات فكتور بحيث لا تتقاطع الخطوط مع بعضها. افتح برنامج الإليستريتور وابدأ ملفًّا جديدًا. ارسم دائرة على لوح الرسم باستخدام أداة القطع الناقص Ellipse tool، ثم ألغِ لون التعبئة واترك فقط الحدود السوداء ظاهرة. غيّر إعدادات الحدود إلى 5pt مع نهايات مستديرة وزوايا مستديرة أيضًا. استخدم أداة النص Type tool لإضافة أي نص إلى لافتة النيون. أنا استخدمت خطًّا اسمه Darwin لكتابة Pizza Planet. اضبط حجم النص ليتوسط الدائرة ويتقاطع مع حدودها الخارجية ثم أمِلهُ بزاوية -10 درجة عموديًّا من القائمة: Object > Transform > Shear option ألغِ لون التعبئة للنص وأضف حدودًا سوداء مستخدمًا ذات الحجم 5pt مع النهايات المستديرة والزوايا المستديرة أيضًا. بالزر الأيمن اختر Convert to Outlines. ارسم دائرة صغيرة وقصّ المسار باستخدام أداة المقص Scissors tool في الجزء العلوي الأيسر. استخدم أداة التحديد المباشر Direct Selection tool لحذف المسار من النقطة السفلية إلى هذا القطع الجديد. اصنع نسخًا عديدة من هذا الشكل الأخير مع تعديل أحجامها وذلك لتعبئة المساحات الفارغة داخل الدائرة لتكوين فوهات وفتحات الكوكب. حدّد الدائرة الرئيسية للكوكب وانسخها CMD+C ثم ألصقها في المقدمة CMD+F. استمر بالضغط على ALT أثناء تمديد وضغط الشكل لتشكيل الحلقة حول الكوكب. ضاعف هذا الشكل الأخير وصغّر حجمه قليلًا بشكل يوازي الأصلي. ارسم شكلًا بيضويًّا في مكان ما على لوح الرسم ثم اسحب النقطة العلوية للأعلى باستخدام أداة التحديد المباشر Direct Selection tool لتمديد الشكل. استخدم أداة Convert Anchor Point tool الموجودة ضمن أدوات القلم لإزالة مقابض البيزير وترك النقطة حادة. أضف دوائر أخرى إلى الشكل لبناء شكل صاروخ بسيط. استخدم لوحة المحاذاة Align panel لتوسيط جميع العناصر مع جعل شكل جسم الصاروخ العنصر المفتاح عبر منحه نقرة إضافية. اصنع نسختين من الصاروخ وعدّل حجمها ودوّر كل صاروخ وضعهُ في موقعه في مدارٍ حول الكوكب مع جعلها أكبر في كل مرّة. التصميم يحوي العديد من المسارات المتداخلة فوق بعضها لذلك دعونا ننشئ المزيد من نماذج أنماط لافتة النيون. حدّد دائرة الكوكب الرئيسية ثم اذهب للقائمة: Object > Path > Offset Path ثم أدخل القيمة 3mm. انقر بالزر الأيمن على المسار الإضافي الجديد واختر Make Guides. تأكد من ظهور الأدلة عبر الضغط على CMD+; ومقفلة عبر الضغط على CMD+Alt+; استخدم أداة المقص Scissors tool لقص مسارات حلقات الكوكب في موقع تقاطعها مع الأدلة الجديدة. استخدم الأدلة الذكية Smart Guides عبر الضغط على CMD+U لتُسهّل عملية مطابقة هذه المنطقة. على الجانب الآخر فإن حرف P يتقاطع مع حدود الكوكب أيضًا لذلك ألغِ تجميع النص Ungroup من أجل تحديد هذا الحرف فرديًّا ثم أضف مسار إضافي بقيمة 3mm. الحرف P بشكل خاص بحاجة لخطوة إضافية من أجل إنشاء الأدلّة. انقر بالزر الأيمن ثم اختر Release Compound Path ثم احذف الجزء الداخلي قبل تحويل الخطوط الرئيسية إلى أدلّة. قص حلقات الكوكب عند تقاطعها مع المسار الإضافي لحرف P ثم احذف الأجزاء غير المرغوبة من المسارات. سنستخدم ذات التقنية في كل التصميم لإزالة جميع المسارات المتقاطعة ولكن بالنسبة للجزء السفلي من الحلقة فإن النص هو من يحتاج للتعديل للسماح للحلقة بالالتفاف حول الكوكب. ألغِ تجميع Ungroup عناصر النص الأخرى وأضف مسار إضافي للحرف الأول والأخير ثم أنشئ أدلّة من النتائج. تذكّر أن تحرر المسار المركب لحرف P ليصبح قابلًا للتحول إلى دليل. استخدم هذه الأدلة الجديدة لقص أي مسارات متداخلة مع بعضها وأزِل التداخلات في كل أنحاء التصميم. بالنسبة للمنطقة التي يتداخل فيها النص مع الحلقة سنحتاج إلى أدلة إضافية من مسارات الحلقة نفسها. استخدم أداة المقص Scissors tool لقص وحذف مناطق تواجد الحروف تحت الحلقة عبر خطوط الأدلة. من الضروري في بعض الأحيان تحرير المسارات المركبة للحروف من أجل تحديد وحذف الأجزاء غير المرغوبة من المسار. بعد إزالة جميع المسارات المتداخلة سيكون التصميم قد أخذ شكلًا أكثر واقعية كلافتة نيون. حدّد المسارات التي تُشكّل جزءًا محددًا وامنحها ألوانًا برّاقة للحدود كالأزرق، الأحمر، الأصفر والأبيض. افصل الألوان المختلفة داخل طبقاتها الخاصة عبر استخدام القائمة: Select > Same > Stroke Color ثم انسخ التحديد وألصقه في المقدمة. وضع الأجزاء التي ستكون متحركة في طبقات خاصة بها كالعناصر التي تُكَوِّن الصواريخ الثلاثة. اذهب إلى القائمة: File > Export وضع نوعية الملف PSD Photoshop وتأكّد من تفعيل خيار Write Layers. افتح الملف الذي تم تصديره من برنامج الإليستريتور في برنامج الفوتوشوب ووسِّع حجم العمل قليلًا. لوِّن الخلفية بالأسود وأضف خامة جدار الطوب. حدّد كل طبقات عناصر لافتة النيون ثم اضغط CMD+J لمضاعفتها ثم اضغط CMD+E لدمجها في طبقة واحدة. أعِد تسمية هذه الطبقة 'Off'. أضف سلسلة من أنماط الطبقة لجعل هذه الطبقة تبدو كالأنابيب بدون إضاءة، أي (تراكب لوني) Color Overlay، (توهج داخلي) Inner Glow و (الظلال) Drop Shadow. ضع هذه الطبقة أسفل جميع الطبقات بحيث لن تكون ظاهرة أثناء إضاءة العناصر وستظهر أكثر في العناصر المتحركة حيث ستنطفئ هذه العناصر عدة مرات. شَغِّل طبقة النيون الأولى عبر سلسلة من أنماط الطبقة. أضِف التوهُّج الداخلي لإضافة الأبيض البرّاق إلى المركز، والتوهُّج الخارجي لإطلاق الهالة الملونة، تليها المزيد من الظلال لتراكب التوهُّجات بأحجام مختلفة. كل هذه الأنماط للطبقات تُنتِج تأثيرًا واقعيًّا إلى حد كبير مشابهًا لإضاءة النيون وتأثيرات التوهُّج والتفاعل مع خلفية جدار الطوب. انسخ وألصق نمط الطبقة إلى الطبقة التالية ثم عدّل إعدادات التوهُّج حتى تناسب لون العنصر. وفّر الوقت عبر نسخ نمط الطبقة إلى باقي الطبقات التي تحمل ذات اللون. لافتة النيون ستبدو رائعة عند الانتهاء من وضع كافة أنماط الطبقات ولكننا سنضيف بعض الحركة على التصميم. اجمع عناصر كل صاروخ معًا بحيث سيكون من السهل تشغيل وإيقاف أي صاروخ أثناء الحركة. أظهر لوحة Timeline من قائمة Window ثم أنشئ إطار جديد New Frame Animation. في هذا الإطار الأول ستكون اللافتة متوقفة عن العمل لذلك سنُظهر فقط الطبقة الداكنة مع خلفية جدار الطوب. عدّل المدة الزمنية لهذا الإطار الأول إلى ثانية واحدة. أضف إطار جديد تظهر فيه أول طبقة نيون. لا تضف أي زمن لظهور هذا الإطار وبذلك سيظهر هذا الضوء على الفور. أضف إطارين بعدها بدون مدة زمنية لإضافة الأضواء الحمراء والزرقاء بحيث ستضيئ اللافتة تباعًا بسرعة. في الإطار التالي أظهر طبقة الصاروخ الأول مع جعل المدة الزمنية لعرض هذا الإطار ثانية واحدة. في الإطار التالي أخفِ الصاروخ الأول وأظهر الثاني لإعطاء الانطباع عن حركة الصاروخ. أضف إطار جديد للصاروخ الثالث من أجل إظهاره وإخفاء الصاروخ الثاني. ضاعف هذه الإطارات الثلاثة الأخيرة لتُطيل مدة الحركة. أو بدلًا من ذلك يمكن جعل هذه الطبقات الثلاثة تضيء باستمرار إلى ما لا نهاية بدون وجود الطبقة الأولى للافتة المتوقفة عن العمل. قم بتصدير العمل كملف GIF من خلال Save for Web أو أرسله إلى برنامج تعديل فيديو لتصنع حركة مستمرة أفضل. ترجمة -وبتصرّف- للمقال: How To Create an Animated Neon Sign Effect لصاحبه: Chris Spooner.1 نقطة
-
قمت بتصميم مجموعة كبيرة من العناصر المتداخلة وأريد رسم حدود سميكة خارجية حول جميع شكل العناصر ولكن كلما حددت جميع العناصر وقمت بزيادة سماكة الحدود كانت النتيجة أن حدود كل عنصر تزيد أيضًا. كيف أجعل الحدود الخارجية حول مجموعة العناصر تزداد بدون أن تزداد حدود كل عنصر على حدة؟ أستخدم تطبيق الإنكسكيب1 نقطة
-
HDFS هي اختصار لـ Hadoop Distributed File System وتعني نظام الملفات الموزّع وهو نظام موزّع، محمول وقابل للتطوير مكتوب بلغة جافا لإطار Hadoop حيث يتم تشكيل كتلة نظام ملفات Hadoop الموزّع عن طريق كتلة cluster من عقد البيانات dataNodes. يقوم نظام HDFS بتوزيع البيانات المخزّنة عبر الخوادم في الكتلة cluster وتخزين نسخ متعددة من البيانات على خوادم مختلفة لضمان عدم ضياع أي من البيانات في حال فشل أحد الخوادم (يوفّر نظام ملفات Hadoop قدرات توافر عالية). يعتبر نظام ملفات Hadoop نظام تخزين سريع الزوال حيث يتم استصلاحه عند إنتهاء الـ cluster. يعتبر HDFS نظام ملفات مفيد للتخزين المؤقت caching والنتائج الفورية أثناء معالجة MapReduce أو كأساس لمستودع البيانات للكتل طويلة الأمد long-running clusters. ما هو نظام ملفات HDFS؟1 نقطة
-
تعاملنا حتّى الآن مع نوعٍ واحد من مكوّنات JavaScript المعدّلة في Angular، وهو المتحكّم. المتحكّمات هي نوعٌ مخصّص من المكوّنات، وكذلك سنجد المرشحات والتوجيهات، التي سنغطّيها قريبًا. تدعم Angular مكوّنًا غير مخصّص، يُسمّى بالخدمات، تعريف الخدمات في Angular فضفاضٌ نوعًا ما، ولكنّ السّمة المميّزة لها هي عدم اقترانها مباشرةً بالقالب، مما يفترض قرابةً بينها وبين نمط طبقة الخدمة في الهيكليّة التّقليديّة للمشاريع. تتضمّن وحدة القلب ng في Angular عددًا من الخدمات المدمجة، ونذكر الخدمات location$ وlog$ وq$ وwindow$ على سبيل المثال، وسنستكشف الخدمة http$ في الفصل الأخير من هذه السلسلة، فصل HTTP. في تطبيقٍ نموذجيٍّ ستحتاج إلى تعريف خدماتك الخاصّة لأيّ سلوكٍ مشترك بين مكوّنات JavaScript المخصّصة التي تنشئها، مثل المتحكّمات. يُمكن للخدمات أن تكون متابعةً للحالة (stateful) إن احتجت إلى ذلك، فمثلًا، إن أردت مكانًا لتخزين نقاط اللاعب في لعبةٍ ما، يُمكنك إنشاء خدمة score لتتمكّن من جلب وعرض النّقاط الحاليّة في عدّة أماكن ضمن تطبيقك. جميع الخدمات متفرّدة (singletons) أي أنه لا يوجد غير نسخةٍ واحدةٍ من خدمةٍ معيّنة طوال دورة حياة تطبيق Angular. الخدمة في Angular يُمكن أن تكون كائنًا، تابعًا، أو حتّى قيمةً أوّليّة (كالأعداد مثلًا)، أنت من يحدّد ذلك. في الواقع، هذا الفصل لن يشرح إلا القليل من الأمثلة عن الخدمات، وذلك لأنّ الخدمات يمكن أن تحوي أيّ شيفرة من شيفرات JavaScript العاديّة. ما سيُغطّيه هذا الفصل هو كيفيّة تسجيل (register) الخدمات في Angular. نقوم بذلك عن طريق توابع معرّفة بواسطة الخدمة provide$، ومغلّفة بواسطة angular.Module. لنتمكّن من تسجيل الخدمة نحتاج إلى مرجعٍ (reference) إلى وحدةٍ ما. لنقُم بتعريف وحدةٍ جذريّة لتطبيقنا الآن. angular.module('app', []);كما تمّ الشّرح في فصل الوحدات، نقوم بتحميل وحدة الجذر في تطبيقنا عن طريق تمرير اسمها إلى التّوجيه ng-app ضمن مستند HTML. <body ng-app="app"> <!-- الأمثلة توضع هنا --> </body>جيّد، أصبحت وحدتنا جاهزة. تُقدّم الخدمة provide$ خمس توابع مختلفةً للقيام بتسجيل الخدمة، يُمكننا تصنيف هذه التّوابع إلى صنفين، أوّلهما سهلٌ جدًّا والثّاني أصعبُ قليلًا. إنشاء خدمات دون استخدام حقن التبعيةقد لا تحتاج إلى حقن أيّ تبعيّاتٍ إلى خدمتك. (قُمنا بتغطية حقن التّبعيّة في الفصل الماضي. وكمثالٍ على تبعيّةٍ محقونة، فالخدمة المدمجة http$ يُمكن لخدمتك أن تستخدمها لجلب بياناتٍ من النّهاية الخلفيّة (backend) البعيدة.) ولكن حتّى لو لم تكن تريد حقن تبعيّاتٍ في خدمتك، ستحتاج إلى وضعها ضمن وحدةٍ لتجعلها متاحةً للحقن ضمن مكوِّناتٍ أخرى. إنّ جعل الخدمة متاحةً للحقن هو ما يجعلها خدمةً في Angular، وإلّا ستكون مجرّد شيفرة JavaScript عاديّة. هناك تابعان خدميّان يسمحان بتسجيل الخدمات من دون تبعيّات: التّابع value والتّابع constant. الفرق بينهما في Angular معقّدٌ قليلًا ويخُصّ المحترفين، فـالثّوابت تكون متاحًةً لتطبيق Angular أثناء الـbootstrapping، أما القِيمة فلا. لن نقوم بتغطية constant في هذه السلسلة. التابع valueلنفترض أنّنا نريد كتابة شيفرةٍ للعبة حيث يحصل فيها اللاعب على نقاطٍ تبدأ من الصفر. يمكننا باستخدام التّابع value من الخدمة provide$ أن نقوم بتسجيل (register) قيمةٍ عدديّةٍ أوّليّة باسم 'score' وستكون متاحةً للمتحكّمات، الخدمات، ومكوّناتٍ أخرى. angular.module('app') .value('score', 0);يُمكننا حقن خدمتنا score عن طريق وضعها ضمن قائمة الوسطاء للمتحكّم، وقد شرحنا ذلك بالتّفصيل في فصل حقن التّبعيّة. angular.module('app') .controller('ScoreController', function($scope, score) { $scope.score = score; $scope.increment = function() { $scope.score++; }; });يستخدم قالب هذا المثال نُسختين من المتحكّم ScoreController لإثبات الطّبيعيّة المتفرّدة (singleton) للخدمة score. <p ng-controller="ScoreController"> Score: {{score}} </p> <p ng-controller="ScoreController"> <button ng-click="increment()">Increment</button> </p>أعتذر، لقد تعمّدت إفشال المثال السّابق، فعند النّقر على زرّ Increment لن يتمّ تغيير قيمة المتغيّر score المعروضة في النّسخة الأولى من المتحكّم. هذه ليست مشكلة مجالات، ولكنّها بسبب الطّبيعة الثّابتة (immutable) للخدمات التي تمثّل قيمًا أوّليّة. يُمكننا إصلاح المثال السّابق بتغيير الخدمة من قيمةٍ أوّليّة إلى كائنٍ يحوي العنصر points. angular.module('app') .value('score', {points: 0});سنستخدم نفس جسم المتحكّم تقريبًا، إلّا أنّنا سنغيّر ++scope.score$ إلى ++scope.score.points$. angular.module('app') .controller('ScoreController', function($scope, score) { $scope.score = score; $scope.increment = function() { $scope.score.points++; }; });بطريقةٍ مماثلة، سنغيّر في القالب العبارة score إلى score.points. <p ng-controller="ScoreController"> Score: {{score.points}} </p> <p ng-controller="ScoreController"> <button ng-click="increment()">Increment</button> </p>لقد استخدمنا للتّو خدمةً تشارك بياناتٍ متغيّرة (mutable) ضمن تطبيقنا، هذا رائع. إضافةً إلى القيمة الأوّليّة والكائنات، يمكن لخدمات Angular أن تمثّل توابعًا. لنفترض أنّنا بحاجةٍ إلى خدمةٍ ثابتةٍ (stateless) تُعيد عدًدا عشوائيًّا بين 1 و 10. angular.module('app') .value('randomScore', function() { return Math.ceil(Math.random() * 10); });إنّ حقن هذه الخدمة أمرٌ سهل، سنقوم ببساطةٍ بإضافة اسمها randomScore إلى قائمة الوسطاء في متحكّمنا. angular.module('app') .controller('ScoreController', function($scope, score, randomScore) { $scope.score = score; $scope.increment = function() { $scope.score.points += randomScore(); }; });لقد تعلّمنا الآن كيفيّة تعريف الخدمات وحقنها ضمن المتحكّم كتبعيّات. ولكن ماذا لو أردنا حقن تبعيّاتٍ إلى خدماتنا؟ إنشاء خدمات باستخدام حقن التبعيةلعبتنا تبدأ دومًا بنقاطٍ قيمتها صفر، هذا منطقيٌّ، ولكن لنفترض أننا نريد أن تكون القيمة البدائيّة عددًا عشوائيًّا. كيف يمكننا جلب مرجعٍ للخدمة randomScore عندما ننشئ الكائن score للمرّة الأولى؟ إنّ التّابع value الذي كُنّا نستخدمه بسيط جدًّا، فأيّ شيءٍ نقوم بتمريره إليه سيكون هو القيمة أو التّابع أو الكائن الكامل والنّهائي الذي ستقوم Angular بحقنه لاحقًا، وهذا يعني بأنّنا لن نحظى بأيّ فرصةٍ لحقن أيّ تبعيّاتٍ لاحقًا. تُقدّم Angular عدّة حلول لهذه المشكلة، وسنبدأ بالحلّ الأوّل، التّابع service كائنيُّ التّوجّه. التابع serviceتدعم JavaScript أسلوب البرمجة كائنيّة التّوجّه، ولذلك يمكننا كتابة خدمة في Angular تقبل التّبعيّات عن طريق الحقن بواسطة الباني (constructor injection). كُلّ ما نحتاج إليه هو كتابة التّابع الباني لخدمتنا score، بدلّا من تهيئتها بقيمةٍ بدائيّة عن طريق مهيِّئ الكائن ({}) الذي استخدمناه قبل قليل. يجب أن يكون أوّل حرفٍ من اسم الباني في JavaScript حرفًا كبيرًا، ولذلك سنُسمّي الباني بالاسم Score، وسنقوم بوضع الخدمة randomScore ضمن قائمة الوسطاء لهذا الباني. function Score(randomScore) { this.points = randomScore(); }التّابع service يحتاج إلى تمرير الباني الخاصّ بالخدمة بدلًا من تمرير الخدمة ذاتها، وعندما تقوم Angular باستدعاء الباني عن طريق العمليّة new ستقوم آليّة حقن التّابعيّة بإسناد الخدمة randomScore إلى وسيط الباني. angular.module('app') .service('score', Score);توصف طريقة إنشاء نُسخة الخدمة في Angular بأنّها كسولة، أي أنّ النّسخة ستُنشأ فقط عندما تُشكِّل تبعيّةً لأحد المكوّنات التي يتمّ إخراجها في القالب. التابع factoryإن كانت خدمتك شيئًا آخر غير الكائن، أو إن أردت الحصول على مرونةٍ أكبر من طريقة إنشاء بانٍ للكائن، عندها يُمكنك استخدام التّابع factory بدلًا من service، حيث نقوم بتمرير تابع استدعاءٍ خلفيٍّ (callback) وسيتمّ حقنه لاحقًا بالتّبعيّات التي نكتب أسماءها في قائمة الوسطاء. يُمكنك كتابة ما تشاء داخل هذا التّابع، ولكن يجب عليك في النّهاية أن تعيد قيمةً، تابعًا أو كائنًا يُمثّل الخدمة. يُطلق على هذا النّوع من الإنشاء عن طريق الاستدعاء الخلفيّ في المرجع الرّسميّ اسمُ الوصفة(recipe). angular.module('app') .factory('score', function(randomScore) { return {points: randomScore()}; });المثال السّابق مكافئٌ للمثال الذي يستخدم تركيبة الباني مع التّابع service الذي رأيناه في الفقرة الماضية. التابع decoratorإن كنت تريد تعديل خدمةٍ موجودةٍ سابقًا، يُمكنك استخدام التّابع decorator الّذي تُوفّره الخدمة provide$. هذا التّابع ليس مُغلّفًا باستخدام angular.Module كحال بقيّة التّوابع، لذا يجب أن يتمّ استدعاؤه مباشرةً من الخدمة provide$. يُمكنك الحصول على مرجعٍ للخدمة provide$ عن طريق تسجيل تابع استدعاءٍ خلفيٍّ (callback) باستخدام التّابع config. angular.module('app') .config(function($provide) { $provide.decorator('score', function($delegate) { $delegate.points = 1000000; return $delegate; }); });يُمكن لتابع decorator أن يقوم بإعادة الخدمة الأصليّة التي تمّ تمريها ضمن الوسيط ذي علامات الاقتباس ' ' أو أن يقوم بإعادة نُسخةٍ (instance) من خدمةٍ جديدةٍ كُلّيًّا. ولكن عليك بالحذر من التّأثيرات الجانبيّة غير المرغوبة. التغليف (Encapsulation)في الفقرة السّابقة أسأنا استخدام التّابع decorator، ونتيجةً لذلك تمّ تقييد الوصول إلى العنصر points. لحسن الحظّ، يُقدّم التّغليف الخاصّ بحقن التّابع factory مجالًا مُغلقًا (closure)، ممّا يسمح لنا بإخفاء بعض المعلومات، أو بعبارةٍ أخرى، التّغليف (encapsulation). سنقوم باستبدال العنصر points المرئيّ في المجال العام بالمتغيّر المحلّي points المحدود الرؤية ضمن التّابع الّذي يغلّفه، وهذا سيسمح لنا بحمايته من التّعديل خارج التّابع. والآن سنقوم بجعل كائن الخدمة يكشف عن تابعٍ للوصول إلى قيمة المتغيّر، getPoints، وعن تابعٍ يقيَّد التعديل فيه فقط، increment. angular.module('app') .factory('score', function(randomScore) { var points = randomScore(); return { increment: function() { return ++points; }, getPoints: function() { return points; } }; });سنحتاج إلى تغيير بسيطٍ في المتحكّم كي نسمح له باستدعاء التّابع increment من الخدمة. angular.module('app') .controller('ScoreController', function($scope, score) { $scope.score = score; $scope.increment = function() { $scope.score.increment(); }; });وسنغيّر أيضًا القالب، ليكون مرتبطًا بتابع الوصول ()score.getPoints بدلًا من الوصول إلى العنصر points مباشرةً. <p ng-controller="ScoreController"> Score: {{score.getPoints()}} </p> <p ng-controller="ScoreController"> <button ng-click="increment()">Increment</button> </p>بما أنّ التابع increment يقوم أيضًا بإعادة قيمة المتغيّر points بعد التّعديل، إذًا بإمكاننا الكشف (expose) عنها ضمن العرض (view) في عبارة. قد تُفاجئك النّتيجة، قُم باستبدال الاستدعاء في السّطر الثاني، وضع ()score.increment بدلًا من ()score.getPoints، ثُمّ قُم بنقر الزّر عدّة مرّات. هل يُمكنك معرفة سبب زيادة القيمة بسرعةٍ كبيرة؟ هذا صحيح: تقوم Angular غالبًا باستدعاء العناصر والتّوابع المرتبطة بالقالب عدّة مرّات قبل أن تنتهي دورة الإخراج. هذه معلومةٌ هامّة يجب معرفتها لنفهم التّأثير الجانبيّ لها كالمثال السّابق، وأيضًا لتحسين كفاءة التّطبيق. خاتمةوصلنا إلى ختام الفصول الثّلاثة التي تتحدّث عن دعم Angular للبرمجة باستخدام الوحدات. بدأنا مع فصل الوحدات، وتابعنا مع الفصل القصير عن حقن التّبعيّة، وختمنا هذه الثّلاثيّة بهذا الفصل عن الخدمات. قد تستغرب إفراد الخدمات بفصلٍ مستقلٍّ عندما ترى أنّها ليست سوى JavaScript المعتادة ليس إلّا، ولكنّنا لم نقم بتغطيةٍ كاملة لما يجب معرفته، فإضافةً إلى التّوابع constant وvalue و service وfactory و decorator لا يزال هناك تابعٌ منخفض المستوى هو التّابع provider الذي يقدّم تعلّقات دورة الحياة (lifecycle hooks) لإعداد خدماتك بطريقةٍ متقدّمة. إن كنت تتساءل فيما إذا كنت تحتاج إلى مساعدة Angular في هذا المجال بالفعل، فلتبقِ في ذهنك بأنّك لست مضطرًّا لإدارة كلّ شيفراتك باستخدام Angular، ورغم ذلك فإنّ Angular 2.0 ستنتقل إلى نظام وحدات ES6 كما أشار العرض التّقديمي "RIP angular.module" الّذي قُدّم في خطاب فريق التّطوير في ng-europe 2014. وإلى أن يتمّ ذلك فإنّك تحتاج بالفعل إلى أن تضع شيفراتك داخل وحدات Angular عندما تحتاج إلى استخدام مكوّناتٍ مدمجة في Angular (أو مكوّناتٍ طوّرها طرفٌ ثالث) يتمُّ الوصول إليها عن طريق حقن التّبعيّة. لقد قمتُ بعرض بديلٍ لحقن التّبعيّة في نهاية الفصل الماضي. فقط أبقِ في ذهنك أنّ دعم اختبار الوحدة (unit testing support) في Angular قد عزّز من أهمّيّة استخدام حقن التّبعيّة، لذا عليك أن تهتمّ باستخدامك له أيضًا. هناك أيضًا بعض المكوِّنات المخصّصة التي يجب عليك تسجيلها باستخدام نظام الوحدات في Angular، لتجعلها متوفّرة ضمن القالب. أحد هذه المكوّنات هو المُرشّحات، وسنُغطّيها في الفصل القادم. ترجمة وبتصرّف للفصل الثامن من كتاب: Angular Basics لصاحبه: Chris Smith.1 نقطة
-
تدير Angular الموارد باستخدام نظام الوحدات، ولهذا السّبب فهي تحتاج أيضًا إلى تقديم طريقةٍ للوصول إلى هذه الموارد المنظّمة ضمن حاويات (container-managed)، حيث تقوم Angular بذلك باستخدام نمطٍ إنشائيّ يُدعى حقن التبعية. إن لم يكن لديك معرفةٌ مسبقةٌ بهذا المفهوم فسأقوم هنا بأفضل ما لديّ لتلخيصه لك: لنفترض أنّك تحتاج إلى الحصول على مَوردٍ (resource) من Angular، المَورد هو الحاوية. للحصول عليه يجب أن تكتب تابعًا يُعرّف وسيطًا له نفس اسم هذا المَورد بالضّبط. تقوم الحاوية باكتشاف التّابع الذي كتبته، وتتعرّف على توافق الوسيط مع المَورد المطلوب، فتقوم بإنشاء نُسخةٍ (instance) من هذا المَورد (أو تقوم بأخذ النُّسخة المنفردة (singleton) من هذا المَورد، إن كان من النّوع المنفرد) ثُمّ تقوم باستدعاء التّابع الخاص بك وجعل هذه النّسخة هي قيمة الوسيط الخاص بالتابع. بما أنّ الحاوية هنا تلعب الدّور الفعّال (على عكس الطلب الذي تقوم به للحصول على نسخة من المَورد)، لذلك يُعتبر حقن التّابعيّة عكسًا للتّحكّم (inversion of control)، ويُقدّم على أنّه تطبيق لمبدأ Hollywood، "لا تكلّمنا، نحن سوف نكلِّمُك". أعتقد بأنّ مخترعي Angular قد اختاروا طريقة حقن التّابعيّة بسبب تاريخ Google الطّويل مع منصّة Java، بيئة برمجة ساكنة يقوم فيها حقنُ التّابعيّة بدورٍ فعّال في عمليّات تغيير الأنواع أثناء وقت التّشغيل. (لقد تخطّت Google الحدود في ذلك إلى درجة أنّها أنشأت إطار عمل Java خاصٍّ بها، Guice، الذي يعتمد على حقن التّابعيّة كُلّيًّا.) أمّا في JavaScript، وهي البيئة المرنة والديناميكيّة، حيث يمكن أن تتغيّر الأنواع أثناء وقت التّشغيل، فقد حظِيَ فيها أسلوب محدّد موضع الخدمة (service locator) البسيط والمباشَر بشعبيّة هائلة عن طريق الواجهة البرمجيّة لـCommonJS، وهي عبارة require المستخدمة في Node.js وbrowserify. والأكثر من ذلك، أنّ الطريقة البدائيّة في القيام بحقن التّابعيّة قد تبيّن أنّ لها نقطة ضعفٍ عند استخدامها في JavaScript من طرف العميل، وذلك بسبب تعديل أسماء الوُسطاء باستخدام المُقصّرات (minifiers). ولنستطيع التّعامل مع هذه المشكلة، من الضّروريّ أن توجد أداة بناءٍ بديلة، أو أن نتعلّم ونستخدم حواشي التّبعيّات، وسنصل إلى ذلك بعد قليل، ولكن لنتعرّف أوّلًا على النّموذج البدائيّ. التبعيات الضمنيةلن نستخدم خارج هذا الفصل للقيام بحقن التّبعيّة غير طريقة التّبعيّات الضّمنيّة لأنّها الأسهل بين جميع الطُّرق. كما ذكرت سابقًا، يمكننا جلب مرجعٍ لأحد الموارد المتاحة عن طريق وضعه كوسيطٍ في تابعنا الإنشائيّ، ولقد قمنا بذلك للمرّة الأولى عندما أضفنا الوسيط scope$ الذي يعطي تابع التّحكّم مرجعًا إلى كائن المجال المنظّمٍ ضمن حاوية (container-managed). يقوم نظام حقن التّبعيّة في Angular بالعثور على نسخةٍ للمَورد المطلوب (أو بإنشاء نسخةٍ لهذا المَورد) وتمريره إلى المتحكّم. لنرى مرّةً أخرى كيف نقوم بذلك على المَورد المدمج في Angular، الخدمة locale$. نحتاج إلى تعريف وحدتنا app لأنّ بعض أمثلة هذا الفصل تستخدم نظام الوحدات. angular.module('app', []);وبعد ذلك سنقوم بتحميل الوحدة عن طريق تمرير اسمها إلى التّوجيه ng-app. (أكرّر التّنبيه إلى أنّ الاسم app ليس إجباريًّا ويمكن استخدام أيّ اسم آخر.) <body ng-app="app"> <!-- الأمثلة توضع هنا --> </body>نحن الآن جاهزون للانطلاق مع مثالنا الأوّل، وبطريقةٍ مماثلةٍ لإضافة الوسيط scope$ سنضيف الوسيط locale$، وستلاحظ Angular هذين الوسيطين وتقوم بحقنهما. تقوم Angular بحقن الموارد داخل التّابع لأنّ هذا التّابع يمثّلُ متحكّمًا. angular.module('app') .controller('LocaleController', function($scope, $locale) { $scope.locale = $locale.id; });داخل جسم المتحكّم قمنا ببساطةٍ بإسناد المتغيّر locale الذي يمكننا تغيير اسمه إلى أيّ اسمٍ آخر، إلى العنصر id من الوسيط locale$ الذي لا يمكننا استخدام اسمٍ آخر له. <p ng-controller="LocaleController"> Your locale is <strong ng-bind="locale"></strong> </p>الناتج: Your locale is en-usيُفترض أن ترى شيئًا مماثلًا لعبارة "Your locale is en-us" في المخرجات. ما الذي سيحدث لو أنّك أضفت الوسيط myResource إلى تابع التّحكّم؟ هل عطّلت عمل المثال؟ هل يمكنك قراءة الخطأ في الـconsole الخاصة بـJavaScript في متصفّحك؟ تعرض أخطاء Angular غالبًا رابطا مفيدا، يمكنك عن طريق هذا الرابط أن تحصل على درسٍ رائع وقصير عن حلّ مشاكل حقن التّبعيّة، انقر على الرّابط السّابق واقرأ الشرح إن أردت. الحواشي (Annotations)تمثّلُ الحاشية في لغة برمجةٍ مثل Java، معلوماتٍ إضافيّة تُضاف إلى الشيفرة المصدريّة ويتجاهلها المترجم. أمّا في سياق الحديث عن حقن التّبعيّة في Angular، فتعني كلمة الحاشية التّصريح عن الموارد التي نريد حقنها بطريقةٍ صريحةٍ تحافظ على أسماء الوسطاء قصيرةً باستخدام أسلوب التّصغير (minification). (استخدام أداة البناء UglifyJS مثالٌ على أسلوب التّصغير.) لنتابع الآن طريقة Angular التي تسمح لنا فيها بإضافة الحواشي إلى التّبعيّات. ng-annotateمن الطرق الملائمة للتخلص من إزعاج مهمّة بناء ما، استخدام مهمّة بناءٍ أخرى. ستقوم أداة البناء ng-annotate بإضافة الحواشي للتّبعيّات، ومن ثمّ ستسمح لنا بمواصلة استخدام طريقة التّبعيّات الضّمنيّة التي شرحناها في الفقرة السّابقة. ستحتاج فقط إلى تشغيل ng-annotate قبل أن تُشغّل المقصّر (minifier) الخاصّ بك. هذه الأداة المركزيّة صُمّمت لتُستخدم عن طريق سطر الأوامر، إلّا أنّه يوجد غلافٌ لها لتفادي التّعامل مع سطر الأوامر، كما يوجد غلافٌ لمعظم أدوات البناء وحزم الأدوات، من ضمنها grunt-ng-annotate وgulp-ng-annotate وbrowserify-ngannotate وng-annotate-webpack-plugin. الحاشية السطريةهناك أسلوبان لكتابة الحواشي، وأكثرهما شُهرةً يُعرف باسم الحاشية السّطريّة (inline annotation)، وهي تتضمّن وضع تابع التّحكّم داخل مصفوفةٍ كما يلي. angular.module('app') .controller('LocaleController', ['$scope', '$locale', function(s, l) { s.locale = l.id; }]);الناتج: Your locale is en-usفي المثال السّابق، قُمت بمحاكاة تأثير التّقصير عن طريق تغيير أسماء الوُسطاء من scope$ و locale$ إلى s وl بالترتيب. بالطّبع لا يمكن لـAngular أن تجد مَوردين لهما الأسماء s وl لو اعتمدنا على أسلوب إضافة الحواشي الضّمنيّ، ولكن هنا، ولأنّ المصفوفة تحوي أسماء الوسطاء الحقيقيّين ستتمكّن من حقنهم بنجاح. إضافة الحاشية بواسطة inject$إن كان قد انتابك شعورٌ بأن طريقة إضافة الحواشي السّطريّة، قبيحة، فالأرجح أنك ستجد الطريقة البديلة هذه أكثر قبحًا. فهي تعتمد على إنشاء عنصرٍ ذا اسمٍ مخصّص، inject$، في التّابع الإنشائيّ، وهذا سبب تسمية الطّريقة بهذا الاسم. var LocaleController = function(s, l) { s.locale = l.id; }; LocaleController['$inject'] = ['$scope', '$locale']; angular.module('app') .controller('LocaleController', LocaleController);الناتج: Your locale is en-usالمهمّ أنّك الآن تعرف الخيارات المتاحة للقيام بإضافة الحواشي. angular.injectorأرجو أن تكون عند هذه النّقطة قد قمت بإضافة ng-annotate إلى بُنيتك، لتتمكّن من استخدام الأسلوب البدائيّ في التّبعيّات الضّمنيّة التي ستراها في هذه السلسلة دون مشاكل. على أيّ حال، إن لم تكن قد قمت بذلك، لديّ اقتراح لك، إلّا أنّه ليس اقتراحًا جادًّا: قم بكتابة تابع require الخاصّ بك، وأفصح عن التّبعيّات الّتي تريد ضمن عمليّة البحث المباشر عن الخدمات، وذلك بدلًا من استخدام أسلوب حقن التّبعيّة. يمكنك القيام بذلك عن طريق استدعاء تابع angular.injector مباشرةً، وعليك تمرير وسيط وحيدٍ إليه هو مصفوفةٌ فيها أسماء الوحدات التي ترغب بالبحث ضمنها، ويجب عليك تمرير اسم الوحدة ng دومًا وجعلها في بداية القائمة. var require = function(name) { return angular.injector(['ng','app']).get(name); }; angular.module('app') .controller('LocaleController', ['$scope', function($scope) { var $locale = require('$locale'); $scope.locale = $locale.id; }]);الناتج: Your locale is en-usلاحظ أنّ المثال لايزال يعتمد على حقن التّبعيّة في تمرير كائن المجال الصّحيح للمتحكّم، سأسعى في الفقرة القادمة لأبيّن لك أحد أهمّ المشاكل العمليّة مع الحواشي في الأنظمة الضّخمة، وذلك خشية أن يتبادر إلى ذهنك بأنّ الاستثناء الّذي واجهناه للتّو يلغي الحاجة إلى تبنّي طريقة محدّد موضع الخدمة. مخاطرالمثال التّالي سيستبق الأحداث، ويأخذنا إلى الفصل القادم، الخدمات. سنستخدم في هذا المثال التّابع factory، ورغم أنّك لم تألف استخدامه من قبل إلّا أنّه بإمكانك تخمين وظيفته، فهو يقوم بإعداد مصنعٍ للمكوّن باستخدام نظام الوحدات. لاحظ أيضًا أنّ الخدمة http$ (التي سنناقشها في فصلٍ لاحق HTTP) ستكون خدمةً نموذجيّةً ومثالًا من الحياة العمليّة لاستخدام حقن التّبعيّة داخل خدماتٍ كهذه. angular.module('app') .factory('fullPrice', ['$http', function($http) { return function() { // Use $http to fetch remote data. return 100; } }]) .factory('discountPrice', ['$http', function($http) { return function() { // Use $http to fetch remote data. return 40; } }]);استلهمتُ المثال التّالي من تطبيق Angular حقيقيّ، حيث استُبدلت التّبعيّات بقائمةً طويلةً من الخدمات المدمجة في Angular، ولكنّ طول القائمة هو نفسه تقريبًا. angular.module('app') .controller('PriceController', ['$scope', '$anchorScroll', '$animate', '$cacheFactory', '$compile', '$controller', '$document', '$exceptionHandler', '$filter', '$http', '$httpBackend', '$interpolate', '$interval', 'fullPrice', 'discountPrice', '$locale', '$location', '$log', '$parse', '$q', '$rootElement', '$rootScope', '$sce', '$sceDelegate', '$templateCache', '$timeout', '$window', function( $scope, $anchorScroll, $animate, $cacheFactory, $compile, $controller, $document, $exceptionHandler, $filter, $http, $httpBackend, $interpolate, $interval, discountPrice, fullPrice, $locale, $location, $log, $parse, $q, $rootElement, $rootScope, $sce, $sceDelegate, $templateCache, $timeout, $window) { $scope.fullPrice = fullPrice(); $scope.discountPrice = discountPrice(); }]);من الواضح أنني اختصرت جسم المتحكّم PriceController وكذلك اختصرت شيفرة العرض التّالية. <table ng-controller="PriceController"> <tr> <td>Full price:</td> <td>{{fullPrice}}</td> </tr> <tr> <td>Discount price:</td> <td>{{discountPrice}}</td> </tr> </table>الناتج: Full price: 40 Discount price: 100لقد تعمّدت القيام بخطأٍ في المثال السابق، فالمفترض أن يكون السعر الكلّي أكبر دومًا من السّعر المخفّض، ولكنّهما انعكسا لسببٍ ما، والمشكلة ليست في شيفرة العرض أو في جسم المتحكّم، هل يمكنك إيجادها؟ ماذا تستنتج من ذلك بخصوص كتابة حاشية التّبعيّات يدويًّا في المشاريع الحقيقيّة؟ خاتمةهذا هو الفصل الثّاني من أصل ثلاثة فصول في هذه السلسلة تغطّي البنية التّحتيّة لـAngular الخاصّة بإدارة شيفرة التّطبيق. الفصل الأوّل، الوحدات، بيّنَ كيف سنقوم بتهيئة خشبة المسرح الّتي سيقف عليها الممثّلون ليقوم كلٌّ منهم بدوره. وفي هذا الفصل شرحنا ببعض التّفصيل الآليّات المتاحة لجعل كلِّ ممثّلٍ يقفُ في مكانه الصّحيح. أمّا الفصل الثّالث ضمن هذا المجال، الخدمات، سيشرح كيفيّة إنشاء الممثّلين أنفسهم. ترجمة وبتصرّف للفصل السابع من كتاب: Angular Basics لصاحبه: Chris Smith.1 نقطة