المحتوى عن 'نماذج'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • الإدارة والقيادة
  • مقالات ريادة أعمال عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML5
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات برمجة عامة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • مقالات تصميم عامة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات DevOps عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عمل حر عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 7 نتائج

  1. تطبيقك الجديد لتصميم المواقع جاهز للانطلاق بعد أشهر من العمل الشاق. أنت وفريقك سعداء بالنتيجة وقد أحبّه المستخدمون ممن اختبروه ؛ وخاصة ميزات البناء الإضافية. لديك كل الأسباب للاعتقاد بأن هذا التطبيق ناجح. ماذا يحدث عندما لا يكون كذلك؟ وهنا تتساءل، لماذا يمرّ موقعك أو تطبيقك بمرحلة ركود. كان هناك موجة نشاط لطيفة عقب إطلاقه أما الآن فعدد قليل من الأشخاص يستخدمونه. ما يُحيرك هو هذا النقص المفاجئ في الاهتمام بما تثق بأنه تطبيق جيد. قد يكون الحل بسيطًا مثل إعادة تصميم نماذج (التسجيل/تسجيل الدخول). إذا واجه المستخدم صعوبة في الوصول إلى الموقع، فهو لن يعود إليه وسينشر تجربته السيئة أيضًا. ما زالت السبل القديمة للاشتراك وتسجيل الدخول مألوفة. إلا أن هناك تقنيات جديدة متاحة الآن تعمل على تبسيط ملء النماذج، ويمكن لهذا وحده أن يحل المشكلة إذا كان التغيير ممكن في حالتك. بالنسبة لمعظمنا، فتسجيل الدخول إلى المواقع هو أمر روتيني ولذا فنحن نمنحه القليل من التفكير. إلى أن تصر سياسة الأمان للموقع على كلمة مرور جديدة ونعجز عن تذكر القديمة. يسهل نسيان معلومات تسجيل الدخول للمواقع التي نستخدمها بشكل غير منتظم. نحن نجهل حتى عنوان البريد الإلكتروني الذي استخدمناه في الاشتراك لنكتشف لاحقًا أننا لم نشترك أساسًا. اضف إلى ذلك، مَن يمكنه تذكّر 100 تسجيل الدخول ومثلها لأسماء المستخدمين وكلمات السر؟ خيبة الأمل الناتجة عن مشاكل تسجيل الدخول ذات أثر سيء على الشركات. فهذه التجارب المحبطة تصل بنا إلى النقطة التي نتخلى فيها عن محاولة الدخول للموقع. ويزداد الأمر سوءًا بالنسبة للشركات التي تبيع عن طريق الإنترنت. في الواقع، بحسب إحدى الدراسات فإنه من أصل 160،000 شخص طلبوا كلمة المرور الخاصة بهم،قام 75٪ منهم بالتخلي عن فكرة الشراء دون استكمال ذلك. يمكن لعملية ملء نموذج الاشتراك وإرساله أن تكون مملة إذا كانت طويلة ومعقدة. وقد يفقد العميل حماسه للشراء خلال هذه العملية. إذا فقد الزائر الاهتمام قبل تسجيل الدخول أو بسبب شعوره بخيبة الأمل، فلن يستعرض منتجات/عروض الموقع. والنتيجة هي إضاعة الشركات لفرصة تحويل الزائر إلى مشتري. إن تسجيل الدخول هو أكثر من مجرد روتين. هي عملية مهمة بما فيه الكفاية للبدء باستخدام تصاميم جديدة لحل مشكلة متنامية للمستخدمين والشركات. فكر في الأمر: ظاهريًا، تصميم صفحة الدخول التفاعلية هو أمرٌ بسيط. ولا يدرك الكثيرون العديد من اعتبارات التصميم المختلفة التي تساهم في صفحة تسجيل الدخول. وبمجرد الجمع بينها، غالبًا ما تكون النتيجة حدوث التعقيدات والتي بدورها تؤدي إلى الشعور بخيبة الأمل. ما هي المنصة الجماهيرية التي يتم استخدامها؟ ما هي العمليات التجارية الداخلية؟ ما هي إجراءات سياسة خصوصية الموقع؟ تصميم واجهة الصفحة. و لا تنسى السريّة. يجب أن يكون موضع التسجيل واضحًا عندما يستعد مستخدم الموقع لتسجيل الدخول، لا بد أن يكون موضع التسجيل واضحًا ويظهر نموذج الإدخال مباشرة على الصفحة. تقتصر العديد من مواقع الويب على توفير رابط لصفحة تسجيل الدخول مما يعدّ خطوة إضافية تُبعد المستخدم عن الصفحة الرئيسية. عمليات تسجيل الدخول المفضلة يحب مستخدمو المواقع تسجيل الدخول عن طريق صفحاتهم في مواقع التواصل الاجتماعي. إذا كان هناك طريقة أسهل فهي لم ترَ النور بعد. كل ما هو مطلوب هو النقر على زر وها أنت ذا قد دخلت. مواقع الويب التي تقبل هذا النوع من تسجيل الدخول لا تطلب منك إنشاء حساب. والطريقة الأخرى للدخول هي، بطبيعة الحال، مع اسم المستخدم وكلمة المرور أو عنوان بريدك الإلكتروني وكلمة مرور. هناك مجال لتحسين هذه الطريقة التقليدية. الأمر بأسره متعلق بالسريّة السريّة أمرٌ مهم ولهذا السبب نتجنب استخدام نفس اسم المستخدم وكلمة المرور لجميع حساباتنا على مواقع الإنترنت. أحيانًا يكون نظام الحماية لدينا وقائيًا أكثر من اللازم لدرجة منعنا من الدخول إلى موقع نثق بأنه آمن. لذلك قد نطلب منه فتح الموقع على أي حال، مما يمكن أن يُضعفه. لا بد أن تكون هناك طريقة أفضل. فنحن بحاجة إلى الأمان وسهولة الاستخدام. عند محاولة تسجيل الدخول إلى موقع ويب لا تتذكر اسم المستخدم أو كلمة المرور، يمكنك في كثير من الأحيان استعادتها إن كان الموقع يوفر لك المعلومات اللازمة. لسوء الحظ، يمكن أن يؤدي ما سبق إلى سرقة الهوية. إن توجب عليك الاستمرار في التخمين إلى أن يقوم الموقع بقفل حسابك و إلزامك بالاتصال بخدمة العملاء.فربما يكون ذلك محبط جدًا لدرجة ألّا تهتم بالأمر بعدها. وإليك بعض الحلول العملية للمشكلة: عندما تفشل صفحة تسجيل الدخول في إخبار المستخدم عن السبب أكان بسبب اسم المستخدم أو كلمة المرور فعليك بإتاحة ثلاث محاولات لأننا جميعا نقع في الأخطاء المطبعية. وبدلًا من إجبار المستخدمين على الاتصال بخدمة العملاء، قم تعيّين حدّ زمني. كأن يتمكن المستخدم من المحاولة مرة أخرى في غضون 15 دقيقة. وربما بحلول ذلك الوقت، يكون قد تذكر ما قد نسيه. استخدم البريد الإلكتروني كإسم مستخدم تتطلب معظم مواقع الويب اسم مستخدم لتسجيل الدخول، وتتيح لك بعض المواقع استخدام عنوان بريدك الإلكتروني كاسم مستخدم. يجب أن يكون كلاهما خيارًا وأن يتم الإشارة لذلك بحيث يعرف المستخدمون بامتلاكهم للخيارين. عادة ما يتذكر الأشخاص عنوان بريدهم الإلكتروني وهو ما يُسهل الأمر كثيرًا. تجنب ألعاب التخمين من فضلك تبدو الحقول على شاشات تسجيل الدخول في كثير من الأحيان وكأنها حقول ثانوية، وذلك بوضعها في آخر الصفحة. يمكن لهذا أن يشوش الزائر في حين أن البساطة مطلوبة. وفي أحيان أخرى يتم تعيين اسم المستخدم دون أن تمتلك فكرة عن ماهيّته أو أين يمكنك العثور عليه. على سبيل المثال: ربما ترغب في دفع فاتورة لشركة المرافق على موقعهم على الإنترنت، ولكن لا يمكنك تسجيل الدخول لأنك لا تعرف رقم حسابك. ستحتاج للأخير كاسم المستخدم الخاص بك. و غني عن الذكر أن العناوين يمكنها توجيه المستخدم إلى حيث يمكنه العثور على رقم حسابه. عندما يكون اسم المستخدم هو عنوان البريد الإلكتروني فلا تعلّم مربع الإدخال كاِسم مستخدم. بل كعنوان بريد إلكتروني. في الموقع المثال أعلاه، لديك رمز عوضًا عن كلمة مرور. لا تَسِمه ككلمة مرور. بل كرمز سريّ. هذه الحلول تساهم في القضاء على خيبة الأمل، وتساعد في تسجيل الدخول مع بقاء العملية آمنة. استخدم الصورة كتوكيد استخدام صورة الملف الشخصي أو أنماط أخرى للصور هو أداة أمان رائعة للتأكيد المرئي بأن حساب موقع الويب هو حسابك بالفعل، حتى إن لم تتمكن من تذكر كلمة المرور الخاصة بك. فمثلًا إن لم يكن هناك صورة لكلب، إذًا فهذا ليس حسابي. تسجيل الدخول الفوري اجتماع السهولة مع الأمان هو أمر ممكن، وهو ما أثبته نموذج تسجيل الدخول المستخدم في موقع Quora. حيث تمتلك خيار تسجيل الدخول بحساباتك في مواقع التواصل الاجتماعي. بعد تسجيلك، سيكون المطلوب منك في كل مرة تقوم بتسجيل الدخول مرة أخرى هو النقر على الصورة أو الاسم. هل هذا تسجيل دخول أم اشتراك في الموقع؟ في العديد من المواقع، تتشابه حقول تسجيل الدخول مع حقول التسجيل و أحيانًا حدّ المطابقة. ويمكن لوسَم كل منها أن يزيل الارتباك عن المستخدم. نحتاج جميعًا للمساعدة عندما نرتكب الأخطاء الجميع يضغط -أحيانًا- المفتاح الخطأ دون أن ينتبه. سيكون من المفيد -عندما يحدث ذلك أثناء إدخال معلومات تسجيل الدخول- أن تعطي المستخدم فكرة عن موطن الخطأ. على سبيل المثال، ربما أكون قد نسيت النقطة في com. ولذلك من الجيد أن أعرف كمستخدم أنني كتبت البريد الإلكتروني وكلمة المرور الصحيحان. وهذا سيحلّ المشكلة سريعًا. يُقدّر مستخدمي الموقع تأثير إعلامهم بأن مفتاح caps lock في لوحة مفاتيحهم مُضاء. بعد بضع محاولات غير ناجحة للدخول ، يتم منع المستخدم من الدخول لحسابه (أو حسابها) لدواعٍ أمنية. و سيكون من المفيد إعلام المستخدم -بعد فشل محاولة التسجيل الأولى- أنه إثر محاولتين آخرتين سيتم تأمين الحساب لمدة 20 دقيقة. هذا سيقلل من حيرتهم فيما يجب عليهم القيام به بعد ذلك. إن وضع التسميات بدقة يجعل تجربة المستخدمين سهلة. تأكد من أن الزر أو التصنيف يبيّن الغرض المحدد له. سواء أكان تسجيل الدخول أو تقديم نموذج فإن وضع التسميات بدقة سيُجنب المستخدم الشعور بالارتباك. التبسيط دعونا نعد إلى أحجية التطبيق الرائع الذي لم يرق إلى مستوى التوقعات. ربما الحل سهل كأن تغيّر في عملية تسجيل الدخول لتصبح أسهل بالنسبة للمستخدم. ومن المعلوم أن ذاك سيتطلب المزيد من العمل لفريقيّ التصميم والتطوير في شركتك ومن المرجح أن يشعر أفراد الفريقين بعدم الجدوى. ولا بأس بذلك بما أنك تدرك صواب ما تفعله. تحتاج لتبسيط التصميم بالنسبة لعملاءك فمن دونهم ربما انتقلت لتصميم علب حبوب الإفطار. تواجه أهم الشركات الناشئة على هذه المشكلات عند تصميم مواقعها على الويب. الق نظرة عن كثب لبعض الشركات الناشئة المشهورة في وقتنا الحاضر وسترى أن عملية تسجيل الدخول خاصتهم لا تشوبها شائبة. ترجمة -بتصرف- لمقال How to Improve the User Login Experience لصاحبهIggy حقوق الصورة البارزة محفوظة لـ Freepik
  2. هذا هو الجزء الأخير من سلسلة “مدخل إلى إطار العمل Ruby on Rails” وفي هذا الجزء سنعيد هيكلة الشيفرة التي كتبناها في الأجزاء السابقة من السلسلة، وسنتعرّف إلى نظام الاستيثاق البسيط الذي يقدّمه إطار العمل Rails. إعادة هيكلة الشيفرة بعد أن أصبحت المقالات والتعليقات تعمل بصورة جيدة، لنلقِ نظرة على القالب app/views/articles/show.html.erb . يبدو الملف طويلًا جدًّا، لذا سنستخدم الملفات الجزئية لتنظيف وترتيب الشيفرة البرمجية. تصيير مجموعة الملفات الجزئية في البداية سننشئ ملفًّا جزئيًا خاصًّا بالتعليقات وظيفته عرض جميع التعليقات الخاصّة بالمقالة. أنشئ الملف app/views/comments/_comment.html.erb وأضف إليه الشيفرة التالية: <p> <strong>Commenter:</strong> <%= comment.commenter %> </p> <p> <strong>Comment:</strong> <%= comment.body %> </p> والآن يمكنك تعديل الملف `app/views/articles/show.html.erb` كما يلي: <p> <strong>Title:</strong> <%= @article.title %> </p> <p> <strong>Text:</strong> <%= @article.text %> </p> <h2>Comments</h2> <%= render @article.comments %> <h2>Add a comment:</h2> <%= form_for([@article, @article.comments.build]) do |f| %> <p> <%= f.label :commenter %><br> <%= f.text_field :commenter %> </p> <p> <%= f.label :body %><br> <%= f.text_area :body %> </p> <p> <%= f.submit %> </p> <% end %> <%= link_to 'Edit', edit_article_path(@article) %> | <%= link_to 'Back', articles_path %> بهذه الطريقة سيتم تصيير الملف الجزئي في app/views/comments/_comment.html.erb لكلّ تعليق موجود في مجموعة @article.comments، وعندما يتنقّل التابع render بين عناصر مجموعة التعليقات فإنه يُسند كل تعليق إلى متغيّر محلي local variable يحمل اسم الملف الجزئي ذاته، وفي حالتنا هذه comment والذي يكون متوفّرًا في الملف الجزئي. تصيير الملف الجزئي الخاصّ بالاستمارة لنقم بإزالة قسم التعليقات الجديد إلى ملف جزئي خاصّ به، ومرة أخرى أنشئ ملفًّا باسم _form.html.erb في المجلد app/views/comments/ وأضف إليه ما يلي: <%= form_for([@article, @article.comments.build]) do |f| %> <p> <%= f.label :commenter %><br> <%= f.text_field :commenter %> </p> <p> <%= f.label :body %><br> <%= f.text_area :body %> </p> <p> <%= f.submit %> </p> <% end %> ثم عدّل الملف app/views/articles/show.html.erb ليصبح بالصورة التالية: <p> <strong>Title:</strong> <%= @article.title %> </p> <p> <strong>Text:</strong> <%= @article.text %> </p> <h2>Comments</h2> <%= render @article.comments %> <h2>Add a comment:</h2> <%= render 'comments/form' %> <%= link_to 'Edit', edit_article_path(@article) %> | <%= link_to 'Back', articles_path %> يعرّف تابع render الثاني القالب الجزئي الذي نرغب في تصييره وهو comments/form، ونظرًا لوجود المحرّف / ضمن هذه السلسلة النصّية سيعرف Rails بأنّك ترغب في تصيير الملف _form.html.erb الموجود في المجلد app/views/comments. أما الكائن @article فسيكون متوفّرًا لأيّ ملفّ جزئي يتم تصييره في العرض لأنّنا عرّفناه كمتغيّر من نوع instance. حذف التعليقات إن القدرة على حذف التعليقات المزعجة هي من الميزات المطلوب توفرها في المدوّنة، ولتنفيذ ذلك سنحتاج إلى إضافة رابط لحذف التعليقات ضمن العرض وإلى حدث destroy في المتحكّم CommentsController. لذا سنضيف أوّلًا رابط الحذف ضمن الملفّ الجزئي app/views/comments/_comment.html.erb وكما يلي: <p> <strong>Commenter:</strong> <%= comment.commenter %> </p> <p> <strong>Comment:</strong> <%= comment.body %> </p> <p> <%= link_to 'Destroy Comment', [comment.article, comment], method: :delete, data: { confirm: 'Are you sure?' } %> </p> سيؤدّي النقر على هذا الرابط إلى إرسال الفعل DELETE متمثّلًا بالرابط /articles/:article_id/comments/:id إلى المتحكّم CommentsController، والذي سيبحث بدوره - مستعينًا بهذا الرابط - عن التعليق المراد حذفه من قاعدة البيانات. لنضِف حدث destroy إلى المتحكّم في الملف app/controllers/comments_controller.rb: class CommentsController < ApplicationController def create @article = Article.find(params[:article_id]) @comment = @article.comments.create(comment_params) redirect_to article_path(@article) end def destroy @article = Article.find(params[:article_id]) @comment = @article.comments.find(params[:id]) @comment.destroy redirect_to article_path(@article) end private def comment_params params.require(:comment).permit(:commenter, :body) end end سيبحث الحدث destroy عن التعليق المراد حذفه، ثم يعيّن موقعه في مجموعة @article.comments ثم يحذفه من قاعدة البيانات ويعيد توجيهنا إلى حدث show الخاصّ بالمقالة. حذف الكائنات المترابطة من البديهي أنّه عند حذف مقالة معيّنة فإن من الواجب أن يتم حذف التعليقات المرتبطة بها، وإلا فستشغل هذه التعليقات مساحة ضمن قاعدة البيانات دون أيّ فائدة. يتيح لنا Rails استخدام الخيار dependent لتحقيق ذلك. توجّه إلى نموذج Article (app/models/article.rb) وعدّله بالصورة التالية: class Article < ApplicationRecord has_many :comments, dependent: :destroy validates :title, presence: true, length: { minimum: 5 } end الاستيثاق Authentication في Rails إن كنت ترغب في نشر المدوّنة على الإنترنت، سيكون بإمكان أي شخص إضافة وتعديل وحذف المقالات والتعليقات فيها. يقدّم Rails نظام استيثاق HTTP بسيط يمكن استخدامه في التطبيقات البسيطة كتطبيقنا هذا. سنحتاج في المتحكّم ArticlesController إلى وسيلة لمنع وصول الشخص غير المستوثق منه إلى الأحداث التي يتضمّنها هذا المتحكّم، ويمكن استخدام تابع http_basic_authenticate_with لتحقيق ذلك. ولاستخدام نظام الاستثياق سنقوم بالإفصاح عنه في بداية ملف المتحكّم ArticlesController in app/controllers/articles_controller.rb وسنستوثق من جميع الأحداث المتوفّرة في هذا المتحكّم عدا حدثي index وshow: class ArticlesController < ApplicationController http_basic_authenticate_with name: "dhh", password: "secret", except: [:index, :show] def index @articles = Article.all end # بقيّة الشيفرة ... كذلك سنسمح للمستخدمين المستوثق منهم فقط بحذف التعليقات، لذا أضف الشيفرة التالية إلى المتحكّم CommentsController في الملف app/controllers/comments_controller.rb: class CommentsController < ApplicationController http_basic_authenticate_with name: "dhh", password: "secret", only: :destroy def create @article = Article.find(params[:article_id]) # ... end # بقيّة الشيفرة ... والآن إن حاولت إنشاء مقالة جديدة، ستتلقّى طلب استيثاق كهذا: جدير بالذكر أنّ هناك العديد من وسائل الاستيثاق في تطبيقات Rails، أشهرها Devise rails engine و Authlogic. إطار العمل Rails ونظام الترميز UTF-8 إن أسهل طريقة للعمل مع Rails هي تخزين جميع البيانات الخارجية بنظام الترميز UTF-8، وإن لم تفعل ذلك فغالبًا ما تقوم مكتبات Ruby وإطار العمل Rails بتحويل البيانات الأصلية إلى هذا الترميز، ولكن لا يمكن الاعتماد على هذه المكتبات بصورة تامّة، ويفضّل التأكد من أنّ جميع البيانات الخارجية مرمّزة بهذا النظام. وفي حال حدوث أي خطأ في نظام الترميز فإن الحروف ستظهر في المتصفّح غالبًا على هيئة أشكال معينية سوداء بداخلها علامة استفهام، أو قد تظهر الحروف على هيئة رموز غريبة كأن يظهر الرمز “ü” بدلاً من الحرف “ü”. يتّخذ Rails بعض الإجراءات في نظامه الداخلي للتقليل من المسبّبات الشائعة لهذه المشاكل والتي يمكن الكشف عنها وتصحيحها بصورة تلقائية. ولكن، إن كنت تتعامل مع بيانات من مصادر خارجية غير مخزّنة بترميز UTF-8، لن يكون Rails قادرًا على الكشف بصورة تلقائية عن أسباب المشكلة أو تقديم حلّ لها. وهناك مصدران شائعان للبيانات غير المخزّنة بترميز UTF-8: محرر النصوص: تحفظ معظم محرّرات النصوص الملفات البرمجية بصيغة UTF-8، وإن لم يقم محرّر النصوص الذي تستخدمه في كتابة الشيفرات البرمجية بذلك، فقد ينتج عن ذلك تحوّل الحروف الخاصّة أو حروف اللغات الأخرى غير الإنكليزية إلى التحول في المتصفّح إلى أشكال معينية بداخلها علامة استفهام. ينطبق هذا الأمر كذلك على ملفات الترجمة i18n. تجدر الإشارة إلى أنّه تتيح معظم محررات النصوص التي لا تحفظ الملفات البرمجية بهذا الترميز افتراضيًّا (مثل Dreamweaver) إمكانية تغيير الترميز الافتراضي للملفات المحفوظة إلى نظام UTF-8، وننصح بالقيام بذلك. قاعدة البيانات: يحوّل Rails البيانات القادمة من قاعدة البيانات إلى ترميز UTF-8، ولكن إن لم يكن هذا نظام الترميز هذا مستخدمًا من طرف قاعدة البيانات فلن يكون بالإمكان تخزين جميع المحارف المدخلة من قبل المستخدم. فعلى سبيل المثال، إن كان نظام الترميز الداخلي لقاعدة البيانات هو Latin-1 وأدخل المستخدم كلمات باللغة الروسية أو العربية أو اليابانية، فستخسر البيانات إلى الأبد بمجرد دخولها إلى قاعدة البيانات. لذا ينصح دائمًا بتحويل نظام الترميز الداخلي في قاعدة البيانات إلى نظام UTF-8. المصدر: توثيقات Ruby on Rails.
  3. تحدّثنا في الجزء السابق من هذه السلسلة عن النماذج في إطار العمل Ruby on Rails وتعرّفنا على طريقة إنشائها والتعامل معها من خلال كتابة الشيفرة المسؤولة عن حفظ المقالة الجديدة في قاعدة البيانات. في الجزء الثاني من هذا الموضوع سنتعلّم كيفية ربط نموذجين مع بعضهما البعض من خلال إنشاء نموذج جديد خاصّ بالتعليقات. ولكن قبل ذلك سنكمل ما بدأناه في الدروس السابقة من السلسلة في بناء عمليات “CRUD” حيث غطّينا سابقًا عمليتي الإنشاء Create و القراءة Read، وسنغطي اليوم العمليتين المتبقّيتين وهما التحديث Update والحذف Destroy. تحديث المقالات الخطوة الأولى في عملية تحديث المقالات هي إضافة حدث edit إلى المتحكم ArticlesController بين حدثي new و create وكما يلي: def new @article = Article.new end def edit @article = Article.find(params[:id]) end def create @article = Article.new(article_params) if @article.save redirect_to @article else render 'new' end end سيتضمن العرض استمارة مشابهة لتلك التي استخدمناها في إنشاء المقالات الجديدة. أنشئ ملفًّا باسم app/views/articles/edit.html.erb وأضف إليه الشيفرة التالية: <h1>Edit article</h1> <%= form_for(@article) do |f| %> <% if @article.errors.any? %> <div id="error_explanation"> <h2> <%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved: </h2> <ul> <% @article.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <p> <%= f.label :title %><br> <%= f.text_field :title %> </p> <p> <%= f.label :text %><br> <%= f.text_area :text %> </p> <p> <%= f.submit %> </p> <% end %> <%= link_to 'Back', articles_path %> سنوجّه الاستمارة هذه المرة إلى حدث update والذي لم نقم بتعريفه حتى الآن. يؤدي تمرير كائن المقالة للتابع إلى إنشاء عنوان url لإرسال استمارة المقالة التي تم تعديلها، ومن خلال هذا الخيار نخبر Rails بأنّنا نرغب في أن يتم إرسال هذا النموذج من خلال فعل HTTP PATCH وهو أحد أفعال HTTP التي تستخدم في تحديث الموارد حسب بروتوكول REST. يمكن أن يكون المعامل الأول لـ form_for كائنًا، مثلًا @articl، والذي سيؤدي بالدالة المساعدة إلى ملء الاستمارة بالحقول التابعة للكائن، ويؤدي تمرير الرمز (:article) بنفس اسم المتغيّر من نوع instance (@article) إلى نفس النتيجة تلقائيًا. والآن سنقوم بإنشاء الحدث update في المتحكّم app/controllers/articles_controller.rb وسنضيفه بين حدث create والتابع ذي المحدّد الخاصّ private: def create @article = Article.new(article_params) if @article.save redirect_to @article else render 'new' end end def update @article = Article.find(params[:id]) if @article.update(article_params) redirect_to @article else render 'edit' end end private def article_params params.require(:article).permit(:title, :text) end يستخدم الحدث update عندما ترغب في تحديث سجل موجود في قاعدة البيانات، ويستقبل هذا الحدث جدول تقطيع hash يحتوي الخصائص التي ترغب في تحديثها. وكما سبق، في حال وجود خطأ في عملية التحديث سنعرض الاستمارة على المستخدم من جديد. سنستخدم التابع article_params الذي عرّفناه في وقت سابق للحدث create. لا حاجة لتمرير جميع الخصائص لغرض تحديثها، فعلى سبيل المثال، إن تم استدعاء @article.update(title: 'A new title') فسيقوم Rails بتحديث خاصية العنوان فقط، ويترك باقي الخصائص دون تعديل. أخيرًا، نرغب في عرض رابط إلى الحدث edit في الصفحة التي نعرض فيها قائمة المقالات، لذا توجّه إلى الملف app/views/articles/index.html.erb وأضف الرابط ليظهر إلى جانب رابط “Show”: <table> <tr> <th>Title</th> <th>Text</th> <th colspan="2"></th> </tr> <% @articles.each do |article| %> <tr> <td><%= article.title %></td> <td><%= article.text %></td> <td><%= link_to 'Show', article_path(article) %></td> <td><%= link_to 'Edit', edit_article_path(article) %></td> </tr> <% end %> </table> سنضيف كذلك رابطًا إلى قالب app/views/articles/show.html.erb ليظهر رابط “Edit” في صفحة المقالة أيضًا: ... <%= link_to 'Edit', edit_article_path(@article) %> | <%= link_to 'Back', articles_path %> هذا هو شكل تطبيقنا حتى هذه اللحظة: استخدام الملفات الجزئية partials لإزالة التكرار من العروض تبدو صفحة تحرير المقالة مشابهة تمامًا لصفحة إنشاء مقالة جديدة، وفي الواقع تستخدم الصفحتان الشيفرة ذاتها لعرض الاستمارة. سنقوم الآن بالتخلص من هذا التكرار باستخدام ملفات العرض الجزئية. تحمل هذه الملفات أسماء تبدأ بالمحرف (_). أنشئ ملفًّا جديدًا باسم _form.html.erb ضمن المسار app/views/articles/ وأضف إليه الشيفرة التالية: <%= form_for @article do |f| %> <% if @article.errors.any? %> <div id="error_explanation"> <h2> <%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved: </h2> <ul> <% @article.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <p> <%= f.label :title %><br> <%= f.text_field :title %> </p> <p> <%= f.label :text %><br> <%= f.text_area :text %> </p> <p> <%= f.submit %> </p> <% end %> لاحظ أننا لم نغيّر شيئًا باستثناء الإعلان عن التابع form_for وسبب استخدام هذه الأسلوب المختصر والبسيط في الإعلان عن التابع form_for للتعبير عن الاستمارتين هو أن @article عبارة عن مورد يرتبط بمجموعةٍ من مسارات RESTful، وبإمكان Rails أن يخمّن عنوان URI والتابع الذي يجب استخدامه. والآن لنقم بتحديث العرض app/views/articles/new.html.erb لاستخدام الملف الجزئي الذي أنشأناه وسنقوم بإعادة كتابة العرض من جديد وكما يلي: <h1>New article</h1> <%= render 'form' %> <%= link_to 'Back', articles_path %> ثم قم بالأمر عينه في ملف العرض app/views/articles/edit.html.erb: <h1>Edit article</h1> <%= render 'form' %> <%= link_to 'Back', articles_path %> حذف المقالات هذه هي العملية الأخيرة ضمن عمليات CRUD، وبحسب معايير REST فإن المسار الذي يؤدي إلى حذف المقالات وكما يظهر في مخرجات الأمر bin/rails routes هو: DELETE /articles/:id(.:format) articles#destroy يجب استخدام الفعل DELETE في المسار المسؤول عن حذف الموارد، أما في حال استخدام الفعل GET فسيكون بالإمكان إنشاء رابط خبيث كهذا الرابط مثلًا: <a href='http://example.com/articles/1/destroy'>look at this cat!</a> سنستخدم التابع delete لحذف المصادر، وهذا المسار مرتبط بالحدث destroy ضمن المتحكّم app/controllers/articles_controller.rb والذي لم نقم بإنشائه بعد. عادة ما يكون التابع destroy التابع الأخير ضمن المتحكّم، وكما هو الحال مع بقية التوابع العامّة public يجب الإعلان عنه قبل أي توابع خاصّة أو محميّة protected. def destroy @article = Article.find(params[:id]) @article.destroy redirect_to articles_path end الصورة النهائية للمتحكّم ArticleController في الملف app/controllers/articles_controller.rb هي: class ArticlesController < ApplicationController def index @articles = Article.all end def show @article = Article.find(params[:id]) end def new @article = Article.new end def edit @article = Article.find(params[:id]) end def create @article = Article.new(article_params) if @article.save redirect_to @article else render 'new' end end def update @article = Article.find(params[:id]) if @article.update(article_params) redirect_to @article else render 'edit' end end def destroy @article = Article.find(params[:id]) @article.destroy redirect_to articles_path end private def article_params params.require(:article).permit(:title, :text) end end يمكن استدعاء التابع destroy في كائنات التسجيلة النشطة Active Record عندما ترغب في حذفها من قاعدة البيانات. لاحظ أنّنا لسنا بحاجة لإضافة عرض خاص بهذا الحدث لأنّنا نعيد توجيه المستخدم إلى الحدث index. أخيرًا أضف رابط ‘Destroy’ إلى القالب app/views/articles/index.html.erb لنربط كل الصفحات مع بعضها البعض. <h1>Listing Articles</h1> <%= link_to 'New article', new_article_path %> <table> <tr> <th>Title</th> <th>Text</th> <th colspan="3"></th> </tr> <% @articles.each do |article| %> <tr> <td><%= article.title %></td> <td><%= article.text %></td> <td><%= link_to 'Show', article_path(article) %></td> <td><%= link_to 'Edit', edit_article_path(article) %></td> <td><%= link_to 'Destroy', article_path(article), method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </table> استخدمنا هنا التابع link_to بطريقة مختلفة، حيث مررّنا اسم المسار كمعامل ثانٍ، ثمّ مرّرنا الخيارات الأخرى بعد ذلك. تستخدم الخيارات method: :delete وdata: { confirm: 'Are you sure?' } كخصائص HTML5 بحيث يؤدي الضغط على الرابط إلى عرض مربع حوار للتأكد من رغبة المستخدم في حذف المقالة، ثم إرسال الرابط باستخدام التابع delete. تتمّ تعملية التحقّق هذه بواسطة ملف JavaScript الذي يحمل الاسم rails-ujs والموجود بصورة افتراضية في مخطط التطبيق (app/views/layouts/application.html.erb)، وفي حال عدم وجود هذا الملف لن يظهر مربع الحوار التأكيدي للمستخدم. تهانينا أصبح بإمكانك الآن إنشاء وعرض وسرد وتحديث وحذف المقالات في مدوّنتك. إضافة النموذج الخاصّ بالتعليقات سنقوم الآن بإنشاء نموذج جديد في تطبيقنا هذا ستكون وظيفته التعامل مع التعليقات. إنشاء النموذج لإنشاء النموذج الخاص بالتعليقات سنتبع الأسلوب السابق نفسه وذلك باستخدام أداة المولّد لإنشاء نموذج يحمل الاسم Comment ويمثّل مرجعًا إلى المقالة. اكتب الأمر التالي في سطر الأوامر: $ bin/rails generate model Comment commenter:string body:text article:references سينشئ هذا الأمر أربعة ملفات: الملف Purpose الملف/المجلد الوظيفة db/migrate/20140120201010_create_comments.rb ملف التهجير المسؤول عن إنشاء جدول التعليقات في قاعدة البيانات (سيحمل اسم الملف لديك ختمًا زمنيًا مختلفًا) app/models/comment.rb النموذج الخاص بالتعليقات test/models/comment_test.rb ملف الاختبارات الخاص بنموذج التعليقات test/fixtures/comments.yml نماذج تعليقات تستخدم في إجراء الاختبارات لنلق نظرة في البداية على ملف app/models/comment.rb: class Comment < ApplicationRecord belongs_to :article end كما تلاحظ فمحتوى هذا الملف مشابه لنموذج Article الذي أنشأناه سابقًا، والفارق الوحيد هو السطر belongs_to :article والذي ينشئ رابطًا بين النموذجين، وسنتحدّث عن الروابط بعد قليل. أما الكلمة المفتاحية (:references) ضمن الأمر الذي قمنا بتنفيذه في سطر الأوامر، فهي نوع خاص من البيانات بالنسبة للنماذج. تنشئ هذه الكلمة المفتاحية عمودًا في الجدول الموجود في قاعدة البيانات يحمل اسم النموذج الذي تمّ تمريره إلى هذه الكلمة مع إضافة _id والذي يمثّل عددًا صحيحًا. ستتضح الأمور أكثر بالنسبة إليك إن تفحّصت ملف db/schema.rb أدناه. قام Rails - بالإضافة إلى إنشاء النموذج - بإنشاء تهجير وظيفته إنشاء الجدول المقابل للنموذج في قاعدة البيانات: class CreateComments < ActiveRecord::Migration[5.0] def change create_table :comments do |t| t.string :commenter t.text :body t.references :article, foreign_key: true t.timestamps end end end يُنشئ السطر t.references عمودًا من نوع integer باسم article_id إضافة إلى فهرس index خاص بهذا العمود وقيد مفتاح خارجي Foreign Key Constraint والذي يشير إلى عمود id في جدول المقالات. والآن نفذ التهجير باستخدام الأمر التالي: $ bin/rails db:migrate ينفّذ Rails التهجيرات غير المنفّذة فقط؛ لذا ستكون نتيجة الأمر التالي كما يلي: == CreateComments: migrating ================================================= -- create_table(:comments) -> 0.0115s == CreateComments: migrated (0.0119s) ======================================== ربط النماذج مع بعضها البعض تسهّل روابط التسجيلة النشطة تكوين العلاقات بين النماذج، وفي حالتنا هذه سنُنشئ علاقة بين جدولي التعليقات والمقالات، ولو فكّرنا في طبيعة العلاقة التي تربط بينهما فسنجد أنه: ينتمي كل تعليق إلى مقالة واحدة. تمتلك المقالة الواحدة العديد من التعليقات. يستخدم Rails صياغة مشابهة للربط بين النماذج، وقد شاهدنا في نموذج Comment في الملف app/models/comment.rb الشيفرة المسؤولة عن ربط كل تعليق بمقالة واحدة: class Comment < ApplicationRecord belongs_to :article end سنحتاج الآن إلى تكوين الجانب الثاني من الرابطة، أي ربط المقالات بالتعليقات، لذا توجّه إلى الملف app/models/article.rb وعدّله بالصورة التالية: class Article < ApplicationRecord has_many :comments validates :title, presence: true, length: { minimum: 5 } end والآن أصبح النموذجان مرتبطين مع بعضهما البعض تلقائيًا، فعلى سبيل المثال، في حال كان لدينا متغيّر @article والذي يمثّل مقالة معيّنة، يمكن استدعاء جميع التعليقات المرتبطة بتلك المقالة على هيئة مصفوفة وذلك من خلال @article.comments. إضافة مسار خاص بالتعليقات كما هو الحال مع متحكم welcome سنحتاج إلى إضافة مسار نحدّد من خلاله العنوان الذي نرغب في استخدامه لمشاهدة التعليقات؛ لذا افتح ملف config/routes.rb مرة أخرى، وعدّله كما يلي: resources :articles do resources :comments end بهذه الطريقة تصبح التعليقات بمثابة موارد مضمّنة في المقالات، وهذه الطريقة هي جزء من العلاقة الهرمية التي تنشأ بين المقالات والتعليقات. إنشاء المتحكّم الخاصّ بالتعليقات بعد أن انتهينا من إعداد النموذج، أصبح بإمكاننا الآن إنشاء المتحكّم الخاص بالتعليقات، وسنستخدم أداة المولّد كما فعلنا سابقًا: $ bin/rails generate controller Comments سينشئ هذا الأمر خمسة ملفات إضافة إلى مجلّد فارغ: الملف/المجلد الوظيفة app/controllers/comments_controller.rb المتحكّم الخاص بالتعليقات /app/views/comments يتم تخزين العروض الخاصّة بالتعليقات في هذا المجلد test/controllers/comments_controller_test.rb ملف الاختبار الخاصّ بالمتحكّم app/helpers/comments الملف الخاصّ بمساعد العرض app/assets/javascripts/comments.coffee ملف CoffeScript الخاصّ بالمتحكّم app/assets/stylesheets/comments.scss أوراق الأنماط المتتالية CSS الخاصّة بالمتحكّم كما هو الحال مع أي مدوّنة، فإن القرّاء سيكتبون تعليقاتهم بعد قراءة المقالة مباشرة، وبعد أن يرسلوا تعليقاتهم يتم توجيههم إلى صفحة عرض المقالة ليتمكّنوا من مشاهدة التعليقات. وستكون وظيفة المتحكّم CommentsController هي توفير التوابع اللازمة لإنشاء التعليقات وحذف التعليقات المزعجة حال وصولها. سنقوم أولًا بتعديل قالب عرض المقالات app/views/articles/show.html.erb لنتمكن من إضافة تعليق جديد: <p> <strong>Title:</strong> <%= @article.title %> </p> <p> <strong>Text:</strong> <%= @article.text %> </p> <h2>Add a comment:</h2> <%= form_for([@article, @article.comments.build]) do |f| %> <p> <%= f.label :commenter %><br> <%= f.text_field :commenter %> </p> <p> <%= f.label :body %><br> <%= f.text_area :body %> </p> <p> <%= f.submit %> </p> <% end %> <%= link_to 'Edit', edit_article_path(@article) %> | <%= link_to 'Back', articles_path %> ستضيف الشيفرة السابقة استمارة إلى صفحة عرض المقالات يمكن من خلالها إضافة تعليق جديد من خلال استدعاء الحدث create ضمن المتحكّم CommentsController. ويستخدم الاستدعاء form_for مصفوفة ستعمل على إنشاء مسار متداخل nested route مثل: /articles/1/comments. لنجرِ الآن التعديلات اللازمة على الحدث create في الملفّ app/controllers/comments_controller.rb: class CommentsController < ApplicationController def create @article = Article.find(params[:article_id]) @comment = @article.comments.create(comment_params) redirect_to article_path(@article) end private def comment_params params.require(:comment).permit(:commenter, :body) end end ستتعقّد الأمور هنا قليلًا وذلك بسبب التداخل nesting الحاصل بين المسارات، إذ في كل مرة يتمّ فيها طلب تعليق معيّن يجب أن يتابع ذلك الطلب المقالة التي يرتبط بها هذا التعليق، وبالتالي استدعاء التابع find في نموذج Article والمسؤول عن اختيار المقالة المطلوبة حسب المعرّف المحدّد في المسار. بالإضافة إلى ذلك، استفدنا من بعض التوابع التي تقدّمها عملية الربط بين النموذجين، فقد استخدمنا التابع create على @article.comments لإنشاء التعليق وحفظه، وسيؤدي هذا إلى ربط التعليق الجديد بالمقالة المحدّدة. وبعد إنشاء التعليق الجديد نعيد توجيه المستخدم إلى المقالة الأصلية باستخدام الدالة المساعد article_path(@article). وكما شاهدنا تستدعي هذه الدالة الحدث show ضمن المتحكّم ArticlesController والذي يعمل بدوره على تصيير القالب show.html.erb، وهو المكان الذي نرغب أن تظهر التعليقات فيه؛ لذا سنقوم بإجراء التعديلات اللازمة على الملف app/views/articles/show.html.erb. <p> <strong>Title:</strong> <%= @article.title %> </p> <p> <strong>Text:</strong> <%= @article.text %> </p> <h2>Comments</h2> <% @article.comments.each do |comment| %> <p> <strong>Commenter:</strong> <%= comment.commenter %> </p> <p> <strong>Comment:</strong> <%= comment.body %> </p> <% end %> <h2>Add a comment:</h2> <%= form_for([@article, @article.comments.build]) do |f| %> <p> <%= f.label :commenter %><br> <%= f.text_field :commenter %> </p> <p> <%= f.label :body %><br> <%= f.text_area :body %> </p> <p> <%= f.submit %> </p> <% end %> <%= link_to 'Edit', edit_article_path(@article) %> | <%= link_to 'Back', articles_path %> أصبح بإمكانك الآن إضافة المقالات والتعليقات إلى مدوّنتك وعرضها في الأماكن الصحيحة. في الدرس القادم سنكمل العمل على التعليقات، حيث سنستخدم الملفات الجزئية لترتيب القوالب أوّلًا، ثم نضيف إمكانية حذف التعليقات من قاعدة البيانات، وفي الختام سنتطرّق إلى عملية الاستيثاق Authentication بصورة سريعة ومبسّطة. المصدر: توثيقات Ruby on Rails.
  4. تعرّفنا في الدرس السابق بإيجاز على طريقة عمل إطار العمل Ruby on Rails حيث تعرّفنا على المتحكّمات والعروض وبدأنا بإنشاء تطبيق المدوّنة البسيطة وأنشأنا في الدرس السابق الاستمارة الخاصة بإضافة مقالة جديدة، ولكن وصلنا إلى النقطة التي نحتاج فيها إلى تخزين المقالة في قاعدة البيانات، وهنا يأتي دور النماذج Models. تحمل النماذج في Rails اسمًا بصيغة المفرد في حين يحمل الجدول المرتبط بها في قاعدة البيانات اسمًا بصيغة الجمع. تتيح أداة المولّد generator في Rails إنشاء النماذج ويلجأ أغلب المطوّرين إلى هذه الأداة لإنشاء النماذج. لإنشاء نموذج جديد استخدم الأمر التالي في سطر الأوامر: $ bin/rails generate model Article title:string text:text من خلال هذه الأمر نخبر Rails بأننا نرغب في إنشاء نموذج باسم Article إلى جانب خاصّية title من نوع string، وخاصّية text من نوع text. تضاف هذه الخواص بصورة تلقائية إلى جدول المقالات في قاعدة البيانات ويتم ربطها بنموذج Article. ويستجيب Rails لهذا الأمر بإنشاء عدد من الملفات، وما يهمّنا منها الآن هما app/models/article.rb و db/migrate/20140120191729_create_articles.rb (لاحظ أن اسم الملف الثاني يختلف قليلًا عن هذا الاسم). الملف الثاني مسؤول عن إنشاء بنية قاعدة البيانات، وهو ما سنتحدث عنه بعد قليل. إجراء عملية التهجير Migration كما لاحظنا فإن الأمر bin/rails generate model قد أنشأ ملف تهجير لقاعدة البيانات داخل المجلد db/migrate. والتهجيرات هي عبارة عن أصناف مصمّمة لتسهيل عملية إنشاء الجداول في قواعد البيانات والتعديل عليها. يستخدم Rails أوامر rake لإجراء التهجيرات، ويمكن التراجع عن عملية التجهير بعد إجرائها على قاعدة البيانات. تتضمّن أسماء ملفات التهجير ختمًا زمنيًا لضمان معالجة هذه الملفات حسب التسلسل الزمني لإنشائها. لو ألقينا نظرة في ملف db/migrate/YYYYMMDDHHMMSS_create_articles.rb (تذكّر أن الملف عندك يحمل ختمًا زمنيًّا مختلفًا) فسنجد التالي: class CreateArticles < ActiveRecord::Migration[5.0] def change create_table :articles do |t| t.string :title t.text :text t.timestamps end end end ستنشئ عملية التهجير أعلاه تابعًا يحمل اسم `change` والذي يتم استدعاؤه عند إجراء عملية التهجير. حتى الحدث المُعرّف ضمن التابع قابل للتراجع، ما يعني أن Rails قادر على التراجع عن التغييرات الحاصلة من إجراء عملية التهجير في حال أردت ذلك في وقت لاحق. عند إجراء عملية التهجير هذه سيتم إنشاء جدول باسم `articles` يتضمن عمودًا من نوع `string` وآخر من نوع `text`، إضافة إلى عمودين للختم الزمني يمكن لـ Rails من خلالهما متابعة تواريخ إنشاء وتعديل المقالات. لتنفيذ عمية التهجير توجّه إلى سطر الأوامر ونفذ الأمر التالي: $ bin/rails db:migrate سينفّذ Rails أمر التهجير التالي وسيخبرك بإنشاء جدول Articles. == CreateArticles: migrating ================================================== -- create_table(:articles) -> 0.0019s == CreateArticles: migrated (0.0020s) ========================================= حفظ البيانات بواسطة المتحكّم سنعود الآن إلى المتحكّم ArticlesController، حيث سنعمل على تعديل الحدث create ليستخدم النموذج الجديد Article لحفظ البيانات في قاعدة البيانات. افتح الملف app/controllers/articles_controller.rb وعدّله بالصورة التالية: def create @article = Article.new(params[:article]) @article.save redirect_to @article end يمكن استحداث initialize كل نموذج في Rails مع الخصائص Attributes المرتبطة به، والتي يتم ربطها تلقائيًا مع الأعمدة المقابلة في قاعدة البيانات. وقد قمنا بذلك في السطر الأول في الحدث create (هل تذكر params[:article] والذي يضمّ الخصائص التي نريدها). بعد ذلك يمكن حفظ النموذج في قاعدة البيانات من خلال الدالة @article.save. وفي النهاية نعيد توجيه المستخدم إلى الحدث show الذي سنعرّفه في وقت لاحق. توجّه الآن إلى العنوان http://localhost:3000/articles/new وستتلقّى الخطأ التالي: يدعم Rails العديد من مزايا الأمان التي تساعد في كتابة تطبيقات أمينة، ونحن الآن نتعامل مع إحدى هذه المزايا. تدعى هذه الميزة بالمعاملات القوية strong parameters والتي تجبرنا على تحديد المعاملات المسموح بها في الأحداث الموجودة ضمن المتحكم. ما الفائدة من ذلك؟ صحيح أن القدرة على إضافة جميع المعاملات إلى النموذج دفعة واحدة وبصورة تلقائية يختصر الكثير من الجهد بالنسبة للمبرمج، إلا أنّ البرنامج يكون في هذه الحالة عرضة للاستخدامات الخبيثة. فماذا لو تمّ إنشاء طلب إلى الخادوم يتضمن استمارة إنشاء مقالة جديدة إضافة إلى حقول أخرى تحتوي على معلومات تضرّ بالتطبيق؟ سيتم إسناد المعلومات الإضافية بصورة شاملة “Mass Assignment” إلى النموذج ثم إلى قاعدة البيانات جنبًا إلى جنب مع البيانات الأصلية، وهذا قد يتسبب في تعطيل عمل برنامجك أو قد يحدث ما هو أسوأ من ذلك بكثير. يجب علينا إذًا تحديد المعاملات المسموح بإدخالها إلى النموذج، وفي حالتنا هذه سنسمح بإدراج معاملي title و text ونطلب توفّر قيم لهما. وللقيام بذلك عدّل السطر الأول من حدث create بالصورة التالية: @article = Article.new(params.require(:article).permit(:title, :text)) غالبًا ما يتمّ تحديد المعاملات المسموح بإدخالها إلى النموذج في تابع خاص ليصبح بالإمكان إعادة استخدامها بواسطة عدة أحداث في المتحكّم نفسه مثل حدثي create و update، إضافة إلى ذلك يكون هذا التابع خاصًّا وذلك باستخدام المحدّد private لضمان عدم إمكانية استدعائه من خارج السياق المقرّر له، وبالشكل التالي: def create @article = Article.new(article_params) @article.save redirect_to @article end private def article_params params.require(:article).permit(:title, :text) end عرض المقالات إن قمت بتعبئة استمارة المقالة الجديدة وإرسالها فستتلقّى خطأ مفاده عدم عثور Rails على الحدث show، لذا سنقوم بإنشاء هذا الحدث الآن. كما رأينا سابقًا في مخرجات الأمر bin/rails routes فإن مسار الحدث show هو: article GET /articles/:id(.:format) articles#show تعني الصيغة الخاصة :id أن هذا المسار يطلب وجود معامل :id والذي يمثّل في حالتنا هذه معرّف المقالة. وكما فعلنا سابقًا، يجب علينا إضافة الحدث show إلى ملف المتحكّم app/controllers/articles_controller.rb وتحديد العرض المرتبط به. عادة ما تأخذ أحداث CRUD في المتحكّمات الترتيب التالي: index, show, new, edit, create, update, destroy. ويمكن اتّباع الترتيب الذي يعجبك، ولكن تذكّر أن هذه التوابع هي توابع عامّة public، ويجب الإعلان عنها قبل الإعلان عن التوابع الخاصّة. سنضيف الآن الحدث show آخذين ما سبق بعين الاعتبار: class ArticlesController < ApplicationController def show @article = Article.find(params[:id]) end def new end # بقيّة الشيفرة ..... استخدمنا الدالة Article.find للبحث عن المقالة المطلوبة، وذلك بتمرير المعامل params[:id] للحصول على قيمة المعرّف من الطلب الذي أرسلته صفحة إنشاء مقالة جديدة. كذلك استخدمنا متغيّرًا من نوع instance (مسبوقًا بعلامة @) ليكون مرجعًا لكائن المقالة، وذلك لأنّ Rails يمرّر هذا النوع من المتغيّرات إلى العرض. أنشئ الآن ملفًّا جديدًا باسم show.html.erb في المسار app/views/articles/ وأضف إليه الشيفرة التالية: <p> <strong>Title:</strong> <%= @article.title %> </p> <p> <strong>Text:</strong> <%= @article.text %> </p> ستكون الآن قادرًا على إنشاء مقالة جديدة؛ لذا توجّه إلى العنوان http://localhost:3000/articles/new وجرّب إضافة مقالة جديدة. عرض قائمة بمقالات المدوّنة نحتاج الآن إلى عرض قائمة بجميع المقالات الموجودة في المدونة، وسيكون المسار المرتبط بهذا الحدث وبحسب مخرجات الأمر bin/rails routes كالتالي: articles GET /articles(.:format) articles#index أضف الحدث index المرتبط بهذا المسار إلى المتحكّم ArticlesController في الملف app/controllers/articles_controller.rb. من الممارسات الشائعة بين المطوّرين هو كتابة الحدث index في بداية المتحكّم: class ArticlesController < ApplicationController def index @articles = Article.all end def show @article = Article.find(params[:id]) end def new end # بقية الشيفرة ... بعدها أضف العرض الخاصّ بهذا الحدث والموجود في المسار app/views/articles/index.html.erb والذي يتضمّن الشيفرة التالية: <h1>Listing articles</h1> <table> <tr> <th>Title</th> <th>Text</th> </tr> <% @articles.each do |article| %> <tr> <td><%= article.title %></td> <td><%= article.text %></td> <td><%= link_to 'Show', article_path(article) %></td> </tr> <% end %> </table> توجّه الآن إلى العنوان http://localhost:3000/articles في المتصفّح وستشاهد قائمة بجميع المقالات التي أنشأتها مسبقًا. إضافة الروابط للتنقل بين صفحات المدوّنة أصبح بمقدورنا الآن إنشاء وعرض وسرد قائمة المقالات المتوفّرة في المدونة، ولكنّنا بحاجة إلى بعض الروابط التي تساعدنا في التنقل بين صفحات الموقع. افتح الملف app/views/welcome/index.html.erb وعدّله كما يلي: <h1>Hello, Rails!</h1> <%= link_to 'My Blog', controller: 'articles' %> التابع link_to هو أحد دوال العروض المساعدة والمضمّنة في Rails، ووظيفة هذا التابع إنشاء رابط تشعّبي بالاستناد إلى النصّ الذي نمرّره إليه، وهو في حالتنا هذه المسار الخاص بسرد قائمة المقالات. لنضف بعض الروابط إلى العروض الأخرى، ولنبدأ بإضافة رابط إنشاء مقالة جديدة إلى الملف app/views/articles/index.html.erb قبل وسم <table>: <%= link_to 'New article', new_article_path %> سيوجّه هذا الرابط المستخدم إلى الصفحة التي تتضمن استمارة إنشاء مقالة جديدة. سنضيف رابطًا آخر إلى الملفّ app/views/articles/new.html.erb بعد الاستمارة مباشرة، ليتمكن المستخدم من العودة إلى الصفحة الرئيسية: <%= form_for :article, url: articles_path do |f| %> ... <% end %> <%= link_to 'Back', articles_path %> وأخيرًا، سنضيف رابطًا إلى القالب app/views/articles/show.html.erb يوجّه المستخدم إلى الصفحة الرئيسية أيضًا، وبهذا يصبح بميسور من يستعرض مقالة معيّنة أن يرجع إلى الصفحة التي تعرض جميع المقالات: <p> <strong>Title:</strong> <%= @article.title %> </p> <p> <strong>Text:</strong> <%= @article.text %> </p> <%= link_to 'Back', articles_path %> التحقّق من المدخلات لو نظرت إلى النموذج الذي أنشأناه سابقًا فسترى أنّ الملف بسيطٌ للغاية: class Article < ApplicationRecord end لاحظ أنّ الصنف Article موروث من الصنف ApplicationRecord وهو بدوره موروث من الصنف ActiveRecord::Base والذي يتضمّن الكثير من الوظائف والإجراءات الخاصة بالنماذج، مثل عمليات CRUD البسيطة (Create, Read, Update, Destroy) والتحقّق من البيانات Validation، إضافة إلى عمليات البحث المعقّدة وربط النماذج المختلفة مع بعضها البعض. ويقدّم إطار العمل Rails توابع متعدّدة تساعد في التحقق من البيانات المرسلة إلى النموذج. افتح الملف app/models/article.rb وأضف إليه الشيفرة التالية: class Article < ApplicationRecord validates :title, presence: true, length: { minimum: 5 } end سيضمن هذا التغيير امتلاك كل مقالة جديدة في المدونة لعنوان يتألف من خمسة أحرف على الأقل. يتيح Rails التحقّق من أمور متنوّعة في النماذج، مثل التحقّق من وجود أو عدم تكرار الأعمدة والتحقّق من تنسيقها ووجود كائنات مرتبطة بها. لنجرّب الآن استدعاء الدالة @article.save في مقالة لا تمتلك عنوانًا وسنلاحظ أن الدالة ترجع القيمة false. لو عدنا إلى المتحكّم في الملف app/controllers/articles_controller.rb مرّة أخرى سنلاحظ بأنّنا لم نتحقّق من النتيجة التي ترجعها الدالة @article.save ضمن الحدث create. إن فشلت الدالة @article.save في أداء عملها، يجب أن نعيد المستخدم إلى استمارة إضافة مقالة جديدة، وللقيام بذلك عدّل حدثي new و create في الملف app/controllers/articles_controller.rb بالصورة التالية: def new @article = Article.new end def create @article = Article.new(article_params) if @article.save redirect_to @article else render 'new' end end private def article_params params.require(:article).permit(:title, :text) end سينشئ الحدث new متغيّرًا جديدًا من نوع instance يحمل الاسم @article وستتعرّف إلى سبب القيام بذلك بعد قليل. لاحظ أنّنا استخدمنا render داخل الحدث create بدلًا من redirect_to في حال إرجاع الدالة save للقيمة false. يستخدم التابع render لكي يتم تمرير الكائن @article إلى القالب الجديد عند تصييره. وعملية التصيير هذه تتم ضمن نفس الطلب الناتج من إرسال الاستمارة، في حين أن الدالة redirect_to تتسبّب في إرسال طلب آخر. الآن أعد تحميل الصفحة ذات العنوان http://localhost:3000/articles/new وحاول إضافة مقالة جديد دون عنوان، سترى بأنّ Rails يعيدك إلى صفحة الاستمارة، ولكن هذا ليس مفيدًا جدًّا. يجب إخبار المستخدم بحدوث خطأ ما، وللقيام بذلك عدّل الملف app/views/articles/new.html.erb للتحقّق من رسائل الخطأ: <%= form_for :article, url: articles_path do |f| %> <% if @article.errors.any? %> <div id="error_explanation"> <h2> <%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved: </h2> <ul> <% @article.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <p> <%= f.label :title %><br> <%= f.text_field :title %> </p> <p> <%= f.label :text %><br> <%= f.text_area :text %> </p> <p> <%= f.submit %> </p> <% end %> <%= link_to 'Back', articles_path %> تحقّقنا في البداية من وجود أي أخطاء من خلال @article.errors.any?، وفي حال وجودها نعرض قائمة الأخطاء المتوفّرة من خلال @article.errors.full_messages. تأخذ الدالة pluralize معاملين الأول رقمي والثاني نصّي. إن كان العدد أكبر من واحد تتحوّل السلسلة النصّية تلقائيًا إلى صيغة الجمع. إن سبب إضافة @article = Article.new إلى المتحكّم ArticlesController هو أنّنا لو لم نقم بذلك لأصبحت قيمة المتغيّر @articl هي nil، وسيؤدي الاستدعاء @article.errores.any? إلى إطلاق خطأ. يحيط Rails الحقول التي تحتوي على أخطاء بوسم <div> مع صنف CSS يحمل الاسم field_with_errors، ويمكنك تعريف صنف CSS هذا لتنسيق الحقول حسب الرغبة. والآن ستتلقّى رسالة خطا مرتّبة عندما تحاول حفظ مقالة لا تتضمن عنوانًا. في الدرس القادم سنواصل العمل على النموذج حيث سنكتب الشيفرة المسؤولة عن تعديل المقالات وحذفها، ثم سنتعرّف على طريقة إنشاء علاقات بين النماذج المختلفة من خلال إضافة نموذج للتعامل مع التعليقات في المدونة. المصدر: توثيقات Ruby on Rails.
  5. سنتعلّم في هذا الدرس كيفية استخدام تقنيات رسم الأشكال المختلفة وأساليب التلوين والكتابة والأنماط المختلفة في برنامج الإليستريتور لتصميم شعار خيالي لمدينة دبي. سنرسم رموزًا تعبيرية لأهم معالم المدينة بالإضافة إلى وضع بعض الأنماط على اسم المدينة وإدراج صور شعارات المدينة السياحية والدولة. افتح برنامج أدوبي إليستريتور وأنشئ مستندًا جديدًا بأبعاد 1600x1200، سنعتمد هذا الشعار للويب لذلك سندع نظام الألوان RGB والدقة 72ppi. استخدم أداة رسم الأشكال البيضوية وارسم دائرة مثالية مع الاستمرار بالضغط على مفتاح Shift أثناء سحب الشكل للمحافظة على تساوي الأبعاد وبالتالي الحصول على دائرة مثالية. اجعل حجم هذه الدائرة يغطي النصف الأعلى من لوح الرسم. استخدم أداة رسم المنحنيات Arc Tool وارسم قوسًا يبدأ من النقطة اليسرى للدائرة وينتهي في أسفل لوح الرسم بالتوازي مع منتصف الدائرة. لتتمكن من القيام بذلك بدقة وسهولة قم بتفعيل الأدلّة الذكية من الاختصار Ctrl+U واتبع الخطوط الخضراء التي ستقدّم لك المساعدة في الحصول على المطابقة أثناء الرسم. انقر بالزر الأيمن للفأرة على القوس واختر القائمة Transform > Reflect ومن نافذة Reflect اختر الخيار العمودي Vertical ثم انقر على زر COPY للحصول على نسخة معكوسة من القوس عموديًّا. حرّك النسخة الجديدة مع الاستعانة بالأدلّة الذكية إلى الجهة المقابلة من التصميم. استخدم أداة القلم Pen Tool لرسم الشكل التالي اعتبارًا من منتصف الدائرة تقريبًا. كرّر العملية السابقة لإنشاء نسخة معكوسة عن هذا الشكل وحرّك تلك النسخة إلى مكانها الصحيح في الجهة المقابلة. حدّد كلا الشكلين وافتح لوحة Pathfinder ثم اختر الخيار Unite لدمج هذين الشكلين في شكل واحد. استخدم أداة النص Text Tool لكتابة عبارة "مدينة دبي" مع مراعاة الحجم الكبير المتناسب مع حجم الشعار. اختر خطًّا عريضًا، أنا اخترت هنا خط Motken Noqta II. والآن استخدم مجدّدًا أداة القلم لرسم هذا الشكل أيضًا بذات الطريقة أسفل اسم المدينة. كرّر العملية ذاتها من إنشاء نسخة معكوسة وحرّكها إلى موضعها الصحيح ثم أدمج الشكلين معًا في شكل واحد. سنبدأ الآن برسم معالم المدينة، وسيكون برج خلفية أعلى برج في العالم أول ما سنبدأ به. استخدام أداة القلم لرسم شكل تخطيطي تقريبي يشبه البرج. وضعه فوق النصف العلوي من الدائرة. ارسم الآن باستخدام أداة القلم أيضًا شكلًا يمثّل انعكاس الإضاءة داخل شكل البرج للجهة اليسرى. لوّن شكل البرج الأساسي بلون أسود وأبقِ الشكل الداخلي باللون الأبيض. سنرسم الآن شكلًا رمزيًّا لفندق برج العرب. استخدم أداة القلم لرسم الخطوط الخارجية لشكل الفندق الخارجي. ويجب أن يكون أقصر من شكل برج خليفة. زِد حجم الحدود من لوحة الحدود Stroke واجعلها 8 ثم ارسم شكل انعكاس الإضاءة في الجزء الأيسر من المبنى أيضًا مع رسم الشكل العلوي المميز للفندق، وارسم شكلًا بيضويًّا مضغوطًا في الأعلى يمثّل مهبط الطائرات. لوّن شكل الفندق بالأسود وشكل الإضاءة بالأبيض. استمر بذات الطريقة والأسلوب وارسم أشكالًا إضافية تمثّل أهم مباني ومعالم المدينة الأخرى. يجب الانتباه إلى توافق الارتفاعات بشكل متناسب مع الواقع إلى حد ما، كما يجب التنبّه إلى المحافظة على وحدة جهة انعكاس الإضاءة لجميع المباني. حدّد شكل الشريط الملتوي العلوي واذهب إلى لوحة الحدود Stroke ثم زِد حجم الحدود لنحو 12. لوّن هذا الشكل باللون الأسود. أنشئ نسخة عنه وصغّر حجمها قليلًا واجعل لونها أبيض واستخدم أداة التحديد المباشر Direct Selection Tool لتحريك النقاط السفلية من الجزء العلوي من الشريط للداخل قليلًا لمنح شعور وجود ظلال كثيفة أسفل الشكل العام للشريط. زِد حجم الحدود بذات الطريقة والقيمة للشريط السفلي. سنقوم بإنشاء ظلال بطريقة مختلفة هذه المرّة وذلك لتتعلموا كيفية استخدام الطرق المختلفة للقيام ببعض الأمور. حدّد شكل الشريط واذهب للقائمة Effect > Stylize > Drop Shadow نحن بصدد تصميم شعار مسطّح لذلك لا نريد استخدم أية توهّجات حول الأشكال أو ظلال متلاشية لذلك اجعل قيمة Opacity عند 100% وقيمة Blur عند 0، وبما أننا جعلنا ظلال الشريط العلوي للأسفل تحديدًا فيجب علينا أن نطبّق التناسق بين عناصر التصميم لذلك اجعل قيمة المحور x عند 0 وقيمة المحور y عند 10، وسيكون اللون هو الأسود. سنقوم بتجهيز النص الآن. كبّر حجم الخط للنص إلى 175. انقر على زر Warp لتفتح خيارات التحويل الخاصة به. اختر من قائمة Style الخيار Bulge ثم ضع الخيار Bend عند -6%. حدّد النص واذهب إلى القائمة Object > Path > Offset Path ضع القيمة 8 عند خيار Offset واضغط OK. ألغِ تجمّع الشكل الجديد عبر الزر الأيمن للفأرة والخيار Ungroup ثم حدّد الشكل الإضافي الأكبر من النص الأصلي ولوّنه بلون مختلف وبدون لون للحدود. لوّن النص الأساسي باللون الأبيض والحدود بالأسود وزِد حجم الحدود لإبرازها. ارسم هذا الشكل فوق النص السفلي من النص. يمكنك رسم هذا الشكل باستخدام أداة القلم أو باستخدام رسم مستطيل والتعديل عليه للوصول إلى هذا الشكل. أنشئ نسخة عن الشكل الأساسي للنص عبر Ctrl+C للنسخ وCtrl+F للصق ثم حدّد النسخة الجديدة مع الشكل الأسود الذي يغطي نصف النص السفلي واختر Intersect من لوحة Pathfinder. لوّن الشكل الجديد بلون رمادي فاتح. الشكل العام للشعار بدأ يتضّح أكثر فأكثر. لوّن الدائرة بتدرج لوني من الأزرق إلى البرتقالي الفاتح. ارسم شكلًا هندسيًّا بنمط فن الأرابيسك الذي يرمز إلى الأصالة العربية والإسلامية للمدينة. يمكنك تعلّم كيفية رسم مثل هذه الأشكال من درس فن الأرابيسك. سنقوم الآن بدمج أشكال الشعار الخارجية والتي تتضمن الدائرة والقوسين. حدّد جميع هذه الأشكال ثم انقر بزر الفأرة الأيمن واختر Join وبذلك سيتم وصل القوسين وتشكيل شكل موّحد يتضمن ما بينهما. حدّد الدائرة والشكل الجديد ثم انقر على خيار Unite من لوحة Pathfinder ليتم توحيد جميع هذه الأشكال ضمن شكل واحد. لوّن الشكل الكلي بتدرج لوني مطابق للتدرج المستخدم من قبل. أصبح هذا الشكل فوق شكل الأرابيسك لذلك اختفى نموذج الأرابيسك ولاستعادته قم بإرسال الشكل الكلي الجديد للخلف عبر النقر بالزر الأيمن للفأرة واختيار القائمة Arrange > Send to Back أضِف حدودًا سوداء للشكل الكلي الجديد وبحجم 10pt. استخدم أداة التحديد المباشر Direct Selection Tool واختر النقطة السفلية للشكل وحرّك للأعلى لتضغط الشكل عموديًّا. ومن شريط خيارات الأداة في الأعلى اختر من قسم Convert الزاوية الحادة. أضِف مستطيلًا مستدير الزوايا من خلال استعمال أداة رسم المستطيلات مستديرة الزوايا وضعه في منتصف الشريط السفلي بشكل يمتد من أعلى وأسفل الشريط. لوّنه باللون الأبيض وأضِف له حدودًا مطابقة لحدود الشريط باللون الأسود. احصل على شعار دبي السياحي من البحث في الإنترنت من أحد المصادر المجانية ثم أدرجه داخل المستطيل الأخير. أضِف نصًّا جديدًا بلون أسود وبخط عادي عريض واكتب عبارة " تأسست 1833 " ثم اجعل النص منحنيًّا بذات انحناءة الشريط وضعه داخل الشريط السفلي وعدّل الحجم بما يتناسب مع حجم الشريط. والآن أضِف نصًّا جديدًا "مدينة المستقبل" وضعه بإعدادات متناسبة ضمن الشريط العلوي مع وضع ثلاثة نجوم على كل من طرفي الشريط. استخدم أداة القلم لرسم زاويتي إشعاع بيضاء أسفل شكل الشعار الكلي. احصل على شعار دولة الإمارات وأدرجها في المساحة الفارغة في أسفل شكل الشعار الكلي. هذا هو شكل الشعار النهائي ويمكن إنشاء شعارات لمدن أخرى على ذات النمط والأسلوب مع تغيير رموز معالم المدن وشعاراتها. ومع تعديل الألوان وإلغاء التدرجات اللونية سنجعل الشعار مسطّحًا بالكامل ونجعله بنمط مختلف، طبعًا لكل منّا أسلوبه التصميمي المميز وقد يضطر المصمم إلى إجراء الكثير من التعديلات بما يتناسب مع رغبة العميل أو الرؤية العامة للمشروع الذي يعمل عليه.
  6. مدخل إلى html5

    كلنا نعرف نماذج الويب، أليس كذلك؟ أنشِئ <form>، وبعض عناصر <input type="text"‎>، وربما عنصر <input type="password"‎> وإنهِ النموذج بزر <input type="submit"‎>. معلوماتك السابقة منقوصة، إذ تُعرِّف HTML5 ثلاثة عشر نوع إدخالٍ جديدٍ التي تستطيع استعمالها في نماذجك. لاحظ أنني ذكرتُ كلمة "تستطيع" بصيغة المضارع، أي أنَّك تستطيع استخدامها الآن دون أيّة أمور التفافية أو إضافات مُخصَّصة. لكن لا تتحمس كثيرًا؛ فلم أكن أقصد أنَّ جميع تلك الميزات الرائعة مدعومة في كل متصفح؛ ما أقصده هو أنَّ تلك النماذج ستعمل بشكلٍ رائع في المتصفحات الحديثة، لكنها ستبقى تعمل في المتصفحات القديمة (بما في ذلك IE6) وإن لم يكن سلوكها مماثلًا لسلوكها في المتصفحات الحديثة. النص البديل placeholder IE Fiefox Safari Chrome Opera iPhone Android 10+ 3.7+ 4.0+ 4.0+ 11.0+ 4.0+ 2.3+ أول تحسين لنماذج الويب أتت به HTML5 هو القدرة على ضبط نص بديل (placeholder text) في حقل الإدخال. "النص البديل" هو النص الذي سيُعرَض داخل حقل الإدخال لطالما كان حقل الإدخال فارغًا، وسيختفي النص البديل بعد بدء الكتابة في الحقل. من المرجَّح أنَّك شاهدت نصًا بديلًا من قبل، فمتصفح Firefox فيه نصٌ بديلٌ في شريط العنوان مكتوبٌ فيه "Search Bookmarks and History" (النص البديل في الإصدارات الحديثة هو "Search" فقط): وعندما تهمُّ بكتابة أيّ شيءٍ فيه، فسيختفي النص البديل: هذه آلية تضمين النص البديل في نماذج الويب الخاصة بك: <form> <input name="q" placeholder="Search Bookmarks and History"> <input type="submit" value="Search"> </form> ستتجاهل المتصفحاتُ التي لا تدعم النص البديل الخاصيةَ placeholder ببساطة. انظر إلى الجدول أعلاه لمعرفة ما هي المتصفحات التي تدعم النص البديل. س: هل يمكنني وضع وسوم HTML في خاصية placeholder؟ أريد أن أضيف صورةً أو أن أغيِّرَ الألوان. ج: لا يمكن أن تحتوي خاصية placeholder إلا على نصٍ بسيط، ولا يُسمَح بوضع وسوم HTML فيها. لكن هنالك إضافات CSS تسمح لك بتنسيق النص البديل في بعض المتصفحات. التركيز التلقائي على الحقول autofocus IE Fiefox Safari Chrome Opera iPhone Android 10+ 4.0+ 5.0+ 5.0+ 10.1+ . 3.0+ يمكن لمواقع الويب استخدام JavaScript للتركيز على حقلٍ للإدخال في نموذج الويب تلقائيًا. على سبيل المثال، الصفحة الرئيسية لمحرك البحث Google ستُركِّز تلقائيًا (auto-focus) على حقل البحث لكي تستطيع البدء في كتابة عبارة البحث مباشرةً؛ وعلى الرغم من أنَّ هذا الأمر ملائمٌ للكثيرين، لكنه قد يُزعِج المستخدمين المتقدمين أو أولي الاحتياجات الخاصة؛ فلو ضغطتَ على زر المسافة (space) متوقعًا أن تُمرَّر الصفحة إلى الأسفل، فستفاجأ بعدم التمرير، لأنَّ مؤشر الكتابة موجودٌ في حقلٍ من حقول النموذج (سيُكتَب فراغ في ذاك الحقل بدلًا من التمرير). وإن ضغطت على حقل إدخالٍ مختلف أثناء تحميل الصفحة وبدأت الكتابة فيه، فسيأتي سكربت التركيز التلقائي (بعد اكتمال تحميل الصفحة) و"يُساعِدُك" وينقل التركيز إلى حقل الإدخال الأصلي، مما يجعلك تكتب في حقلٍ مختلف، ويقطع عليك «سلسلة أفكارك». ولمّا كان التركيز التلقائي يُنفَّذ عبر JavaScript، فمن الصعب التعامل مع كل الحالات الغريبة؛ وليس هنالك منقذٌ لِمَن يريدون تعطيل ميزة التركيز التلقائي. لحل هذه المشكلة، وفَّرَت HTML5 خاصية autofocus لجميع عناصر التحكم في نماذج الويب. عمل الخاصية autofocus واضحٌ من اسمها: نقل التركيز إلى حقل إدخال مُعيّن في أقرب فرصة ممكنة عند تحميل الصفحة. ولكن لمّا كانت هذه الخاصية موجودة في HTML وليست مُطبَّقة عبر JavaScript، فسيكون سلوكها متماثلًا في جميع مواقع الويب وعلى جميع المتصفحات. وسيتمكن مطورو المتصفحات (أو مطورو الإضافات) من منح المستخدمين إمكانية تعطيل التركيز التلقائي تمامًا. هذا مثالٌ عن كيفية التركيز التلقائي عبر الخاصية autofocus: <form> <input name="q" autofocus> <input type="submit" value="Search"> </form> المتصفحات التي لا تدعم الخاصية autofocus ستتجاهلها تمامًا. انظر إلى الجدول أعلاه لتعرف ما هي المتصفحات التي تدعم خاصية autofocus. هل تريد أن تعمل ميزة التركيز التلقائي في جميع المتصفحات، وليس تلك التي تدعم HTML5 فقط؟ يمكنك الاستمرار في استخدام سكربت التركيز التلقائي، لكن عليك إجراء تعديلين بسيطين: أضف الخاصية autofocus إلى شيفرة HTML اكتشف إذا كان المتصفح يدعم الخاصية autofocus، وشغِّل سكربت التركيز التلقائي إن لم يكن يدعم المتصفح الخاصية autofocus داخليًا. <form name="f"> <input id="q" autofocus> <script> if (!("autofocus" in document.createElement("input"))) { document.getElementById("q").focus(); } </script> <input type="submit" value="Go"> </form> ضبط التركيز التلقائي في أقرب فرصة ممكنة تنتظر العديد من صفحات الويب إلى أن يقع الحدث window.onload لكي تضبط التركيز؛ لكن الحدث window.onload لا يُفعَّل إلا بعد تحميل جميع الصور؛ وإذا حوَت صفحتك على الكثير من الصور، فمن المحتمل أن السكربت الذي ستستخدمه سيؤدي إلى إعادة التركيز على حقل الإدخال المُعيّن بعد أن يبدأ المستخدم تفاعله مع قسمٍ آخر في صفحتك. هذا هو سبب كره المستخدمين المتقدمين لسكربتات التركيز التلقائي. وضعنا سكربت التركيز التلقائي في المثال الموجود في القسم السابق بعد حقل الإدخال مباشرةً؛ وهذا حلٌ مثاليٌ لمشكلتنا، لكن قد ترى أنَّ وضع شيفرة JavaScript في منتصف الصفحة هو أمرٌ سيئ (أو قد لا يسمح لك السند الخلفي [back-end] بذلك)؛ فإن لم تستطع وضع السكربت في منتصف الصفحة، فعليك أن تضبط التركيز أثناء وقوع حدث مخصص مثل ‎$(document).ready()‎ في jQuery بدلًا من window.onload. <head> <script src=jquery.min.js></script> <script> $(document).ready(function() { if (!("autofocus" in document.createElement("input"))) { $("#q").focus(); } }); </script> </head> <body> <form name="f"> <input id="q" autofocus> <input type="submit" value="Go"> </form> تُفعِّل مكتبة jQuery الحدث الخاص ready في أقرب فرصة تتوفر فيها شجرة DOM للصفحة، أي أنها تنتظر إلى أن ينتهي تحميل النص في الصفحة، لكنها لن تنتظر تحميل جميع الصور فيها. لكن هذا ليس حلًا مثاليًا، فإن كانت الصفحة كبيرةً جدًا أو كان الاتصال بطيئًا للغاية، فقد يبدأ المستخدم تفاعله مع الصفحة قبل تنفيذ سكربت التركيز التلقائي؛ إلا أنَّ هذا الحل أفضل بكثير من انتظار وقوع الحدث window.onload. إذا كنت قادرًا على إضافة تعبير JavaScript وحيد في شيفرة صفحتك، فهنالك حلٌ وسطٌ بين الأمرين. يمكنك استخدام الأحداث الخاصة في jQuery لتعريف حدث خاص بك، ولنقل أنَّ اسمه هو autofocus_ready. ثم تستطيع تفعيل هذا الحدث يدويًا بعد أن تُتاح خاصية autofocus مباشرةً. <head> <script src=jquery.min.js></script> <script> $(document).bind('autofocus_ready', function() { if (!("autofocus" in document.createElement("input"))) { $("#q").focus(); } }); </script> </head> <body> <form name="f"> <input id="q" autofocus> <script>$(document).trigger('autofocus_ready');</script> <input type="submit" value="Go"> </form> هذا الحل مثاليٌ مثل الحل الأول، حيث يضبط التركيز إلى الحقل المُحدَّد في أقرب فرصة ممكنة، وذلك أثناء تحميل بقية نص الصفحة. لكنه ينقل تنفيذ التسلسل المنطقي لتطبيقك (التركيز على حقل الإدخال) من جسم الصفحة إلى ترويستها. يعتمد المثال السابق على مكتبة jQuery، لكن مفهوم الأحداث الخاصة ليس مقتصرًا على jQuery فحسب، فلدى مكتبات JavaScript الأخرى مثل YUI و Dojo إمكانياتٌ مشابهة. الخلاصة هي: من المهم ضبط التركيز التلقائي ضبطًا سليمًا. يُفضَّل أن تدع المتصفح يضبط التركيز التلقائي عبر خاصية autofocus في حقل الإدخال الذي تريد التركيز تلقائيًا عليه إذا كان ذلك ممكنًا. إذا كنتَ تريد حلًا للمتصفحات القديمة، فاكتشف أولًا دعم المتصفح للخاصية autofocus لكي تتأكد أنَّ السكربت الذي كتبتَه سيُنفَّذ على المتصفحات القديمة فقط. حاول ضبط التركيز التلقائي في أقرب فرصة ممكنة، حاول مثلًا أن تضع سكربت التركيز في شيفرة HTML بعد حقل الإدخال مباشرةً. فإن لم تستطع، فاستعمل مكتبة JavaScript تدعم الأحداث المُخصَّصة، وفعِّل الحدث المُخصَّص مباشرةً بعد شيفرة النموذج؛ وإن لم يكن ذلك ممكنًا، فاعتمد على حدثٍ مثل الحدث ‎$(document).ready()‎ في مكتبة jQuery. لا تنتظر الحدث window.onload لكي يضبط التركيز تحت أيّ ظرفٍ كان. عناوين البريد الإلكتروني لفترةٍ تجاوزت العقد من الزمن، احتوت نماذج الويب على عدِّد قليلٍ من الحقول، وكان أكثرها شيوعًا: نوع الحقل شيفرة HTML ملاحظات مربع تأشير (checkbox) "input type="checkbox يمكن تفعيله أو تعطيله زر انتقاء (radio button) "input type="radio يمكن تجميعه مع حقول أخرى حقل كلمة مرور input type="password"‎ يُظهِر نقطًا بدلًا من المحارف التي تكتبها قائمة منسدلة <select> </select> - مُنتقي الملفات "input type="file يُظهِر مربع حوار "اختيار ملف" زر الإرسال "input type="submit - نص عادي ‎input type="text"‎‎ يُمكن حذف الخاصية type تعمل جميع أنواع الحقول السابقة في HTML5، فلو أردت "التحديث إلى HTML5" (ربما بتغيير نوع المستند DOCTYPE)، فلن تحتاج إلى إجراء أيّة تعديلات على نماذج الويب عندك، والفضل بذلك يعود إلى توافقية HTML5 مع الإصدارات التي تسبقها. لكن HTML5 أضافت ثلاثة عشر نوعًا جديدًا من الحقول، ولأسبابٍ ستتضح لك بعد قليل، لا يوجد سببٌ يمنعك من استعمالها الآن. أول أنواع المدخلات الجديدة مخصصٌ لعناوين البريد، ويبدو كما يلي: <form> <input type="email"> <input type="submit" value="Go"> </form> أوشكتُ على كتابة جملةٍ مطلعها: "أما في المتصفحات التي لا تدعم type="email"‎..." لكنني تداركتُ نفسي وتوقفت. لكن ما السبب؟ لأنني لستُ متأكدًا من ماذا يعني عدم دعم المتصفح للحقل type="email"‎، حيث «تدعم» جميع المتصفحات type="email"‎‎، لكنها قد لا تفعل شيئًا خاصًا لها (سترى بعد قليل بعض الأمثلة عن المعاملة الخاصة لهذا الحقل)؛ لكن المتصفحات التي لا تتعرف على type="email"‎ ستعامله على أنَّه type="text"‎ وسيظهر كحقلٍ نصيٍ عاديٍ. لا تسعني الكلمات للتعبير عن مدى أهمية ما سبق، لأنَّ في الويب ملايين النماذج التي تسألك أن تدخِل عنوان بريدك الإلكتروني، وجميعها تستعمل <input type="text"‎> وستشاهد مربعًا نصيًا، ثم تُدخِل فيه عنوان بريدك، وانتهى. ثم أتت HTML5 التي أضافت type="email"‎، فهل سترتبك المتصفحات؟ لا، يُعامِل كل متصفح على وجه هذا الكوكب القِيم غير المعروفة لخاصية type على أنها type="text"‎، بما في ذلك IE 6. لذلك تستطيع استعمال type="email"‎ حالًا دون القلق حول دعم المتصفحات. لكن ماذا يعني أنَّ المتصفح "يدعم" الحقل type="email"‎؟ حسنًا، قد يعني هذا عدِّة أشياء. لم تُحدِّد مواصفة HTML5 أيّة توصية حول الواجهة الرسومية التي تظهر للمستخدم لأنواع المدخلات الجديدة. ستعرضه أغلبية متصفحات سطر المكتب مثل Safari و Chrome و Opera و Firefox كحقلٍ نصيّ؛ ولهذا لن يُلاحِظ مستخدمو موقعك الفرق (إلى أن يُحاولوا إرسال النموذج). ثم ها قد أتت الهواتف المحمولة… ليس للهواتف المحمولة لوحة مفاتيح فيزيائية، فكل "الكتابة" تتم بالضغط على لوحة مفاتيح ظاهرة على الشاشة التي تُعرَض عند الحاجة لها (عند التركيز على حقل من حقول أحد النماذج في صفحة الويب على سبيل المثال). تتعرف متصفحات الهواتف المحمولة الذكية على العديد من أنواع المدخلات الجديدة في HTML5، وتُجري تعديلات ديناميكية على لوحة المفاتيح الظاهرة على الشاشة لكي تُلائم نوع المدخلات. مثلًا، عناوين البريد الإلكتروني هي نصوص، صحيح؟ بالطبع، لكنها نوع خاص من النصوص، فمثلًا يحتوي كل عنوان بريد إلكتروني (نظريًا) على رمز @ وعلى نقطة (.) واحدة على الأقل؛ ومن غير المحتمل أن يحتوي على فراغات؛ لذا لو كنتَ تستعمل هاتف iPhone وحاولت الكتابة في عنصر <input type="email‎"‎>، فستظهر لوحة مفاتيح تحتوي على زر مسافة أصغر من المعتاد، بالإضافة إلى أزرار مخصصة لمحرفَي @ و . . لا توجد سلبيات لتحويل جميع الحقول التي تُمثِّل عناوين البريد الإلكتروني إلى type="email"‎ في الحال. فلن يلاحظ ذلك أحدٌ إلا مستخدمي الهواتف المحمولة، الذين أظن أنَّهم لن ينتبهوا لذلك أيضًا. لكن من سيلاحظ ذلك سيبتسم بصمت ويشكرك في قلبه لأنَّك سهلت عليه الأمر قليلًا. عناوين الويب عناوين مواقع الويب -التي يُسمّيها مهووسو المعايير "URLs"، إلا بعض المتحذلقين الذين يدعونها "URIs"- هي نوعٌ آخرٌ من النص المُخصَص؛ البنية العامة لعناوين الويب مرتبطة بمعايير الإنترنت ذات الصلة. إذا طلب منك أحدهم كتابة عنوان لموقع ويب في نموذج، فسيتوقعون منك كتابة شيءٍ مثل "http://www.google.com/‎" وليس "125 Farwood Road"؛ ومن الشائع استخدام الخط المائل / في العناوين (الخط المائل مذكورٌ ثلاث مرات في عنوان صفحة Google الرئيسية)؛ وينتشر استخدام النقط . أيضًا، لكن يُمنَع وضع فراغات في العنوان. لدى جميع عناوين الويب لاحقة للنطاق مثل "‎.com" أو "‎.org". تعرض أغلبية متصفحات الويب لسطح المكتب الحديثة حقل type="url"‎ كحقلٍ نصيّ عادي، لذلك لن يُلاحظ مستخدمو موقعك ذلك إلى أن يحاولوا أن يُرسِلوا النموذج. ستُعامِل المتصفحات التي لا تدعم HTML5 الحقل type="url"‎ كحقل type="text"‎ تمامًا، فلا بأس من استعمال هذا الحقل في صفحات الويب الحديثة عند الحاجة. ستُعدِّل الهواتف الذكية من طريقة عرض لوحة المفاتيح كما في حقل عنوان البريد الإلكتروني، لكن لوحة المفاتيح في هذه المرة ستُخصَّص لتسهيل إدخال عناوين الويب. ففي هواتف iPhone سيُزال زر المسافة تمامًا وسيُستعاض عنه بنقطة وخط مائل وزر "‎.com" (يمكنك الضغط مطولًا على زر "‎.com" للاختيار بين اللاحقات الشهيرة الأخرى مثل "‎.org" أو "‎.net")؛ وستُخصِّص هواتف أندرويد لوحة مفاتيحها بشكلٍ مشابه. إدخال الأرقام طلب إدخال الأرقام أصعب من طلب كتابة عنوان بريد إلكتروني أو موقع ويب؛ لأنَّ الأرقام معقدة أكثر مما تظن. اختر رقما ما بسرعة. -1؟ لا، كنت أقصد رقمًا بين 1 و 10. ‎7½‎؟ لا، ليس رقمًا كسريًا. π؟ لماذا تختار الأرقام العجيبة؟! الفكرة التي أود إيصالها هي أنَّك لا تسأل عن "رقمٍ ما"، فمن المحتمل أنَّك ستطلب من المستخدم إدخال رقم في مجال معيّن، ولا تريد إلا نوعًا محدَّدًا من الأرقام ضمن ذلك المجال، وقد تريد استبعاد الأعداد الكسرية أو العشرية، أو أن تسمح بإدخال الأرقام التي تقبل القسمة على 10. ستسمح لك HTML5 بكل هذا. <input type="number" min="0" max="10" step="2" value="6"> لنتحدث عن الخاصيات السابقة كلًا على حدة (يمكنك المتابعة مع المثال الحي إن شئت). الخاصية type="number"‎ تعني أنَّ الحقل يقبل الأرقام. الخاصية min="0"‎ تُحدِّد القيمة الدنيا المقبولة لهذا الحقل. الخاصية max="10"‎ تُحدِّد القيمة القصوى المقبولة. الخاصية step="2"‎ مجتمعةً مع قيمة الخاصية min ستُعرِّف ما هي الأرقام المسموحة في المجال: 0 و 2 و 4 وهكذا إلى أن تصل إلى قيمة الخاصية max. الخاصية value="6"‎ تُحدِّد القيمة الافتراضية. يُفترَض أن تكون هذه الخاصية مألوفةً لديك، فهي نفس الخاصية التي تستعملها دومًا لتحديد قيم حقول النموذج (ذكرتُ هذه النقطة هنا لكي أذكِّرك أنَّ HTML5 مبنية على إصدارات HTML السابقة، فلا حاجة أن تعيد تعلم كل الأمور التي تعرفها من قبل!). هذه هي الشيفرة الخاصة بحقل الأرقام. ابقِ في ذهنك أنَّ جميع الخاصيات السابقة اختيارية. فإذا كانت لديك قيمة دنيا للمجال المقبول لكن دون وجود حد أقصى للأرقام، فيمكنك ضبط خاصية min وعدم ضبط الخاصية max. الخطوة الافتراضية هي 1، ويمكنك عدم ذكر الخاصية step إلا إذا كانت قيمة الخطوة عندك مختلفةً عن 1. تستطيع إسناد سلسلة نصية فارغة إلى الخاصية value إن لم تكن هنالك قيمةٌ افتراضيةٌ، أو بإمكانك حذف الخاصية تمامًا. لكن HTML5 لا تقف عند هذا الحد، حيث توفِّر لك دوال JavaScript للتحكم بهذا الحقل: الدالة (input.stepUp(n تزيد قيمة الحقل بمقدار n. الدالة (input.stepDown(n تنقص من قيمة الحقل مقدار n. الخاصية input.valueAsNumber تُعيد القيمة الحالية للحقل كعدد ذي فاصلةٍ عشرية (تذكَّر أنَّ الخاصية input.value تُعيد سلسلةً نصيةً دومًا). هل صَعُبَ عليك تخيل شكل هذا الحقل؟ حسنًا، طريقة عرض هذا الحقل عائدة تمامًا لمتصفحك، ويدعم مختلف مُصنِّعي المتصفحات هذا الحقل بطرائق مختلفة. فعلى هواتف iPhone -التي يصعب فيها كتابة المدخلات عمومًا- سيُحسِّن المتصفح من لوحة المفاتيح مرةً أخرى لكتابة الأرقام. أما في نسخة سطح المكتب من متصفح Opera، سيظهر نفس الحقل type="number"‎ كعنصر "spinbox" الذي يملك أسهمًا صغيرةً للأعلى والأسفل تستطيع الضغط عليها لتغيير القيمة. تحترم المتصفحات قيم الخاصيات min و max و step، لذلك ستكون قيمة ذاك الحقل مقبولة دومًا، فلو وصلت إلى القيمة القصوى، فسيُعطَّل زر السهم العلوي ولن تستطيع زيادة الرقم الموجود. وكما في بقية حقول الإدخال التي شرحناها سابقًا في هذا الدرس، المتصفحات التي لا تدعم type="number"‎ ستُعامِل الحقل وكأنَّه type="text"‎، وستظهر القيمة الافتراضية في الحقل النصي (لأنها مُخزَّنة في الخاصية value)، لكن سيتجاهل المتصفح الخاصيات الأخرى مثل min و max؛ لكنك تستطيع إنشاء spinbox بنفسك، أو قد تستعمل مكتبة JavaScript تحتوي على هذا العنصر؛ لكن تذكَّر أن تتحقق من دعم المتصفح لهذا الحقل أولًا، على سبيل المثال: if (!Modernizr.inputtypes.number) { //لا يوجد دعم لحقول type=number //ربما تجرِّب Dojo أو مكتبة JavaScript أخرى } تحديد الأرقام عبر المزلاج هنالك آليةٌ أخرى لتمثيل المدخلات الرقمية، فمن المحتمل أنَّك رأيك "مزلاجًا" (slider) من قبل يُشبِه: يمكنك وضع المزلاج في نماذج HTML5 أيضًا، والشيفرة الخاصة به شبيهة جدًا بحقل spinbox: <input type="range" min="0" max="10" step="2" value="6"> جميع الخاصيات المتوفرة مماثلة لحقل type="number"‎ (أي min و max و step و value)، ولها نفس المعنى. الفرق الوحيد هو في واجهة الاستخدام؛ فبدلًا من وجود حقل لكتابة الرقم، ستعرض المتصفحات الحديثة الحقل type="range"‎ كمزلاج، بينما ستعرضه المتصفحات القديمة التي لا تدعم HTML5 كحقل type="text"‎، لذا لا يوجد سبب يمنعك من البدء باستخدامه مباشرةً. منتقي التاريخ Date picker لم تتضمن HTML 4 حقلًا لاختيار التاريخ، لكن مكتبات JavaScript تداركت الأمر (Dojo و jQuery UI و YUI و Closure Library) لكن هذه الحلول كانت تتطلب الخوض في مكتبة JavaScript التي تدعم حقل مُنتقي التاريخ (date picker). أضافت HTML5 أخيرًا حقلًا لانتقاء التاريخ دون الحاجة إلى كتابته يدويًا عبر JavaScript؛ وفي الواقع، أضفات ستة حقول: واحد للتاريخ (date) وآخر للشهر (month) وآخر للأسبوع (week) وآخر للوقت (time) وآخر للتاريخ والوقت (date + time) وآخر للتاريخ والوقت لكن دون ذكر المنطقة الزمنية (date + time – timezone). لكن للأسف، هذا الحقل غير مدعوم من أغلبية المتصفحات. إذ يدعمه متصفح Opera منذ الإصدار التاسع و Chrome من الإصدار 20. هذه هي طريقة عرض متصفح Opera لحقل <input type="date"‎>: وإذا أردت من المستخدم انتقاء الوقت والتاريخ، فهنالك حقل <input type="datetime"‎>: أما لو كنت تحتاج إلى الشهر والسنة فقط (ربما تريد إدخال تاريخ انتهاء البطاقة الائتمانية)، فهنالك حقل <input type="month"‎>: ويتوفر أيضًا حقلٌ لانتقاء أسبوع معيّن في السنة –وإن لم يكن ذلك شائعًا– عبر الحقل <input type="week"‎>: أخيرًا وليس آخرًا، يمكنك اختيار الوقت عبر الحقل <input type="time"‎>: من المحتمل أن تدعم المتصفحات حقول الإدخال السابقة تباعًا، لكن كما في حقل type="email"‎ وغيره، ستُعرَض هذه الحقول كحقولٍ نصيةٍ بسيطةٍ في المتصفحات التي لا تدعم الحقل type="date"‎ وأخوته. يمكنك ببساطة أن تستعمل الحقل <input type="date"‎> وأخوته لتوفِّر مُنتقي التاريخ لمستخدمي متصفحَي Opera و Chrome وتنتظر دعم بقية المتصفحات. أو أن تعتمد حلًا عمليًا هو استعمال <input type="date"‎> ثم تكتشف إن كان المتصفح يدعم مُنتقي التاريخ، ثم تستعمل حلًا برمجيًا إن لم يكن يدعمه (مثل Dojo و jQuery UI و YUI و Closure Library أو حلًا آخر). <form> <input type="date"> </form> ... <script> var i = document.createElement("input"); i.setAttribute("type", "date"); if (i.type == "text") { //لا يوجد دعم لمنتقي التاريخ :-( //استخدام مكتبة Dojo/jQueryUI/YUI/Closure لإنشاء واحد //ثم استبدل حقل <input> ديناميكيًا } </script> حقول البحث حسنًا، وظيفة هذا الحقل واضحة من اسمه، لكن قد نحتاج إلى شرح آلية تطبيقه في المتصفحات. البحث لا يكون فقط في محركات البحث مثل Google أو Yahoo!‎، فمن الممكن أن يكون حقل البحث في أيّ صفحة وفي أيّ موقع؛ فهنالك واحدٌ في موقع أمازون، وآخر في موقع CNN، ويتواجد أيضًا في أغلبية المدونات. لكن ما هو الوسم المستخدم لتلك الحقول؟ <input type="text"‎>، مثل بقية حقول النص الموجودة في الويب. لنحاول تصحيح الأمر… <form> <input name="q" type="search"> <input type="submit" value="Find"> </form> ما رأيك بتجربة حقل <input type="search"‎> في متصفحك. قد لا تلاحظ أيّة اختلافات بينه وبين الحقل النصي العادي؛ لكن إن كنتَ تستعمل Safari على نظام Mac OS X، فسيبدو الحقل كما يلي: هل لاحظت الفرق؟ لدى حقل البحث زوايا مدورة! أعلم أنَّك لا تستطيع احتواء نفسك من الفرح، لكن انتظر، فهنالك المزيد! عندما تبدأ الكتابة في حقل type="search"‎، فسيضع المتصفح زر "x" صغير في الجانب الأيمن من الحقل؛ ويؤدي الضغط عليه إلى حذف محتويات الحقل (متصفح Chrome، الذي يتشارك مع Safari في البنية الداخلية، له نفس السلوك السابق). الغرض من التعديلات البسيطة السابقة هي إعطاء حقول البحث شكلًا وسلوكًا شبيهًا بحقول البحث في تطبيقات Mac OS X المكتبية مثل iTunes. يستعمل موقع Apple.com الحقل <input type="search"‎> لحقل البحث في الموقع لإعطائه شكلًا مألوفًا لمستخدمي Mac، لكن ذلك ليس خاصًا بنظام Mac فقط؛ إذ أنَّه شيفرة HTML فحسب، وبهذا يستطيع كل متصفح على كل منصة (أو نظام تشغيل) أن يعرض الحقل بشكلٍ مشابه لعناصر الواجهة الرسومية الخاصة بالمنصة. وكما هو الحال في بقية أنواع الحقول، المتصفحات التي لا تتعرف على حقل type="search"‎ ستعامِله كأنَّه type="text"‎؛ فلا يوجد سببٌ يمنعك من استخدام type="search"‎ في حقول البحث حالًا. منتقي الألوان تُعرِّف HTML5 حقل <input type="color"‎> الذي يسمح لك باختيار لونٍ ما ويُعيد التمثيل الست عشري للون المُختار؛ تأخرت المتصفحات في دعم هذا الحقل، حيث يدعمه Opera منذ الإصدار 17، و Firefox منذ الإصدار 29، و Chrome منذ الإصدار 20، وما زلنا في انتظار دعم بقية المتصفحات له. يندمج هذا الحقل جيدًا مع منتقي الألوان الموجود في نظامَيّ ويندوز و Mac، أما في لينُكس فهو يعرض مُنتقي ألوان أساسي. وهو يُعيد قيمة ست عشرية للون RGB الذي يمكن استخدامه في أي مكان يقبل ألوان CSS (جرِّب مُنتقي الألوان في متصفحك). التحقق من صحة مدخلات المستخدم IE Fiefox Safari Chrome Opera iPhone Android 10+ 4.0+ 5.0+ 10.0+ 9.0+ 4.1+ 4.0+ تحدثت في هذا الفصل عن عددٍ من حقول الإدخال الجديدة وبعض الميزات المحدثة مثل التركيز التلقائي لحقلٍ من حقول النموذج، لكنني لم أذكر ما أعتبره أهم جزء من النماذج الحديثة في HTML5: التحقق التلقائي من صحة مدخلات المستخدم. خذ على سبيل المثال مشكلةً شائعةً هي إدخال عنوان بريد إلكتروني في نموذج ويب؛ ربما ستجري تحققًا من مدخلات المستخدم من طرف العميل عبر JavaScript، متبوعًا بتحققٍ من جهة الخادوم عبر PHP أو Python أو أيًّا كانت لغة البرمجة التي تستعملها. لن يُشكِّل التحقق من مدخلات المستخدم عبر HTML5 بديلًا عن التحقق من جهة الخادوم، لكن من المحتمل أن تشكِّل بديلًا عن سكربتات JavaScript التي تستعملها. هنالك مشكلتين كبيرتين في التحقق من البريد الإلكتروني عبر JavaScript: عددٌ كبيرٌ جدًا من زوار موقعك (حوالي 10% تقريبًا) يُعطِّلون JavaScript في متصفحهم ستفشل في التحقق من صحة البريد الإلكتروني أنا آسف لقول هذا، لكنك ستفشل في ذلك. فعملية تحديد فيما إذا كانت سلسلة نصية ما هي عنوان بريد إلكتروني معقدةٌ بشكلٍ لا يُصدَّق. فكلما أمعنت النظر في الأمر، لوجدت مدى تعقيده. هل ذكرتُ لتوي أنَّ الأمر معقدٌ جدًا جدًا؟ أليس من الأسهل إلقاء ذاك الحِمل والصداع الناتج عنه على عاتق المتصفح؟ لقطة الشاشة السابقة مأخوذة من متصفح Opera 10، إلا أنَّ إمكانية التحقق من حقول النماذج متوفرة منذ الإصدار 9. ولدى Firefox 4 و Chrome 10 آليةٌ مشابهة. كل ما عليك فعله هو ضبط الخاصية type إلى "email". وعندما يحاول المستخدم إرسال (submit) نموذج فيه حقل <input type="email"‎>، فسيتحقق المتصفح تلقائيًا من عنوان البريد الإلكتروني حتى لو كانت JavaScript معطَّلةً في المتصفح. توفِّر HTML5 أيضًا تحققًا من عناوين الويب المُدخَلة في حقول <input type="url"‎>، والأرقام المدخلة في حقول <input type="number"‎>؛ ستؤخذ قيم الخاصية min و max بعين الاعتبار عند التحقق من الأرقام، فلن تسمح لك المتصفحات بإرسال النموذج إذا أدخلتَ رقمًا كبيرًا أكبر من الحد الأقصى. لا حاجة إلى وضع شيفرات لتفعيل التحقق من المدخلات في HTML5؛ حيث تكون مفعَّلة افتراضيًا، إلا أنَّك تستطيع تعطيلها عبر وضع الخاصية novalidate. <form novalidate> <input type="email" id="addr"> <input type="submit" value="Subscribe"> </form> الحقول المطلوبة required IE Fiefox Safari Chrome Opera iPhone Android 10+ 4.0+ 5.0+ 10.0+ 9.0+ 4.1+ 4.0+ التحقق من مدخلات المستخدم في HTML5 ليس محدودًا بنوع الحقل، إذ تستطيع أيضًا أن تُشير إلى أنَّ بعض الحقول "مطلوبةٌ"؛ يجب تحديد قيم للحقول المطلوبة قبل أن ترسِل النموذج. شيفرة الحقول المطلوبة بسيطةٌ جدًا: <form> <input id="q" required> <input type="submit" value="Search"> </form> يمكنك تجربة حقل <input required> في متصفحك. قد تُغيّر بعض المتصفحات الشكل الافتراضي للحقول المطلوبة. وإذا حاول المستخدم إرسال النموذج دون تعبئة الحقل المطلوب، فسيظهر إشعار يخبر المستخدم أنَّ من الضروري إدخال قيمة في الحقل وعدم تركه فارغًا (الصورة الآتية من متصفح Chrome): ترجمة -وبتصرّف- للفصل "HTML5 Forms" من كتاب Dive Into HTML5 لمؤلفه Mark Pilgrim.
  7. هناك عدد كبير من ملحقات ووردبريس التي تسمح لك بتضمين كل أنواع الاستمارات والنّماذج forms إلى موقعك، سواء تعلق الأمر بنماذج التواصل العامة (contact forms)، الاستبيانات الاستقصائية المفصلة (detailed surveys) أو النماذج المتقدمة (premium forms) التي تحمل العديد من الخانات القابلة للتعديل والميزات الإضافية. لكن قبل أن تقوم بتحميل وتنزيل ملحق ووردبريس الشائع الذي تصادفه في المرة القادمة، يجب عليك أن تأخذ أولا بعين الاعتبار نماذج جوجل (Google Forms)، خصوصا أن هناك ملحقا خاصًا بها يجعل إدماج هذه النماذج في موقع ووردبريس الخاص بك أمرا سلسا. نماذج جوجل (Google forms) تتجلى روعة نماذج جوجل في كونها متعددة الاستعمالات ومجانية في نفس الوقت، رغم ذلك فإن حَشْرَها كجزء صغير في الخدمة السَحَابية الخاصة بجوجل يؤدي إلى عدم معرفة المستعملين بها. إن لم تكن تملك حسابا في جوجل درايف (Google drive) وهو أمر مستبعد، يمكن لك الحصول على حساب بشكل مجاني وفي لمح البصر، أما إن كنت تملك حسابا، فيمكنك التوجه إلى My drive لتطّلع على هذه النماذج من خلال الضغط على الزر الأحمر الكبير New في العمود المتواجد في اليسار. في القائمة الظاهرة قم بالضغط على خيار More في الأسفل، حيث ستظهر قائمة أخرى تتضمن Google Forms بالضغط عليها تُفْتَحُ صفحة جديدة لتحرير محتوى النموذج. باستعمال نماذج جوجل يمكن لك القيام بـ: إنشاء مسوح استقصائية، تطبيقات، تسجيلات، استبيانات، استطلاعات الرأي، اختبارات وأكثر من هذا. استعمال تَفَرُّعات الصفحات وخاصية تجاوز الأسئلة ( page branching and question skip logic ) للحصول على نماذج أكثر تقدما. استعمال إضافات (add-ons) من أجل نماذج أكثر كفاءة. معاينة نموذجك. إعطاء تصميم خاص لصفحة التأكيد الخاصة بك. إدارة الأجوبة التي تتلقاها. تنسيق حقول النصوص، الفقرات، إمكانية استخدام الخيارات المتعددة، الخانات أو قائمة الخيارات حسب رغبتك. تجميع عناوين البريد الإلكتروني من المشتركين لغرض مُراسلتهم بنشرات إخبارية (Newsletter). إعادة ترتيب الأسئلة بسهولة من خلال خاصية السحب والإفلات (Drag and drop). إضافة صور ومقاطع فيديو من يوتيوب. تصميم النموذج بشكل مرئي (Visual theme design). التعاون مع مستعملي جوجل درايف آخرين لإنجاز نماذجك. و غيرها من الخصائص. إن مشاركة النموذج من خلال رابط أمر سهل للغاية لكن ماذا إن أردت أن تضعه في صفحة على موقع ووردبريس الخاص بك؟ إحدى الطرق السريعة للقيام بذلك هي استخدام خاصية التضمين (embed)، والتي يمكن إيجادها من خلال الضغط على File في القائمة أعلى الصفحة التي تقوم فيها بصياغة نموذج جوجل الخاص بك، اضغط على Embed ثم قم بنسخ ولصق شيفرة HMTL في محرر النص الخاص بصفحة أو منشور ما على موقعك، يمكن لك أن تعمل على تعديل ارتفاع وسمك النموذج لتتأكد من احتواء الصفحة له بشكل جيد. أكبر مشكل فيما يخص الاقتصار على القيام بتضمين شفرة نموذجك التي يقدمها جوجل، هو حفاظه على النمط الافتراضي (default style) الخاص بنموذج جوجل، وعدم اندماجه مع تصميم موقعك، حيث أنه لا يستفيد من أنماط CSS الموجودة كما أنه يُظْهِرُ شعار جوجل فضلا عن العديد من الروابط نحو المزيد من المعلومات الخاصة بجوجل. لحسن الحظ، يوجد ملحق لحل هذا المشكل. ملحق Google Forms Plugin for WordPress يسمح لك هذا الملحق باستخدام نماذج جوجل وإدارتها من خلال لوحة التّحكم على وورديريس. كما يقدم الكثير من الخاصيات لتحسين عملية الدمج مع ووردبريس وجعلها أكثر خصوصية مقارنة باستعمال شيفرة HTML مباشرة على صفحتك أو منشورك. إليك فيما يلي أولى الخطوات للقيام بذلك. استعمال نماذج جوجل مع ملحق Google Forms Plugin for WordPress بمجرد تنصيب وتفعيل الملحق، تظهر خاصية جديدة: Google Forms في الشريط الجانبي الخاص بووردبريس، عندما تضع مؤشر الفأرة عليها دون الحاجة إلى الضغط، ستظهر ثلاثة خيارات: Google forms ،Add New Google Form و Form Submission Log. يسمح لك تبويب Google forms بإلقاء لمحة سريعة بنفس الطريقة التي يمكن لك من خلالها رؤية كل منشوراتك أو صفحاتك، كما يُمكنك تصنيف، تعديل أو حذف عدّة نماذج دُفعة واحدة. لن يظهر أي شيء أسفل تبويب Google forms في حال ما إن لم تملك أي نماذج بعد، قم بالضغط على Add New Google Form في التبويب سالف الذكر أو في خيار Add New Google Form في القائمة لإنشاء نموذج جديد من خلال تحديد عنُوان للنموذج وملء الحقول. يمكن أن تستعمل هذا الملحق لإنشاء نماذجك. في المثال التالي، سنستعمل نموذجا بسيطا للتسجيل في حدث ما: للقيام بهذا، ستحتاج إلى نموذج سبق لنا إنشاؤه، فكما ستلاحظ في تبويب Add New Google Form الخاص بالملحق أن Form URL هو أحد أول الحقول التي يجب ملؤها. إن القيام بهذا أمر سهل للغاية. بالرجوع إلى جوجل درايف حيث تقوم بإنشاء نموذجك، قم بالضغط على الزر الأزرق Send Form المتواجد في الزاوية أعلى اليمين أو أسفل الصفحة، سيتم فتح علبة تتضمن خيارات المشاركة والتي تتضمن الرابط الخاص بالنسخ والنشر. بمجرد أن تقوم بنسخ الرابط، قم بلصقه في حقل Form URL في الملحق. لاحقا يمكن لك أن تقوم أيضا بإضافة رابط التأكيد Confirm URL. بما أن صفحة التأكيد الافتراضية (default Confirmation Page) قاعدية جدا ودمجها في موقع ووردبريس الخاص بك غير ممكن فإنه من الأفضل ملء هذا الحقل لإبقاء صفحات كامل النّموذج على موقعك. فيما يتعلق بميزة Custom Confirmation Page Style، يمكن لك أن تحدد كيفية تقديمها من خلال تحديد أحد الخيارية Redirect أو AJAX. تذكر أنه في حال ما إذا تركتها في خيار None، فإنّه ستتم إعادة تحويل الصّفحة redirect بشكل قياسي. هذه هي الحقول الثلاثة الأساسية التي يجب عليك ملؤها في نموذجك ليعمل بشكل جيد. فيما يلي، لنلقي نظرة على كيفية أخرى لتخصيص نموذجك على موقع ووردبريس الخاص بك. ملء الحقول الإضافية في ملحق Google Forms WordPress إضافة إلى حقلي Form URL و Confirm URL هناك الكثير من الحقول الأخرى لتقوم بملئها، لكن من المستبعد أن تحتاج ملأها أو تعديلها كلها خصوصا إذا كنت تقوم بإعداد نموذج بسيط. تحريا للدقة، لنقم على أي حال بتفحصها أهمّها وشرح معانيها. Alert (تنبيه): من أجل إعلام المستعملين أنه قد تم إرسال النّموذج بنجاح، يمكن لك أن تقوم بكتابة رسالة بسيطة على سبيل المثال: "شكرا على التسجيل" سيتم عرضها في علبة تنبيه جافا سكريبت (JavaScript Alert box). Class (صنف): إن كنت تنوي التعديل على الـ CSS الخاص بنموذجك، يمكن لك أن تستعمل خانة class لتقوم بإضافة صنف أو أصناف لعنصر div الذي يحتوي النموذج. افصل بين كل صنف والآخر بإضافة فراغ بينهما. Email (بريد إلكتروني): يمكن لك أن تختار إرسال رسالة إلى بريد المدير أو إلى أي بريد آخر كلما تم بنجاح إدخال واستقبال نموذج جديد. تحتوي هذه الرسالة على رابط URL للنموذج فضلا عن وقت وتاريخ الإدخال. Send to (أرسل إلى): إن قمت بتفعيل خيار Email أعلاه، فعليك أن تقوم في هذا الحقل بإدخال البريد الإلكتروني الذي تريد أن تستقبل فيه رسالة التنبيه. لا تنس أنه سيتم دائما إرسال رسالة إلى المدير على هيئة (BCC (Blind Carbon Copy. Form CSS: يُستعمل هذا الحقل لإضافة أية أنماط CSS خاصة تريد إضافتها لتعديل شكل ظهور النّموذج. Form Caching: يمكنك تفعيل هذا الخيار إن كنت ترغب تفعيل خاصّيّة التخزين، مع إمكانية تحديد مُدّة التّخزين. Google Form Field Validation (التحقق من حقول نماذج جوجل): بشكل افتراضي تكون هذه الخاصية غير مفعلة، تفعيلها سيضيف دعم خاصية التحقق من حقول النموذج قبل إرسالها (باستخدام jQuery). Google Form Hidden Fields (حقول نموذج جوجل المخفية): إن كان لديك حقول مخفية في نموذجك وتريد التحكّم فيها، هذه الخاصيّة مُعطّلة بشكل قياسي. ستحتاح إلى معرفة أسماء الحقول التي ترغب في التّحكّم فيها، يمكن فقط استعمال أنواع الحقول التالية: value ،url و timestamp. Google Form Field Placeholder: إن أردت إظهار "أمثلة" عن القيم التي تتوقّعها في الحقل، بإمكانك القيام بذلك عبر إضافة ما يُسمّى بـ placeholder عبر هذه الخاصّيّة. Google Form Default Text Overrides (تغير النّصوص الافتراضية في النموذج): هذه آخر الخاصيات المتقدمة المتوفرة، تسمح لك بالتّحكم في النّص إذا لم يُعجبك النّص الذي تُظهره نماذج Google. إعداد خصائص الملحق هناك المزيد، فحتى وإن كانت كل الإعدادات التالية اختيارية يمكن لك أن تقوم بإعداد العديد منها حتى تبدوا نماذج جوجل الخاصة بك وتعمل بشكل جيد. عليك بكل بساطة التوجه إلى Google Form Options الموجودة في العمود يمين الخانات التي سبق أن تحدثنا عنها أعلاه. CAPTCHA (كابتشا): لتعزيز الحماية ضد السبام، يمكن أن تعمل على تفعيل حقل CAPTCHA الذي يتوجب على المستعملين ملؤه لإثبات أنهم بشر وليسوا برامج. Columns (الأعمدة): افتراضيا، يتم عرض نماذج جوجل في عمود واحد، باستعمال هذه الخاصية يمكن أن تحصل على عدد الأعمدة الذي تريده (10 أعمدة كأقصى حد). يمكن أيضا أن تحدد ترتيب الأعمدة من اليسار إلى اليمين باختيار Left-to-Right أو من اليمين إلى اليسار باختيار Right-to-Left. Email End User (راسل المُستخدم): قم بتفعيل هذه الخاصية إن أردت إرسال رسالة إلى المُستخدم الذي قام بملء النّموذج بمجرد أن يقوم بذلك. Legal: تتوفر نماذج جوجل على عبارة "Powered by Google Docs" أسفلها، يمكنك إخفاؤها من خلال تعطيل هذا الخيار. Read Only (قراءة فقط): إن أردت أن يكون النموذج قابلا للقراءة فقط دون إمكانية الكتابة يمكنك القيام بذلك من خلال هذه الخاصية. BR: إضافة سطر فارغ ما بين عنوان الحقل والحقل (يظهر العنوان فوق الحقل). CSS Prefix: إضافة بادئة في بداية اسم كل صنف (class name) في نموذج جوجل، لتحكّم أفضل في CSS النّموذج. Title (العنوان): إن أردت أن لا يظهر عنوان النموذج على موقعك قم بتعطيل هذه الخاصية. Map H1 to H2: إن كنت تريد الاحتفاظ بالعنوان لكن لا ترغب في استخدام وسم H1 معه (الذي يُستخدم معه بشكل قياسي) يُمكنك تفعيل هذه الخاصية لجعله يبدو كـ H2. نشر نموذج جوجل على موقع ووردبريس الخاص بك الآن بما أنك تملك نموذج جوجل جديدا مُعَدًا على ووردبريس (على الأقل بتحديد Form URL)، يمكن لك أن تقوم بحفظه كمسودة، معاينته أو نشره مباشرة. سيكون الرابط الثابت على شكل http://example.com/wpgforms/title، تستطيع التعديل على العنوان (title) عند الحاجة قبل القيام بالنشر. بمجرد أن تقوم بالنشر، يمكنك أن توجّه المُستخدمين إلى صفحة النموذج لملئه، أو يمكن لك تضمينه في صفحة أو منشور آخر على موقعك من خلال استعمال شيفرة مختصرة (short code)، لتحصل عليها، اذهب إلى Google Forms ستجد شفرة نموذجك المختصرة قرب اسمه. قم بنسخ الشفرة المختصرة للصقها في أي صفحة أو منشور. بعد ذلك يمكن أن ترى صفحتك لتتفقد كيف تم تضمين نموذجك معها، إليك كيف يبدو مع قالب Twenty Fifteen : الاطلاع على النماذج التي تم إرسالها يمكن الاطّلاع على النماذج التي تم إرسالها من خلال الذهاب إلى Form Submission Log، حيث تجد تاريخ إرسالها (timestamp) ورابط URL الخاصين بكل إدخال، كما تستطيع القيام بمسحها دفعة واحدة عندما تريد ذلك. بدلا من ذلك، يمكن أن تتوجه إلى نموذجك في جوجل درايف لتطلع على الأجوبة هناك. في القائمة أعلاه، يتواجد خيار Responses، الذي يسمح لك برؤية ملخص الأجوبة، فضلا عن إمكانية ضغط الزر View responses في الأسفل الذي يسمح لك برؤيتها في مُجَدْوَلَةً. خلاصة انطلاقا من تجربتي الخاصة، يمكنني أن أجزم بأن نماذج جوجل رائعة جدا، أكيد أنها ليست أغنى أداة بالخصائص من نوعها، لكن ثمنها أكثر من مغر مقارنة مع ما تقدمه. بناء على ما سبق، إن أردت تحكمًا كاملًا في شكل نموذج جوجل على موقع ووردبريس الخاص بك فإن ملحق Google Forms plugin ضروري جدا. بإدماج نماذج جوجل بشكل مناسب في موقعك والعمل على إعطائها طابعا خاصا، لن يلاحظ المستعملون أنك تستعمل خدمة جوجل المجانية. هل تستعمل نماذج جوجل؟ لأي غرض بالضبط؟ شارك معنا أية أفكار حولها في التعليقات. ترجمة -وبتصرّف- للمقال: How to Integrate Google Forms With WordPress لصاحبه: Tom Ewer.