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

حسام برهان

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

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

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

  • عدد الأيام التي تصدر بها

    31

آخر يوم ربح فيه حسام برهان هو نوفمبر 3 2019

حسام برهان حاصل على أكثر محتوى إعجابًا!

آخر الزوار

لوحة آخر الزوار معطلة ولن تظهر للأعضاء

إنجازات حسام برهان

عضو نشيط

عضو نشيط (3/3)

172

السمعة بالموقع

12

إجابات الأسئلة

  1. سنتعرف في هذا الدرس على طريقة التعامل مع عناصر الإدخال في بوتستراب، إذ توفّر بوتستراب دعمًا قويًا لعناصر الإدخال من خلال إضفاء لمسة جمالية واضحة عليها. سنتعرّف على العناصر الأساسية التي تُستخدم بشكل متكرّر في جميع تطبيقات الويب ثم سنعمل، كما جرت العادة، على تطبيق ما تعلّمناه على موقعنا "نبيه" الذي بنيناه من المقالات السابقة. ستحتاج إلى مراجعة المقالات السابقة في هذه السلسلة كي تتعرّف أكثر على هذا الموقع. سنتعلّم في هذا الدرس: تنسيق أشهر عناصر الإدخال في بوتستراب. إنشاء صفحة الدفع ضمن موقع نبيه. هذا الفصل جزء من سلسلة فصول عن بوتستراب 5، وإليك كامل فهرس السلسلة: مدخل إلى إطار العمل بوتستراب 5 شريط التنقل في بوتستراب 5 مخطط الصفحة في بوتستراب 5 تطبيق مخطط الصفحة في بوتستراب على صفحات الويب مكون البطاقة Card ومكون الشرائح الدوارة Carousel في بوتستراب مكون الرسائل المنبثقة Modal في بوتستراب عناصر الإدخال: إنشاء استمارة دفع في بوتستراب تنسيق أشهر عناصر الإدخال في بوتستراب تُستخدم عناصر الإدخال عادةً لاستقبال المدخلات من المستخدم، وكما نعلم توفّر HTML عناصر جيدة بهذا الصدد. تضفي بوتستراب ناحية جمالية وتناسق واضح على هذه العناصر. فيما يلي أشهر هذه العناصر التي لا غنى عنها في أي تطبيق ويب يستقبل الدخل من المستخدم. عنصر الإدخال النصي وهو من أشهر العناصر وأكثرها استخدمًا، ويمكن تنسيق هذا العنصر عن طريق استخدام الصنف التنسيقي form-control. السبب في أنّ هذا الصنف يبدأ بالكلمة form هو أنّه عادةً ما يوضع (وغيره من عناصر الإدخال) ضمن عنصر النموذج <form> رغم أنّه ليس من الضروري ذلك. الشكل العام هو: <input type="text" class="form-control" > ومن الممكن أيضًا بدلًا من استخدام الصنف form-control، استخدام الصنفين التنسيقيين form-control-lg و form-control-sm اللذين يجعلان عنصر الإدخال النصي كبيرًا أو صغيرًا على الترتيب. عنصر العنوان هو العنصر <label> وعادةً ما يُستخدم مع العديد من عناصر الإدخال لتوضيح الغاية منها. الصنف التنسيقي المستخدم هنا هو form-label والشكل العام له: <label for="DEST_ID" class="form-label">العنوان المطلوب</label> <input id="DEST_ID" type="text" class="form-control" > حيث DEST_ID هو معرّف عنصر الإدخال الذي سيكون عنصر العنوان مخصّصًا له كما موضع. ومرّة أخرى يمكن استخدام الصنفين التنسيقيين form-control-lg و form-control-sm كما في عنصر الإدخال النصي. عنصر الاختيار من الممكن أيضًا تنسيق عنصر الاختيار checkbox على الشكل التالي: <input class="form-check-input" type="checkbox" id="normal_unchecked"> لاحظ الصنف التنسيقي form-check-input. سيظهر هذا العنصر بحالته العادية دون وجود علامة الاختيار ضمنه. أمّا إذا أردت ظهوره بحالة الاختيار فأضف السمة checked فقط إلى هذا العنصر: <input class="form-check-input" type="checkbox" id="normal_checked" checked> في كلتا الحالتين السابقتين سيظهر عنصر الاختيار على شكل مربّع صغير بحالة عدم اختيار أو بحالة اختيار على الترتيب، ولكن من الضروري بالطبع إضافة عنصر عنوان توضيحي يوضّح الغاية من عنصر الاختيار، لذلك يمكن وضع عنصر عنوان بجوار عنصر الاختيار له الصنف التنسيقي form-check-label على النحو التالي: <input class="form-check-input" type="checkbox" id="normal_unchecked"> <label class="form-check-label" for="normal_unchecked">عنصر اختيار عادي</label> عادةً ما يوضّع العنصرين السابقين ضمن عنصر div له التنسيق form-check، وبهذا يصبح مثالنا البسيط على الشكل التالي: <div class="form-check"> <input class="form-check-input" type="checkbox" id="normal_unchecked"> <label class="form-check-label" for="normal_unchecked">عنصر اختيار عادي</label> </div> سيولّد ذلك شكلًا شبيها بما يلي: عنصر الانتقاء يمكن بشكل مشابه لعنصر الاختيار وضع عنصر الانتقاء radio مع عنصر العنوان الخاص به ضمن عنصر div له التنسيق form-check على الشكل التالي: <div class="form-check"> <input class="form-check-input" type="radio" name="radioGroup" id="normal_radio"> <label class="form-check-label" for="normal_radio"> عادي </label> </div> <div class="form-check"> <input class="form-check-input" type="radio" name="radioGroup" id="selected_radio" checked> <label class="form-check-label" for="selected_radio"> في وضع انتقاء </label> </div> وضعت في الشيفرة السابقة عنصري انتقاء مع ضبط السمة name لهما على النفس القيمة radioGroup لكي نستطيع انتقاء واحد منهما فقط في كل مرّة. يمكن بالطبع إضافة أي عدد من عناصر الانتقاء بحيث يكون لكل منها نفس قيمة السمة name لكي تُعامل على شكل مجموعة واحدة. ستولّد الشيفرة السابقة شكلًا شبيهًا بما يلي: إنشاء صفحة الدفع ضمن موقع "نبيه" حان الآن موعد تجهيز صفحة الدفع checkout.html الخاصة بموقع نبيه. سنجري بدايةً تعديلين صغيرين على الملفين: shopping-cart.html و styles.css. بالنسبة للملف styles.css سنضيف تنسيق بسيط لمحاذاة بيانات الدفع بشكل ملائم. أضف التنسيق التالي إلى نهاية هذا الملف: /*Checkout*/ .payment-details{ padding: 3% 5%; } بالنسبة للملف shopping-cart.html فسنضيف زر "الشراء الآن" إلى أسفل الصفحة الذي سيحولنا إلى صفحة الدفع التي سنبنيها تاليًا، لذا أضف الشيفرة التالية إلى الملف shopping-cart.html قبل القسم ‎section id="footer"‎ مباشرةً: <div class="row"> <div class="col-4 shopping-cart-content"><a href="checkout.html" class="btn btn-primary">الشراء الآن</a></div> </div> جاء الآن دور الملف checkout.html والتي ستكون محتوياته على النحو التالي: <!DOCTYPE html> <html lang="ar" dir="rtl"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.rtl.min.css" integrity="sha384-gXt9imSW0VcJVHezoNQsP+TNrjYXoGcrqBZJpry9zJt8PCQjobwmhMGaDHTASo9N" crossorigin="anonymous"> <link href="css/styles.css" rel="stylesheet" /> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Almarai:wght@300;400;700;800&family=Tajawal:wght@200;300;400;500;700;800;900&display=swap" rel="stylesheet"> <!-- Boostrap 5 icons - web font --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.0/font/bootstrap-icons.css"> <title>دورات نبيه | صفحة الدفع</title> </head> <body> <section id="header"> <!-- Nav Bar --> <nav class="navbar navbar-expand-lg navbar-light"> <div class="container-fluid"> <a class="navbar-brand" href="#"> <img src="images/nabih-logo.png" style="margin-left: 8px;" alt="" height="32"> نبيه </a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav me-2 mb-2 mb-lg-0 ms-3"> <li class="nav-item"><a class="nav-link" href="#">التصنيفات</a></li> </ul> <form class="d-flex me-auto w-100"> <input class="form-control" type="search" placeholder="ابحث عن أي موضوع"> <div class="nav-link" style="position: relative;"> <div class="counter zero"></div> <img src="images/icons8-shopping-cart-32.png" /> </div> <button type="button" class="btn btn-dark nabih-buttons">دخول</button> <button type="button" class="btn btn-outline-dark nabih-buttons">تسجيل جديد</button> </form> </div> </div> </nav> </section> <div class="payment-details"> <div class="col-md-7 col-lg-8"> <h4 class="mb-3">بيانات الدفع</h4> <form> <div class="row g-3"> <!-- الموضع 1 --> <div class="col-sm-6"> <label for="firstName" class="form-label">الاسم</label> <input type="text" class="form-control" id="firstName"> </div> <div class="col-sm-6"> <label for="lastName" class="form-label">الكنية</label> <input type="text" class="form-control" id="lastName"> </div> <div class="col-12"> <label for="username" class="form-label">اسم المستخدم</label> <div class="input-group"> <!-- الموضع 2 --> <span class="input-group-text">#</span> <input type="text" class="form-control" id="username" placeholder="اسم المستخدم"> </div> </div> <div class="col-12"> <label for="email" class="form-label">البريد الإلكتروني <span class="text-muted">(اختياري)</span></label> <input type="email" class="form-control" id="email" placeholder="you@example.com"> </div> </div> <hr class="my-4"> <!-- الموضع 3 --> <h4 class="mb-3">الدفع</h4> <div class="my-3"> <div class="form-check"> <input id="credit" name="paymentMethod" type="radio" class="form-check-input"> <label class="form-check-label" for="credit">بطاقة إئتمان</label> </div> <div class="form-check"> <input id="debit" name="paymentMethod" type="radio" class="form-check-input"> <label class="form-check-label" for="debit">بطاقة عادية</label> </div> <div class="form-check"> <input id="paypal" name="paymentMethod" type="radio" class="form-check-input"> <label class="form-check-label" for="paypal">باي بال</label> </div> </div> <div class="row"> <div class="col-md-6"> <label for="cc-name" class="form-label">الاسم على البطاقة</label> <input type="text" class="form-control" id="cc-name" placeholder=""> <small class="text-muted">الاسم الكامل كما يظهر على البطاقة</small> </div> <div class="col-md-6"> <label for="cc-number" class="form-label">رقم البطاقة</label> <input type="text" class="form-control" id="cc-number" placeholder=""> </div> <div class="col-md-3"> <label for="cc-expiration" class="form-label">تاريخ الانتهاء</label> <input type="text" class="form-control" id="cc-expiration" placeholder=""> </div> <div class="col-md-3"> <label for="cc-cvv" class="form-label">CVV</label> <input type="text" class="form-control" id="cc-cvv" placeholder=""> </div> <div class="form-check"> <input type="checkbox" class="form-check-input" id="save-card"> <label class="form-check-label" for="save-card">احفظ بيانات البطاقة</label> </div> </div> <hr class="my-4"> <button class="w-100 btn btn-primary btn-lg" type="submit">الدفع</button> <!-- الموضع 4 --> </form> </div> </div> <section id="footer"> <footer> <div class="container-fluid"> <i class="bi bi-facebook social-icon"></i> <i class="bi bi-twitter social-icon"></i> <i class="bi bi-instagram social-icon"></i> <i class="bi bi-envelope social-icon"></i> <p>© دورات نبيه 2021</p> </div> </footer> </section> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html> ستحصل بعد المعاينة على شكل شبيه بما يلي: يبدو أنّ الشيفرة السابقة يجب أن تكون واضحة الآن، ولكن رغم ذلك لنستعرض بعض النقاط الواردة فيها. بالنظر إلى "الموضع 1" ستلاحظ أنّني استخدمت الصنف g-3 مع عنصر div، فتشير العائلة g-*‎ إلى Gutters وهي عبارة عن فراغات هامشية معرّفة مسبقًا يمكن وضعها بين الأعمدة (أفقي) أو حتى بين الأسطر (عمودي). وظيفة هذه العائلة وغيرها من العائلات التي سنراها تباعًا هي توفير اختصار سريع لضبط الفراغات بين العناصر المستهدفة دون الحاجة إلى تعريف تنسيقات ضمن ملف تنسيقي منفصل مثلًا. بالنسبة للفراغات الأفقية نستخدم العائلة الفرعية gx-*‎، أمّا بالنسبة للفراغات العمودية فنستخدم العائلة الفرعية gy-*‎. أمّا إذا أردنا ضبط الفراغات الأفقية والعمودية معًا فنستخدم العائلة g-*‎. توجد ست قيم معرّفة مسبقًا وهي من g-0 إلى g-5 بحيث أنّ كل رقم منها (أي من 0 حتى 5) يُضرب بثابت معرّف مسبقًا في بوتستراب وهو ‎ $spacer وقيمته هي 1rem. ففي مثالنا هذا يُشير الصنف g-3‎ أنّنا نريد ضبط حشوات أفقية وعمودية بمقدار 3rem. بالنسبة "للموضع 2"، لاحظ الصنف input-group مع العنصر div. لهذا الصنف فائدة تنسيقية جميلة تتمثّل في إمكانية رصف نص عادي (يمكن استخدام العنصر <span>) يمثّل نصًا تعريفيًا، مع عنصر إدخال نصي عادي بحيث يبدوان وكأنّهما عنصر واحد. يمكن استخدام هذه الميزة مثلًا لكي تشير للمستخدم أن يُدخل معرّف تويتر ما، وذلك بوضع الرمز "@" قبل عنصر الإدخال النصي. في مثالنا هنا، وضعت الرمز "#" للإشارة إلى أنّنا نريد اسم المستخدم الخاص بالموقع. لكي يتم التراصف بشكل صحيح، ستحتاج أيضًا إلى استخدام التنسيق input-group-text مع عنصر <span> (انظر إلى السطر الذي يليه في الشيفرة) الذي يمثّل الحاضن للنص التعريفي، يليه عنصر الإدخال النصي الذي يحمل التنسيق form-control كما هو متوقع. لننتقل الآن إلى "الموضع 3". لاحظ كيف استخدمنا الصنف my-4. هذا الصنف يعود إلى العائلة الرئيسية m-*‎ وهي مسؤولة عن ضبط الهوامش margins والتي يتبع لها عدة عائلات فرعية وهي: العائلة mt-*‎ وهي لضبط الهامش العلوي margin-top. العائلة mb-*‎ وهي لضبط الهامش السفلي margin-bottom. العائلة ms-*‎ وهي لضبط هامش البداية (وهو margin-left في اللغات التي تتجه من اليسار LTR أو margin-right في اللغات التي تتجه من اليمين RTL). العائلة me-*‎ وهي لضبط هامش النهاية (وهو margin-left في اللغات RTL وهو margin-right في اللغات LTR). العائلة mx-*‎ وهي لضبط الهامشين الأيمن والأيسر بنفس الوقت (margin-right و margin-left). العائلة my-*‎ وهي لضبط الهامشين العلوي والسفلي بنفس الوقت (margin-top و margin-bottom). وكما في العائلة g-*‎ توجد ستة قياسات يمكن استخدامها مع العائلة m-*‎ وهي من 0 حتى 5. استخدمنا في "الموضع 2" القياس رقم 4 لضبط الهامشين العلوي والسفلي، أي: my-4. وأخيرًا بالنظر إلى "الموضع 4"، لاحظ أنني قد استخدمت الصنف w-100، يعني ذلك أني أريد أن يشغل هذا العنصر عرضًا مقداره 100% ضمن أقرب حاوية هو موجود ضمنها، كما توجد قيم أخرى أيضًا مثل w-25 و w-50 و w-75. يمكنك تنزيل الشيفرة الكاملة لهذا الدرس من bootstrap5-tutorial.zip، كما ويمكنك الإطلاع على نسخة حيّة من هذه الصفحة من هنا. كما أنصحك بالإطلاع على صفحة التوثيق الرسمية في أكاديمية حسوب. خاتمة تعرّفنا في هذا الدرس على كيفية تنسيق بعض عناصر الإدخال الشائعة باستخدام بوتستراب، وعملنا على تطبيق ما تعلّمناه عن طريق تجهيز صفحة الدفع الخاصة بموقع "نبيه". نكون بذلك قد وصلنا إلى نهاية هذه السلسلة التي أرجو أن تكون قد حقّقت الفائدة المرجوة في التعرّف العملي على هذه المكتبة المهمة "بوتستراب" مع الإصدار الأخير لها 5.0 حتى تاريخ كتابة هذا المقال. اقرأ أيضًا بناء قائمة شجرية باستخدام البوتستراب 10 أخطاء شائعة عند استخدام إطار العمل Bootstrap
  2. سنتعامل في هذا الدرس مع مكوّن جديد ومفيد من بوتستراب، ألا وهو مكوّن الرسائل المنبثقة Modal. يُستخدم هذا المكوّن في إضفاء ميزة جمالية عندما نريد التواصل مع المستخدم، كأن نُظهر به رسالة تفيد بالانتهاء من تنفيذ إجراء معيّن، أو الإبلاغ عن حدوث خطأ ما، أو حتى عندما نريد أن نُخبر المستخدم بمعلومة معيّنة بحيث يمكنه أن يتخذ قرارًا ما بناء على ذلك. وكما جرت العادة، سنطبّق ما سنتعلّمه في هذا الدرس على موقع" نبيه" الذي بنيناه في مقالات سابقة من هذه السلسلة. سنعمل في هذا الدرس على: التعرّف على مكوّن الرسائل المنبثقة Modal في بوتستراب. إضافة المنتجات إلى سلة المشتريات في موقع نبيه. إنشاء صفحة جديدة في موقع نبيه لعرض محتويات سلة المشتريات. هذا الفصل جزء من سلسلة فصول عن بوتستراب 5، وإليك كامل فهرس السلسلة: مدخل إلى إطار العمل بوتستراب 5 شريط التنقل في بوتستراب 5 مخطط الصفحة في بوتستراب 5 تطبيق مخطط الصفحة في بوتستراب على صفحات الويب مكون البطاقة Card ومكون الشرائح الدوارة Carousel في بوتستراب مكون الرسائل المنبثقة Modal في بوتستراب عناصر الإدخال: إنشاء استمارة دفع في بوتستراب التعرف على مكون الرسائل المنبثقة Modal في بوتستراب يمكن إنشاء أشكال متنوّعة وغنيّة من مكوّن الرسائل المنبثقة. سنستعرض فيما يلي الشكل المبسّط الأساسي التالي: <div class="modal" tabindex="-1" id="exampleModal"> <!-- الموضع 1 --> <div class="modal-dialog"> <!-- الموضع 2 --> <div class="modal-content"> <!-- الموضع 3 --> <div class="modal-header"><!-- الموضع 4 --> <h5 class="modal-title">العنوان هنا</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <!-- الموضع 5 --> <p>محتويات النافذة المنبثقة هنا</p> </div> <div class="modal-footer"> <!-- الموضع 6 --> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إغلاق</button> <button type="button" class="btn btn-primary">حفظ التغييرات</button> </div> </div> </div> </div> من الشيفرة السابقة يبدأ تعريف النافذة المنبثقة في "الموضع 1" من خلال الصنف modal لعنصر div عادي. أما في "الموضع 2" نستخدم الصنف modal-dialog الضروري أيضًا لكي تعمل النافذة المنبثقة بشكل صحيح. تُوضع محتويات النافذة المنبثقة بشكل كامل ضمن عنصر div يحمل الصنف modal-content ويمثِّل "الموضع 3" الحاضن لمحتويات النافذة المنبثقة. يمكن أن يحتوي العنصر div.modal-content بدوره على ثلاثة أقسام: ترويسة النافذة المنبثق"الموضع 4" وهي عنصر div له الصنف modal-header. جسم النافذة المنبثقة "الموضع 5" وهي عنصر div له الصنف modal-body. تذييل النافذة المنبثقة "الموضع 6" وهي عنصر div له الصنف modal-footer. بالنسبة للترويسة، فيمكن أن نضع فيها عنوان النافذة المنبثقة (عن طريق عنصر div له التنسيق modal-title) أو بمعنى آخر عنوان الرسالة التي نريد عرضها للمستخدم، بالإضافة إلى إمكانية وضع زر صغير (له التنسيق btn-close) لنسمح للمستخدم بإغلاق هذه النافذة. أمّا جسم النافذة، فمكن أن نضع فيه أي محتوى ملائم نريد عرضه للمستخدم. وبالنسبة للتذييل، فيوضع فيه عادةً أزرار التحكّم التي يمكن من خلالها الاستجابة للرسالة أو المعلومة التي يعرضها التطبيق. لتجربة الشيفرة السابقة، ستحتاج مثلًا إلى زر منفصل لكي يعمل على تفعيل ظهور النافذة المنبثقة المعرّفة ضمن هذه الشيفرة. أقترح أن تستخدم الزر البسيط التالي: <!-- Button trigger modal --> <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal"> أظهر النافذة </button> يمكن وضع هذا الزر قبل أو بعد الشيفرة السابقة ضمن القسم body من الصفحة. لاحظ أنّ السمة data-bs-target من الزر السابق لها القيمة ‎#exampleModal وهي نفسها معرّف عنصر div الرئيسي "الموضع 1" الذي يحضن النافذة المنبثقة. يجب عليك الانتباه أيضًا أنّه لن يمكنك تجربة الشيفرة السابقة بشكل ناجح دون استيراد مكتبات بوتستراب بشكل صحيح، كما تعلّمنا ذلك مسبقًا. بعد أن تعمل الشيفرة السابقة بشكل صحيح، ستحصل على شكل شبيه بما يلي: ستلاحظ عند الضغط على الزر "إغلاق" اختفاء هذه النافذة وسبب ذلك هو وجود السمة data-bs-dismiss مع القيمة modal لها، ويمكنك أيضًا الخروج من هذه النافذة بالنقر في أي مكان خارجها، وهو السلوك الافتراضي. يمكنك منع هذا السلوك، أي أنّك تجعل إخفاء هذه النافذة يكون حصرًا بالنقر على الزر "إغلاق" بأن تضع السمة data-bs-backdrop مع القيمة static لها وذلك ضمن عنصر div الرئيسي "الموضع 1". يمكنك أيضًا الحصول على تأثير لطيف عند إظهار النافذة وإخفائها وذلك بأني تضيف التنسيق fade إلى الصنف modal ضمن عنصر div الرئيسي "الموضع 1". سيصبح عنصر div الرئيسي بعد التعديلين المقترحين على الشكل التالي: <div class="modal fade" tabindex="-1" id="exampleModal" data-bs-backdrop="static"> في الحقيقة، توجد العديد من الإضافات والتنسيقات المختلفة التي يمكنك الإطلاع عليها من خلال صفحة التوثيق الرسمية لهذا المكوّن. إضافة المنتجات إلى سلة المشتريات في موقع نبيه سنعمل في هذه الفقرة على محاكاة عملية إضافة المنتجات إلى سلّة المشتريات الخاصة بموقع نبيه (يمكنك تنزيل شيفرة الدرس الخامس السابق من الملف المرفق في الأسفل). في الحقيقة هناك العديد من الملاحظات حول هذا الموضوع، من أهمّها، أّنه من المنطقي إنشاء حسابات للمستخدمين كي يستطيع المستخدم إضافة أي منتج يرغبه إلى سلّة المشتريات الخاصة به، وأيضًا أنّنا في هذا المشروع سنعمل على حفظ المنتجات المضافة للسلة إلى التخزين المحلّي الخاص بالمتصفّخ وليس إلى قاعدة بيانات موجودة على الإنترنت. سنتغاضى في الحقيقة عن هذين المتطلّبين المهمّين والبديهيين في التطبيقات العمليّة، وذلك بسبب أنّ الهدف من هذا المشروع هو شرح مفاهيم بوتستراب 5 بصورة مبسّطة وميسرة. سنعمل على إجراء بعض التعديلات على ملف الصفحة الرئيسية index.html القديم، وذلك للسماح بإضافة المنتجات إلى سلة المشتريات، أهم هذه التعديلات هي: إضافة الشيفرة اللازمة للإظهار نافذة منبثقة عندما يريد المستخدم أن يضيف منتج ما إلى سلّة المشتريات. إضافة قسم لشيفرة جافاسكريبت تتمثّل مهمتها في إدارة عملية إضافة المنتجات التي يرغبها المستخدم إلى التخزين الداخلي ضمن المتصفّح وأيضًا تحديث أيقونة سلّة المشتريات الموجودة في أعلى الصفحة بالعدد الحالي للمنتجات التي اختارها المستخدم. في الحقيقة ستعمل شيفرة جافاسكربت السابقة على تضمين وحدة برمجية module اسمها main الموجودة ضمن الملف main.js، حيث تحتوي هذه الوحدة على بعض التوابع المفيدة التي تدير العمليات البرمجية الكاملة التي نحتاجها في هذا الدرس (سنتحدّث عن هذه الوحدة بعد قليل). ستصبح الشيفرة الخاصة بالملف index.html على الشكل التالي (الملف مرفق في نهاية المقال): <!doctype html> <html lang="ar" dir="rtl"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.rtl.min.css" integrity="sha384-gXt9imSW0VcJVHezoNQsP+TNrjYXoGcrqBZJpry9zJt8PCQjobwmhMGaDHTASo9N" crossorigin="anonymous"> <link href="css/styles.css" rel="stylesheet" /> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Almarai:wght@300;400;700;800&family=Tajawal:wght@200;300;400;500;700;800;900&display=swap" rel="stylesheet"> <!-- Boostrap 5 icons - web font --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.0/font/bootstrap-icons.css"> <title>دورات نبيه</title> </head> <body> <!-- نافذة منبثقة --> <div class="modal fade" id="addToCartConfirmation" tabindex="-1" aria-labelledby="addToCartConfirmation" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="modalLabel">نبيه</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> تمت الإضافة بنجاح </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إغلاق</button> <button type="button" class="btn btn-primary" onclick="window.location='shopping-cart.html'">الذهاب إلى السلة</button> </div> </div> </div> </div> <section id="header"> <!-- Nav Bar --> <nav class="navbar navbar-expand-lg navbar-light"> <div class="container-fluid"> <a class="navbar-brand" href="#"> <img src="images/nabih-logo.png" style="margin-left: 8px;" alt="" height="32"> نبيه </a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav me-2 mb-2 mb-lg-0 ms-3"> <li class="nav-item"><a class="nav-link" href="#">التصنيفات</a></li> </ul> <form class="d-flex me-auto w-100"> <input class="form-control" type="search" placeholder="ابحث عن أي موضوع"> <div class="nav-link" style="position: relative;" onclick="goToShoppingCart()"> <div class="counter zero"></div> <a href="shopping-cart.html"><img src="images/icons8-shopping-cart-32.png" /></a> </div> <button type="button" class="btn btn-dark nabih-buttons">دخول</button> <button type="button" class="btn btn-outline-dark nabih-buttons">تسجيل جديد</button> </form> </div> </div> </nav> <!--Main View--> <div class="mainview"> <div class="row"> <div class="col-lg-6"> <h1 class="mainview-heading">دورات غنية بجودة عالية</h1> <h3 class="mainview-subheading"> طور نفسك لتنافس في سوق العمل</h3> </div> <div class="col-lg-6"> <img class="mainview-image" src="images/show-case.jpg" /> </div> </div> </div> </section> <section id="best-selling"> <div class="section-title">الدورات الأكثر مبيعًا</div> <div id="bestSellingCourses" class="carousel carousel-dark slide" data-bs-ride="carousel"> <div class="carousel-inner"> <div class="carousel-item active"> <div class="row"> <div class="col-lg-3"> <div class="card" name="productCard" id="P1"> <img src="images/python-product.jpg" class="card-img-top product-image" alt="python-course"> <div class="card-body"> <h5 class="product-title card-title">دورة أساسيات البرمجة باستخدام بايثون</h5> <p class="product-text card-text">في هذه الدورة سنتعلّم مبادئ البرمجة في لغة بايثون</p> <a href="#" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addToCartConfirmation">أضف إلى السلة</a> <div class="price-tag">$10</div> </div> </div> </div> <div class="col-lg-3"> <div class="card" name="productCard" id="P2"> <img src="images/github-product.jpg" class="card-img-top product-image" alt="github-course"> <div class="card-body"> <h5 class="product-title card-title">دورة التعامل مع GitHub</h5> <p class="product-text card-text">تعلّم كيف تدير مشاريعك البرمجية من حيث إدارة الإصدار والمساهة في مشاريع برمجية أخرى.</p> <a href="#" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addToCartConfirmation">أضف إلى السلة</a> <div class="price-tag">$15</div> </div> </div> </div> <div class="col-lg-3"> <div class="card" name="productCard" id="P3"> <img src="images/python-django-product.jpg" class="card-img-top product-image" alt="django-course"> <div class="card-body"> <h5 class="product-title card-title">دورة تطوير تطبيقات ويب باستخدام بايثون مع Django</h5> <p class="product-text card-text">تعلّم كيف تبني تطبيقات ويب باستخدام لغة بايثون مع Django </p> <a href="#" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addToCartConfirmation">أضف إلى السلة</a> <div class="price-tag">$20</div> </div> </div> </div> <div class="col-lg-3"> <div class="card" name="productCard" id="P4"> <img src="images/javascript-product.jpg" class="card-img-top product-image" alt="javascript-course"> <div class="card-body"> <h5 class="product-title card-title">دورة أساسيات البرمجة باستخدام جافاسكريبت</h5> <p class="product-text card-text"> سنتعلّم في هذه الدورة كيفية تطوير تطبيقات الواجهة الأمامية باستخدام جافاسكريبت </p> <a href="#" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addToCartConfirmation">أضف إلى السلة</a> <div class="price-tag">$25</div> </div> </div> </div> </div> </div> <div class="carousel-item"> <div class="row"> <div class="col-lg-3"> <div class="card" name="productCard" id="P5"> <img src="images/php-product.jpg" class="card-img-top product-image" alt="php-course"> <div class="card-body"> <h5 class="product-title card-title">دورة أساسيات البرمجة باستخدام PHP</h5> <p class="product-text card-text">في هذه الدورة سنتعلّم مبادئ البرمجة في لغة PHP</p> <a href="#" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addToCartConfirmation">أضف إلى السلة</a> <div class="price-tag">$13</div> </div> </div> </div> <div class="col-lg-3"> <div class="card" name="productCard" id="P6"> <img src="images/arduino-product.jpg" class="card-img-top product-image" alt="arduino-course"> <div class="card-body"> <h5 class="product-title card-title">دورة التعامل مع أساسيات Arduino</h5> <p class="product-text card-text">تعلّم كيف تبني أنظمة مضمنه تتضمّن مشاريع بسيطة باستخدام Arduino</p> <a href="#" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addToCartConfirmation">أضف إلى السلة</a> <div class="price-tag">$30</div> </div> </div> </div> </div> </div> </div> <button class="carousel-control-prev" type="button" data-bs-target="#bestSellingCourses" data-bs-slide="prev"> <span class="carousel-control-prev-icon" aria-hidden="true"></span> </button> <button class="carousel-control-next" type="button" data-bs-target="#bestSellingCourses" data-bs-slide="next"> <span class="carousel-control-next-icon" aria-hidden="true"></span> </button> </div> </section> <section id="course-categories"> <div class="section-title">الأقسام المتاحة</div> <div class="row"> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/programming-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">البرمجة</p> </div> </div> </a> </div> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/marketing-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">التسويق</p> </div> </div> </a> </div> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/freelance-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">العمل الحر</p> </div> </div> </a> </div> </div> <div class="row"> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/cloud-computing-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">التطبيقات السحابية</p> </div> </div> </a> </div> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/certificates-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">الشهادات العالمية</p> </div> </div> </a> </div> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/apps-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">البرامج والتطبيقات</p> </div> </div> </a> </div> </div> </section> <section id="footer"> <footer> <div class="container-fluid"> <i class="bi bi-facebook social-icon"></i> <i class="bi bi-twitter social-icon"></i> <i class="bi bi-instagram social-icon"></i> <i class="bi bi-envelope social-icon"></i> <p>© دورات نبيه 2021</p> </div> </footer> </section> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> <script type="module"> import {updateCartLabel, saveItem} from './js/main.js'; let products = document.getElementsByName('productCard'); for (let product of products) { const product_id = product.attributes['id'].value; const product_title = product.getElementsByClassName('product-title')[0].innerHTML; const product_price = product.getElementsByClassName('price-tag')[0].innerHTML; const addToCartButton = product.getElementsByClassName('btn-primary')[0]; addToCartButton.addEventListener('click', (e) => { const item_to_post = { id: product_id, course_name: product_title, price: product_price.substring(1) }; saveItem(item_to_post); updateCartLabel(); }); } </script> </body> </html> ستكون هناك أيضًا تعديلات طفيفة على ملف التنسيقات styles.css لكي يدعم صفحة سلة المشتريات. المحتوى الجديد للملف سيكون على النحو التالي: body{ font-family: 'Tajawal', sans-serif; font-size: 1em; } .nabih-buttons{ margin: 0 4px; padding: 6px 8px; width: 7rem; white-space: nowrap; } .container-fluid{ padding:0 5%; } .section-title{ text-align: center; font-size: xx-large; padding: 3rem 0; } /*Header Section*/ .counter{ color: white; margin: 0; position: absolute; font-size: 15px; text-align: center; right: 6px; top: 0px; width: 20px; height: 20px; background: red; border-radius: 50%; } .zero{ opacity: 0; } #header{ background-color: #eee; } .navbar-brand{ font-family: 'Almarai'; color:#393e46; font-size: 2.5rem; font-weight:900; margin: 0; } .mainview-heading { color: white; font-size: 4em; text-align: right; } .mainview-subheading{ color: white; margin: 64px 0; text-align: right; } .mainview{ background-color: #233e8b; padding: 3% 5%; } .mainview-image{ border-radius: 2%; width: 500px; float: left; } /*Best Selling Section*/ .carousel-inner{ padding: 0 5%; } .carousel-control-prev { background: linear-gradient(to right, rgba(200,200,200,0), rgba(200,200,200,1)); } .carousel-control-next { background: linear-gradient(to left, rgba(200,200,200,0), rgba(200,200,200,1)); } .product-image{ height: 12rem; } .product-title{ height: 4rem; } .product-text{ height: 6rem; } .price-tag{ float: left; border-width: 1px; border-style: solid; width: 3rem; height: 2rem; text-align: center; padding:2px; margin-top:2px; } /*Course Categories Section*/ #course-categories{ background-color: #eee; padding: 0 10% 8px; } #course-categories .row{ margin-bottom: 72px; } .category-card{ margin-left: 24px; margin-right:24px; padding: 48px 0px 32px; } .category-image{ width: 50%; height: auto; margin: 0 auto; } .category-text{ text-align: center; font-size: 1.3rem; } .category-link{ text-decoration: none; color:inherit; } /*Footer Section*/ footer{ height: 200px; } .social-icon { margin: 20px 10px; } #footer .container-fluid{ padding: 7% 15%; text-align: center; } /*Shopping Cart*/ .shopping-cart-title{ padding: 3% 5%; } .shopping-cart-content{ padding: 0 5%; } .shopping-cart-total{ padding:0 5% 3%; font-weight: bold; } .shopping-cart-item{ padding-top: 8px; padding-bottom: 8px; font-size: 1.1rem; } ستحصل على نافذة منبثقة شبيهة بما يلي: إضافة الوحدة البرمجية main إذا لم تكن قد أنشأت المجلّد js ضمن المجلّد الرئيسي للمشروع فافعل ذلك الآن، بعد ذلك أضف الملف main.js لهذا المجلّد. انسخ الشيفرة البرمجية التالية لهذا الملف: export function saveItem(item) { let key = Object.keys(localStorage) .find(e => e === String(item.id)); if(key){ let tmp = JSON.parse(localStorage.getItem(key)); tmp.push(item); localStorage.setItem(item.id, JSON.stringify(tmp)); } else{ localStorage.setItem(item.id, JSON.stringify([item])); } } export function getItem(id) { return window.localStorage.getItem(item.id); } export function getAllItems(){ const keys = Object.keys(window.localStorage); let entries = []; for(let key of keys){ entries.push(JSON.parse(localStorage.getItem(key))) } return entries; } export function updateShoppingCartList(){ let shoppingCartContent = document.getElementById('shoppingCartContent'); let counter = 1; let total_products = 0; let amount_due = 0; for (let group of getAllItems()) { const div = document.createElement('div'); div.className = 'row shopping-cart-item'; div.innerHTML = ` <div class="col-1"> <span>${counter}</span> </div> <div class="col-6"> <span>${group[0].course_name}</span> </div> <div class="col-1"> <span>${group.length}</span> </div> <div class="col-1"> <span>$${group[0].price}</span> </div> <div class="col-1"> <span>$${group.length * group[0].price}</span> </div> `; shoppingCartContent.appendChild(div); amount_due += group.length * group[0].price; counter++; total_products += group.length; } document.getElementById('amountDue').innerHTML = '$' + amount_due; } export function updateCartLabel(){ const counterElement = document.getElementsByClassName('counter')[0]; let count = 0; count = getAllItems().reduce( (acc, group) => acc + group.length, 0) if(count > 0){ counterElement.innerHTML = count; counterElement.classList.remove('zero'); } } يحتوي هذا الملف على خمسة توابع، وهي: التابع saveItem ويقبل وسيطًا وحيدًا وهو العنصر "المنتج" الذي اختاره المستخدم، حيث يحفظه ضمن التخزين الداخلي للمتصفّح. التابع getItem ويقبل وسيطًا واحيدًا هو معرّف المنتج الذي نود الحصول على بياناته من التخزين الداخلي. التابع getAllItems وهو لا يحتاج إلى أية وسائط، ويُرجع مصفوفة تحتوي على جميع المنتجات المحفوظة ضمن التخزين الداخلي. التابع updateShoppingCartList ومهمّته تحديث الصفحة الخاصة بسلّة المشتريات، بالمنتجات الموجودة ضمن التخزين الداخلي، حيث يعرضها بطريقة جدولية بسيطة، موضّحا اسم المنتج وعدد النسخ المطلوب شرائها منه، وسعر النسخة، وإجمالي المبلغ الواجب دفعه لهذا المنتج تحديدًا. وفي نهاية الجدول سيعرض أيضًا المجموع النهائي الواجب دفعه من قبل المستخدم (سنرى توضيحًا لبنية هذا الجدول بعد قليل). التابع updateCartLabel ووظيفته تحديث أيقونة سلّة المشتريات الموجودة أعلى الصفحة بعدد نسخ المنتجات المطلوب شراؤها. عرض محتويات سلة المشتريات أضف الملف shopping-cart.html إلى المشروع، وانسخ إليه المحتويات التالية: <!DOCTYPE html> <html lang="ar" dir="rtl"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.rtl.min.css" integrity="sha384-gXt9imSW0VcJVHezoNQsP+TNrjYXoGcrqBZJpry9zJt8PCQjobwmhMGaDHTASo9N" crossorigin="anonymous"> <link href="css/styles.css" rel="stylesheet" /> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Almarai:wght@300;400;700;800&family=Tajawal:wght@200;300;400;500;700;800;900&display=swap" rel="stylesheet"> <!-- Boostrap 5 icons - web font --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.0/font/bootstrap-icons.css"> <title>دورات نبيه | سلة المشتريات</title> </head> <body> <section id="header"> <!-- Nav Bar --> <nav class="navbar navbar-expand-lg navbar-light"> <div class="container-fluid"> <a class="navbar-brand" href="#"> <img src="images/nabih-logo.png" style="margin-left: 8px;" alt="" height="32"> نبيه </a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav me-2 mb-2 mb-lg-0 ms-3"> <li class="nav-item"><a class="nav-link" href="#">التصنيفات</a></li> </ul> <form class="d-flex me-auto w-100"> <input class="form-control" type="search" placeholder="ابحث عن أي موضوع"> <div class="nav-link" style="position: relative;"> <div class="counter zero"></div> <img src="images/icons8-shopping-cart-32.png" /> </div> <button type="button" class="btn btn-dark nabih-buttons">دخول</button> <button type="button" class="btn btn-outline-dark nabih-buttons">تسجيل جديد</button> </form> </div> </div> </nav> </section> <!--Main View--> <div class="shopping-cart-title"><h2>سلة المشتريات</h2></div> <div id="shoppingCartContent" class="shopping-cart-content"> <div class="row"> <div class="col-1"> </div> <div class="col-6"> <h5>الدورة</h5> </div> <div class="col-1"> <h5>العدد</h5> </div> <div class="col-1"> <h5>السعر</h5> </div> <div class="col-1"> <h5>الإجمالي</h5> </div> </div> </div> <div class="row shopping-cart-total"> <div id="amountDue" class="offset-9 col-1" style="border-top-style: solid;"></div> </div> <div class="row"> <div class="col-4 shopping-cart-content"><a href="checkout.html" class="btn btn-primary">الشراء الآن</a></div> </div> <section id="footer"> <footer> <div class="container-fluid"> <i class="bi bi-facebook social-icon"></i> <i class="bi bi-twitter social-icon"></i> <i class="bi bi-instagram social-icon"></i> <i class="bi bi-envelope social-icon"></i> <p>© دورات نبيه 2021</p> </div> </footer> </section> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> <script type="module"> import {updateShoppingCartList, updateCartLabel} from './js/main.js'; updateShoppingCartList(); updateCartLabel(); </script> </body> </html> القسم الأول من الشيفرة السابقة مألوف بالنسبة لك، فهو مسؤول عن تعريف شريط التنقّل كما في الصفحة الرئيسية بالضبط. القسم الثاني من الشيفرة بدءًا من "الموضع 1" يعرّف بنية بسيطة تشبه الجدول مهمتها عرض محتويات سلة المشتريات. الشيفرة البرمجية المسؤولة عن تعبئة هذه البنية موجودة ضمن "الموضع 2". تستورد هذه الشيفرة المكتوبة بلغة جافا سكريبت، تابعين من الملف main.js (أضفناه قبل قليل)، ثم تعمل على استدعائهما تباعًا. في حال وجود منتجات في السلة ستحصل على شكل شبيه بما يلي: يمكنك الوصول إلى الشيفرة الكاملة لهذا الدرس من الملف bootstrap5-tutorial.zip، كما ويمكنك الإطلاع على نسخة حيّة من هذه الصفحة من هنا. خاتمة كان الدرس طويلًا بعض الشيء إلّا أنّنا أنجزنا الكثير! الميزة الجديدة التي تعرّفنا عليها في هذا الدرس هي مكوّن الرسائل المنبثقة Modal الذي يسمح بالتفاعل الفعّال مع المستخدم من خلال توفير وسيلة لعرض المعلومات للمستخدم، مع إمكانية توفير إمكانية التفاعل من خلال تلقي رد من المستخدم حول سؤال محّدد نرغب بالحصول على الإجابة عليه. سنتابع عملنا في الدرس القادم في توفير صفحة خاصّة للدفع، لشراء المنتجات التي اختارها المستخدم. اقرأ أيضًا بناء قائمة شجرية باستخدام البوتستراب 10 أخطاء شائعة عند استخدام إطار العمل Bootstrap
  3. سنتعرّف في هذا الدرس على مكوّنين جديدين من مكوّنات بوتستراب 5، وهما مكوّن البطاقة Card، ومكوّن الشرائح الدوّارة Carousel. ومن ثمّ سنطبّق ما سنتعلّمه هنا في متابعة عملنا في إكمال تصميم موقع "نبيه". سنعمل في هذا الدرس على: التعرّف على مكوّن البطاقة Card في بوتستراب. التعرّف على مكوّن الشرائح الدوّارة Carousel في بوتستراب. إنجاز قسم الدورات الأكثر مبيعًا Best Selling. إنجاز القسم الخاص بأصناف الدورات Course Categories. أيقونات Bootstrap 5 إنجاز قسم التذييل Footer. هذا الفصل جزء من سلسلة فصول عن بوتستراب 5، وإليك كامل فهرس السلسلة: مدخل إلى إطار العمل بوتستراب 5 شريط التنقل في بوتستراب 5 مخطط الصفحة في بوتستراب 5 تطبيق مخطط الصفحة في بوتستراب على صفحات الويب مكون البطاقة Card ومكون الشرائح الدوارة Carousel في بوتستراب التعرف على مكون البطاقة Card في بوتستراب لمكوّن البطاقة Card في بوتستراب استخدامات متعدّدة. فغالبًا ما يُستخدم عندما نود توضيح أو وصف شيء محدّد، كوصف منتج ما مثلًا، أو وصف صنف كامل من من المنتجات.في درسنا هذا سنستخدم مكوّن البطاقة لوصف دورة محدّدة يقدّمها موقع نبيه، وأيضًا لتصنيف مجالات الدورات التي تُقدّم في الموقع. بُنيت البطاقة في بوتستراب باستعمال التخطيط المرن Flex Box وهي لا تحوي أية هوامش بشكل افتراضي. أي بطاقة في بوتستراب يجب أن يكون لها "حاوية". هذه الحاوية عبارة عن عنصر div له الصنف التنسيقي ‎.card. بالنسبة لمحتويات الحاوية فلدينا العديد من الإمكانيات. يمكن بشكل أساسي، أن تحتوي البطاقة على نص عادي فحسب. أمّا بالنسبة للشكل النموذجي، فيمكن أن يكون لها التنسيق التالي: صورة توضيحية في الأعلى. جسم البطاقة، والذي يحتوي على عنوان البطاقة ونص توضيحي. انظر إلى البطاقة النموذجية التالية: <div class="card" style="width: 18rem;"> <img src="..." class="card-img-top" alt="image-description"> <div class="card-body"> <h5 class="card-title">عنوان البطاقة</h5> <p class="card-text">نص بسيط لوصف المنتج أو أي شيء تود الحديث عنه</p> <a href="#" class="btn btn-primary">زر عادي</a> </div> </div> سيشكل العنصر div مع الصنف ‎ .card الحاوية الخاصة بالبطاقة ككل. داخل هذا الحاوية، لاحظ وجود عنصر الصورة img مع الصنف ‎ .card-img-top، ستلاحظ أيضًا وجود عنصر div آخر يمثّل جسم البطاقة له الصنف ‎ .card-body. يتكوّن جسم البطاقة في مثالنا هذا من قسمين: القسم الأول هو عنوان البطاقة باستخدام الصنف ‎.card-title القسم الثاني هو نص البطاقة باستخدام الصنف ‎.card-text . يمكن بشكل اختياري إضافة زر لهذا القسم كما فعلنا في مثالنا هذا. عند معاينة الشيفرة السابقة ستحصل على شكل شبيه بما يلي: كما أسلفت قبل قليل توجد الكثير من الإمكانيات التي توفرها البطاقة. يمكن مثلًا إضافة عنوان فرعي باستخدام الصنف ‎.card-subtitle ويُوضع هذا العنوان الفرعي كما هو واضح أسفل العنوان الرئيسي في حال الرغبة. كما يمكن وضع روابط ضمن جسم البطاقة، بتنسيق متوافق معها باستخدام عنصر a مع الصنف ‎.card-link يمكن أيضًا جعل البطاقة تعرض قائمة من مجموعة من العناصر . انظر إلى التعديل التالي الذي أجريته على الشيفرة السابقة: <div class="card" style="width: 18rem;"> <img src="images/tmp.png" class="card-img-top" alt="image-description"> <div class="card-body"> <h5 class="card-title">عنوان البطاقة</h5> <p class="card-text">نص بسيط لوصف المنتج أو أي شيء تود الحديث عنه</p> <a href="#" class="btn btn-primary">زر عادي</a> </div> <!--بداية التعديل --> <ul class="list-group list-group-flush"> <li class="list-group-item">عنصر 1</li> <li class="list-group-item">عنصر 2</li> <li class="list-group-item">عنصر 3</li> </ul> <!--نهاية التعديل --> </div> لاحظ الشيفرة الجديدة من المثال الأخير. وضعت عنصر قائمة غير مرتبة ul مع الصنف ‎.list-group و الصنف ‎.list-group-flush. الصنف الأخير وظيفته جمالية فقط، حاول إزالته وانظر الفرق. عند معاينة الشيفرة السابقة ستحصل على شكل شبيه بما يلي: يمكن أيضًا الاستغناء عن الصورة التوضيحية في الأعلى واستخدام ترويسة بدلًا منها. كما ويمكن أيضًا وضع تذييل للبطاقة. انظر إلى الشيفرة التالية: <div class="card" style="width: 18rem;"> <div class="card-header">ترويسة مناسبة</div> <div class="card-body"> <p class="card-text">نص بسيط لوصف المنتج أو أي شيء تود الحديث عنه</p> <a href="#" class="btn btn-primary">زر عادي</a> </div> <div class="card-footer text-muted">تذييل مناسب</div> </div> لاحظ اولًا أن كلًا من الترويسة والتذييل موجودان خارج جسم البطاقة ضمن عنصر يdiv منفصلين. لعنصر div الذي يحوي الترويسة الصنف ‎.card-header أما لعنصر div الذي يحوي التذييل الصنف ‎.card-footer. لاحظ أيضًا كيف استخدمت الصنف ‎.text-muted لجعل نص التذييل باهتًا بعض الشيء. يمكنك بالطبع إزالة هذا التنسيق إن أحببت. ستحصل على الشكل التالي عند معاينة الشيفرة السابقة: يمكنك الإطلاع على المزيد من الخيارات المتاحة بزيارة صفحة التوثيق الرسمية لمكوّن البطاقة Card. التعرّف على مكون الشرائح الدوارة Carousel في بوتستراب هو من المكوّنات المفيدة ضمن صفحات الويب. فمن خلاله يمكن عرض شرائح للمستخدمين ذات محتوى متنوّع وقابل للدوران بشكل تلقائي، أو بالنقر على أزرار تنقّل أو بمزيج بينهما. يمكن أن يكون هذا المحتوى عبارة عن صورة مع نص وصفي، أو يمكن حتى أن يكون محتوى مخصّص للغاية كما سنفعل في مشروعنا "نبيه". ولا يمكن في بوتستراب أن تكون مكوّنات Carousel متداخلة nested فيما بينها. يمكن استخدام هذا المكوّن من خلال عنصر div مع التنسيقين ‎.carousel و ‎.slide. يحتوي كل مكّون Carousel على عنصر div آخر له التنسيق ‎.carousel-inner يحتوي بدوره على الشرائح الفعلية التي ستظهر للمستخدم. كل شريحة من هذه الشرائح عبارة عن عنصر div له التنسيق ‎.carousel-item. يجب أن يكون لإحدى هذه الشرائح تنسيق آخر هو ‎.active للدلالة إلى الشريحة الحالية (الفعّالة) التي سُتعرض أولًا للمستخدم. انظر إلى مكوّن Carousel نموذجي ضمن الشيفرة التالية: <div id="carouselComponent" class="carousel slide" data-bs-ride="carousel"> <div class="carousel-inner"> <div class="carousel-item active"> <img src="..." class="d-block w-100" alt="..."> </div> <div class="carousel-item"> <img src="..." class="d-block w-100" alt="..."> </div> <div class="carousel-item"> <img src="..." class="d-block w-100" alt="..."> </div> </div> </div> ستظهر الشريحة التي تحمل التنسيق active أولًا أمام المستخدم. ثم ستدور الشرائح بالتناوب أمام المستخدم بشكل تلقائي ضمن فترات زمنية محّددة. يمكنك وضع صور مناسبة ضمن السمة src لكل صورة لكي ترى النتيجة بشكل فعلي. يمكن وكخيار إضافي، استخدام التنسيق ‎.carousel-dark (يُوضع بجوار التنسيقين ‎.carousel و ‎.slide لعنصر div الذي يمثّل الحاوية الرئيسية لمكوّن Carousel)، وذلك لإكساب مكوّن carousel تنسيقًا داكنًا بعض الشيء. كما وسبق أن رأينا في عنصر البطاقة ، يحتوي عنصر Carousel على تشكيلة متنوّعة من الخيارات في العرض. يمكن مثلًا إضافة أزرار انتقال تسمح للمستخدم بالتنقّل اليدوي عوضًا عن التنقّل التلقائي. أضف إلى الشيفرة السابقة، الشيفرة التالية (ضعها قبل آخر وسم إغلاق <‎/div>): <button class="carousel-control-prev" type="button" data-bs-target="#carouselComponent" data-bs-slide="prev"> <span class="carousel-control-prev-icon" aria-hidden="true"></span> <span class="visually-hidden">Previous</span> </button> <button class="carousel-control-next" type="button" data-bs-target="#carouselComponent" data-bs-slide="next"> <span class="carousel-control-next-icon" aria-hidden="true"></span> <span class="visually-hidden">Next</span> </button> يمكن أيضًا وضع مؤشّر يظهر أسفل مكوّن Carousel للدلالة على عدد الشرائح الموجودة بالإضافة إلى موقعك الحالي ضمن هذه الشرائح. يمكن وضع هذا المؤشّر من خلال عنصر div له التنسيق ‎.carousel-indicators. انظر إلى الشيفرة التالية (ضعها قبل عنصر div ذي التنسيق ‎.carousel-inner مباشرةً): <div class="carousel-indicators"> <button type="button" data-bs-target="#carouselComponent" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button> <button type="button" data-bs-target="#carouselComponent" data-bs-slide-to="1" aria-label="Slide 2"></button> <button type="button" data-bs-target="#carouselComponent" data-bs-slide-to="2" aria-label="Slide 3"></button> </div> يمكنك الإطلاع على المزيد من الخيارات المتاحة بزيارة صفحة التوثيق الرسمية لمكوّن Carousel. إنجاز قسم الدورات الأكثر مبيعًا سنطبّق ما تعلّمناه في الفقرتين السابقتين في إنجاز قسم الدورات الأكثر مبيعًا Best Selling ضمن موقع نبيه. أدرج الشيفرة التالية ضمن القسم best-selling في الملف index.html: <div class="section-title">الدورات الأكثر مبيعًا</div> <div id="bestSellingCourses" class="carousel carousel-dark slide" data-bs-ride="carousel"> <div class="carousel-inner"> <div class="carousel-item active"> <!-- الموضع 1--> <div class="row"> <div class="col-lg-3"> <div class="card"> <!-- الموضع 2--> <img src="images/python-product.jpg" class="card-img-top product-image" alt="python-course"> <div class="card-body"> <h5 class="product-title card-title">دورة أساسيات البرمجة باستخدام بايثون</h5> <p class="product-text card-text">في هذه الدورة سنتعلّم مبادئ البرمجة في لغة بايثون</p> <a href="#" class="btn btn-primary">أضف إلى السلة</a> </div> </div> </div> <div class="col-lg-3"> <div class="card"> <!-- الموضع 3--> <img src="images/github-product.jpg" class="card-img-top product-image" alt="github-course"> <div class="card-body"> <h5 class="product-title card-title">دورة التعامل مع GitHub</h5> <p class="product-text card-text">تعلّم كيف تدير مشاريعك البرمجية من حيث إدارة الإصدار والمساهة في مشاريع برمجية أخرى.</p> <a href="#" class="btn btn-primary">أضف إلى السلة</a> </div> </div> </div> <div class="col-lg-3"> <div class="card"> <!-- الموضع 4--> <img src="images/python-django-product.jpg" class="card-img-top product-image" alt="django-course"> <div class="card-body"> <h5 class="product-title card-title">دورة تطوير تطبيقات ويب باستخدام بايثون مع Django</h5> <p class="product-text card-text">تعلّم كيف تبني تطبيقات ويب باستخدام لغة بايثون مع Django </p> <a href="#" class="btn btn-primary">أضف إلى السلة</a> </div> </div> </div> <div class="col-lg-3"> <div class="card"> <!-- الموضع 5--> <img src="images/javascript-product.jpg" class="card-img-top product-image" alt="javascript-course"> <div class="card-body"> <h5 class="product-title card-title">دورة أساسيات البرمجة باستخدام جافاسكريبت</h5> <p class="product-text card-text"> سنتعلّم في هذه الدورة كيفية تطوير تطبيقات الواجهة الأمامية باستخدام جافاسكريبت</p> <a href="#" class="btn btn-primary">أضف إلى السلة</a> </div> </div> </div> </div> </div> <div class="carousel-item"> <div class="row"> <div class="col-lg-3"> <div class="card"> <!-- الموضع 6--> <img src="images/php-product.jpg" class="card-img-top product-image" alt="php-course"> <div class="card-body"> <h5 class="product-title card-title">دورة أساسيات البرمجة باستخدام PHP</h5> <p class="product-text card-text">في هذه الدورة سنتعلّم مبادئ البرمجة في لغة PHP</p> <a href="#" class="btn btn-primary">أضف إلى السلة</a> </div> </div> </div> <div class="col-lg-3"> <div class="card"> <!-- الموضع 7--> <img src="images/arduino-product.jpg" class="card-img-top product-image" alt="arduino-course"> <div class="card-body"> <h5 class="product-title card-title">دورة التعامل مع أساسيات Arduino</h5> <p class="product-text card-text">تعلّم كيف تبني أنظمة مضمنة تتضمّن مشاريع بسيطة باستخدام Arduino</p> <a href="#" class="btn btn-primary">أضف إلى السلة</a> </div> </div> </div> </div> </div> </div> <!-- الموضع 8--> <button class="carousel-control-prev" type="button" data-bs-target="#bestSellingCourses" data-bs-slide="prev"> <span class="carousel-control-prev-icon" aria-hidden="true"></span> </button> <button class="carousel-control-next" type="button" data-bs-target="#bestSellingCourses" data-bs-slide="next"> <span class="carousel-control-next-icon" aria-hidden="true"></span> </button> </div> انتقل الآن الى الملف styles.css وأضف إليه التنسيق التالي قبل تنسيقات قسم الترويسة Header Section: .section-title{ text-align: center; font-size: xx-large; padding: 3rem 0; } الهدف من ذلك هو فقط تنظيم الملف styles.css. ثم بعد ذلك أضف التنسيقات التالية إلى آخر محتويات الملف: /*Best Selling Section*/ .carousel-inner{ padding: 0 5%; } .carousel-control-prev { background: linear-gradient(to right, rgba(200,200,200,0), rgba(200,200,200,1)); } .carousel-control-next { background: linear-gradient(to left, rgba(200,200,200,0), rgba(200,200,200,1)); } .product-image{ height: 12rem; } .product-title{ height: 4rem; } .product-text{ height: 6rem; } بالنسبة لشيفرة HTML، نبدأ قسم المنتجات الأكثر مبيعًا بنص توضيحي يُشير إلى بداية هذا القسم له التنسيق ‎.section-title ثم يبدأ بعد ذلك مكوّن Carousel بتنسيق داكن ‎.carousel-dark وبمعرّف bestSellingCourses. يبدأ بعد ذلك مباشرةً الجسم الداخلي له ‎.carousel-inner. في الواقع سيكون مكوّن Carousel هنا بسيطًا للغاية. سيحتوي هذا المكوّن على عنصري ‎.carousel-item وبعبارة أخرى سيحتوي على شريحتين. ستحمل الشريحة الأول الصنف ‎.active كما هو واضح (الموضع 1). يوجد ضمن الشريحة الأولى أربعة منتجات وُضعت ضمن سطر ‎.row ووُزّعت على أربعة أعمدة ‎.col-lg-3. وُضِع كل منتج ضمن بطاقة card منفصلة (انظر إلى المواضع 2 و 3 و 4 و 5). أمّا الشريحة الثانية فتحتوي على منتجين فقط (انظر إلى الموضعين 6 و 7). بالنسبة إلى زري التنقّل لمكوّن الشرائح الدوّارة فيمكنك أن تجدهما اعتبارًا من الموضع 8. لاحظ أنني قد أجريت بعض التعديل على الصنفين ‎ .carousel-control-prev و ‎ .carousel-control-next ضمن الملف styles.css حيث أنّني قد أضفت تدرّجًا لونيًا لهذين الزرّين كي يسهل للمستخدم تمييزهما فورًا. بمعاينة الشيفرة السابقة ضمن المتصفّح ستحصل على شكل شبيه بما يلي: إنجاز القسم الخاص بأصناف الدورات لنبدأ الآن بتجهيز القسم الخاص بأصناف الدورات، والذي سيتكوّن في مشروعنا هذا من ستة أقسام وهي: البرمجة. التسويق. العمل الحر. التطبيقات السحابية. الشهادات العالمية. البرامج والتطبيقات. سنستخدم من أجل كل قسم مكوّن البطاقة من بوتستراب، وسنوزّع هذه البطاقات على سطرين مستقلين كما في الشكل التالي: أضف الآن شيفرة HTML التالية إلى القسم course-categories: <div class="section-title">الأقسام المتاحة</div> <div class="row"> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/programming-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">البرمجة</p> </div> </div> </a> </div> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/marketing-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">التسويق</p> </div> </div> </a> </div> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/freelance-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">العمل الحر</p> </div> </div> </a> </div> </div> <div class="row"> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/cloud-computing-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">التطبيقات السحابية</p> </div> </div> </a> </div> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/certificates-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">الشهادات العالمية</p> </div> </div> </a> </div> <div class="col-lg-4"> <a class="category-link" href="#"> <div class="card category-card"> <img src="images/apps-category.png" class="card-img-top category-image" alt="certifications-category"> <div class="card-body"> <p class="card-text category-text">البرامج والتطبيقات</p> </div> </div> </a> </div> </div> تتألف كل بطاقة من صورة توضيحية، بالإضافة إلى نص وصفي تحت الصورة. ستحتاج أيضًا إلى إضافة التنسيقات التالية إلى الملف styles.css أسفل التنسيقات السابقة: #course-categories{ background-color: #eee; padding: 0 10% 8px; } #course-categories .row{ margin-bottom: 72px; } .course-categories-title{ text-align: center; font-size: xx-large; padding: 3rem 0; } .category-card{ margin-left: 24px; margin-right:24px; padding: 48px 0px 32px; } .category-image{ width: 50%; height: auto; margin: 0 auto; } .category-text{ text-align: center; font-size: 1.3rem; } .category-link{ text-decoration: none; color:inherit; } أعتقد أنّه لا جديد في التنسيقات السابقة أو حتى في شيفرة HTML الخاصّة في هذا القسم. أيقونات Bootstrap 5 يأتي مع بوتستراب 5 مجموعة غنية من الأيقونات الجميلة والمتنوّعة التي يمكنك استخدامها في التطبيقات التي تُنشئها سواءً باستخدام بوتستراب 5 أو حتى بغيره. لأيقونات بوتستراب 5 نوعان: أيقونات على شكل خطوط ويب Web Fonts. أيقونات بتنسيق SVG. سنستخدم هنا النوع الأوّل: أيقونات Web Fonts. تكون هذه الأيقونات منفصلة عن بوتستراب، وقبل استخدامها، ينبغي إضافة مرجع إلى الصفحة الرئيسية الخاصة بنا. أضف الشيفرة التالية إلى قسم head ضمن الملف index.html: <!-- Boostrap 5 icons - web font --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.0/font/bootstrap-icons.css"> يمكن استخدام هذه الأيقونات بشكل مستقل كما سنفعل في الفقرة التالية. كما يمكن استخدامها مع الأزرار العادية وغيرها من العناصر. إنجاز قسم التذييل Footer وصلنا إلى الجزء الأخير في موقع "نبيه" وهو قسم التذييل. سيكون هذا القسم بسيطًا وجميلًا إذ أنّنا سنضيف إليه الأيقونات المعبّرة عن قنوات التواصل الإجتماعي بالإضافة إلى أيقونة إرسال رسالة بريد إلكتروني، ولن تكون هذه الأيقونات تُشير إلى صفحات حقيقية بطبيعة الحال. كما سندرج تحت الأيقونات السابقة، نصًا بسيطًا يُشير إلى موقع نبيه كعلامة مسجلة. أضف الشيفرة البرمجية التالية ضمن القسم footer ضمن الملف index.html: <footer> <div class="container-fluid"> <i class="bi bi-facebook social-icon"></i> <i class="bi bi-twitter social-icon"></i> <i class="bi bi-instagram social-icon"></i> <i class="bi bi-envelope social-icon"></i> <p>© دورات نبيه 2021</p> </div> </footer> التنسيقات مثل bi bi-facebook وغيرها ضرورية لاستخدام الأيقونة المطلوبة مع عنصر i ما. أضف أيضًا التنسيقات التالية إلى الملف styles.css: footer{ height: 200px; } .social-icon { margin: 20px 10px; } #footer .container-fluid{ padding: 7% 15%; text-align: center; } عند المعاينة، ستحصل على شكل شبيه بما يلي: أعتقد أنّ التنسيقات السابقة واضحة ومباشرة ولا تحتاج إلى أي تعليق إضافي. وبذلك نكون قد وصلنا إلى نهاية هذا الدرس، وبالتالي إلى نهاية تصميم الصفحة الرئيسية لموقع "نبيه". يمكنك الوصول إلى الشيفرة كاملة عن طريق زيارة هذا المستودع، ضمن المجلّد chapter05 أو من الملف المرفق في نهاية المقال، وكما ويمكنك الإطلاع على نسخة حيّة من هذه الصفحة من github.io. خاتمة تعرّفنا في هذا الدرس على مكوّنين مهمّين وهما البطاقة Card والشرائح الدوّارة Carousel، وتعرّفنا على أهم الخصائص المتاحة لهما. كما تعرّفنا على مكتبة أيقونات Font Awesome التي تضم تشكيلة رائعة من الأيقونات المميزة، والتي يمكنك استخدامها بشكل مجاني في تطبيقاتك المختلفة. كما عملنا على تطبيق ما تعلّمناه في تصميم وإنجاز باقي أقسام الصفحة الرئيسية لموقع نبيه (قسم الدورات الأكثر مبيعًا والقسم الخاص بأصناف الدورات و قسم التذييل). bootstrap5-tutorial-master.zip اقرأ أيضًا المقال السابق: تطبيق مخطط الصفحة في بوتستراب على صفحات الويب بناء قائمة شجرية باستخدام البوتستراب 10 أخطاء شائعة عند استخدام إطار العمل Bootstrap
  4. سنتعلّم كيفية تطبيق مخطّط الصفحة في بوتستراب على صفحات الويب من خلال تحديث موقع "نبيه" بآخر ما تعلّمناه في الفصول الثلاثة السابقة، فصل مدخل إلى إطار العمل بوتستراب 5 وفصل شريط التنقل في بوتستراب 5، وبالأخص الفصل الأخير "مخطط الصفحة في بوتستراب 5" من سلسلة bootstrap 5، فمن الضروري جدًا أن تكون قد اطلعت على الدروس السابقة قبل الإكمال في هذا الدرس لأنّه مرتبط بها بشكل وثيق. سنبدأ بتحديد الأقسام الأساسية في الصفحة الرئيسية، ومن ثمّ سنعمل على تنسيقها بحيث تكون الصفحة متجاوبة مع قياسات الشاشة المختلفة. سيكون هذا الموضوع موزعًا على هذا الدرس بالإضافة إلى الدروس اللاحقة. سنهتم في هذا الدرس بتعريف الأقسام الرئيسية، وتحضير أصول الموقع، بالإضافة إلى تصميم القسم الأول (الترويسة). بينما سنعمل في الدروس اللاحقة على إكمال تصميم وتنفيذ باقي أقسام الصفحة. سنعمل في هذا الدرس على: تعريف الأقسام الأساسية للصفحة الرئيسية في موقع "نبيه". تحضير أصول الموقع من خطوط وصور وألوان. تصميم قسم الترويسة. هذا الفصل جزء من سلسلة فصول عن بوتستراب 5، وإليك كامل فهرس السلسلة: مدخل إلى إطار العمل بوتستراب 5 شريط التنقل في بوتستراب 5 مخطط الصفحة في بوتستراب 5 تطبيق مخطط الصفحة في بوتستراب على صفحات الويب مكون البطاقة Card ومكون الشرائح الدوارة Carousel في بوتستراب تعريف الأقسام الأساسية للصفحة الرئيسية في موقع "نبيه" سنجعل للصفحة الرئيسية في موقع "نبيه" أربعة أقسام أساسية هي: الترويسة Header. قسم الدورات الأكثر مبيعًا Best Selling. القسم الخاص بأصناف الدورات Course Categories. قسم التذييل Footer. سأعمل على وضع كل قسم من الأقسام الأربعة السابقة ضمن عنصر <section> مع تسمية مناسبة، ليسهل فيما بعد استهداف كل قسم على حدة باستخدام CSS. بالعودة إلى الملف index.html ضمن مجلّد مشروع "نبيه" ضمن Visual Studio Code، سنعمل على إضافة الأقسام الأربعة الرئيسية. سيكون القالب الذي سننطلق منه على النحو التالي: <!doctype html> <html lang="ar" dir="rtl"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.rtl.min.css" integrity="sha384-gXt9imSW0VcJVHezoNQsP+TNrjYXoGcrqBZJpry9zJt8PCQjobwmhMGaDHTASo9N" crossorigin="anonymous"> <link href="/css/styles.css" rel="stylesheet" /> <title>دورات نبيه</title> </head> <body> <section id="header"> </section> <section id="best-selling"> </section> <section id="course-categories"> </section> <section id="footer"> </section> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html> استخدمنا نسخة بوتستراب الخاصة بدعم اللغة العربية، وغيّرنا اتجاه اللغة للصفحة كاملةً لتكون من اليمين إلى اليسار (انظر إلى السمتين dir و lang ضمن الوسم <html>) - عد إلى درس شريط التنقل في بوتستراب 5. لاحظ أيضًا كيف وضعنا أربعة عناصر <section> ضمن القسم <body> وذلك للتعبير عن الأقسام الأربعة الأساسية في الصفحة الرئيسية. سنبدأ في الفقرة التالية التحدث عن أصول الموقع. تحضير أصول الموقع من خطوط وصور وألوان تُعتبر أصول الموقع من خطوط وصور وألوان بمثابة الروح لجسد الموقع! فمن خلالها يتم إكساب الموقع تلك الجاذبية التي تحفّز الزوار على التفاعل مع صفحاته. في موقعنا "نبيه" سنعمل على بناء تصميم بسيط ولكنّه جذّاب باستخدام أقل الأصول الممكنة، لأنّ الهدف من وراء هذه السلسلة هو التركيز على الاستخدام العملي لبوتستراب 5. الخطوط بالنسبة للخطوط يمكنك زيارة موقع خطوط غوغل والبحث عن الخطين التاليين: Almarai و Tajawal. سأستخدم الخط Tajawal كخط أساسي لمحتوى الموقع، أمّا الخط Almarai فسأستخدمه فقط من أجل اسم الموقع الرئيسي (اسم العلامة التجارية في قسم العنوان). بعد البحث عن خط Tajawal ضمن موقع خطوط غوغل وإيجاد هذا الخط، انقر عليه لفتح الصفحة الرئيسية له. لاحظ توفر أنماط مختلفة لهذا الخط. اختر الأنماط: 200 و 300 و 400 و 500 و 700 و 800 و 900 (انظر الوصف الخاص بكل نمط في الطرف الأيسر) وذلك بالنقر على الزر Select this style الموجود في الطرف الأيمن. ستلاحظ أنّه بمجرّد اختيارك للنمط الأوّل سيبدأ الموقع بتجهيز الرابط اللازم لتضمين هذا الخط في موقعك، كما في الشكل التالي: عُد إلى الصفحة الرئيسية للموقع، وابحث الآن مرة أخرى عن الخط Almarai. اختر الأنماط 300 و 400 و 700 و 800 بنفس الطريقة السابقة. يمكنك في أي وقت استعراض الخطوط والأنماط التي اخترتها بالنقر على زر استعراض عائلات الخطوط المختارة الموجود كأيقونة في الطرف الأيمن العلوي من الصفحة بجوار زر Download family. عند هذه النقطة انسخ الرابط الخاص بعائلات الخطوط التي اخترتها. ستحصل على رابط شبيه بما يلي: <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Almarai:wght@300;400;700;800&family=Tajawal:wght@200;300;400;500;700;800;900&display=swap" rel="stylesheet"> سنضع هذه الروابط ضمن القسم <head> من الصفحة، قبل وسم الإغلاق </head> مباشرة. الألوان والصور تتيح لنا العديد من مواقع الإنترنت استخدام تشكيلة منسجمة من الألوان لاستخدامها في تصميماتنا، وذلك لتوفير الوقت والجهد على المطوّر أو المصمّم في الموائمة بين الألوان واختيار المتجانس منها في تصميماته. بالنسبة لي، استخدمت هذا الموقع لاختيار تشكيلة ألوان موقع "نبيه". حيث عملت على استخدام ألوان بسيطة للغاية ضمنه وهي على الشكل التالي: ‎ #‎eee‎ و ‎#fff و ‎#393e46 و ‎#233e8b. من الأفضل دومًا اختيار أربعة ألوان على الأكثر. انظر إلى موقع ColorHunt. أمّا بالنسبة للصور، فهناك العديد من المواقع الأخرى التي توفّر صور جيدة سواءً كانت مجانية أو بمقابل مادي لاستخدامها في تصميماتك المختلفة. في حالتنا هذه، استخدمنا صور مجّانيّة بالطبع. يمكنك الحصول على مثل هذه الصور من موقع unsplash مثلًا. على أية حال يمكنك الحصول على تشكيلة الصور التي اخترتها من ملف الصور المرفق في نهاية المقال. اعمل على تنزيل الملف، ثم فك ضغطه، وبعد ذلك انقل الصور الموجودة ضمن المجلّد الناتج إلى المجلّد images الذي أنشأناه مسبقًا ضمن مجلّد مشروع "نبيه". تصميم قسم الترويسة سيحتوي قسم الترويسة بحد ذاته على شريط للتنقل بالإضافة إلى مساحة خاصة سنسميها Main View لإبراز الهدف من الموقع كما في الشكل التالي: تصميم شريط التنقل انتقل إلى الملف index.html، ثم أضف ضمن قسم الترويسة header ضمن جسم المستند <body> الشيفرة التالية: <section id="header"> <!-- Nav Bar --> <nav class="navbar navbar-expand-lg navbar-light"> <!-- الموضع 1 --> <div class="container-fluid"> <a class="navbar-brand" href="#"> <img src="/images/nabih-logo.png" style="margin-left: 8px;" alt="" height="32"> نبيه </a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <!-- الموضع 2 --> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <!-- الموضع 3 --> <ul class="navbar-nav me-2 mb-2 mb-lg-0 ms-3"> <li class="nav-item"><a class="nav-link" href="#">التصنيفات</a></li> </ul> <form class="d-flex me-auto w-100"> <!-- الموضع 4 --> <input class="form-control" type="search" placeholder="ابحث عن أي موضوع"> <img class="nav-link" src="images/icons8-shopping-cart-32.png" /> <button type="button" class="btn btn-dark nabih-buttons">دخول</button> <button type="button" class="btn btn-outline-dark nabih-buttons">تسجيل جديد</button> </form> </div> </div> </nav> </section> أود التحدث عن بعض النقاط الواردة في الشيفرة السابقة: أولًا، استخدمت في "الموضع 1" الصنف ‎.navbar-expand-lg مع العنصر nav، إذ يسمح هذا الصنف بنشر عناصر شريط التنقّل، أو لنقل يجعلها مرئية عندما يكون عرض الشاشة كبيرًا أو فوق الكبير. أمَا في حال كان الأمر خلاف ذلك، فستُطوى "تختفي" عناصر شريط التنقل ويظهر مكانها زر قابل للنقر. انظر الشكل التالي: يسمح ذلك بإنشاء صفحات ويب متجاوبة مع الأجهزة ذات الشاشات الصغيرة. إذا نقرت الزر الذي يظهر في يسار الشكل السابق، ستظهر العناصر الخاصة بشريط التنقل. ثانيًا، يمكن إنجاز هذه الميزة بوضع زر <button> "الموضع 2" ومنحه الصنف ‎.navbar-toggler. سيحتاج هذا الزر أيضًا إلى أن نمنحه السمة data-bs-target والتي تحدّد معرّف العنصر المراد طيّه. وضعت القيمة ‎#navbarSupportedContent لهذه السمة. وهي معرّف العنصر <div> الموجود في ثالثًا، "الموضع 3" والذي يحتوي بطبيعة الحال على العناصر المراد طيها في حال كان عرض الشاشة أقل من الحجم "كبير" في مثالنا هذا، فستجد في "الموضع 3" عنصر <div> الذي تحدثنا عنه توًا. لاحظ كيف أسندنا له الصنفان collapse navbar-collapse لمنحه قابلية الطي (أو الاختفاء إن صح التعبير في حال كان عرض الشاشة أقل من كبير). على أية حال، عند نقر الزر الصغير، سيظهر هذا العنصر بمحتوياته (عناصر شريط التنقل) مرّة أخرى. رابعًا، يوجد في "الموضع 4" عنصر <form>، وضعت ضمنه مربع البحث بالإضافة إلى سلة التسوّق وزرين لتسجيل الدخول ولتسجيل جديد. في الحقيقة يحتوي هذا العنصر على معظم عناصر شريط التنقّل، وسنتحدث عن المزيد حول عناصر الإدخال من المستخدم لاحقًا في درس قادم. انتقل الآن إلى الملف styles.css الذي أنشأناه في الدرس الثاني، وضع فيه التنسيقات التالية: body{ font-family: 'Tajawal', sans-serif; font-size: 1em; } .nabih-buttons{ margin: 0 4px; padding: 6px 8px; width: 7rem; white-space: nowrap; } .container-fluid{ padding:0 5%; } /*Header Section*/ #header{ background-color: #eee; } .navbar-brand{ font-family: 'Almarai'; color:#393e46; font-size: 2.5rem; font-weight:900; margin: 0; } التنسيقات الثلاثة الأولى هي تنسيقات عامة يمكن استخدامها في كامل الصفحة. التنسيق الأول body مسؤول عن ضبط نوع الخط لكامل الصفحة إستنادًا للخط الذي حصلنا عليه من موقع خطوط غوغل كما مرّ معنا قبل قليل. التنسيق الثاني ‎.nabih-buttons فمسؤول عن ضبط الشكل العام لأي زر سنستخدمه ضمن الصفحة. أمّا التنسيق الثالث ‎.container-fluid فهو تنسيق محجوز لبوتستراب، لكننا سنجري تعديلا بسيطا على الحشوة padding الخاصة به لكي تمنحه مساحة من اليمين ومن اليسار بمقدار 5% كما هو واضح. بالنسبة لما يخص قسم الترويسة Header Section، فقد وضعت حاليًا تنسيقين متعلّقان بشريط التنقل، على الشكل التالي: استهدفت القسم header بتنسيق بسيط، حيث عملت على تغيير لون الخلفية له. التنسيق ‎.navbar-brand هو أيضًا تنسيق محجوز لبوتستراب، ولكن أردت هنا إضافة بعض التعديلات عليه لكي يتناسب مع احتياجاتنا، وخصوصًا فيما يتعلّق بنوع خط العلامة التجارية والذي حصلنا عليه أيضًا من موقع خطوط غوغل. نكون بذلك قد انتهينا من تهيئة شريط التنقّل، ولكننا مازلنا ضمن قسم الترويسة. سننتقل الآن إلى تهيئة قسم العرض الرئيسي Main View في الموقع. تصميم قسم العرض الرئيسي Main View أضف الشيفرة التالية ضمن الملف index.html مباشرةً بعد الشيفرة الخاصة بشريط التنقّل، وقبل وسم الإغلاق <‎ /section> : <!--Main View--> <div class="mainview"> <div class="row"> <div class="col-lg-6"> <h1 class="mainview-heading">دورات غنية بجودة عالية</h1> <h3 class="mainview-subheading"> طور نفسك لتنافس في سوق العمل</h3> </div> <div class="col-lg-6"> <img class="mainview-image" src="/images/show-case.jpg" /> </div> </div> </div> قسم العرض الرئيسي بسيط وواضح. استخدمت هنا مخطط الشبكة، وذلك بإضافة سطر عن طريق وضع الصنف التنسيقي row ضمن عنصر <div> كما هو واضح. ثم عملت على تقسيم هذا السطر إلى قسمين متساويين (لاحظ التنسيقين ‎.col-lg-6 ). وضعت في القسم الأول نصّين وصفيين، أمّا في القسم الثاني فقد وضعت صورة تعبيرية. لكي يظهر قسم العرض الرئيسي بشكل صحيح، أضف التنسيقات التالية إلى آخر محتويات الملف styles.css: .mainview-heading { color: white; font-size: 4em; text-align: right; } .mainview-subheading{ color: white; margin: 64px 0; text-align: right; } .mainview{ background-color: #233e8b; padding: 3% 5%; } .mainview-image{ border-radius: 2%; width: 500px; float: left; } أعتقد أنّ هذه التنسيقات بسيطة وواضحة: نعمل في البداية على تنسيق النصوص التي ستظهر في الجانب الأيمن (الصنفان ‎.mainview-heading و ‎.mainview-subheading)، ستعمل التنسيقات على تحديد لون الخط وحجمه ومحاذاة النص نحو اليمين. نعمل أيضًا على تنسيق عنصر الصورة الذي سيظهر في الجانب الأيسر، حيث نحدّد عرض الصورة ونكسب حوافها الأربعة انحناءً جميلًا، كما نجعلها أيضًا تظهر (تطوف) في أقصى اليسار (float: left). ننسّق أيضًا قسم العرض الرئيسي بكامله (الصنف ‎.mainview) بإكسابه لون خلفية محدّد وإضافة بعض الحشوة المناسبة إلى أطرافه الأربعة. بعد حفظ الملفين index.html و styles.css يمكنك معاينة الصفحة الآن. ستحصل على شكل شبيه بما يلي: نكون الآن قد انتهينا من قسم الترويسة. سنكمل باقي الأقسام الخاصة بالصفحة في الدروس التالية. خاتمة أنجزنا في هذا الدرس الكثير من العمل! حيث خططنا الصفحة الرئيسية وقسمناها إلى أربعة أقسام رئيسية أنجزنا منها القسم الأول (قسم الترويسة). سنتابع عملنا في الدروس التالية في التعرّف على مكوّنات جديدة في بوتستراب 5، بالإضافة إلى إكمال ما تبقى من أقسام رئيسية ضمن موقع "نبيه". ملف ch04-images-resource اقرأ أيضًا المقال التالي: مكون البطاقة Card ومكون الشرائح الدوارة Carousel في بوتستراب بناء قائمة شجرية باستخدام البوتستراب 10 أخطاء شائعة عند استخدام إطار العمل Bootstrap
  5. أنت تريد أن تحصل على بيانات من قاعدة بيانات، ثم تريد أن تمر على هذه البيانات بواسطة حلقة تكرارية for. الحقيقة هذا الموضوع منفصل وغير مغطى مع الأسف في هذه السلسلة. توجد عدة طرق للتواصل مع قاعدة بيانات في سي شارب، ويعتمد ذلك على الإصدار الذي تستخدمه من اللغة، بالإضافة إلى نوع قاعدة البيانات المراد القراءة منها. زودني بمثل هذه المعلومات كي أستطيع إعطائك مثال عن ذلك.
  6. أهلا شيخه. الحقيقة لم أفهم سؤالك بشكل جيد.
  7. مرحبًا بك في الدرس الثالث من سلسلة تعليم بوتستراب 5. سنتعرّف في هذا الدرس على مخطط الشبكة Grid Layout وهو المخطط المعتمد في بوتستراب. سنمر على النقاط التالية في هذا الدرس: الحاوية Container. مخطط الشبكة Grid. استخدام الأعمدة بطريقة متجاوبة. هذا الدرس مهم وأساسي في التعرّف على بوتستراب وكيف يعمل. الحاوية Container تُعَد الحاوية حجرة البناء الأساسية في بوتستراب، وهي عبارة عن عنصر div يحمل التنسيق container أو أخواته، وذلك لكي يكسب هذا العنصر بعض التنسيقات المسبقة والمفيدة مما يسمح باحتواء بقية العناصر ضمن الشاشة المطلوبة بيسر وسهولة. يُعتبر استخدام الحاوية ضروريًا مع مخطط الشبكة ضمن بوتستراب كما سنرى بعد قليل. يوجد ثلاثة أنواع من الحاويات في بوتستراب وهي: الحاوية العادية: عبارة عن عنصر div يحمل صنف التنسيق container. الحاوية الإنسيابية: وهي عنصر div يحمل الصنف التنسيقي container-fluid ويكون عرض هذه الحاوية هو العرض الكامل للشاشة أي ‎ 100% الحاويات ذات العرض المخصص: وهي عبارة عن خمس حاويات: container-sm و container-md و container-lg و container-xl و container-xxl ومعناها على الترتيب: الحاوية ذات العرض الصغير، وذات العرض المتوسط، وذات العرض الكبير، وذات العرض الأكبر، وذات العرض الكبير جدًا. الأمر المميز في حاويات العرض المخصّص هو أنّ الصفة المرتبطة معها (صفة العرض) لا تُفعّل إلّا إذا وصل عرض الحاوية إلى عرض أصغري يمكنك أن تدعوه عتبة الاستجابة Break Point. لكي نفهم الموضوع على أكمل وجه، أنشئ ملفًا جديدًا ضمن مجلّد العمل nabih سمّ الملف test-container.html وانسخ الكود التالي إليه مع ملاحظة أنّ التنسيقات التي تحتوي على background-color وضعتها فقط لتمييز الحاويات عن بعضها وليس لها أي دور آخر: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>اختبار الحاويات</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <div class="container" style="background-color: royalblue;">حاوية عادية</div> <div class="container-sm" style="background-color:sandybrown;">عرض مئة بالمئة حتى عتبة العرض الصغير</div> <div class="container-md" style="background-color: salmon;">عرض مئة بالمئة حتى عتبة العرض المتوسط</div> <div class="container-lg" style="background-color: lightpink;">عرض مئة بالمئة حتى عتبة العرض الكبير</div> <div class="container-xl" style="background-color: lightgreen;">عرض مئة بالمئة حتى عتبة العرض الأكبر</div> <div class="container-xxl" style="background-color: lightsteelblue;">عرض مئة بالمئة حتى عتبة العرض الكبير جدًا</div> <div class="container-fluid" style="background-color: lightpink;">حاوية انسيابية</div> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html> احفظ التغييرات ثم انقر بزر الفأرة الأيمن على هذا الملف، واختر تشغيله عن طريق الإضافة Live Server. ستظهر محتويات الملف ضمن المتصفح. جرّب الآن تصغير عرض نافذة المتصفّح إلى أصغر حد ممكن، ستلاحظ أنّ جميع الحاويات قد شغلت العرض الأعظمي الممكن ‎ 100%كما في الشكل التالي وذلك بسبب أنّ العرض الحالي هو صغير جدًا ولم يصل بعد إلى عتبة الإستجابة الأولى "صغير" : ابدأ الآن بالسحب وتوسيع عرض النافذة تدريجيًا. ستلاحظ أنّ الحاويتان العادية وذات العرض الصغير قد أخذتا منحًا مغايرًا عن باقي الحاويات الأخرى. كما في الشكل التالي: وسبب ذلك أنّ الحاوية العادية يكون عرضها دومًا مساويًا لقيمة الثابت max-width والذي تتغيّر قيمته وفقًا لاستعلامات Media Queries. أمّا الحاوية ذات العرض الصغير فقد بلغت عتبة الاستجابة الخاصة بها عندما بدأت بتوسيع عرض النافذة، وبالتالي سيصبح عرضها مساويًا أيضًا لقيمة الثابت max-width. إذا تابعت توسيع عرض النافذة بنفس الأسلوب، ستلاحظ أنّه عندما تبلغ كل عتبة ستنضم إحدى الحاويات إلى رفيقاتها السابقة في اكتساب العرض max-width حتى إذا ما وصل عرض النافذة لأقصى حد ممكن (على اعتبار أنّك تستخدم شاشة حاسوب عادية) ستحصل على شكل شبيه بما يلي: لاحظ أنّ الحاوية الإنسيابية container-fluid بقي عرضها ثابتًا بحيث يأخذ عرض الشاشة كاملًا ‎ 100%. يلخص الجدول التالي عتبات الإستجابة (قيم max-width) لكل من الحاويات السابقة: 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; } صغير جدا - أصغر من 576 بيكسل صغير - أكبر من أو يساوي 576 بيكسل متوسط - أكبر من أو يساوي 768 بيكسل كبير- أكبر من أو يساوي 992 بيكسل الأكبر - أكبر من أو يساوي 1200 بيكسل كبير جدًا - أكبر من أو يساوي 1400 بيكسل .container 100% 540px 720px 960px 1140px 1320px .container-sm 100% 540px 720px 960px 1140px 1320px .container-md 100% 100% 720px 960px 1140px 1320px .container-lg 100% 100% 100% 960px 1140px 1320px .container-xl 100% 100% 100% 100% 1140px 1320px .container-xxl 100% 100% 100% 100% 100% 1320px .container-fluid 100% 100% 100% 100% 100% 100% يمكنك الآن التخلص من الملف test-container.html من مجلّد المشروع إن أحببت. مخطط الشبكة Grid يمكنك أن تبني باستخدام مخطط الشبكة في بوتستراب واجهات بمختلف الأشكال والأحجام. يعتمد مخطط الشبكة على مفهوم صندوق التخطيط المرن Flex Box في بناء الواجهات، وهو يستخدم، كما سنرى بعد قليل، مزيج من الحاويات والأسطر والأعمدة لتحقيق هذا الهدف. يدعم مخطط الشبكة ست عتبات استجابة بنفس مبدأ عتبات الإستجابة التي مرّت معنا في فقرة الحاويات، وهي: sm و md و lg و xl و xxl، أمّا السادس فهو للقياس: "صغير جدًا" (أقل من 576 بيكسل) وفعليًا ليس له اختصار محدّد. يتكوّن مخطّط الشبكة من 12 عمود. تكون الأعمدة محدّدة ضمن أسطر وذلك للتحكم بعدد الأعمدة الموجودة بكل سطر على حدة. في أي سطر، يتوزّع العرض المُتاح بالتساوي على الأعمدة المتماثلة الموجودة ضمنه. انظر إلى المثال الأساسي التالي الذي يوضّح بنية بسيطة جدًا لاستخدام مخطط الشبكة: <div class="container"> <div class="row"> <div class="col" style="background-color: lightgreen;"> Row 1 - Col 1 </div> <div class="col" style="background-color: lightpink;"> Row 1 - Col 2 </div> </div> <div class="row"> <div class="col" style="background-color: lightsalmon;"> Row 1 - Col 1 </div> <div class="col" style="background-color: lightblue;"> Row 2 - Col 2 </div> <div class="col" style="background-color: lightseagreen;"> Row 3 - Col 3 </div> </div> </div> لاحظ في البداية وجود حاوية وهي ضرورية لكي يعمل مخطط الشبكة. بعد ذلك نبدأ بتعريف الأسطر باستخدام عنصر div مع الصنف التنسيقي row. في الكود السابق عرّفنا سطرين. يحتوي السطر الأوّل على عمودين. نعرّف أي عمود باستخدام العنصر div مع الصنف التنسيقي col (أو أخواته كما سنرى بعد قليل) أمّا السطر الثاني فيحتوي على ثلاثة أعمدة كما هو واضح. النصوص التي تراها في الكود السابق مثل: "Row 1 - Col 1" هي نصوص توضيحية، أيضًا هنا، جميع تنسيقات background-color هي فقط لتوضيح البنية الناتجة وليس لها أي دور في مخطّط الشبكة. لاختبار الكود السابق بسرعة يمكن تجريبه مباشرة على موقع مثل codeply.com. يمكنك فيه تجريب الكود بلا تسجيل مسبق. اختر Bootstrap 5 من القائمة الجانبية اليسرى ليظهر مختبر جاهز لتجريب الكود. احذف جميع الكود التلقائي الموجود مسبقًا في قسم HTML الموجود في الناحية اليسرى، وانسخ الكود السابق إليه ضمن هذه المنطقة. بعد ذلك ستلاحظ وجود أيقونة صغيرة أعلى الصفحة تحمل ما يشبه زر تشغيل، انقرها لترى النتائج في الأسفل. ستحصل على شكل شبيه بما يلي: يمكنك استخدام هذا الموقع دومًا في حال أردت تجريب ميزة جديدة بسرعة. كما أوضحنا توًا لدينا 12 عمود ضمن مخطّط الشبكة لكل منها العرض نفسه. ولكن في بعض الأحيان قد نحتاج إلى أن يكون أحد الأعمدة أعرض من باقي الأعمدة الأخرى، أو أن تحتاج أن يكون للأعمدة ضمن سطر ما عرض مختلف لكل منها. في الحقيقة يدعم مخطّط الشبكة هذا الأمر بصورة جميلة. لكي نفهم هذا الأمر تمامًا، تخيّل أنّ العرض المتاح ضمن الحاوية مقسّم إلى 12 حصّة متساوية فيما بينها. عندها يسمح بوتستراب بتخصيص أي عدد من هذه الحصص لأي عمود. لنفرض مثًلا أنّه يوجد لدينا ثلاثة أعمدة ضمن أحد الأسطر. يمكننا مثلًا تخصيص حصتين للعمود الأول وأربع حصص للعمود الثاني ونترك العمود الثالث في الحالة الافتراضية، أي بدون تعيين أي حصة له. أي كما في الكود التالي: <div class="container"> <div class="row"> <div class="col-2" style="background-color: lightgreen;"> Row 1 - Col 1 </div> <div class="col-4" style="background-color: lightpink;"> Row 1 - Col 2 </div> <div class="col" style="background-color: lightblue;"> Row 1 - Col 3 </div> </div> </div> لاحظ كيف عيّنت الحصص من خلال الأرقام الموجودة بجوار الصنف التنسيقي col، فالعمود الأول أصبح له الصنف التنسيقي col-2 أمّا العمود الثاني فأصبح له الصنف التنسيقي col-4 أمّا العمود الثالث فله الصنف التنسيقي col فقط بدون أي تخصيص للحصص. جرّب الكود السابق في codeply لتحصل على شكل شبيه بما يلي: لاحظ كيف أنّ عرض العمود الثاني هو ضعف العمود الأوّل وهذا أمر منطقي بالطبع، ولاحظ أيضًا أنّ العمود الثالث الذي لم نخصص له أي حصة قد شغل باقي الحصص المتاحة وهي في حالتنا هذه 6 حصص (تذكر حصة العمود الأول + حصة العمود الثاني = 6). إذًا، عندما لا نحدّد أي حصة للعمود فإنّه يشغل دومًا باقي الحصص المتاحة. ولو فرضنا وجود عمود رابع لم نحدد له أيضًا أي حصة (مثل العمود الثالث) فإنّه سيتقاسم باقي الحصص المتاحة الباقية مع العمود الثالث (سيأخذ كل واحد منها 3 حصص) وهكذا. ولا يهم بالطبع فيما إذا كان مثل هذين العمودين (أو أكثر) متجاورين أم متفرقين ضمن بقية الأعمدة الأخرى في حال وجودها. من الواضح بحسب السيناريو السابق أنّ عدد الأعمدة التي يمكننا إنشاؤها ضمن مخطّط الشبكة هي 12 عمود على الأكثر. وإذا نظرنا إلى هذا الأمر من زاوية أخرى، فيجب أن يكون مجموعة الحصص دومًا يساوي 12 حصة. استخدام الأعمدة بطريقة متجاوبة كما رأينا في الفقرة السابقة يمكننا إنشاء حتى 12 عمود ضمن مخطط الشبكة، ولكن المشكلة أنّ هذه الأعمدة ستسلك نفس السلوك عبر جميع الشاشات الممكنة. بمعنى آخر لا يمكننا بحسب المعلومات التي حصلنا عليها في الفقرة السابقة أن نغيّر مثلًا عرض أي عمود إذا تغيرت الشاشة الحالية من شاشة جوال إلى شاشة حاسوب كبيرة وهذا أمر مرغوب جدًا. ففي الحالة العامة يمكن لأي موقع أن يُعرض على شاشة حاسوب عادي، أو على شاشة جوال، ومن المفترض أن يتغير شكل الموقع بشكل يتناسب مع حجم الشاشة التي يُعرض ضمنها لكي يُعتبر هذا الموقع متجاوبًا. في الحقيقة يوجد حل أنيق يوفره لنا بوتستراب يتمثّل في إضافة بسيطة بجوار رقم الحصة التي ننوي تخصيصها للعمود وذلك على الشكل التالي: col-{sm|md|lg|xl|xxl}-n فمثًلا يمكننا أن نخبر أحد الأعمدة أننا نرغب بأن يأخذ 6 حصص في حال كانت الشاشة متوسطة العرض أو أكثر عندها نكتب col-md-6. في هذه الحالة سيأخذ العمود نصف العرض المتاح للشاشة إذا كان قياسها متوسط أو أعلى. أمّا إذا كان قياس الشاشة أقل من متوسط فإنّه سيأخذ العرض الكامل المتاح للشاشة (إذا كان العمود موجود لوحده ضمن السطر) لأننا لم نخبر العمود كيف يتصرف في حال كانت الشاشة أصغر من القياس المتوسط. يمكننا أيضًا الدمج بين أكثر من صنف تنسيقي لكي نُكسب العمود سلوكًا مختلفًا من أجل قياسات مختلفة للشاشة. انظر مثلًا إلى العمود التالي: <div class="col-6 col-md-4"></div> سيأخذ العمود السابق نصف العرض المتاح لأي شاشة يكون قياسها أقل من المتوسط بسبب وجود الصنف التنسيقي col-6. أمّا عندما يبلغ قياس الشاشة متوسط أو أكثر فعندها سيأخذ العمود أربع حصص فقط من عرض الشاشة بسبب وجود الصنف التنسيقي col-md-4. يمكن إضافة أي عدد من الأصناف التنسيقية التي تضبط عرض العمود من أجل كل قياس من القياسات الخمسة الرئيسية التي تعرفنا عليها في هذا الدرس. لنأخذ الآن مثال أكبر قليلًا يحتوي على عدة أسطر وأعمدة لكي نتأكّد من أنّنا قد استوعبنا الفكرة جيّدًا. انظر إلى الكود التالي: <div class="container"> <!-- الموضع 1 --> <div class="row"> <div class="col-md-8">.col-md-8</div> <div class="col-6 col-md-4">.col-6 .col-md-4</div> </div> <!-- الموضع 2--> <div class="row"> <div class="col-6 col-md-4">.col-6 .col-md-4</div> <div class="col-6 col-md-4">.col-6 .col-md-4</div> <div class="col-6 col-md-4">.col-6 .col-md-4</div> </div> <!-- ستأخذ الأعمدة في هذا السطر 50% من العرض الكلي المتاح بصرف النظر عن نوع الشاشة --> <div class="row"> <div class="col-6">.col-6</div> <div class="col-6">.col-6</div> </div> </div> انظر إلى الموضع 1 ضمن الكود السابق. في الشاشات الصغيرة ستتكدّس الأعمدة في هذا السطر فوق بعضها بحيث يحتل العمود الأول العرض الكلي والعمود الثاني نصف العرض الكلي. أمّا في الكود الذي يلي الموضع 2، فيشير إلى أنّه في الشاشات الصغيرة سيحتل كل عمود 50% من العرض الكلي. أمّا في الشاشات المتوسطة فأكبر، سيأخذ كل عمود ثلث العرض الكلي المتاح. بادر فورًا إلى تجربته ضمن Visual Studio Code (وليس ضمن codeply.com لكي تحصل على تجربة أدق). صغّر نافذة المتصفّح وكبّرها ولاحظ ماذا يحدث للأعمدة. يمكنك بالطبع إضافة تنسيقات لونية باستخدام background-color لكي تلاحظ التغييرات. ستحصل في حالة الشاشة الكبيرة على شكل شبيه بما يلي: يمكنك أيضًا استخدام أدوات المطوّر التي توفّر تجربة جيدة للمطورين في تجربة واختبار تطبيقات الويب الخاصة بهم. يمكنك قراءة المزيد حول هذا الموضوع من هنا. خاتمة نكون بهذا قد وصلنا إلى نهاية هذا الفصل المهم الذي سنبقى نستقي من المعلومات الواردة فيه حتى نهاية هذه السلسلة. سنعمل في الدرس التالي على تطبيق المفاهيم الواردة في هذا الدرس ضمن موقعنا الذي نبنيه تدريجيًا "نبيه"، وسنعمل في الدرس القادم على تحديث مشروعنا "نبيه" بالمعلومات الواردة في هذا الدرس بالإضافة إلى المعلومات التي سنحصل عليها في الدرس القادم. اقرأ أيضًا شريط التنقل في بوتستراب 5 مدخل إلى إطار العمل بوتستراب 5 10 أخطاء شائعة عند استخدام إطار العمل Bootstrap
  8. أهلًا بكم في الدرس الثاني من سلسلة تعليم بوتستراب 5، سنتعلم في هذا الدرس كيف ننشئ شريط تنقّل باستخدام بوتستراب من خلال موقع بسيط جدًا وظيفته توضيح هذه الفكرة، ومن ثمّ سنعمل على دعم اللغة العربية من خلال جعل جهة الموقع من اليمين إلى اليسار. سنركّز على النقاط التالية في هذا الدرس: تجهيز البنية التحتية للمشروع معاينة الموقع ضمن خادوم تجريبي لبُّ الموضوع: شريط التنقّل في بوتستراب تعديل الموقع ليدعم الاتجاه من اليمين إلى اليسار تجهيز البنية التحتية للمشروع لنعمل على تجهيز البنية التحتية لمشروعنا الخاص ببيع الدورات التعليمية "نبيه". أنشئ مجلّدًا جديدًا في المكان الذي ترغبه وسمّه nabih. انتقل بعد ذلك إلى Visual Studio Code واختر من القائمة File الأمر Open Folder ثم انتقل إلى المجلّد الذي أنشأته توًّا ثم اختر Select Folder لفتحه. أصبحت الآن جاهزًا للبدء بإضافة ملفات المشروع. ستلاحظ في الجهة اليسرى من نافذة Visual Studio ظهور المجلّد الذي اخترناه قبل قليل مع توفّر إمكانية إضافة ملفات أو مجلّدات أخرى إليه كما في الشكل التالي: أضف الملف index.html الذي سيمثّل ملف الواجهة الرئيسية في موقعنا. أضف أيضًا المجلدين التاليين: css الخاص بملفات التنسيق و images المجلّد الذي سنضع فيه الصور المستخدمة بالموقع (سنحتاج إليه في دروس لاحقة). أضف أيضًا الملف styles.css ضمن المجلّد css. سيكون هذا الملف في درسنا هذا فارغًا، ولكن سنعمل على استخدامه في دروس لاحقة. ستحصل في النهاية على شكل شبيه بالتالي: افتح الملف index.html بالنقر المزدوج عليه ثم انسخ الكود التالي إليه: <!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <title>السلام على الجميع!</title> </head> <body> <h1>Hello, world!</h1> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html> احفظ التغييرات الأخيرة. وبهذا يصبح الملف index.html جاهزًا للمعاينة. معاينة الموقع ضمن خادوم تجريبي إذا كنت تذكر في المقال الأول من هذه السلسلة، فقد أضفنا الإضافة Live Server إلى Visual Studio Code. سنستخدم هذه الإضافة الآن لمعاينة الصفحة index.html ضمن المتصفّح الإفتراضي. انقر بزر الفأرة الأيمن على الملف index.html ثم اختر الأمر Open with Live Server. سيؤدي ذلك إلى فتح نافذة أو لسان من المتصفّح الافتراضي على حاسوبك، وسترى الآن الصفحة index.html وقد ظهرت محتوياتها ضمن نافذة المتصفّح. ستحصل على شكل شبيه بما يلي: يعد هذا مؤشرًا على أنّ الأمور تجري على ما يرام. لاحظ العنوان الظاهر في شريط العنوان في نافذة المتصفّح من الشكل السابق: 127.0.0.1:5501 العنوان 127.0.0.1 هو عنوان IP للجهاز المحلّي. أمّا المنفذ 5501 فهو المنفذ الذي تُصغي فيه الإضافة Live Server للطلبات الواردة من المتصفح، يمكن بطبيعة الحال أن يختلف هذا الرقم على حاسوبك. شريط التنقل في بوتستراب تمتلك معظم المواقع على الإنترنت شريطًا رئيسيًا يتموضع عادةً في الجزء العلوي من الصفحة. يحتوي هذا الشريط على روابط تساعد في التنقّل السريع بين أجزاء الموقع. من الممكن أن تكون بعض هذه الروابط على شكل أزرار. يمكن أن يؤدي النقر على بعض هذه الأزرار إلى ظهور قائمة منسدلة مثلًا تحتوي على أوامر أخرى. كما ويمكن أن يحتوي هذا الشريط على مربع نص يسمح للمستخدمين بالبحث ضمن الموقع، وغيرها من المتطلّبات الأخرى. يدعم بوتستراب شريط القائمة هذا بصورة ممتازة. فعند ضبط بعض أصناف التنسيق القليلة ستحصل على شريط تنقّل عصري يلبّي احتياجاتك المتنوّعة. شريط تنقل بسيط لنبدأ بتشكيل شريط تنقّل بسيط. الكود التالي هو نسخة معدّلة عن الكود الموجود في صفحة التوثيق الخاصة الخاصة بشريط التنقّل في بوتستراب. انسخ الكود التالي إلى الملف index.html وضعه مكان العنصر <h1> الذي يحتوي على رسالة الترحيب التي رأيناها في الفقرة السابقة: <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container-fluid"> <a class="navbar-brand" href="#">نبيه</a> <ul class="navbar-nav me-auto"> <li class="nav-item"> <a class="nav-link active" aria-current="page" href="#">رابط فعال</a> </li> <li class="nav-item"> <a class="nav-link" href="#">عادي1</a> </li> <li class="nav-item"> <a class="nav-link" href="#">عادي2</a> </li> <li class="nav-item"> <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">غير فعال</a> </li> </ul> </div> </nav> غيّر أيضًا عنوان الصفحة (ضمن الوسم title) ليصبح "دورات نبيه". بعد حفظ التغييرات ستحصل على الشكل التالي في المتصفح (إذا لم تظهر التغييرات فورًا، يمكنك تحديث الصفحة ضمن المتصفّح): شرح الكود السابق سنتحدّث بشيء من الإسهاب عن الكود السابق كونه أساسي في بناء أشرطة التنقّل في بوتستراب. إذا نظرت إلى الكود السابق سترى أنّ العنصر الأساسي المستخدم هنا هو nav وهو عنصر HTML يُستخدم عادةً عندما نريد بناء شريط تنقل في صفحات الويب. يمكن أيضًا استخدام عنصر div عادي بدلًا من العنصر nav، ولكن عندها سنحتاج إلى بعض التعديلات الطفيفة. لذلك سنبقي على العنصر nav. لاحظ أيضًا أصناف التنسيق المستخدمة مع العنصر nav التي تأتي مع بوتستراب: navbar navbar-expand-lg navbar-light bg-light سنتحدّث هنا قليلًا عن هذه الأصناف الأربعة: الصنف navbar فهو يمنح العنصر nav هيئة شريط التنقّل مباشرةً. حيث يصبح متجاوبًا مع قياسات الشاشات المختلفة، ويقبل احتواء العناصر المفيدة الأخرى مثل العلامة التجارية branding الخاصة بالموقع، وروابط التنقّل، وإمكانية ضم الأزرار ضمن قائمة مطوية واحدة تفتح بزر collapsing للحد من عرض الشريط في حال الشاشات الصغيرة كما سنرى ذلك فيما بعد. يحتاج الصنف navbar كي يعمل بطريقة صحيحة إلى الصنف navbar-expand-lg وأخواته navbar-expand-{-sm|-md|-lg|-xl|-xxl} ‎. ووظيفة هذه الأصناف هي السماح بنشر محتويات شريط التنقّل بشكل أفقي. جرب أن تزيل هذا الصنف، لتجد أنّ محتويات شريط التنقّل قد أصبحت مكدّسة عموديًا. بالنسبة للصنف navbar-light فهو يتحكم بالنمط theme يوجد ثلاثة أنماط رئيسية في بوتستراب هي: النمط الفاتح navbar-light والنمط الغامق navbar-dark والنمط الرئيسي navbar-primary. تتحكم هذه الأصناف بلون الخط للعناصر الموجودة ضمن شريط التنقّل nav. تعمل الأصناف الثلاثة السابقة مع الصنف الذي يتحكم بلون الخلفية لشريط التنقّل وهو عبارة عن مجموعة من الأصناف مثل: bg-light و bg-dark و bg-primary و bg-success و bg-warning. لكي تحصل على أفضل النتائج استخدم الصنف bg-light مع الصنف navbar-light والصنف bg-dark مع الصنف navbar-dark. الحرفان bg من الصنف bg-light أو الصنف bg-dark أو غيرهما، يعبّران عن الكلمة background أي الخلفية. يجعل الصنف bg-light خلفية شريط التنقّل ذا لون فاتح. كما أنّ الصنف bg-dark يجعل الخلفية تبدو غامقة، وهكذا. بالنسبة للأصناف الباقية، جرّب استخدام مزيج من ‎أصناف التنسيق مع أصناف الخلفية لكي تختار منها ما يناسبك. جرب مثلًا النمط الغامق navbar-dark مع bg-success وهكذا. يدعم شريط التنقّل في بوتستراب (ومحتوياته أيضًا) الشكل المرن أو المتدفق Fluid في التصميم. بمعنى أنّ شريط التنقّل ينتشر أفقيًا ليحاول تعبئة عرض الشاشة المتاح. يمكن استخدام أي حاوية Container تراها مناسبة للتحكّم في مدى الانتشار الأفقي. هذا ما يبرّر استخدامنا لعنصر div مع الصنفcontainer-fluid الموجود ضمن العنصر nav مباشرةً (انظر الكود السابق). في هذه الحالة استخدمنا هذه الحاوية لضبط الانتشار الأفقي لمحتويات شريط التنقّل. على العموم يمكننا استخدام نفس التقنية تمامًا مع العنصر nav نفسه. سنتحدث عن الحاويات لاحقًا في هذه السلسلة. ولكن إذا أردت معرفة فائدة وجود هذه الحاوية. أزل صنف التنسيق container-fluid من عنصر div الذي يأتي ضمن العنصر nav مباشرةً لترى كيف يؤثّر وجودها على محتويات شريط التنقّل. سنضع ضمن عنصر div (الذي يحوي الصنف container-fluid) محتويات شريط التنقّل. والتي تنحصر في مثالنا هذا على اسم الموقع، بالإضافة إلى أربعة عناصر توضّح أنواع الروابط التي يمكن وضعها ضمن شريط التنقّل. قطعة الكود التالية موجودة ضمن عنصر div‎ ذا الصنف ‎container-fluid‎ من الكود السابق: <a class="navbar-brand" href="#">نبيه</a> <ul class="navbar-nav me-auto"> <li class="nav-item"> <a class="nav-link active" aria-current="page" href="#">رابط فعال</a> </li> <li class="nav-item"> <a class="nav-link" href="#">عادي1</a> </li> <li class="nav-item"> <a class="nav-link" href="#">عادي2</a> </li> <li class="nav-item"> <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">غير فعال</a> </li> </ul> نضع عادةً اسم الموقع ضمن عنصر الارتباط التشعبي a. سيكون لهذا العنصر التنسيق navbar-brand ليُنسّق على شكل علامة تجارية أو أيقونة واضحة للموقع. يمكن بالطبع إضافة صورة لاسم الموقع بإضافة عنصر صورة كما سنرى فيما بعد. بعد عنصر الارتباط التشعبي وضعنا عنصر القائمة غير المرتبة ul وهي التي ستحوي الروابط الرئيسية على شريط التنقّل. لاحظ كيف وضعنا الصنف navbar-nav لهذه القائمة كي تنسجم مع شريط التنقل الموضوعة ضمنه. ولاحظ أيضًا وجود صنف آخر هو me-auto. أول حرفين من اسم هذا الصنف يشيران إلى الكلمتين margin end، وتعنيان الهامش من النهاية. مع الكلمة ‎-auto يعني ذلك أنّنا سنجعل الهامش من الطرف النهائي تلقائي أي أنّه سيأخد أكبر هامش ممكن من الطرف النهائي، وهذا ما سيجعل عنصر القائمة يُزاح كاملًا نحو اليسار (نحو البداية) بجوار اسم الموقع (جرب إزالة هذا الصنف وانظر ماذا سيحدث). قد تتسائل عن سبب استخدام تعبير "الهامش من النهاية" في حين أنّه كان من الممكن استخدام التعبير "الهامش من اليمين" فحسب! الجواب على ذلك بسيط. باستخدام هذا التعبير الرائع نستطيع إكساب موقعنا قابلية الاتجاه من اليمين إلى اليسار بكل بساطة. فعندما يكون اتجاه موقعنا من اليسار إلى اليمين تكون البداية من اليسار والنهاية من اليمين أمًا عندما يكون اتجاه موقعنا من اليمين إلى اليسار يحدث العكس! بمعنى آخر أنّه يمكن تعديل اتجاه موقعنا البسيط كاملًا ليصبح من اليمين إلى اليسار (بدلًا من الوضع الحالي) وذلك بتعديل بسيط جدًا في الموقع كما سنرى ذلك بعد قليل. قبل الإصدار 5 من بوتستراب، كان من الممكن الوصول إلى نفس النتيجة من خلال استخدام الصنف mr-auto وهو اختصار للكلمات: margin right auto، وتعني أنّ الهامش من الطرف الأيمن سيكون تلقائي. من الواضح أنّ هذا الصنف مفيد عندما عندما يكون اتجاه الصفحة من اليسار إلى اليمين. ولكن عندما يكون اتجاه الصفحة من اليمين إلى اليسار، سيكون استخدام هذا الصنف غير مناسب كما هو واضح. هذا ما كان يجبر المطورين على إنشاء قالبين منفصلين لصفحات الموقع في حال كان هناك حاجة لدعم لغتين باتجاهين مختلفين (مثل اللغة العربية، واللغة الانجليزية). وصلنا الآن إلى عناصر القائمة li. في الحقيقة هي عناصر بسيطة يحمل كل منها الصنف nav-item، ويحوي كل منها عنصر ارتباط تشعبي a. ولكل عنصر ارتباط تشعبي منها الصنف nav-link. العنصر الأوّل الذي يحوي النص "رابط فعال" سيكون له بالإضافة للصنف nav-link الصنف active للإشارة إلى أنّ الرابط الحالي يُشير إلى الصفحة الحالية التي تُعرض أمام المستخدم. وهذا أمر مفيد كما هو واضح. أمّا العنصران الثاني والثالث اللذان يحملان النص "عادي1" و "عادي2" على الترتيب فهما عنصران عاديان افتراضيان على شريط التنقّل. أمّا العنصر الأخير: "غير فعّال" فقد نحتاج أحيانًا إلى جعل أحد الارتباطات على شريط التنقّل غير فعّالة، وهذا يمكن الحصول عليه بتطبيق الصنف disabled كما هو واضح. هذا كل شيء! في الفقرة التالية سنحوّل الموقع السابق إلى الاتجاه الذي يناسب اللغة العربية. تعديل الموقع ليدعم الاتجاه من اليمين إلى اليسار بقي علينا إضافة بعض اللمسات الأخيرة لكي نُكسب الموقع الاتجاه المناسب لدعم اللغة العربية. في البداية أود أن أشير إلى أنّ ميزة الاتجاه من اليمين إلى اليسار RTL هي ميزة تجريبية في بوتستراب حتى وقت كتابة هذا المقال. ولكن ذلك لا يمنع بالطبع من استخدامها لأنّه من المتوقّع في الفترة القريبة القادمة أن تصبح نهائية بعد التأكّد من استقرارها. نحتاج لاستخدام الاتجاه من اليمين إلى اليسار RTL إلى إجراء ثلاثة تعديلات بسيطة ضمن الملف index.html: 1- استبدال القيمة ar بالقيمة en للسمة lang ضمن الوسم html. 2- إضافة سمة جديدة للوسم html وهي السمة dir وهي مسؤولة عن تحديد اتجاه الصفحة. سنسند القيمة rtl لها. 3- استبدال العنصر التالي بالعنصر link المسؤول عن استيراد مكتبة التنسيق الخاصة ببوتستراب: <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.rtl.min.css" integrity="sha384-gXt9imSW0VcJVHezoNQsP+TNrjYXoGcrqBZJpry9zJt8PCQjobwmhMGaDHTASo9N" crossorigin="anonymous"> هذه نسخة من مكتبة بوتستراب التي تدعم ‎ (لاحظ اسمها bootstrap.rtl.min.css). يجب أن يكون الكود النهائي الموجود ضمن الملف index.html مماثلًا لما يلي: <!doctype html> <html lang="ar" dir="rtl"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.rtl.min.css" integrity="sha384-gXt9imSW0VcJVHezoNQsP+TNrjYXoGcrqBZJpry9zJt8PCQjobwmhMGaDHTASo9N" crossorigin="anonymous"> <link href="/css/styles.css" rel="stylesheet" /> <title>دورات نبيه</title> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container-fluid"> <a class="navbar-brand" href="#">نبيه</a> <ul class="navbar-nav me-auto"> <li class="nav-item"> <a class="nav-link active" aria-current="page" href="#">رابط فعال</a> </li> <li class="nav-item"> <a class="nav-link" href="#">عادي1</a> </li> <li class="nav-item"> <a class="nav-link" href="#">عادي2</a> </li> <li class="nav-item"> <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">غير فعال</a> </li> </ul> </div> </nav> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html> عاين الملف index.html باستخدام الإضافة Live Server لتحصل على شكل شبيه بما يلي: لاحظ أنّنا لم نمس كود HTML مطلقًا. وذلك بسبب استخدمنا لأصناف تنسيقية تصلح للاستخدام في طريقتي العرض يمين إلى يسار RTL أو يسار إلى يمين LTR. ففي حالتنا هذه استخدمنا الصنف me-auto المسؤول عن سلوك الهامش من النهاية، والذي أصبح في هذه الحالة من جهة اليسار بدلًا من جهة اليمين كما في الفقرة السابقة. يمكنك تنزيل شيفرة المقال من الملف hsoub-bootstrap5-ch02.zip. خاتمة أرجو أن تكون قد استمتعت بهذا الدرس! لقد تعلّمنا الكثير في هذا الدرس حول شريط التنقّل في بوتستراب. حيث بنينا شريط تنقّل بسيط، وأسهبنا في الشرح حول أجزاء هذا الشريط، وكيفية الإستفادة من التقنيات الجديدة في بوتستراب 5 لتحويل اتجاه الصفحة لتصبح من اليمين إلى اليسار. وفي الدرس التالي سنتحدّث عن بنية صفحة الويب باستخدام بوتستراب. اقرأ أيضًا 10 أخطاء شائعة عند استخدام إطار العمل Bootstrap بناء قائمة شجرية باستخدام البوتستراب تصميم صفحة موقع باستخدام 3 Bootstrap - الجزء الأول
  9. مرحبًا بك في هذه السلسلة التي سنتحدث من خلالها عن إطار العمل Bootstrap 5 ذلك الإطار الذي يهيمن على معظم عمليات التطوير التي تحدث في الواجهة الأمامية Front-End Development في مواقع الإنترنت عمومًا. لا تفترض هذه السلسلة أن يكون لديك أي فكرة مسبقة عن بوتستراب Bootstrap (ولو أنّ بعض المعرفة القليلة مرحّب بها)، في حين أنّ الإلمام بـ HTML و أساسيات CSS هو أمر ضروري للمتابعة في هذه السلسلة. رغم أنّ بوتستراب يستخدم جافاسكريبت في بعض المكوّنات إلى أنّه ليس من الضروري أن يكون لديك معرفة بها لكي تتعلّم بوتستراب، ولو أنّ الإلمام بجافاسكريبت يُعدّ بديهيًا لمطوري الواجهة الأمامية عمومًا. هذا هو المقال الأوّل في هذه السلسلة، وهو مقال تمهيدي بطبيعة الحال، وفيه سنتحدّث عن النقاط التالية: ماهو بوتستراب؟ مالجديد في بوتستراب 5؟ إعداد بوتستراب للعمل. استخدام محرر برمجي مناسب ما الذي سنبنيه في هذه السلسلة؟ ماهو بوستراب؟ بوتستراب ببساطة هو إطار عمل Framework متكامل مبني على CSS و جافاسكريبت JavaScript يُستخدم لتنسيق صفحات الويب وإكسابها نواح جمالية بدون الحاجة إلى استخدام تنسيقات معقدة من CSS. يدعم بوتستراب مبدأ تنسيق الأجهزة المحمولة أولًا Mobile First Style وهذا يعني توافقية عالية مع الأجهزة المحمولة ذات الشاشات الصغيرة. عندما يُذكر بوتستراب فأول ما يتبادر إلى الذهن هو السرعة والأناقة والسهولة والتصميم المتجاوب Responsive Design مع مختلف أنواع الشاشات. كان أول من طور بوتستراب شركة تويتر الشهيرة، وبعد عام تقريبًا، جعلته مفتوح المصدر ومتاحًا بالكامل من خلال GitHub. يستند بوتستراب كما أشرنا مسبقًا إلى CSS فهو يوفّر كمّا كبيرًا من الجهد لتنسيق المكوّنات في صفحة الويب. يهدف بوتستراب كما هو واضح إلى تبسيط عمليات التصميم التي تحدث في الواجهة الأمامية Front-End وجعلها معيارية. يسهّل هذا الأمر إلى حدّ بعيد من حياة المصممين والمطورين على حدّ سواء، ويجعل عملية انضمام مصمّم جديد إلى فريق العمل في شركة تعتمد بوتستراب أمرًا يسيرًا نسبيًا. استخدام بوتستراب سهل جدًا. فيمكن من خلال إضافة صنف Class أو أكثر إلى عنصر HTML أن تحصل على أثر فوري يحوّل هذا العنصر إلى شكل جميل وعصري. انظر مثلًا إلى شيفرة HTML التالية: <button>مرحبًا</button> سيولّد الكود السابق الزر البسيط التالي: سأضيف الآن صنفان بسيطان من بوتستراب إلى الكود السابق: <button class="btn btn-primary">مرحبًا</button> ستحصل على الشكل الجميل التالي: لاحظ كيف اكتسب هذا الزر الألوان المناسبة بالإضافة إلى حاشية Padding مناسبة أيضًا وبتلقائية حول النص الموجود ضمن الزر. وأيضًا كيف أصبحت حواف الزر منحنية. توجد العديد من التشكيلات الأخرى التي يمكن اكسابها للأزرار كما سنرى فيما بعد. مالجديد في بوتستراب 5؟ يُعَد الإصدار 5 إصدارًا رئيسيًا وهو الأحدث من بوتستراب حاليًا (وقت كتابة هذا المقال)، وكما جرت العادة، فهناك العديد من التغييرات التي طرأت على الإصدار الذي يسبقه (الإصدار 4) فمثًلا فقد أزيل المكوّن Jumbotron بالإضافة إلى إزالة الدعم عن المتصفحين IE 10 و IE 11، وأيضًا أزيل عدد من أصناف التنسيق التي كانت موجودة في الإصدار 4. هناك تغييرات أخرى قد حدثت ضمن مخطط الصفحة حيث أضيف قياس آخر جديد لم يكن موجودًا في الإصدار السابق وهو القياس xxl. و توجد تحسينات أخرى في نظام الألوان. كما أضيف دعم أيقونات SVG جميلة ومتنوّعة ومفتوحة المصدر أيضًا. يمكنك مع مكتبة الأيقونات هذه الاستغناء عن مكتبات أيقونات إضافية مثل Font Awesome. في الإصدار 5 أيضًا لم يعد هناك حاجة لاستخدام المكتبة jQuery بعد الآن (بعض المزايا الموجودة في بوتستراب تحتاج إلى جافاسكريبت)، فقد انتقل مطوّرو بوتستراب إلى استخدام جافاسكريبت فقط، مع إمكانية الإبقاء على استخدام jQuery في حال الرغبة. أود أن أركّز هنا على ميزة مهمة أضيفت إلى بوتستراب 5، طالما انتظرها المصممين والمطورين العرب! وهي دعم الاتجاه من اليمين إلى اليسار ‏ RTL مما يسهّل حياتهم إلى حدّ كبير. إعداد بوتستراب للعمل يمكن تضمين بوتستراب في صفحة الويب التي نعمل بها بإدراجه عن طريق العنصر link ضمن العنصر head في ترويسة الصفحة، ويمكن اختيار تضمين بوتستراب من مزوّد محتوى على الإنترنت CDN وهو الخيار الأفضل. ومن الممكن كذلك تنزيل نسخة من بوتستراب محليًا ومن ثمّ تضمينها ضمن صفحة الويب التي تعمل بها. سنعمل في هذه السلسلة على الخيار الأول، أي أنّنا سنستخدم مزوّد محتوى CDN. سنعتمد القالب الأساسي التالي أثناء عملنا على بوتستراب: <!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <title>Hello, world!</title> </head> <body> <h1>السلام على الجميع</h1> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html> لاحظ أنّه وقبل نهاية وسم الإغلاق ‎</body>‎ وضعنا الوسم <script> الذي يسمح بتحميل كود جافاسكريبت الذي تحتاجه بعض مكوّنات بوتستراب لكي تعمل عملًا صحيحًا. استخدام محرر برمجي مناسب توجد العديد من الخيارات المتاحة لاستخدام محرّر برمجي مناسب في سياق عملك كمطوّر واجهة أمامية، ومن المحرّرات الشهيرة Visual Studio Code و Sublime و Atom. بالنسبة لي أفضل استخدام Visual Studio Code من مايكروسوفت لما يتمتع به من مرونة ودعم كبيرين. لتثبيت محرر vs code انتقل إلى الموقع الخاص به لتنزيله. سيظهر زر التحميل في الصفحة الرئيسية. عندما تنتهي من تنزيله وتثبيته، افتحه وانتقل إلى قسم الإضافات Extensions ضمنه في الشريط الموجود على الناحية اليسرى كما في الشكل التالي: بعد ذلك وفي خانة البحث في الأعلى اكتب Live Server للبحث عن هذه الإضافة التي ستسمح لك بتشغيل خادوم مبسّط على حاسوبك الشخصي مما يسمح لنا بتجريب الشيفرة التي نكتبها مباشرةً على المتصفح الافتراضي الموجود على حاسوبنا. بعد اختيار الإضافة انقر الزر Install في الناحية الخاصة بشرح الإضافة (في الطرف الأيمن) لتثبيتها. بنفس الأسلوب السابق تمامًا ننصحك بتثبيت إضافة Auto Rename Tag، حيث تساعد هذه الإضافة على التعديل التلقائي لوسم ما عند تعديل الوسم المرافق له. ما الذي سنبنيه في هذه السلسلة؟ سنبني في هذه السلسلة موقع ويب بسيط عبارة عن صفحة واحدة يمكن أن يُعتبر كقالب يشرح مزايا بوتستراب 5 التي سنتناولها تباعًا أثناء تقدمنا في هذه السلسلة. هذا الموقع عبارة عن موقع يبيع دورات تعليمية على الإنترنت. يوفر الموقع إمكانية التسجيل الجديد للمستخدمين بالإضافة إلى تسجيل دخول للمستخدمين السابقين. كما سيعرض آخر الدورات التدريبية (المنتجات) المتوفرة، وأيضًا الدورات الأكثر مبيعًا. كما سنوفّر ميزة سلة المشتريات التي تسمح للمستخدم بالتسوّق من خلال اختيار الدورات التي يرغب بشرائها. بالإضافة إلى ما سبق سنضيف بعض الأقسام على الصفحة الرئيسية التي توفّر بعض المعلومات عن الموقع وبنفس الوقت توضّح لنا كيفية استخدام مزايا بوتستراب 5 المتنوّعة. سنعمل على بناء هذا الموقع شيئًا فشيئًا أثناء عملنا في هذه السلسلة. انظر إلى الشكل التالي الذي يعطيك شكلًا تقريبيًا لما سنحصل عليه في نهاية هذه السلسلة. مصدر الصور في آخر هذه السلسلة سنتعلّم كيف نرفع الموقع كاملًا على إحدى الإستضافات لكي يصبح بالإمكان معاينته بصورة حية. اقرأ أيضًا 10 أخطاء شائعة عند استخدام إطار العمل Bootstrap بناء قائمة شجرية باستخدام البوتستراب تصميم صفحة موقع باستخدام 3 Bootstrap - الجزء الأول
  10. سنتعلّم في هذا الدرس: تجهيز التطبيق قبل النشر إنشاء موقع جديد على منصة Netlify بالإستناد إلى مستودع GitHub هذا الدرس هو الأخير ضمن سلسلة Vue.js، حيث سنتوّج هذه السلسلة بشرح كيفية نشر التطبيق الوارد في الدرس السابق، وهو عبارة عن تطبيق SPA يدعم التخاطب مع قاعدة بيانات موجودة على Firebase كما تذكر. بعد بناء التطبيق ونشره، سيتمكّن أي مستخدم حول العالم من الوصول إلى تطبيقنا هذا والتفاعل معه. سأعتمد استخدام المنصّة المجانية Netlify لهذا الغرض، ويمكنك بالطبع استخدام أي منصّة أو خادوم مخصّص ترغب به. تجهيز التطبيق قبل النشر كما ذكرت قبل قليل، سنعتمد التطبيق المبني في الدرس السابق لتشغيله على خدمة Netlify. بغية ذلك، عملت على رفع هذا التطبيق بشكل كامل على مستودع Github التالي: HsoubAcademy/vuejs-spa سبب ذلك هو أنّ Netlify يسحب التطبيقات الموجودة على خدمات Git مثل GitHub. ستحتاج بالطبع إلى أن يكون لديك حساب على GitHub. زُر المستودع السابق، وسجّل دخولك على GitHub إذا لم تكن قد فعلت ذلك مسبقًا، ومن الصفحة الرئيسية لمستودعنا، انقر الزر Fork في الزاوية اليمنى العليا لإنشاء تفريعة جديدة من الشيفرة البرمجية الحالية. سيتطلب الأمر لحظات حتى يتم إنشاء التفريعة من الشيفرة البرمجية ووضعها ضمن حسابك الخاص. إنشاء موقع جديد على منصة Netlify بالإستناد إلى مستودع GitHub أنشئ حسابًا جديدًا على Netlify عن طريق زيارة الصفحة الرئيسية له الموقع الرسمي. انقر Sign up من الزاوية اليمنى العليا لتظهر لك الصفحة الخاصة بإنشاء اشتراك جديد. تبدو هذه الصفحة حاليًا على النحو التالي: لاحظ معي وجود خيارات متعددة للتسجيل. سنستخدم في حالتنا هذه التسجيل باستخدام البريد الإلكتروني. انقر الخيار الأخير "Email". بعد كتابة البريد الإلكتروني الذي تودّ التسجيل عن طريقه، سيرسل الموقع رسالة تحقق إلى هذا البريد تحتوي على رابط لتفعيل الحساب الجديد، انقر ذلك الرابط المرسَل إلى بريدك، وبعد تسجيل الدخول إلى Netlify باستخدام حسابك الجديد ستظهر صفحة مشابهة لما يلي: هذه هي الصفحة الرئيسية والتي تحتوي على جميع عناصر التحكم الخاصة بحسابك. نحن الآن موجودون ضمن الصفحة الخاصة بمواقع الويب التي أنشأتها أنت مسبقًا، وهي فارغة الآن بطبيعة الحال. انقر الزر "New site from Git" من الطرف الأيمن في الأعلى، للإتصال بمستودع من النوع Git. ستحصل على شكل شبيه بما يلي: انقر الزر GitHub الموجود في الأسفل، سيؤدي ذلك إلى فتح نافذة جديدة قد تطلب منك تسجيل الدخول بحسابك على GitHub في حال لم تكن مسجلًا دخولك على GitHub بعد (ذلك الحساب الذي أنشأت التفريعة ضمنه): انقر الزر Authorize Netlify للسماح لـ Netlify بالوصول إلى حساب GitHub الخاص بك. بعد إكمال عملية الاستيثاق (Authorization)، ستظهر لك صفحة تسمح لك بالاختيار بين السماح الكامل لـ Netlify للوصول إلى جميع المستودعات ضمن حسابك أو السماح بالوصول إلى مستودع محدّد. بالنسبة إلي، سأسمح له بالوصول إلى المستودع vuejs-spa فقط، وهو المستودع الذي أنشأناه كتفريعة قبل قليل من الفقرة السابقة. انقر زر Install لتبدأ عملية التنصيب التي تتضمّن الانتقال إلى موقع GitHub بشكل تلقائي وذلك لإكمال عملية الربط (قد يطلب منك كلمة المرور لحسابك في GitHub مرة أخرى). بعد الإنتهاء من العملية السابقة ستحتاج إلى العودة إلى الصفحة الرئيسية لموقع Netlify وتكرار عملية إنشاء موقع من مستودع GitHub (الشكل رقم 3). هذه المرة سيظهر لنا المستودع الذي نرغب باستيراده. انظر إلى الشكل التالي: لاحظ معي كيف ظهر المستودع vuejs-spa مع اسم حساب GitHub التابع لي husamburhan. سأختار هذا المستودع بالنقر عليه، سيؤدي ذلك إلى الخطوة النهائية والتي تتمثّل بتحديد الفرع الرئيسي (Branch) التي سنستخدمه في عملية نشر التطبيق، بالإضافة إلى تحديد التعليمة الخاصة ببناء التطبيق، والمجلّد الخاص بالنشر. احرص على أن تحصل على شكل شبيه بما يلي: أخيرًا، انقر الزر Deploy site لبناء التطبيق ونشر الموقع على الانترنت. ستأخذ هذه العملية القليل من الوقت، حيث ستنتقل إلى صفحة تخبرك بأنّ عملية البناء والنشر قيد التجهيز. بعد أن تنتهي عملية البناء والنشر ستحصل على رابط حي للصفحة تستطيع مشاركته مع من ترغب. بالنسبة إلي حصلت على الرابط التالي: suspicious-mahavira-10e9ac.netlify.app لاحظ أنّ اسم الموقع يُولَّد بشكل عشوائي. يمكنك بالطبع تغيير هذا الاسم بحيث يصبح منطقيًا أكثر. كما يمكنك إضافة اسم نطاق مخصّص مثل www.example.com وربطه مع هذا الموقع إن أحببت. جميع الخيارات السابقة وأكثر يمكن التحكم بها من خلال خيارات الموقع في Netlify. ختامًا ختمنا في هذا الدرس السلسلة التعليمية الخاصة بـ Vue.js بشرح كيفية نشر التطبيق إلى خدمة مجانية ليصبح تطبيقنا متاحًا على الانترنت. توجد العديد من الخدمات التي تسمح بالنشر المجاني، ولكنّني اخترت أبسطها وهي Netlify حسب رأيي. حاولت في هذه السلسلة تغطية الأمور الأساسية فقط في Vue.js، لذلك فأمامك الكثير بكل تأكيد لتتعلّمه حول هذه التقنية الواعدة. يمكنك زيارة الموقع الرسمي لإطار العمل Vue.js والاستزادة حوله. اقرأ أيضًا المقال السابق: بناء تطبيقات ذات صفحة واحدة باستخدام التوجيه Routing في Vue.js النسخة الكاملة لكتاب أساسيات إطار العمل Vue.js
×
×
  • أضف...