المحتوى عن 'forms'.



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

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

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

نوع المُحتوى


التصنيفات

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

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML
    • HTML5
  • CSS
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • Sass
    • إطار عمل Bootstrap
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • ASP.NET
    • ASP.NET Core
  • سير العمل
    • 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

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

  1. تقدّم المواصفات الجديدة في CSS3 محدّدين Selector مفيدين للغاية هما :valid و :invalid وهي أصناف زائفة pseudo-class يمكن استخدامها مع عناصر الإدخال الخاصة بالاستمارات. لنفترض أن لديك عنصر إدخال تتحقّق من خلاله فيما إذا كان ما أدخله المستخدم صحيحًا أم خاطئًا. لإجراء عملية التحقق ستحتاج إلى إضافة خاصية HTML5 required إلى الوسم الخاص بعنصر الإدخال، وبهذا يمكن الاستفادة من المحدّدين :valid/:invalid لتغيير لون حقل الإدخال ليعرف المستخدم من خلال ذلك أنّ ما أدخله صحيح أو خاطئ. فعلى سبيل المثال يتحول مربع الإدخال إلى اللون الأخضر عندما تكون العبارة صحيحة، وكما يلي: input:required { background: #AAA; } input:valid { background: #0A0; } input:invalid { background: #A00; } سننشئ في هذا الدرس استمارة بنمط Material وسننبّه المستخدم على صحة البيانات المدخلة في الاستمارة من خلال الصنفين الزائفين :valid و :invalid. تتألف الاستمارة من مربع نصّي وحيد وقد أحطنا عنصري input[type="text"] وlabel بعنصر div يحمل المحدّد .form-control من إطار عمل Bootstrap. لدينا أيضًا شريط سيتغير لونه بين الأخضر والأحمر للدلالة على صحة المعلومات المدخلة من عدمها. <div class="form-control"> <input type="text" required /> <span class="bar"></span> <label for="First Name">First Name</label> </div> في البداية سنزيل جميع الحدود المحيطة بمربّع النص باستثناء الحدّ السفلي وسنلوّنه باللون الأزرق ليكون متناسقًا مع نمط التصميم Material. .form-control { position:relative; margin-top:40px; width:400px; } input { border:none; border-bottom:3px solid #34495e; padding:10px 0; width:400px; display:block; font-size:16px; } سيؤدي العنصر label دور ماسك مكان placeholder، لذا سنجعل موقعه مطلقًا مع تعيين المسافة اليسرى والعلوية المناسبة، ليبدو العنصر بهيئة ماسك مكان اعتيادي. label { position:absolute; top:8px; left:5px; font-size:16px; color:#333; transistion: 0.3s ease all; -webkit-transition:0.3s ease all; } والآن عندما يضغط المستخدم أو يجعل التركيز على مربّع النص سنقوم بإلغاء الحدّ السفلي، وسنغير موقع ماسك المكان ليصبح فوق مربع النص ليبدو كـ label. input:focus{ border:none; outline:none; } سيبقى الـ label فوق مربع النص إلى أن يجعل المستخدم التركيز على مربّع النص ويضيف إليه أي معلومات صحيحة. input:focus ~ label, .form-control input:valid ~ label { top:-10px; font-size:12px; left:2px; color:#111; } لن يظهر المحدّد .bar بصورة تلقائية، بمعنى أن عرضه سيكون صفرًا، وإن قمنا بالتركيز على مربع النص فإن عرض المحدّد .bar سيزداد. كما ستلاحظ فقد حدّدنا العرض ضمن الصنفين الكاذبين (:after و :before) حيث سيزداد العرض 50% لكل عنصر زائف، بمعنى أن الزيادة الكلية ستكون 100%، وهكذا سنحصل على تأثير توسّع جميل. .bar:before, .bar:after { content:''; height:3px; width:0; bottom:1px; position:absolute; transition:0.2s ease all; -moz-transition:0.2s ease all; -webkit-transition:0.2s ease all; } .bar:before { left:50%; } .bar:after { right:50%; } input:focus ~ .bar:before, input:focus ~ .bar:after { width:50%; } سنغيّر الآن لون خلفية الشريط حسب صحة أو عدم صحة البيانات المدخلة، وذلك باستخدام الصنفين الزائفين :valid و :invalid. input:valid ~ .bar:before, input:valid ~ .bar:after{ background:#2ecc71; } input:invalid ~ .bar:before, input:invalid ~ .bar:after{ background:#e74c3c; } تعمل هذه الطريقة على متصفحات (+Chrome(10 و (+Firefox(4 و (+Safari(5 و (+Opera(10 و (+IE(10، ولكن لا تعمل على الإصدار التاسع وما دونه من متصفح IE. وجدير بالذكر أنّه لن يتم التحقّق من صحة البيانات بأي شكل من الأشكال، ويمكن استخدام هذه الطريقة في مجال تجربة المستخدم فقط. ترجمة - وبتصرّف - للمقال Form validation in pure css لصاحبه Arkaprava Majumder.
  2. سنبدأ في هذا الدرس من سلسلة برمجة تطبيقات الأجهزة المحمولة باستخدام Xamarin بالتعرّف على بنية التطبيق ضمن الحل Solution في Visual Studio 2015، بالإضافة إلى إنشائنا لتطبيق بسيط نتعرّف من خلاله على آلية عمل التطبيقات المبنية بواسطة Xamarin والتي تشبه في العديد من الجوانب مثيلاتها المنشأة باستخدام التقنيّات الأساسيّة المعتمدة في إنشاء تطبيقات أندرويد (لغة جافا مع Android Studio). بنية التطبيق المنشأ باستخدام Xamarin شغّل برنامج Visual Studio 2015، وبعد ظهور النافذة الرئيسيّة انتقل إلى القائمة File ومنها إلى New ثم اختر من القائمة الفرعيّة التي ستظهر الخيار Project. وكما فعلنا في الدرس السابق، اختر من الجهة اليسرى للنافذة التي ستظهر Cross-Platform، ثمّ اختر المشروع (Blank App (Xamarin.Forms Portable من القسم الأوسط للنافذة. امنح هذا المشروع الاسم SimpleTextApp ثم انقر الزر OK. سنبني تطبيقًا بسيطًا يوضّح كيفيّة استخدام لُصيقة Label وحيدة في إظهار النص في التطبيقات المبنيّة باستخدام Xamarin. من مستكشف الحل Solution Explorer الذي يوجد عادةً في الجهة اليمنى لنافذة بيئة التطوير Visual Studio، أبقِ فقط على المشروعين SimpleTextApp.Droid و (SimpleTextApp (Portable لأنّنا سنتعامل مع تطبيقات أندرويد فحسب (كما اتفقنا أيضًا من الدرس السابق). احذف باقي المشاريع الإضافيّة، يجب أن تحصل على شكل شبيه بما يلي: يحتوي المشروع (SimpleTextApp (Portable على معظم الشيفرة البرمجيّة، وهذا سلوك عام في المشاريع ذات النمط PCL. حيث تُعتبر الشيفرة الموجودة ضمن المشروع (الذي يحمل المقطع Portable بالإضافة لاسمه) مشتركة لجميع أنواع التطبيقات العاملة على أيّ نظام تشغيل بما فيه أندرويد. نلاحظ الملف App.cs الأساسي الذي سيكون موجودًا في أيّ تطبيق Xamarin وقد تحدثنا عنه في الدرس السابق ورأينا كيف يحتوي على الصنف App الذي يرث من الصنف Application، وكيف أنّ بانية هذا الصنف هي المسؤولة عن إنشاء الصفحة الرئيسيّة للتطبيق. انشر العقدة References لترى المراجع الخاصّة بهذا المشروع. ستلاحظ وجود عدّة مكتبات يهمّنا منها: Xamarin.Forms.Core و Xamarin.Forms.Platform و Xamarin.Forms.Xaml هذه هي المكتبات الرئيسيّة المشكّلة لـ Xamarin.Forms. بالنسبة للمشروع SimpleTextApp.Droid فهو يحتوي على مجلّدين هما: Assets و Resources. بالنسبة للمجلّد Resources فيحتوي على ملفات الصور وملفات معلومات التخطيطات layouts descriptions وغيرها من الملفات التي تُعتبر بمثابة المصادر resources لتطبيقك. انشر المجلّد Resources لترى بنيته. أمّا بالنسبة للمجلّد Assets فتُوضَع ضمنه الملفات العامّة الأخرى التي ترغب بتضمينها مع تطبيقك. يحتوي هذا المشروع أيضًا على الملف MainActivity.cs الذي يحوي ضمنه صنف له نفس الاسم MainActivity وهو يمثّل الفعاليّة Activity الأساسيّة لتطبيق أندرويد. افتح هذا الملف لتجد أنّ هذا الصنف يحتوي على التابع OnCreate الذي يُنفَّذ عند بدء تشغيل تطبيق أندرويد. لاحظ العبارة البرمجيّة التالية ضمن هذا التابع: LoadApplication(new App()); من الواضح أنّها تنشئ كائنًا جديدًا من الصنف App الموجود ضمن المشروع (SimpleTextApp (Portable، ثم تمرّره إلى التابع LoadApplication مباشرةً ليعمل على تحميل التطبيق وإظهاره للمستخدم. إذًا فعند تشغيل تطبيق أندرويد، سينفّذ التابع OnCreate الموجود في الصنف MainActivity أولًا، حيث يعمل هذا التابع على إنشاء كائن جديد من الصنف App فينفّذ بانيته وهي المسؤولة عن إنشاء الصفحة الرئيسيّة للتطبيق كما أشرنا. على أيّة حال ستتوضّح الفكرة بشكل جيّد بعد أن نبدأ بكتابة الشيفرة البرمجيّة. كتابة الشيفرة البرمجية انقر بزر الفأرة الأيمن على اسم المشروع (SimpleTextApp (Portable في مستكشف الحل Solution Explorer لتظهر قائمة سياق، اختر منها Add ثمّ من القائمة الفرعيّة اختر Class. ستظهر النافذة الخاصّة بإضافة صنف جديد. من حقل الاسم Name من الأسفل اكتب الاسم التالي لهذا الصنف الجديد وهو MainPage، ثم انقر Add. سيعمل Visual Studio على إضافة ملف جديد إلى المشروع اسمه MainPage.cs يحتوي على صنف بنفس اسمه ومحتواه شبيه بما يلي: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleTextApp { class MainPage { } } لن نحتاج إلى معظم نطاقات الأسماء الموجودة في الشيفرة السابقة في هذا البرنامج، سنحتاج حاليًا إلى نطاق الاسم Xamarin.Forms. وسنجعل الصنف MainPage يرث من الصنف ContentPage كما سنضيف البانية إليه. عدّل الشيفرة السابقة لتصبح على الشكل التالي: using Xamarin.Forms; namespace SimpleTextApp { class MainPage : ContentPage { public MainPage() { } } } لاحظ أنّني تخلصت من جميع نطاقات الأسماء غير الضرورية (على أية حال سيظهر أي نطاق اسم غير مُستَخدَم في الشيفرة البرمجيّة بلون باهت في بيئة التطوير Visual Studio 2015). سيلعب الصنف MainPage دور صفحة محتوى content page رئيسيّة للتطبيق SimpleTextApp. سنضع ضمن بانية هذا الصنف الشيفرة البرمجيّة اللازمة لإنشاء لُصيقة واحدة Label تحوي نصًّا بسيطًا. ثم سنجري بعض التجارب البسيطة على هذه اللُّصيقة. يُعتبر هذا البرنامج بسيطًا في الواقع، ومهمته جعلك أكثر تآلفًا مع Xamarin. سنبدأ بإنشاء لُصيقة من الصنف Label وذلك ضمن بانية الصنف MainPage. تُستخدم اللُصيقات عادةً لعرض النصوص إلى المستخدم. انظر إلى الشيفرة البسيطة التالية: Label lblMain = new Label(); lblMain.Text = "Welcome to Hsoub Academy!"; ننشئ لُصيقة كما ننشئ أيّ كائن من صنف ما. أنشأنا في الشيفرة السابقة كائنًا جديدًا من الصنف Label وأسندناه إلى المتغيّر lblMain. ثم أسندنا النص "!Welcome to Hsoub Academy" إلى الخاصيّة Text من المتغيّر lblMain. تُستَخدم الخاصية Text لضبط وقراءة المحتوى النصيّ للُّصيقة. كي نستطيع عرض اللُّصيقة السابقة على الصفحة الرئيسيّة للتطبيق، علينا إسناد المتغيّر lblMain إلى الخاصيّة Content من الصنف ContentPage. وبما أنّ الصنف MainPage يرث من ContentPage فستكون الخاصيّة Content موجودة تلقائيًّا ضمنه أيضًا. ستكون عمليّة الإسناد على الشكل التالي: this.Content = lblMain; تكون عمليّة الإسناد السابقة ممكنة لأنّ الصنف Label يرث من الصنف View الذي يمثّل واجهة عرض view بمفهومها العام. وبما أنّ الخاصيّة Content هي من النوع View أيضًا فتكون عمليّة الإسناد هذه ممكنة. ستكون محتويات الملف MainPage.cs شبيهة بما يلي: using Xamarin.Forms; namespace SimpleTextApp { class MainPage:ContentPage { public MainPage() { Label lblMain = new Label(); lblMain.Text = "Welcome to Hsoub Academy!"; this.Content = lblMain; } } } هذا كلّ شيء! علينا الآن القيام بخطوة صغيرة أخيرة، وهي في جعل تطبيقنا يُنشئ كائن من صنفنا الجديد MainPage وذلك ضمن الملف App.cs. انتقل إلى هذا الملف (موجود ضمن المشروع (SimpleTextApp (Portable واحرص على أن تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = new MainPage(); } اضغط الآن المفتاح F5 لتنفيذ التطبيق، لتحصل على شكل شبيه بما يلي: ملاحظة يمكنك وصل جهازك المحمول الذي يعمل بنظام أندرويد إلى الحاسوب لتجريب تشغيل التطبيق عليه مباشرةً. ولكن في هذه الحالة ينبغي أن تتوفّر واجهة برمجيّة API منصّبة على حاسوبك مناسبة لنسخة أندرويد الموجودة على الجهاز المحمول. على أية حال يمكنك تنصيب هذه الواجهة في حال عدم وجودها من خلال Android SDK Manager كما أشرنا في الدرس السابق. كما أنصح بوصل الجوال قبل تشغيل بيئة التطوير Visual Studio، أو أن تعيد تشغيلها إذا كانت تعمل من قبل. تنسيق الشيفرة البرمجية بشكل أفضل في الحقيقة لا تُعتبر الشيفرة البرمجيّة الموجودة ضمن الملف MainPage.cs مثاليّةً رغم بساطتها. ربما لا تشعر بمشكلة الآن، ولكن عندما تصبح برامجك أكبر، ستقع في مشاكل حقيقيّة لأنّ الأسلوب السابق بكتابة الشيفرة يجعلها كبيرة جدًّا. سأستخدم ميّزة الإسناد المباشر للخصائص أثناء إنشاء الكائنات. تفيد هذه الميزة في الاستغناء عن معظم المتغيّرات في البرنامج، التي ينحصر دورها في لعب دور الوسيط المؤقّت. سنعيد صياغة الشيفرة الموجودة في الملف MainPage.cs بشكل أنيق وعمليّ أكثر: using Xamarin.Forms; namespace SimpleTextApp { class MainPage : ContentPage { public MainPage() { this.Content = new Label{ Text = "Welcome to Hsoub Academy!" }; } } } لاحظ أنّني استغنيت عن المتغيّر lblMain لأنّنا أسندنا كائن اللُّصيقة مباشرةً إلى الخاصيّة Content. مزايا إضافية على التطبيق ستلاحظ من التطبيق السابق أنّ اللُّصيقة تظهر في الزاوية اليسرى العليا من النافذة. سنجعلها تظهر في مركز الشاشة. ينبغي ضبط خاصيّتين من خصائص اللُّصيقة لهذا الغرض، وهما HorizontalOptions (لخيارات المحاذاة الأفقيّة) و VerticalOptions (لخيارات المحاذاة الرأسيّة). كل من هاتين الخاصيّتين من النوع LayoutOptions، وهي بنية struct موجودة ضمن نطاق الاسم Xamarin.Forms. تحتوي هذه البنية على عدّة حقول جاهزة تُفيد في خيارات التموضع الأفقيّة والرأسيّة للُّصيقة، وهي خيارات مهمّة للغاية كما سنرى لاحقًا في هذه السلسلة. لنجري الآن التعديل المطلوب على اللُّصيقة الموجودة ضمن بانية الصنف MainPage. ستصبح محتويات الملف MainPage.cs على الشكل التالي: using Xamarin.Forms; namespace SimpleTextApp { class MainPage : ContentPage { public MainPage() { this.Content = new Label{ Text = "Welcome to Hsoub Academy!", HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center }; } } } لاحظ إسناد القيمة LayoutOptions.Center لكل من الخاصّتين HorizontalOptions و VerticalOptions وذلك للتوسيط الأفقي والرأسي على الترتيب. نفّذ البرنامج مرّة أخرى ستلاحظ أنّ اللُّصيقة أصبحت في مركز الشاشة كما هو واضح من الشكل التالي: أمّا إذا أحببت أن يكون النص ضمن اللُّصيقة بلون آخر، وليكن الأحمر مثلًا، فعليك في هذه الحالة إسناد القيمة Color.Red للخاصيّة TextColor لكائن اللُّصيقة، علمًا أنّ Color هو بنية موجودة ضمن نطاق الاسم Xamarin.Forms أيضًا. انظر كيف نفعل ذلك في الشيفرة: this.Content = new Label{ Text = "Welcome to Hsoub Academy!", HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, TextColor = Color.Red }; نفّذ البرنامج مرّة أخرى، لترى النص وقد أصبح لونه أحمر. الخلاصة تعرّفنا في هذا الدرس على البنية العامة لتطبيق Xamarin ضمن بيئة التطوير Visual Studio 2015. كما قمنا ببناء تطبيق بسيط للغاية أسميناه SimpleTextApp. تنحصر وظيفة هذا التطبيق في التّعرف أكثر على Xamarin. سنبدأ اعتبارًا من الدرس القادم ببناء تطبيقات متدرّجة في الصعوبة، وذات مزايا إضافيّة من الممكن أن تستفيد منها كمبرمج تطبيقات محمولة في حياتك العمليّة.
  3. هنالك عدّة طرق لجمع عناوين البريد الإلكتروني على موقع ما، لكن ما هو أكثر الخيارات فعاليّة من بين السّلايدر Sliders، النّوافذ المنبثقة Lightboxes والتبويبات Tabs، ونماذج الاشتراك العاديّة؟ ولماذا؟ سنتعرّف على تقنيات بناء القوائم الخاصة بثلاث خدمات معروفة. رغم كلّ هذه الخيارات، هنالك خيار واحد فقط يمكن لمصمّمي المواقع ومدراء المواقع اختياره. لذا، ومن أجل فهم أفضل لكلّ نوع من النماذج، جمعنا 3 أشخاص يعملون ضمن أشهر نماذج التسجيل المُدمجة بالنسبة لنا وهم: Claudiu Murariu من خدمة PadiAct، Noah Kagan من خدمة AppSumo وMatt Farmer من خدمة Anchor Tab، لنطلب منهم شرح الخدمات الأفضل والسّبب الذي يجعلها كذلك. 3 أنواع من النماذج والهدف واحدعند تقرير نوع النموذج التي يجدر بك استخدامه على موقعك، سيوافق معظم النّاس غالبًا على أنّ الهدف واحد، وهو جمع أكبر عدد ممكن من التّسجيلات الجديدة في قوائم اشتراكك، لكن هنالك أشياء يجب أخذها بعين الاعتبار خلال هذه العملية، منها: ألّا تزعج هذه العمليّة أو تقاطع زوّار الموقع، خصوصًا الذين يزورون الموقع عبر جهاز محمول أو الذين سجّلوا بالفعل.ألّا يتمّ إرغام النّاس على التّسجيل من أجل الحصول على ما يريدونه.ألّا تؤثّر هذه العمليّة على سرعة الموقع بشكل مفرط.دعونا نستعرض كيفيّة عمل كل نموذج مع أخذ هذه المتطلّبات بعين الاعتبار. السلايدرز: Claudiu Murariu من PadiAct مبدأ العمل: كلّما ذهبت إلى متجر بيع الملابس المفضّل لديك وبدأت بالبحث عن شيء لشرائه ولا تجد ما يناسب مقاساتك بشكل مثالي، تصبح المساعدة التي سيقدّمها لك موظّف المتجر الودود –الحاضر دائمًا- محلّ ترحيب، وهو نفس الشّيء الذي تفعله السّلايدرز، فمثل موظف المتجر، إذا ظهرت نموذج في نفس الوقت الذي يدخل فيه زائر إلى موقعك، ستجد غالبًا أنك تفقد الزّوار قبل تصفّحهم لموقعك حتّى، لكن في حال ظهور السلايدر في الوقت المناسب وبالمحتوى المناسب، فلن يرى معظم الزوار السلايدر وإنما الرسالة التي يحملها لهم، في هذه الحالة، يكون تقديم عنوان البريد الإلكتروني إجراءً شكليًّا حيث يودّون البقاء على اتصال بك. ما مدى جودتها: يمكن للسّلايدرز زيادة معدل الاشتراكات بنسبة 15% فما فوق، حيث جمعنا 3.5 مليون بريد إلكتروني من خلالها بفضل ظهورها في الوقت المناسب مع رسالة مخصّصة حسب سلوك الزّوار، دون أي تأثير على أداء مقاييس مثل معدّلات التّحويل، نسبة الخروج من الموقع، الوقت الذي تمّ قضاؤه على الموقع وعدد الصّفحات التي تمّ زيارتها. تكون السّلايدرز فعّالة للغاية عندما تكون مستهدفة، لأنّها لا تضع جميع المستخدمين في نفس الكفّة، بل تتيح للمستخدمين تكوين فكرة عن الموقع قبل أن يقرروا الاشتراك، كما تقدّم السّلايدرز سهولة كبيرة للمستخدمين كونهم لا يحتاجون للبحث عن نموذج الاشتراك بأنفسهم. النوافذ المنبثقة: Noah Kagan من SumoMe مبدأ العمل:أعتقد أنّ نوافذ البريد الإلكتروني المنبثقة التي تظهر على المواقع مزعجة للغاية، لكنّها تعتبر كذلك أنجع طريقة للحصول على اشتراكات بريد إلكتروني جديدة. دعونا نسقط هذه النوافذ المنبثقة على أرض الواقع. لنقل أنّك ذهبت إلى مطعم ولم يعجبك الطعام المقدم هناك، ثم طُلب منك إدخال بريدك الإلكتروني من أجل نشرة المطعم البريدية، فأدخلت بريدك الإلكتروني وبدؤوا بمراسلتك يوميًّا لأسابيع، هل سيكون لبريدهم الإلكتروني تأثير عليك باستثناء زيادة كرهك تجاههم؟ طبعًا لا، فأنت لن تعود أبدًا إلى ذلك المكان ولن توصي غالبًا أشخاصًا آخرين بالذّهاب إليه. لنقل الآن أنّ هنالك مطعمًا يعجبك، وستعود له غالبًا، لكنك تنسى أحيانًا الذّهاب إليه، هنا سيكون تذكير ودّي بالذّهاب إلى المطعم مفيدًا لك. هذه هي فكرتي حول نوافذ البريد الإلكترونيّ المنبثقة، يكون تذكّر موقعك من طرف الزّوار أو العملاء صعبًا أحيانًا وسط كلّ الخيارات الأخرى المتوفّرة، وقد لا يرون طريقة أخرى لإعطائك عناوين بريدهم الإلكتروني، عندها تكون النّوافذ المنبثقة أكثر الطّرق فعاليّة حسب ما وجدت. أشجّع النّاس على تجربة هذا الخيار مادامت منتجاتهم رائعة ومحتوى مدوناتهم ممتاز. ما مدى جودتها: هذا هو عدد الاشتراكات التي حصل عليها موقع Okdork باستخدام النّوافذ المنبثقة لخدمة بناء القائمة على موقع SumoMe.com (موضحة في الجدول أدناه). لا أحاول تحسين الخدمة للحصول على أكبر قدر ممكن من الاشتراكات البريديّة لكنني أقترحها بودّ على الزّوار للاشتراك في نشرتي البريديّة. التاريخ المشتركون النّوافذ التي ظهرت معدّل التّحويل 04/10 26 754 3.45% 04/11 31 950 3.26% 04/12 14 568 4.46% 04/13 19 578 3.29% 04/14 24 1,005 2.39% التبويبات: Matt Farmer من AnchoTabمبدأ العمل:عندما يأتي زائر إلى موقعك، يكون هدفه غالبًا محدّدًا بالفعل، حيث يكون هدف معظم الزّوار الحصول على معلومة ما حول منتجك أو قراءة محتوى مدونتك، من جهة أخرى، فأنت كذلك كمدير موقع لديك هدف معيّن؛ تحويل الزّائر إلى قارئ منتظم أو عميل تستفيد منه مادّيًّا، وهكذا تكون في مواجهة معضلة لطالما عانى منها الباعة لعقود من الزمن، لنأخذ مثال بائع السيّارات، تجد البائع الانتهازيّ الذي يكون دائمًا على استعداد لفعل أي شيء باستطاعته من أجل تحقيق هدفه ببيع سيارة، إذ أنّه لا يأبه إن كان أسلوبه مريحًا أو غير مريح لك، وسيستمرّ باللّحاق بك والحديث وفعل أي شيء لجعلك تشتري. ويعدّ هذا شبه مثاليّ لاستراتيجيّة جلب عناوين البريد الإلكترونيّ التي تشتمل على إظهار نافذة منبثقة شكليّة تتمركز فوق محتواك وتجبر الزّائر على أن يقرّر ما إذا كان يودّ الاشتراك أم لا، لكنّ التّبويبات تحقّق توازنًا نسمّيه بالبائِع المُفيد، حيث لا تظهر التّبويبات أمامك مباشرة، أو تتحدّث إليك طوال الوقت الذي تكون فيه منكبًّا في محاولة تحقيق هدفك، لكنّها تكون متواجدة هنالك دائمًا. ما مدى جودتها: تمّ تحسين التّبويبات بشكل خاص للمدوّنات التي تحتوي على الكثير من المحتوى النّصي، فعند الصعود لأعلى الصّفحة من الأسفل، سيلاحظ القرّاء ظهور التّبويبة لكنّهم غير ملزمين بالتّوقف عن القراءة من أجل التّفاعل معها، كما أن عينهم تتحرّك طبيعيًّا نحو التبويبة التّالية عند انتهائهم من قراءة المقال. هذه الاستراتيجية تتيح لك الموازنة بين الرّغبة في ظهور النموذج بشكل بارز وإخفائها ضمنيًّا بحيث يكاد القرّاء لا يشعرون بها، وبالتّالي تكون قادرًا على تحقيق هدفك بالحصول على اشتراكات لبريدك الإلكتروني دون الاستعانة بتقنيّات تعرقل وصولك إلى هدفك. لاحظنا باستخدام هذه الطّريقة الأقلّ تطفّليّة معدّلات تحويل متواصلة بنسبة 1.25%، ما يجعلنا قريبين من الحلول الأخرى المنافِسة. مع التّحديث الكبير المنتظر لخدمة Anchor Tab، سيحصل "مساعِدنا المفيد" على أدوات أكثر لمساعدة عملائنا على رفع ذلك الرقم أكثر. أيها تستخدم؟بعد اطّلاعنا على الخيارات الأخرى المتاحة غير الخيارات المعهودة، حان وقت اختيارك للخدمة التي تناسبك، فأيّ نوع من نماذج الاشتراك ستختار أو أيّ نوع استخدمته وحقّق لك نجاحًا على موقعك؟ ترجمة -وبتصرّف- للمقال Subscribe form showdown: Do sliders, lightboxes or tabs work best? لصاحبته ROS HODGEKISS. حقوق الصورة البارزة: Designed by Freepik.
  4. بعد أن انتهينا من إعداد قواعد البيانات والطرق (routes)، سوف نتحدث في هذا الجزء عن المتحكِّمات (Controllers)، النماذج (مع العلاقات)، والعروض views. (بما في ذلك نظام blade ومخططات المحتوى). مساعدات النماذج Form Helpers في Laravelبعد كل هذه الإعدادات، إذا ذهبنا الآن (في المتصفح) إلى projects/ فسوف نحصل على صفحة فارغة فما هو السبب؟ حسنا، لنكتشف ذلك، قم بتنفيذ الأمر php artisan route:list على سطر الأوامر مرة أخرى وأنظر إلى هذا السطر: +--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+ | | GET|HEAD | projects | projects.index | App\Http\Controllers\ProjectsController@index | | +--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+يبدو أن رابط projects/ يقوم بتحميل الوظيفة Index الخاصة بـ ProjectsController، لذلك سنقوم بفتح app/Http/controllers/ProjectsController.php/ وسنقوم بتحديث التابع (method) لنقوم بربطه إلى عرض سوف نقوم بإنشائه. قم بإضافة السطر ;('return view('projects.index إلى الوظيفة ()index كالتالي: public function index() { return view('projects.index'); }بما أننا نستخدم في هذا الدرس نظام Blade للقَوْلَبة سنقوم بإنشاء ملف resources/views/projects/index.blade.php/ وسنكتب نص قصير داخله، ثم سنقوم مرة أخرى بالذهاب إلى projects/ في المتصفح، إذا كان كل شيء يعمل جيدا فسوف تجد النص الذي كتبته بالأعلى. والآن قُم بنفس الشيء لتابع المتحكِّم create عن طريق إضافة السطر ;('return view('projects.create إلى التابع ()create كالتالي: public function create() { return view('projects.create'); }إن إظهار محتويات العرض view هو أمر رائع، لكن ماذا لو كنا نملك أكثر من صفحة واحدة في موقعنا ؟ في هذه الحالة، سوف نحتاج إلى قالب ثابت لجميع الصفحات، أي أننا نحتاج إلى عرض محتويات العرض view داخل قالب HTML بسيط، وسنقوم بهذا عن طريق مخططات المتحكِّمات. من أجل عمل مخططات المتحكِّمات سنقوم بالخطوات التالية: إنشاء مخطط العرض، وبما أن Laravel توفر لنا واحدة جيدة تدعى app.blade.php لذلك سنوفر الوقت وسنقوم بإستخدامها. لاحظ أن قرب أسفل المخطط هنالك سطر ('@yield('content وهذه دالة ستقوم بتحميل محتوانا الحالي.الإشارة إلى مخططك في عرضك view باستخدام ('extends('app@ ولفها عن طريق كتلة ('section('content@، مثل التالي: @extends('app') @section('content') This is my /resources/views/projects/index.blade.php file! @endsection سنقوم الآن بتنفيذ هذه الخطوات بإنشاء عروض show.blade.php و create.blade.php و index.blade.php في مجلد resources/views/projects/ مع الشيفرات (markup) المذكورة أعلاه وقُم بتغيير اسم الملف إذا كان الأمر ضروريا، ثم قُم بعمل تحديث للصفحة projects/ في متصفحك، وسوف ترى هيكل app.blade.php حول محتويات عرضك (view). الربط بين الطريق (route) والنموذجسيوفر Laravel بشكل افتراضي معرف رقمي ID للعديد من توابع متحكِّمات الموارد مثل ()show و ()edit و ()update و ()destroy، وهذا الأمر سيضيف العديد من الشيفرات الجاهزة (boilerplate) التي نحتاج إلى كتابتها، مثل الحصول على مثيل النموذج والتأكد من وجودها وغيرها. ولهذا سوف نستخدم إحدى مميزات Laravel والتي تدعى الربط بين الطريق و النموذج route model binding، فبدل من توفير متغير id$، سوف نقوم بإعطاء الوظيفة (method) كائن project$ أو task$. قُم بفتح app/Http/routes.php/ وأضف هذين السطرين (أول سطرين بعد التعليق): // Provide controller methods with object instead of ID Route::model('tasks', 'Task'); Route::model('projects', 'Project'); // Use slugs rather than IDs in URLs Route::bind('tasks', function($value, $route) { return App\Task::whereSlug($value)->first(); }); Route::bind('projects', function($value, $route) { return App\Project::whereSlug($value)->first(); }); Route::resource('projects', 'ProjectsController'); Route::resource('projects.tasks', 'TasksController'); وفي TasksController و ProjectsController (ملفات app/Http/Controllers/ProjectsController.php/ و app/Http/Controllers/TasksController.php/) قُم باستبدال كل وظيفة (method) مُعرف بمرجع id$ بـ task$ أو project$ مثل التالي: // public function edit($id) public function edit(Project $project)لا تنسَ إضافة use App\Task و use App\Project في أعلى المتحكِّمات حتى نشير إلى هذه النماذج. لا تقلق إذا لم تفهم هذه التغييرات، فسنقوم بعرض الشيفرة البرمجة الكاملة لـ TasksController و ProjectsController لاحقا. وفي هذه المرحلة يمكنك تمرير الكائن (object) إلى عرضه في كل متحكِّم لوظيفة (method) الإظهار والتعديل والتحديث حتى نستطيع استخدامهم لاحقا: public function edit(Project $project) { return view('projects.show', compact('project')); }سوف يحتاج TasksController إلى بضعة تعديلات طفيفة أخرى، وبما أننا نستخدم الموارد المضمّنة nested resources، سيخبرنا php artisan route:list أن جميع طرق task تحتوي على قناع {projects} بالإضافة إلى أن بعضها يستقبل قناع {tasks} أيضا. و كنتيجة لذلك، سيتم تمرير مثيل Project كمُعامل أول لتوابع المتحكِّمات (controller methods)، لذلك قُم بتحديثها وقٌم بتمرير متغير project$ الجديد. إذا لم تفهم خطوات الإضافة لـ TasksController و ProjectsController فهذه هي الشيفرة الكاملة للملفين بعد كل التعديلات: // /app/Http/Controllers/ProjectsController.php <?php namespace App\Http\Controllers; use App\Project; use App\Http\Requests; use App\Http\Controllers\Controller; use Illuminate\Http\Request; class ProjectsController extends Controller { /** * Display a listing of the resource. * * @return Response */ public function index() { $projects = Project::all(); return view('projects.index', compact('projects')); } /** * Show the form for creating a new resource. * * @return Response */ public function create() { return view('projects.create'); } /** * Store a newly created resource in storage. * * @return Response */ public function store() { // } /** * Display the specified resource. * * @param \App\Project $project * @return Response */ public function show(Project $project) { return view('projects.show', compact('project')); } /** * Show the form for editing the specified resource. * * @param \App\Project $project * @return Response */ public function edit(Project $project) { return view('projects.edit', compact('project')); } /** * Update the specified resource in storage. * * @param \App\Project $project * @return Response */ public function update(Project $project) { // } /** * Remove the specified resource from storage. * * @param \App\Project $project * @return Response */ public function destroy(Project $project) { // } } // /app/Http/Controllers/TasksController.php <?php namespace App\Http\Controllers; use App\Project; use App\Task; use App\Http\Requests; use App\Http\Controllers\Controller; use Illuminate\Http\Request; class TasksController extends Controller { /** * Display a listing of the resource. * * @param \App\Project $project * @return Response */ public function index(Project $project) { return view('tasks.index', compact('project')); } /** * Show the form for creating a new resource. * * @param \App\Project $project * @return Response */ public function create(Project $project) { return view('tasks.create', compact('project')); } /** * Store a newly created resource in storage. * * @param \App\Project $project * @return Response */ public function store(Project $project) { // } /** * Display the specified resource. * * @param \App\Project $project * @param \App\Task $task * @return Response */ public function show(Project $project, Task $task) { return view('tasks.show', compact('project', 'task')); } /** * Show the form for editing the specified resource. * * @param \App\Project $project * @param \App\Task $task * @return Response */ public function edit(Project $project, Task $task) { return view('tasks.edit', compact('project', 'task')); } /** * Update the specified resource in storage. * * @param \App\Project $project * @param \App\Task $task * @return Response */ public function update(Project $project, Task $task) { // } /** * Remove the specified resource from storage. * * @param \App\Project $project * @param \App\Task $task * @return Response */ public function destroy(Project $project, Task $task) { // } }لاحظ أنه إذا قمت بتحديث صفحة projects/project-1/ سيبقى كل شيء يعمل. عرض نماذجناصفحة عرض قائمة المشاريع، حان الآن وقت البدء بعرض المشاريع والمهام، قٌم بفتح projects/ في متصفحك. وبالاعتماد على php artisan route:list، ستكون هذه الصفحة هي صفحة عرض المشاريع، لذلك قُم بفتح resources/views/projects/index.blade.php/ وأضف التالي: @extends('app') @section('content') <h2>Projects</h2> @if ( !$projects->count() ) You have no projects @else <ul> @foreach( $projects as $project ) <li><a href="{{ route('projects.show', $project->slug) }}">{{ $project->name }}</a></li> @endforeach </ul> @endif @endsectionسوف أشرح بعض النقاط في هذه الشفرة البرمجية: استخدمنا في هذه الشفرة لغة Blade للقَوْلَبة، لذلك فإن if و foreach تتحكم في تدفق flow الدوال بإضافة إلى أنها دالة طباعة (الأقواس المعقوفة المزدوجة).تأكدنا إن كان هنالك أي مشروع لعرضه، إن كان هنالك أية مشاريع فسيقوم بعرضها وإن لم يكن تظهر رسالة تخبرك بذلك.استدعينا مساعد ()route مع طريق ذا اسم (يمكنك رؤية قائمة الطرق ذات الاسم عن طريق php artisan route:list) لربط كل مشروع مع صفحة تفاصيله.سوف تحتاج أيضا إلى تمرير متغير projects$ لهذا العرض view وإلا ستحصل على خطأ متغير غير معرف undefined variable error. قُم بفتح app/Http/controllers/ProjectsController.php/ وقُم بتحديث الوظيفة ()index إلى: public function index() { $projects = Project::all(); return view('projects.index', compact('projects')); }قُم بتحديث الصفحة (Refresh) وستجد قائمة من مشاريعك. علاقات النموذج - صفحة تفاصيل المشروعفي صفحة تفاصيل المشروع نحتاج إلى عرض قائمة من مهام المشاريع، وللقيام بذلك نحتاج إلى تعريف علاقة "واحد إلى الكثير one-to-many" في نموذج Project للسماح له بالحصول على المهام tasks. قُم بفتح app/Project.php/ وأضف التابع ()tasks كالتالي: public function tasks() { return $this->hasMany('App\Task'); }بشكل عكسي، يمكننا إضافة علاقة "الكثير إلى واحد many-to-one" لنموذج المهام Task: public function project() { return $this->belongsTo('App\Project'); }للتأكد من أنها تعمل اكتب الأمر: $ php artisan tinkerوستكون النّتيجة كالتي حسب المدخلات: >App\Project::whereSlug('project-1')->first()->tasks->count(); 5 >App\Project::whereSlug('project-2')->first()->tasks->count(); 2 >App\Task::first()->project->name; Project 1ممتاز، يمكننا الآن تحديث عرض resources/views/projects/show.blade.php/: @extends('app') @section('content') <h2>{{ $project->name }}</h2> @if ( !$project->tasks->count() ) Your project has no tasks. @else <ul> @foreach( $project->tasks as $task ) <li><a href="{{ route('projects.tasks.show', [$project->slug, $task->slug]) }}">{{ $task->name }}</a></li> @endforeach </ul> @endif @endsectionاضغط على أي مشروع في صفحة عرض قائمة المشاريع في متصفحك وسوف يتم عرض المشروع مع جميع المهام المرتبطة به. وأخير تَبقى لدينا صفحة عرض المهام (resources/views/tasks/show.blade.php/)، وهذه سهلة للغاية: @extends('app') @section('content') <h2> {!! link_to_route('projects.show', $project->name, [$project->slug]) !!} - {{ $task->name }} </h2> {{ $task->description }} @endsectionملاحظة: كُن حذرا عندما تستخدم علاقات النماذج (models)، فإنه من السهل إنشاء عدد كبير من استعلامات SQL، وتسمى هذه المشكلة بـ "مشكلة N+1". الخاتمةاليوم تعلمنا الكثير من الأشياء الجديدة مثل: الربط بين الطريق (route) و النموذجالنماذج (مع علاقة واحد إلى الكثير one-to-many)المتحكِّمات (مع الربط بين الطريق و النموذج)العروض (مع لغة blade للقَوْلَبة والمخططات)أصبحت الصفحة تعرض لنا قائمة من المشاريع والمهام، وفي الدرس القادم سوف نركز على تعديل وإضافة وحذف المشاريع والمهام. ترجمة -وبتصرّف- للمقال Creating a Basic ToDo Application in Laravel 5 – Part 2. حقوق الصورة البارزة: Designed by Freepik.
  5. حتى الآن تعلمنا كيفية تثبيت وإعداد Laravel، بالإضافة إلى أننا قمنا بـإعداد بعض موارد المشاريع والمهام وعرضهم للمستخدم. في هذا الدرس، سنتعلم كيفية إنشاء وتعديل وحذف الصفحات والإجراءات. إضافة روابط التصفحقبل أن نفعل أي شيء، سنقوم بإضافة روابط create/edit/delete/back إلى صفحات المشاريع والمهام: <!-- /resources/views/projects/index.blade.php --> @extends('app') @section('content') <h2>Projects</h2> @if ( !$projects->count() ) You have no projects @else <ul> @foreach( $projects as $project ) <li> {!! Form::open(array('class' => 'form-inline', 'method' => 'DELETE', 'route' => array('projects.destroy', $project->slug))) !!} <a href="{{ route('projects.show', $project->slug) }}">{{ $project->name }}</a> ( {!! link_to_route('projects.edit', 'Edit', array($project->slug), array('class' => 'btn btn-info')) !!}, {!! Form::submit('Delete', array('class' => 'btn btn-danger')) !!} ) {!! Form::close() !!} </li> @endforeach </ul> @endif <p> {!! link_to_route('projects.create', 'Create Project') !!} </p> @endsection <!-- /resources/views/projects/show.blade.php --> @extends('app') @section('content') <h2>{{ $project->name }}</h2> @if ( !$project->tasks->count() ) Your project has no tasks. @else <ul> @foreach( $project->tasks as $task ) <li> {!! Form::open(array('class' => 'form-inline', 'method' => 'DELETE', 'route' => array('projects.tasks.destroy', $project->slug, $task->slug))) !!} <a href="{{ route('projects.tasks.show', [$project->slug, $task->slug]) }}">{{ $task->name }}</a> ( {!! link_to_route('projects.tasks.edit', 'Edit', array($project->slug, $task->slug), array('class' => 'btn btn-info')) !!}, {!! Form::submit('Delete', array('class' => 'btn btn-danger')) !!} ) {!! Form::close() !!} </li> @endforeach </ul> @endif <p> {!! link_to_route('projects.index', 'Back to Projects') !!} | {!! link_to_route('projects.tasks.create', 'Create Task', $project->slug) !!} </p> @endsectionهذه الشفرة البرمجية مفهومة، الصعوبة تكمن في رابط الحذف، متحكِّمات الموارد تتطلب إرسال وظيفة HTTP DELETE، وهذا لا يمكن أن يتم مع رابط عادي، لذلك يتطلب نموذج يتم تقديمه إلى طريق route محدد. للمزيد من المعلومات قُم بزيارة إجراءات يتم التحكم بها عن طريق متحكِّمات الموارد. إنشاء صفحات الإضافة والتعديلبعد الانتهاء من صفحات عرض قائمة المشاريع، نحتاج إلى إمكانية إضافة وحذف المشاريع والمهام. استمارات الإضافة والحذف ستكون متشابهة كثيرا، لذلك بدلا من تكرارهم، سنقوم بوراثتهم من نموذج واحد. سوف نبدأ مع عروض create/edit للمشروع: <!-- /resources/views/projects/create.blade.php --> @extends('app') @section('content') <h2>Create Project</h2> {!! Form::model(new App\Project, ['route' => ['projects.store']]) !!} @include('projects/partials/_form', ['submit_text' => 'Create Project']) {!! Form::close() !!} @endsection <!-- /resources/views/projects/edit.blade.php --> @extends('app') @section('content') <h2>Edit Project</h2> {!! Form::model($project, ['method' => 'PATCH', 'route' => ['projects.update', $project->slug]]) !!} @include('projects/partials/_form', ['submit_text' => 'Edit Project']) {!! Form::close() !!} @endsectionقُم بعمل نفس الشيء مع المهام لكن لا تنسَ تحديث الطرق (routes): <!-- /resources/views/tasks/create.blade.php --> @extends('app') @section('content') <h2>Create Task for Project "{{ $project->name }}"</h2> {!! Form::model(new App\Task, ['route' => ['projects.tasks.store', $project->slug], 'class'=>'']) !!} @include('tasks/partials/_form', ['submit_text' => 'Create Task']) {!! Form::close() !!} @endsection <!-- /resources/views/tasks/edit.blade.php --> @extends('app') @section('content') <h2>Edit Task "{{ $task->name }}"</h2> {!! Form::model($task, ['method' => 'PATCH', 'route' => ['projects.tasks.update', $project->slug, $task->slug]]) !!} @include('tasks/partials/_form', ['submit_text' => 'Edit Task']) {!! Form::close() !!} @endsectionالآن توجد عدة مفاهيم جديدة: إضافة جزئيةالاستمارة تتطلب عدة وسوم، وبدلا من ذلك سنقوم بتقسيمها من جزئية _form ونضعها مباشرة في العرض، استمارة Add هي من نوع POST ترسل البيانات إلى طريق projects.store واستمارة Edit هي من نوع PATCH وترسل البيانات إلى projects.update. قد يبدوا هذا معقدا ومبهم لكن هذه هي الطريقة التي تعمل بها المتحكِّمات. لاحظ أننا استخدمنا ()Form::model، وتسمى هذه نموذج الاستمارة الملزمة و ليس لدى هذه أهمية كبيرة الآن، فهي تُستخدم للتعبئة التلقائية وسوف نحتاجها في وقت لاحقا عندما نضيف الحقول باستخدام ()Form::input.الحماية من CSRF:مساعدي الاستمارة (Form helpers) توفر العديد من الوظائف مجانا، فإذا ذهبت إلى projects/create/ ورأيت مصدر الصفحة ستجد شيئا مشابها لهذا: <form method="POST" action="http://l4todo.localhost.com/projects" accept-charset="UTF-8"> <input name="_token" type="hidden" value="Y8uOo7SeD5tQZExezDf5a7UwiYR4P6qIHEUKJNxI"> </form>هل ترى حقل token_ ؟ هذا هو الرمز المميز لـ CSRF مُنشئ تِلقائيا بواسطة استدعاء {{ ()Form::model }} الذي يمنع ثغرة CSRF. يكفي أن نقول أن هذا شيئ مفيد وأننا لم نقم بأي شيئ للحصول عليه. إنشاء استمارة التعديلنحن بحاجة إلى ترميز (markup) الاستمارة للمشاريع والمهام، وبفضل نموذج الاستمارة الملزمة يمكننا فقط استخدام مساعدي الاستمارة في Laravel لإخراج كافة الحقول التي نحتاجها. <!-- /resources/views/projects/partials/_form.blade.php --> <div class="form-group"> {!! Form::label('name', 'Name:') !!} {!! Form::text('name') !!} </div> <div class="form-group"> {!! Form::label('slug', 'Slug:') !!} {!! Form::text('slug') !!} </div> <div class="form-group"> {!! Form::submit($submit_text, ['class'=>'btn primary']) !!} </div> <!-- /resources/views/tasks/partials/_form.blade.php --> <div class="form-group"> {!! Form::label('name', 'Name:') !!} {!! Form::text('name') !!} </div> <div class="form-group"> {!! Form::label('slug', 'Slug:') !!} {!! Form::text('slug') !!} </div> <div class="form-group"> {!! Form::label('completed', 'Completed:') !!} {!! Form::checkbox('completed') !!} </div> <div class="form-group"> {!! Form::label('description', 'Description:') !!} {!! Form::textarea('description') !!} </div> <div class="form-group"> {!! Form::submit($submit_text) !!} </div>هذا كل شيئ، سوف تستطيع الأن التصفح في صفحات الإضافة والتعديل، الأمر كان سهلا للغاية. جعل الاستمارات تعمللدينا استمارات الإضافة والتعديل للمشروع و المهام، بالإضافة إلى استمارة مُضللة لحذفهم، الآن يجب علينا أن نجعلهم يعملون لأداء مهامهم. أولا، أضف هذا في أعلى المتحكِّمات: use Input; use Redirect;والآن لوظائف store و update و destroy: // ProjectsController public function store() { $input = Input::all(); Project::create( $input ); return Redirect::route('projects.index') ->with('message', 'Project created'); } public function update(Project $project) { $input = array_except(Input::all(), '_method'); $project->update($input); return Redirect::route('projects.show', $project->slug) ->with('message', 'Project updated.'); } public function destroy(Project $project) { $project->delete(); return Redirect::route('projects.index')->with('message', 'Project deleted.'); } // TasksController public function store(Project $project) { $input = Input::all(); $input['project_id'] = $project->id; Task::create( $input ); return Redirect::route('projects.show', $project->slug) ->with('message', 'Task created.'); } public function update(Project $project, Task $task) { $input = array_except(Input::all(), '_method'); $task->update($input); return Redirect::route('projects.tasks.show', [$project->slug, $task->slug]) ->with('message', 'Task updated.'); } public function destroy(Project $project, Task $task) { $task->delete(); return Redirect::route('projects.show', $project->slug)->with('message', 'Task deleted.'); }الشفرة البرمجية في الأعلى مفهومة ولا داعي لشرحها. إذا قمت الآن بتقديم إحدى الاستمارات فسوف تحصل على خطأ MassAssignmentException: _token، فالإحالة الكتلية تحدث عندما تقوم بتمرير مصفوفة بيانات إلى ()Model::create أو ()Model::update من المتحكِّمات بدل من وضع حقل واحد في نفس الوقت، ولإصلاح هذا، قم ببساطة بإضافة خاصية guarded إلى كل نموذج. class Project extends Model { protected $guarded = []; class Task extends Model { protected $guarded = [];رسائل الفلاشسوف تلاحظ من الشفرة السابقة أننا استخدمنا دالة ()with، وهذه الدالة تقوم بتمرير متغير فلاش (يستخدم لمرة واحدة) للجلسة session والتي يمكن قراءتها عند تحميل الصفحة التالية. والآن نحتاج إلى التأكد من تلك الرسالة وعرضها على المستخدم. قُم بفتح resources/views/app.blade.php/ وأضف التالي: ... <div class="content"> @if (Session::has('message')) <div class="flash alert-info"> <p>{{ Session::get('message') }}</p> </div> @endif @yield('content') </div> ...حاول إنشاء مشروع، هذه الرسالة ستظهر مهما حدّثت الصفحة وستذهب بعد فترة. خاتمةاليوم قمنا بأشياء مثيرة للغاية، فلقد أضفنا استمارات الإضافة والتعديل والحذف وتعلمنا حول CSRF و نموذج الاستمارة الملزمة بالإضافة إلى تعلمنا المزيد حول blade و الدوال. كل شيئ الآن يعمل، يمكن تجربة التطبيق وإنشاء وتعديل وحذف المهام والمشاريع، وفي أي وقت يمكنك كتابة الأمر: php artisan migrate:refresh –seed وسوف يتم إعادة تعيين قواعد البيانات. في المرحلة القادمة والتي ستكون النهائية سوف نقوم بالتحقق من الاستمارات. ترجمة -وبتصرّف- للمقال Creating a Basic ToDo Application in Laravel 5 – Part 3. حقوق الصورة البارزة: Designed by Freepik.
  6. هل قمت مسبقًا بتعبئة نموذج ما على الويب وطُلب منك إدخال نفس البيانات مرّتين؟ هذا ما يسمى بالإدخال المزدوج (double entry) يدعى أيضًا "إعادة الإدخال" (re-entry) أو "التأكيد" (confirm) ، ومن المؤكَّد أنّك قد صادفت هذا الشيء في العديد من المواقع المشهورة مثل Google (يتم طلب إدخال كلمة المرور مرّتين) و Facebook (يتطلب إدخال البريد الإلكتروني مرّتين. أُنظر الشكل 1). الشّكل 1: نموذج التسجيل لموقع Facebook يتطلب إدخال البريد الإلكتروني مرَّتين. لماذا يطلب منك إدخال نفس المعلومات مرتينكل حقل إضافي في النّموذج يعني عملًا وجهدًا إضافيًا على من سيقوم بتعبئة هذا النّموذج، وهذا يعني زيادة محتملة في الأخطاء ونقصًا في معدَّل إكمال النماذج. إذاً لماذا يتم إضافة حقل إضافي يحتوي على معلومات تمت تعبئتها مسبقًا في حقل آخر؟ يهدف الإدخال المزدوج إلى منع الأخطاءالهدف الرئيسي من الإدخال المزدوج (double entry) هو منع الأخطاء. فعندما يُطلَب من المستخدم إعادة كتابة بريده الإلكتروني أو كلمة المرور فإنّ ذلك يعطينا القُدرة للتّأكد بأنّ معلومات الحقلين متطابقة. أمّا إذا لم تتطابق الحقول، فهذا يعني احتمالية وجود خطإ مطبعي/إملائي (بسبب الإستعجال في الكتابة مثلًا أو عدم الإنتباه). الشّكل 2 يحتوي على لقطة من نموذج التسجيل الخاص بشركة Google وكيف يظهر الخطأ بسبب عدم تطابق الحقلين. الشّكل 2: نموذج تسجيل Google وكيف يظهر الخطأ في حالة عدم تطابق الحقلين. (كلمة احتمالية مهمة هنا لأن الخطأ قد يكون في حقل إعادة الإدخال وليس في الحقل الأصلي. وفي هذه الحالة، سيُطلب من المستخدم إعادة إدخال الحقلين معًا). الإدخال المزدوج يمنع الأخطاء ولكنه يسبب المشاكل أيضاعند استخدام الإدخال المزدوج في أحد النماذج، فإنّنا نطلب من جميع المستخدمين القيام بجهدٍ إضافي مقابل منع ما قد يكون عددًا صغيرًا من الأخطاء. قبل الشُّروع في بناء نماذج الإدخال المزدوج، يجب عليك أن تحدّد حجم المشكلة الّتي تحاول منعها وأن تُقرِّر فيما إذا كانت تستحق التضحية المحتملة بعدد النماذج التي سيتم إكمالها. حتى وإن قمت باستخدام الإدخال المزدوج، فالبشر أذكياء وسيقومون بالبحث عن أفضل الوسائل لتقليل العمل المطلوب منهم. ومن أحد السلوكيات الشائعة نسخ البريد الإلكتروني وكلمة المرور من الحقل الرئيسي وإلصاقه في الحقل الآخر، وهذا التصرف بكل تأكيد ينافي الفائدة المرجوَّة من الإدخال المزدوج. يمكنك أن تبرمج النموذج بحيث يتم منع النسخ واللصق داخل تلك الحقول. ولكن قد يسبب هذا التصرف الإرباك والحيرة لبعض الأشخاص، فقد لا يستطيعون إدارك السبب الكامن وراء توقف اللصق عن العمل. وقد لا يمنع ذلك المستخدمين من نسخ ولصق المعلومات من مصادر أخرى (أحد برامج إدارة كلمة المرور على سبيل المثال). قد يَستخدم بعض الأشخاص أدوات مبرمجة تقوم بتعبئة النماذج بشكل آلي. وقد تكون هذه الأدوات مبنية في المتصفّح أو على شكل إضافة يتم تحميلها وإضافتها للمتصفّح. لهؤلاء المستخدمين، ستكون النماذج المزدوجة معدومة الفائدة (بالنّسبة لحقل البريد الإلكتروني على الأقل). قد يجد بعض المستخدمين في الإدخال المزدوج نوعًا من التعالي عليهم أو الإستهانة بهم. فقد يُفهَمُ من وجود الإدخال المزدوج بأنَّ صاحب النّموذج لا يثق بقدرات المستخدم على إكمال النموذج بشكل صحيح. وبالتالي، فقد يُهَدِّدُ الإدخال المزدوج الثقة المبنية بين المستخدم وصاحب النّموذج والتي تعتبر مُهِمَّة في زيادة نسبة التّحويل (conversion) ومعدلات إكمال النّماذج. لماذا يستخدم الإدخال المزدوج في أغلب الأحيان لعناوين البريد الإلكتروني وكلمات المرور فقط؟مع وجود كل هذه العيوب، فقد يتساؤل أحدكم عن سبب استخدام الإدخال المزدوج. بكل تأكيد، تعتبر هذه العيوب السبب الرئيسي في نُدرة استخدام الإدخال المزدوج وسببًا لتواجدها في حقول البريد الإلكتروني وكلمة المرور فقط. لمَ هذه الحقول فقط؟ لأنه بالنّسبة للعديد من الأنظمة والخدمات، يُعتبر البريد الإلكتروني وكلمة المرور المفاتيح الرّئيسية التي تمنح المستخدم حق الوصول واستخدام العديد من الخدمات. لذلك، فإن الأثر المترتب على وجود خطأ ما في أحد هذه الحقول سيكون أكبر من الأثر المترتب على اختيار خاطئ لعنوان (title) أو كتابة اسمك بشكل خاطئ. قد يجادل بعض الأشخاص بأنّ هناك حقولًا لا تقل أهمية عن البريد الإلكتروني وكلمة المرور كرقم البطاقة الإئتمانية مثلًا. مع ذلك، فإن عمليّة التّحقق من صحة رقم بطاقة الإئتمان تتم في أغلب الأحيان عند نقطة الإدخال. علاوة على ذلك، فإن رقم بطاقة الإئتمان لا تعدّ من معلومات الإتّصال، فإذا تمَّ إدخال الرّقم بطريقة خاطئة فيمكننا التواصل مع المستخدم وإعلامه بذلك، أمّا إذا كانت معلومات الإتصال غير صحيحة فسيكون من الصعب تدارك الموقف. سيقول أولئك الذين يفكرون بطريقة منطقية بأنَّ الإدخال المزدوج سيكون مناسبًا لأرقام الهواتف. وممّا لا شكَّ، أنّه إذا كان رقم الهاتف هو الوسيلة الوحيدة (أو الأساسية) للتواصل مع المستخدم، فسيكون استخدام الإدخال المزدوج أمرًا مناسبًا. وإن كان رقم التّواصل عبارة عن رقم هاتف محمول فيمكننا التّحقق من هويّة المستخدم عن طريق إرسال رسالة نصّيَّة قصيرة تطلب منه القيام بأمرٍ ما لإتمام العملية. طرق أخرى للتأكد بأن البريد الإلكتروني صحيحإن الطريقة المذكورة بالأعلى للتحقق من أرقام الهواتف يمكن أن تُستخدم أيضاً للتأكد من البريد الإلكتروني. فبالإضافة إلى التّحقق من صحَّة البريد الإلكتروني، فإنَّه يجب التحقق أيضاً بأنّ المستخدم يمكنه الدخول إلى ذلك البريد واستعماله. ويتم ذلك بإرسال "رابط تفعيل" إلى ذلك البريد، فإذا تم زيارة وفتح الرابط المُرسل (يكون هذا الرابط فريدًا ومتغيرًا لكل مستخدم) فسوف تتم العمليَّة بشكل جيد، وإذا لم يتمَّ زيارة الرابط فإن عملية التسجيل، البيع أو الخدمة لن تتم. إذا كان عنوان البريد هو اسم المستخدم، فإنَّ طريقة التحقق هذه تعتبر-نوعًا ما- أفضل من الإدخال المزدوج. فبينما يضمن الإدخال المزدوج تطابق البريدين المدخلين في كلا الحقلين، فإنّ عملية المصادقة تضمن بأنّ يكون البريد الإلكتروني صحيحًا ومستعمَلًا. ومما لا شك فيه، فإن طريقة المصادقة هذه تُبعِد المستخدم عن النموذج وتعتمد بشكلٍ رئيسي على وصول رسالة البريد إلى بريد المستخدم وتفاعله معها. كل هذه الأمور قد تدفع المستخدم إلى ترك الموقع أو الخدمة وبالتالي الفشل. لتقليل الأثر السَّلبي المترتب على عملية المصادقة فإنها يجب أن تكون مصمّمة ومبنيّة بعناية وحذر (يمكنك على سبيل المثال أن تُبلغ المستخدم بما يجب عليه فعله وأن تعطيه الوقت الكافي ليقوم بتفعيل الرَّابط). وإذا كان من اللازم أن يكون البريد الإلكتروني صحيحًا، فإن مزايا عملية المصادقة هذه ستتغلب على عيوبها. لقد وُجِدَ في دراسة أجراها موقع Smashing Magazine في عام 2008 على أفضل 100 موقع إلكتروني بأن 18% فقط من تلك المواقع تتطلب من المستخدمين الإدخال المزدوج لعناوين بريدهم الإلكتروني مقارنة مع 72% من المواقع تتطلب الإدخال المزدوج لكلمات المرور. لم يعتبر الإدخال المزدوج لكلمات المرور شائعا أكثر من البريد الإلكتروني؟هناك العديد من الأسباب التي تكمن وراء وجود عدد أكبر من المواقع التي تتطلب الإدخال المزدوج لكلمة المرور أكثر من المواقع التي تتطلب الإدخال المزدوج للبريد الإلكتروني. أحد أهمِّ الأسباب -وعلى عكس البريد الإلكتروني- فإنّه عند إدخال كلمات المرور في الحقول المخصَّصة لها (وعلى افتراض أنّه تمَّ تكويد هذه الحقول بشكلٍ صحيح) ، فإنّها تكون مخفيَّة أو "محجوبة" بشكلٍ افتراضي (على شكل نقاط سوداء دائريّة، كما في الشَّكل 3). وتهدف عمليَّة الحجب هذه إلى منع الأشخاص من استراق النظر ورؤية كلمة المرور التي يدخلها المستخدم. الشكل 3: حجب كلمة المرور. تمَّ كتابة كلمة "testing" في الحقل ولكنها ظهرت على شكل نقاط سوداء. ولأنّ المستخدم لن يتمكنّ من رؤية الرّموز التي يدخلها، فستكون نسبة حدوث الأخطاء أكبر، وبالتالي وجود حاجة أكبر إلى الإدخال المزدوج. علاوة على ذلك، فإنّ كلمات المرور في أغلب الأحيان تكون "عشوائية" أكثر من عناوين البريد الإلكتروني. فعناوين البريد تحتوي في الغالب على اسم الشَّخص، اسم الشَّركة، مزود خدمة البريد أو مزود خدمة الانترنت، وكلُّ هذه الأشياء يُمكن تذكُّرها بسهولة. في المقابل، قد تكون كلمات المرور مزيجًا من رموزٍ وأرقام عشوائية (ليس بالضرورة أن يكون هذا أفضل خيار من ناحية أمنيّة، ولكن بشكلٍ عام، فإن كلمات المرور الطويلة والغامضة تكون آمنة أكثر). بدائل الإدخال المزدوج لكلمات المروريُعتبر الإدخال الوحيد/الفرديّ أحد بدائل الإدخال المزدوج. وقد تعمل هذه الطريقة بشكل مناسب إذا ما افترضنا أنّه تم تزويد المستخدم بطريقة سهلة لِتَذكُّر كلمة المرور أو إعادة ضبطها إذا ما نسيها (يُفضَّل إضافة هذه الخاصيّة في جميع الأحوال، فقد ينسى أيّ شخصٍ كلمة المرور خاصته). ومن المثير للإهتمام بأنّ نماذج التسجيل الموجودة في Facebook ،LinkedIn وTwitter تتطلب إدخال كلمة المرور مرّة واحدة فقط. الشكل 4: لا يوجد إدخال مزدوج في نماذج التسجيل الخاصّة بشركة LinkedIn. و بديل آخر للإدخال المزدوج هو إعطاء المستخدم القدرة على تعطيل خاصيّة الحجب في حقل كلمة المرور. يُعطي هذا للمستخدم الحريّة الكافية لإظهار كلمة المرور إن كان يشعره ذلك بالرّاحة. هناك العديد من الطّرق لفعل هذا ولكنّ الطّريقة التي يوصى بها موضّحة بالشّكل 5. حيث يفضّل إضافة زر "Show password" على إضافة مربّع اختيار (checkbox) أو زوج من أزرار الرّاديو (radio buttons) لأنّه يُسهّل عمليَّة إظهار أو حجب كلمة المرور. الشكل 5: إظهار أو حجب كلمة المرور عند النَّقر على "Show password" قد يواجه المستخدم صعوبة في تفسير مربّع الاختيار، وقد يكون من الصَّعب مَوضَعَة أزرار الرّاديو وترتيبها بشكلٍ فعّال. فقد تأخذ أزرار الرّاديو حَيِّزًا أكبر من السؤال ذاته إذا ما وضعت فوق بعضها البعض، وإذا وُضعت بجانب بعضها قد تسبب لك المشاكل في استعمال ما يسمى بالمجاورة (proximity) لتوضيح أيّ إجابة ترتبط بأيّ زرّ. إنّه لمن الصّعب أيضًا أن تربط حقل كلمة المرور بمربّع اختيار أو زوجٍ من أزرار الرّاديو مقارنة مع ربطه برزٍّ واحد. فكر مليا قبل استخدام الإدخال المزدوجيُعتبر منع الأخطاء في أيّ نموذج من الأمور المحبَّبة، ولكن من المهمّ جدًا أن توجد حاجة ملحّة لاستخدام الإدخال المزدوج وذلك يعود إلى النقاط التالية: أنّها تزيد العبء والجهد على كل المستخدمين.يمكن تجاوزها عن طريق النّسخ واللصق أو باستخدام أدوات تعبئة النماذج بشكل آلي.تضمن فقط أنّ الحقلين متطابقين ولا تضمن احتواء هذه الحقول على معلومات صحيحة.يمكن أن تُرى كنوعٍ من الاستخفاف والإستهانة بالآخرين.إذا كان البريد الإلكتروني أو اسم المستخدم هما الطّريقة الوحيدة للتّواصل مع المستخدم، فيمكنك حينئذ استخدام الإدخال المزدوج. وبطريقة مشابهة، إذا لم تكن ترغب في تمكين المستخدم من إظهار كلمة المرور، فقد يكون الإدخال المزدوج ملائمًا في هذه الحالة. حتّى في الحالات المذكورة في الأعلى، فإنّ البحث عن بدائل للإدخال المزدوج (مثل المصادقة أو بعض الطرق البسيطة لإعادة الضبط والاسترداد) يستحقُّ النَّظر فيه بِجدِّيَّة. ترجمة -وبتصرّف- للمقال Double entry of form fields.
  7. يبدو أن الأسئلة المتعلقة بالمحاذاة تظهر بانتظام. ولكن لسوء الحظ، فحتى مع وجود أبحاث معتبرة تقدم رؤية واضحة فيما يتعلق بالمشكلة، فإن معظم نتائج النقاشات التي تدور حولها تكون مبنية على تفضيلات وتكهنات شخصية. في هذا المقال، سنقدم لكم ملخص الأبحاث لإعطائكم توصيات محددة وسهلة الاستعمال لهذا الجانب المهم من تصميم النماذج. مختلف أنواع المحاذاة (alignment)بالنسبة للمحاذاة، هناك العديد من الأبعاد المختلفة التي تؤخذ بعين الإعتبار، منها: كيفية محاذاة الأسئلة بالنسبة لبعضها البعض.كيفية محاذاة نص السؤال (أعلى أم يسار حقل الإجابة؟).في الأسئلة المغلقة مع فئات استجابة متعددة، كيف يتم محاذاة هذه الفئات.كم عدد الحواف (edges) الموجودة في النموذج لمختلف أنواع المحاذاة.قبل أن نتكلم عن هذه الأبعاد كل على حدة (مع استخدام بعض الرسومات لجعل الصورة أوضح)، ضع في الحسبان أن التوصيات المقدمة في هذا المقال: ستكون خاصة بالنماذج التي لها سياق اللغة الإنجليزية أو ما يشابهها من ناحية نمط القراءة (أي اللغات التي تقرأ من اليسار إلى اليمين). وبالتالي، فإنك قد تحتاج إلى تعديل هذه التوصيات لتتناسب مع الثقافات التي تقرأ من اليمين إلى اليسار (كاللغة العربية). تقدم نهجا افتراضيا لتصميم النماذج. وبما أنه يوجد دائما بعض الاستثناءات لأي قاعدة، فإنه من المهم جدا أن تضبط الأمور لتتناسب مع السياق الخاص بك.1. كيف تقوم بمحاذاة الأسئلة بالنسبة لبعضها البعضعلى افتراض أن البشر يقرؤون من الأعلى إلى الأسفل، فإنه يفضل وضع الأسئلة فوق بعضها (بشكل عمودي) بدلا من وضعها بجانب بعضها البعض (بشكل أفقي). يخلق هذا إيقاعا عموديا متناسقا ويساهم في إيجاد "مسار واضح للإستكمال" كما أسماه Luke Wroblewski. الشكل 1: محاذاة الأسئلة عموديا كما يوضحه السهم الأزرق. قد يكون من المغري رص سؤالين إلى بعضهما لتقليل المساحة العمودية اللازمة. قد يؤدي ذلك إلى حصول بعض الأجزاء في النموذج على سطر كامل لسؤال واحد فقط وترك بقية الأجزاء تحتوي على عدة أسئلة في سطر واحد. وقد يؤدي عدم التناسق هذا إلى: إعاقة من يريد تعبئة النموذج عن معرفة الطريقة التي سيتحرك بها خلال عملية التعبئة، وبالتالي إبطاء عمله.زيادة احتمالية عدم قدرة الشخص على رؤية وإجابة واحد أو أكثر من الأسئلة (وهو ما لا نريده بكل تأكيد).يبين الشكل 2 نموذجا يحتوي على أسئلة مرتبة/متراصة بشكل أفقي حيثما كان ذلك ممكنا. من المحتمل في مثل هذه الحالة أن يتم إهمال الحقول الموجودة في الجزء الأيمن من الصفحة خصوصا إذا لم يقم المستخدم بملئ الحقل السابق إلى نهايته (لأقصى يمين الحقل). الشكل 2: محاذاة الأسئلة أفقيا. يمكن استغلال المساحة في النموذج بشكل أفضل وذلك بفصله إلى عمودين (كما في الشكل 3). فإذا ما فصلت الصفحة إلى عمودين، فسوف تتم محاذاة الأسئلة في كلا العمودين، وهذا يعني أن الأسئلة ستبدأ من الأعلى إلى الأسفل للعمود الأول، ومن الأعلى إلى الأسفل للعمود الثاني وبعدها إلى الصفحة التالية. ولعدد من الأسباب سنذكرها في مقال آخر، فإنه من غير المحبذ استخدام أعمدة متعددة في نموذج إلكتروني (electronic form) خصوصا في النماذج الموجودة على شبكة الإنترنت. الشكل 3: صفحة تحتوي على نموذج مزدوج الأعمدة. 2. كيفية محاذاة نص السؤالافتراضيا، إن أفضل موقع لنص السؤال يكون في أعلى حقل السؤال، كما هو موضح في الشكل 4. الشكل 4: نص السؤال يظهر أعلى حقل السؤال. يوصي مصمم النماذج الاسترالي الشهير Robert Barnett بهذه الطريقة، وقد أثبتت فعالتيها -من حيث عدد مرات إنهاء النموذج- مقارنة بوضع النص إلى يسار حقل الإجابة (أنظر "موضعة التسمية (label) في النماذج" لكاتبه Matteo Penzo). هناك فائدتان أخريان من وضع نص السؤال فوق الحقل: الفائدة الأولى، هي أنها تسهل عملية ترجمة نص السؤال إلى لغات أخرى، لأنه بهذه الحالة لن يهمنا طول أو قصر النص المترجم.الفائدة الثانية، أنها تمكن من يعانون عسر القراءة أو ممن لديهم إعاقة إدراكية أو حتى مستخدمي قارئات الشاشة (screen readers) من تفادي المشاكل التي قد يواجهونها مع النص الموضوع إلى يسار الحقل (سوف نتكلم عن هذا بعد قليل).إن من أحد المساوئ الرئيسية لوضع نص السؤال أعلى حقل الإجابة هو الزيادة الملحوظة في حجم المساحة العمودية التي يحتاجها النموذج. هذا يعني زيادة عدد الصحفات في النماذج الورقية وتمرير(scrolling) أكثر في النماذج الإلكترونية. لذلك، وعلى فرض أنه تم استخدام المحاذاة المناسبة، فقد يكون من الأفضل في بعض الحالات وضع نص السؤال إلى يسار الحقل. محاذاة النصهناك أربع خيارات لمحاذاة النص وهي دفع لليسار (flush left)، دفع لليمين (flush right)، ضبط من الطرفين (justify) وتوسيط (أنظر الشكل 5). قد تجد أيضا من يستخدم كلمتي "ranged" و "ragged" بدلا من كلمة "flush". الشكل 5: أربع طرق رئيسية لمحاذاة النص. إذا وضع نص السؤال فوق حقل الإجابة، فإنه يجب دفعه إلى اليسار للأسباب التالية: تعتبر المحاذاة لليسار من أفضل الممارسات (best practice) ومناسبة لأغلب المواد المقروءة.تعتبر-بشكل عام- أسهل للقراءة مقارنة بالنصوص المدفوعة لليمين (flush right) أو المتوسطة.قابل للقراءة كالنص المضبوط من الطرفين (justified text) ولكنه وعلى عكس النص المضبوط من الطرفين (justified text) فإنه لا يتطلب تدخلا يدويا لإصلاح مشاكل تباعد الكلمات.يعزز المسار العمودي للإنهاء.عند وضع نص السؤال إلى يسار حقل الإجابة، يفضل -على عكس ما قد يتوقعه البعض- أن يكون ذلك النص مدفوعا لليمين. وقد أشار Matteo Penzo في البحث الذي ذكرناه مسبقا بأن الدفع لليمين يعمل بشكل أفضل من الدفع لليسار. (لسوء الحظ، قد لا يكون هذا صحيحا بالنسبة لمن يعانون عسر القراءة. ولهذا السبب فإن الطريقة الأفضل والتي ينصح بها هي وضع التسمية (label) فوق الحقل). الشكل 6: محاذاة نص السؤال إلى يسار حقل الإجابة ودفعه لليمين. يقول البعض بأنه يجب دفع النص إلى اليسار بدلا من اليمين لأن ذلك يسهل عملية تصفح النموذج للأسفل. قد يكون هذا صحيحا، ولكن ما نريده حقا من التصميم هو تعبئة النموذج وليس قراءة الأسئلة بشكل سريع بحثا عن كلمة أو عبارة معينة. كما أن ما نريده هو اختيار أسلوب التصميم الذي يدعم الهدف الرئيسي (أي تعبئة النموذج)، وهو ما يوفره الدفع لليمين. شيء مهم أيضا، وهو أن جعل النص مدفوعا لليسار، يجعل عملية ربطه مع حقل الإجابة الخاص به أمرا صعبا خصوصا لمن يستخدم مكبرات الشاشة (screen magnifiers) أو لمن يعاني من صعوبات في الإدراك. يعود ذلك إلى أن اختلاف أطوال نص السؤال قد يعني في بعض الحالات وجود فجوة/مساحة كبيرة بين نهاية نص السؤال وبداية حقل الإجابة. قد يكون ذلك أحد الأسباب التي دفعت المنظمة العالمية للمعايير (ISO) والمعايير الوطنيّة الأمريكية HFES200 (هندسة العومل البشريّة لواجهات استخدام البرامج) أن توصي بأن يكون نص السؤال مدفوعا لليمين إلا إذا تساوت أطوال جميع الأسطر. 3. كيفية محاذاة فئات الإستجابةإذا كان مصطلح فئات الإستجابة غير مألوف بالنسبة لك، فقد ترغب في الإطلاع على هذا المقال. لنفس الأسباب التي ذكرناها بالنسبة للأسئلة، فإنه يجب محاذاة فئات الإستجابة عموديا (أي وضع الفئة "ب" أسفل الفئة "أ"). الشكل 7: محاذاة فئات الإستجابة عموديا. كما ذكرنا سابقا، فإنه من المغري وضع الأسئلة بجانب بعضها (بشكل أفقي). ينطبق نفس الأمر على فئات الإستجابة، خصوصا إذا كانت التسميات (labels) قصيرة. غالبا ما تكون الأسئلة المتعلقة بالمسميات title (مثل "Mr" أو "Mrs") أحد العناصر الرئيسية للجوء البعض إلى استخدام المحاذاة الأفقية، لأن ذلك قد يؤدي إلى حفظ الكثير من المساحة العمودية. عندما تحدثنا عن الأسئلة، رأينا بأن وضع العناصر إلى جانب بعضها قد يؤدي إلى إبطاء من سيقوم بتعبئة النموذج وإلى ارتفاع معدل الأخطاء. وعند استخدام هذه الطريقة في فئات الإستجابة فإن مشكلة إضافية ستظهر وهي ضعف الرابطة بين مسمى فئة الإستجابة والحقل الخاص به. وكما هو موضح في الشكل 8، فإن المسافة بين المسمى والحقل هي نفسها في كلتا الحالتين. مع ذلك، ففي حالة محاذاة الفئات عموديا يكون من الواضح جدا معرفة أي مسمى يرتبط بأي حقل، على عكس المحاذاة بشكل أفقي. الشكل 8: إذا استخدمنا المحاذاة العمودية (يمين الصورة) بدلا من المحاذاة الأفقية (يسار الصورة)، فسيكون من السهل على من سيقوم بتعبئة النموذج أن يربط مسميات فئات الإستخدام بما يقابلها من حقول. في بعض الحالات، يمكن تعديل المسافة الأفقية للتخفيف من هذه المشكلة. كما يمكن أيضا تلافي هذه المشكلة نهائيا وبأقل جهد، وذلك بمحاذاة فئات الإستجابة عموديا بدل محاذاتها أفقيا. محاذاة النّص لفئات الإستجابةكما هو الحال بالنسبة لنص السؤال، يجب علينا أن نقرر فيما إذا كانت المسميات الخاصة بفئات الإستجابة المختلفة (يطلق عليها أيضا اسم "عناوين فرعية" أو "تعقيبات") مدفوعة لليمين، مدفوعة لليسار، مضبوطة من الطرفين (justified) أو متوسطة. يعتبر هذا أحد أكثر الجوانب جدالا في تصميم النماذج، ويرجع ذلك بشكل جزئي إلى اختلاف الممارسات الشائعة في نماذج شبكة الإنترنت عنها في تلك الموجودة في مجال الطباعة. عندما يتعلق الأمر بالنماذج الورقية (بما في ذلك النماذج الإلكترونية التي يمكن طباعتها وتعبئتها وملفات الـ pdf لأحد النماذج الورقية) فإنه من الواضح بأن أفضل طريقة هي وضع مسميات الفئات إلى يسار الحقول الخاصة بها ودفعها إلى اليمين. الشكل 9: وجود مسميات فئات الإستجابة إلى يسار الحقول ومدفوعة لليمين. قبل 25 سنة، أثبتت Patricia Wright بأن هذه الطريقة هي الأفضل، وقد كانت الأبحاث التي قام بها Robert Barnett على مدى عقود مضت متوافقة مع ما جاءت به Patricia Wright. عندما يتعلق الأمر بالتصميم في العالم الواقعي، فلن يكون الجواب بتلك البساطة. فبالنسبة لمسألة المحاذاة لمسميات وحقول فئات الإستجابة، فسيظهر بعض التعقيد بسبب وجود الإنترنت (the web). تاريخيا، كانت النماذج على شبكة الإنترنت تضع المسميات على يمين الحقل (كما هو الحال في الشكل 7 الموجود في الأعلى)، ويعود ذلك إلى بعض الأسباب البرمجية. على شبكة الإنترنت، يكون من الصعب محاذاة حقول الإستجابة عبر اسئلة متعددة بشكل عمودي. وعلى الرغم من صعوبة تحديد هذه الأمور، فإنه من المعقول قول بأن هذه الطريقة في وضع المسميات أصبح متعارفا عليها بشكل افتراضي (تحديدا كما أصبح نهج شركة مايكروسوفت (Microsoft) في تصميم برامج سطح المكتب أمرا متعارفا عليه افتراضيا). لهذه الأسباب، سوف تستمر مسميات فئات الإستجابة في نماذج الويب بالظهور إلى اليمين من الحقول الخاصة بها. توقع أيضا بعض الأوقات عندما تتصادم الهيمنة التاريخية للنماذج الورقية مع الشعبية المتزايدة النماذج الإلكترونية. 4. عدد الحواف (edges) في النموذجمن آخر جوانب المحاذاة التي سنتحدث عنها في هذا المقال هو عدد الحواف لمختلف طرق المحاذاة الموجودة في النموذج. إن بداية أو نهاية أي كتلة نصية (block of text) أو مساحة بيضاء/فارغة (white space) يخلق ما يسمى "الحافة". قد تكون هذه الحافة هي نهاية حقل الإجابة أو حدود أحد الأعمدة أو المسافات البادئة (indentations) لجميع نصوص الأسئلة. بمقارنة الشكلين 10 و11 في الأسفل، يظهر الشكل 10 نموذجا يحتوي على الكثير من الحواف، أما الشكل11 فيظهر نموذجا بعدد قليل من الحواف، فأيهما تفضل؟ الشكل 10: نموذج بعدد كبير من الحواف. الشكل11: نموذج بعدد قليل من الحواف. عند مقارنة التصاميم ذات الحواف الكثيرة مع التصاميم ذات الحواف القليلة، سنلاحظ بأن الأخيرة تعتبر أكثر جمالا وأسهل في الإستعمال. كما ينصح بأن يتم محاذاة العناصر المتوافقة بشكل عمودي ومتناسق. بعبارة أخرى، يجب على نص مربعات الأسئلة ذات الأطوال المتشابهة أن تبدأ وتنتهي بنفس النقطة العمودية، ويجب أيضا أن تبدأ جميع الأسئلة من نفس النقطة العمودية وهكذا دواليك. ملخص التوصياتكخلاصة لكل ما ذكرناه في هذا المقال، فإن الطرق الواجب اتباعها والتي ننصح بها هي: محاذاة الأسئلة عموديا.وضع نص السؤال فوق حقل الإجابة ودفعه لليسار.محاذاة فئات الإستجابة عموديا.للنماذج الورقية: وضع مسميات فئات الإستجابة إلى يسار الحقول الخاصة بها ودفعها لليمين.لنماذج الإنترنت: وضع مسميات فئات الإستجابة إلى يمين الحقول الخاصة بها ودفعها لليسار.تقليل عدد الحواف العمودية في النموذج على قدر المستطاع.ترجمة -وبتصرّف- للمقال Alignment.
  8. على الرغم من وجود بعض الانتقادات لواجهات المُستخدم المُنبسِطة ووصفها بأنّها مجرد موضة، أو أنها رد على التصميم المُحاكي للواقع (skeuomorpic)، فإن كثيرًا من المصممين تبنّوا فكرة التصميم المُنبسط بسبب أنّ التخفيف من حدّة التّصميم المرئي (مثل التدرج اللّوني، تأثيرات الظل، والحواف) ينتج عنه واجهات أبسط وأنظف. تكمن المشكلة في أنه تم بناء أغلب واجهات المستخدم المنبسطة بشكل يُركّز على توفير المحتوى، أما المكونات التي يتفاعل معها المستخدم (transactional components) مثل النماذج، فلم تحظَ سوى بالقليل من الاهتمام. ماذا سيحدث عندما يتعارض التصميم المُنبسط مع النماذج؟ يُمكن أن يُواجه المُستخدم مشاكل لدى استخدامه للموقع، وهذا أمر واردٌ جدًا. الاهتمام بالنّماذجالمقصود بالنّماذج هنا هو أي تفاعُل (interaction) يتم فيه تبادل للمعلومات لاستقبال منتج أو خدمة. هذا يتضمن عدّة أمور بدءًا بالبنوك الإلكترونية (internet banking) وصولًا إلى التجارة الإلكترونية على الهواتف الذّكيّة (mobile commerce)، ومرورًا بكلٍ من التّسجيل لاستخدام تطبيق على جهاز لوحي والقيام بعملية بحث على الويب. احتياجات المستخدمين إلى تصميم النماذج يختلف كثيرًا عن احتياجهم إلى تصميم المحتوى، كما هو ملخَّص في الجدول التالي: النماذج المحتوى إتمام المهمة الاستكشاف وإتمام المهمة يركِّز المستخدمون على الحقول لا يركز المستخدمون على الحقول عادة ما يكون هناك نقطة دخول واحدة ونقطة خروج واحدة إمكانية وجود عدة نقاط دخول وخروج مفاهيم النجاح والفشل معرَّفة بشكل صارم ودقيق تختلف مفاهيم النجاح والفشل تستخدم لمرّة واحدة تستخدم لعدة مرات على الأرجح، فإن النماذج تُستخدم لإنجاز مهمة معينة. وأنا على يقين أنني واحد من الناس القليلين في العالم الذين يدرسون النّماذج من أجل المُتعة، أما الأشخاص الأسوياء فإنّ جُلّ ما يرغبون به هو تعبئة النموذج لتسجيل سياراتهم أو لشراء ذلك الحذاء الجديد. ولكن لما يتعلّق الأمر بالمُحتوى فإن إنهاء مهمة معينة ليس بالضّرورة أولوية. أحيانًا قد نتصفّح الإنترنت من دون أن يكون لدينا هدف مُحدّد نرغب في الوصول إليه، (كمن يتصفّح موسوعة Wikipedia لساعات). ينظر الناس إلى "إنهاء مهام محددة" بطرق مختلفة عن الاستكشاف والتّعرُّف. لاحظ شخصًا يملأ نموذجًا، وسترى بنفسك تركيزه على الحقول، رجوعه إلى التعليمات، الخطوات وحتى إلى مسميات الحقول، ويسأل فقط عند ما يكون هناك داعٍ. هناك ترتيب: مكان للبدء ومكان للإنهاء، وعند الانتهاء سيعرف ما إذا كان قد نجح أو فشل في إنجاز المهمة. بالمقابل فإنه يتّم الوصول إلى المحتوى عبر مسارات ومن مصادر مُختلفة، ويعمد الناس إلى استعراض والتركيز على المحتوى بعدة طرق مُختلفة. فكرة النَّجاح لا تزال صحيحة هنا، ولكنّها مُختلفة بسبب اختلاف حالات الاستخدام. التركيز على إنهاء المهمة يعني أنَّ على المستخدم ملء النموذج مرة واحدة فقط، بينما يتم زيارة المحتوى أكثر من مرة. إذًا، هناك فرصة ضئيلة أن يتعلّم المُستخدم اللغة البصرية للنموذج (مثال، أن يكون النموذج بدون أزّرار ويتم استبدالها بروابط فقط). التصميم المُنبسِط يعني معلومات أقلكقاعدة أساسية فإنَّ النَّماذج والمحتوى مختلفان. لكن قد تتساءل، ما علاقة هذا الأمر بواجهات المستخدم المُنبسطة flat UI؟ المشكلة الأساسيّة هو أنه في مجال واجهات المُستخدم المُنبسطة تم الدّفع بالتبسيط بشكل يُمكن وصفك بالمُبالغة. لمّا يتعلّق الأمر بالمُحتويات فإنه يُمكن اعتبار كل من تأثيرات الظلّ، التدرُّجات والحواف مجرد زخرفة embellishments، فعند قراءة مقال مكوّن من أكثر من صفحة، فإنه لا يُهم ما إذا كانت آلية الانتقال إلى الصفحة التالية تتم عبر رابط نصّي أو زِّر. أما في النماذج فالأمر يختلف، فالتّفريق ما بين الزِّر والرابط النصّي أمر مُهم. كمثال على ذلك لنلق نظرة على حدثي الإرسال submit والإلغاء cancel في النماذج. كما هو معروف فإن لكل من هذين الحدثين نتائج مختلفة تمامًا، ونُريد من المستخدم أن يختار الحدث الذي يتوافق مع احتياجه بشكل سريع وسهل في آن واحد. لهذا أنصح أنا وغيري من المُصمّمين أن يتمّ التفريق بينهما وأن يكون الحدث الرئيسي (الإرسال أو الموافقة) كزّر، أما الحدث الثانوي (الإلغاء) فيكون كرابط نصّي. التصميم المرئي ليس مجرّد تحسينات جمالية، ولكنّه يُعبّر بشكل صريح عن الاختلاف الوظيفي ما بين العناصر وعن ترتيبها حسب أولويّاتها. في المُقابل، فإن نموذج Klout التالي، يُوضّح كيف يُمكن للمعلومة أن تضيع جرّاء المُبالغة في تبسيط الواجهات المُسطّحة. وضع الزّر "إلغاء cancel" قبل الزّر "إرسال submit " يعتبر نمطًا خبيثًا (dark pattern) سيّئًا جدًا (يستخدم هذا النوع من التصميم في خداع المستخدم لفعل شيء معين)، لكن لندع هذا الأمر جانبًا . لنركز على جانب التّصميم، لاحظ كيف أنّه تمّ تنسيق الحدثين الرئيسي والثانوي كروابط نصّيّة، بنفس اللون وبنفس الخلفية، مما سيُقلّل من سرعة المُستخدم ويدفعه إلى التّركيز أكثر قبل أن يتخذ القرار. تخيّل معي كيف سيكون هذا النموذج أكثر قابلية للاستخدام إذا ما تمًّ التَّفّريق بين الأحداث والتّوضيح بشكل بصري عن ذلك (ومرة أخرى لنترك نمط التصميم الخبيث جانبًا): الطُرق الثلاثة المُؤدّية إلى فشل النماذج المُنبسطةالمثال السابق يوضّح هذه الطُرق والتي تؤدي إلى فشل نماذج الواجهات المُنبسطة في توفير تجربة استخدام سهلة: ضُعف الجانب الإيحائي (affordance): يُقصد بذلك أن المُنتج سواء كان حسّيّا أو غير حسّي فإنّه يُفترض به أن يوحي إليك بطريقة استخدامه. كأن يتبادر إلى ذهنك مفهوم الجلوس بمُجرد أن ترى كُرسيًّا. عدم وجود فروق كافية وواضحة بين عناصر النموذج (مثال، الحقول ومسمياتها والتعليمات والأزرار). عدم وجود تسلسل كافٍ في داخل أصناف عناصر النموذج (مثال، الأزرار الأساسية والأزرار الثانوية). يفتقد حدثا "الإرسال" و "الإلغاء" في واجهة Klout إلى الإيحائية، لأنَّ التصميم لا يدعوك إلى التّفاعل معه (interaction) بشكل صحيح. كان بإمكان هذه الأحداث أن تبدو قابلة للنّقر إذا تم إعطاؤها شكل الزّر (فهي أحداث actions) أو على الأقل لو تم وضع خطّ تحتها حيث أن ذلك ما يُميّز الرّابط من النّصّ العادي على الويب. كما أنّه لم يتم التفريق ما بين عناصر النموذج بشكل جيّد، فالفرق الوحيد الذي يفصل بين الرّابط القابل للنّقر وغير القابل للنّقر هو لون النّص. أما بالنسبة لترتيب الروابط، فمثال Klout مُثير للانتباه بشكل خاص. فوضع زّر "إلغاء" أولًا يُعطيه أهمية وقيمة أكبر مُقارنة بزر "الإرسال" (وهنا حجر زاوية نمط تصميم الخبيث- حيث أن ما اُتّفق عليه هو أنّ ما يأتي أوّلا هو الخيار القياسي). وفوق ذلك، فإن لكلي الرابطين نفس التنسيق، رغم أنّها مُختلفان، وسواءً نظرت إلى الأمر من وجهة نظر Klout أو من وجهة نظر المُستخدم. كيف يمكن تجنب هذه الأخطاء مع الإبقاء على الواجهات مُنبسطة؟ ببساطة، كل ما تحتاج القيام به هو إضافة بعض المؤثّرات البصرية التي توحي بطبيعة كل عنصر وبالعلاقة التي بينها. يُمكن القيام بذلك عبر التركيز على أهم العناصر في النموذج: وهي الحقول والأزرار، والتي تعتبر نواة التّفاعل مع المُستخدم. تعديل تصميم الحقول والأزّراريكون تصميم النماذج المُنبسطة ناجحًا إذا كانت الحقول تبدو مُقعّرة (hollow) والأزرار تكون بارزة. فمثل هذا التصميم يوحي بكيفية استخدام مُختلف عناصر النموذج ويظهرها مختلفة عن بعضها البعض. الصورة التالية مأخوذة من صفحة شراء سماعات Lowdi وتُظهِر نتيجة إغفال القاعدة السابقة (الحقول مُقعّرة والأزرار بارزة). فتصميم كلا من حقل الكمية وزِّر الشراء له نفس درجة التسطُّح أو الانبساط، فلا يوجد أي دعوة للمستخدم للتفاعل مع الحقل أو الزّر. إذا لم يركّز المستخدم فإنه لن يُدرك بأنّه بإمكانه تغيير الكمية، ويصعب عليهم أيضًا معرفة المكان الذي يجب أن ينقر عليه (الزِر) لكي ينتقل إلى الخطوة التالية. إليك كيفية التَّفريق بين الحقول والأزرار وكذلك كيفية إضفاء الإيحائية اللّازمة عليها: ما يمكن فعله كيفية التنفيذ جعل الحقول غائرة أضف حواف للحقول أو ظل داخلي، على الأقل تكون الحواف بعرض 1px، أزل لون الخلفية جعل الأزّرار بارزة أضف تأثيرات الظل للزّر، زوايا دائرية، تدرُّج لوني، أو حواف، حتّى ولو كان الأمر بسيطًا جدًا استعمل لون خلفيّة الزّر مغاير للّون المستخدم في الصفحة أو الحقول إصلاح الحقولدعنا نلقي نظرة على الحقول قبل وبعد إصلاحها، مع التركيز على الحقول أولًا. تظهر شاشة التسجيل في موقع Hipstamatic's Oggl المُخصّصة للهواتف كما في الصورة الأولى (على اليسار) من مجموع الصورة الثلاث في الأسفل. نلاحظ أن إيجاد مكان إضافة عنوان البريد الإلكتروني أشبه بلعبة الغُمّيضة هنا. قارن هذه الصورة مع صور التّصميمين البديلين الذين اقترحتهما (الصورة الثانية والثالثة). في التصميم الثاني تمّت إضافة حواف للحقل، مما يجعله يبدو كعنصر مختلف عن الباقي. في التصميم الثّالث تمّت إضافة الحواف والتّخلّص من لون الخلفية المُستخدم في الصفحة. استخدام هذا النّموذج أصبح أسهل، رغم أن التصاميم البديلة تستخدم واجهات مُنبسطة لكنّها أفضل بكثير خاصّة من حيث إيحائية العناصر التي نلحظها في النّسخة الثّالثة. عندما أطلقت فيس بوك graph search اِكتشفت بأسوأ طريقة مُمكنة أهمية استخدام الحقول المُقعّرة. بداية، لم يكن لحقل البحث أي لون في الخلفية (كانت خلفية حقل البحث بنفس اللّون الأزرق المُستخدم في الشريط العلوي). وماذا كانت النتيجة؟ لم يتمكّن الكثير من المستخدمين من إيجاد هذه الميزة. بعد اختبار أربع نُسخ مختلفة من حقل البحث، توصّلت فيس بوك إلى أنّ الخلفية البيضاء والظل الداخلي الخفيف- مثل الحقل الذي يظهر مُقعّرًا- هو الحل الأمثل. الاتّزان في تصميم الأزراروالآن سنركّز على الأزرار، مع مثال آخر قبل وبعد التعديل. في مثال مُحرّك البحث التّالي، لدينا على اليسار النّسخة الأصلية، والنّسخة المٌحسّنة والأفضل استخدامًا على اليمين. الزّر في التصميم الأصلي كان مُنبسطًا بشكل كبير جدًا، يظهر للمستخدم بشكل مماثل للتّرويسة، لذيل الصّفحة، أو لأي كُتلة من كتل الصّفحة. إنقاص عرض الزِّر وإضافة الزوايا الدائرية، يعطي إيحائية أفضل (affordance) مع المحافظة على وجود مساحة كافية للَّمس/النّقر. الأحداث الرئيسية والأحداث الثانوية.أخيرًا، لا تنسَ أن تُنسّق الأحداث الرئيسية بشكل مُختلف عن الأحداث الثانوية في النموذج. هناك طريقتان للقيام بذلك: استخدم الأزّرار مع الأحداث الرئيسية والروابط النّصّيّة مع الأحداث الثانوية استخدم تنسيق يُبرِز الأزرار المُخصصة للأحداث الرئيسية، مُقارنة مع تنسيق الأزرار المُخصصة للأحداث الثانوية. مثال عن استخدام الروابط النّصّيّة مع الأحداث الثّانوية في نموذج تسجيل الدخول. ويُمكن الذّهاب إلى أبعد من ذلك، مثلما شرحه Riki Tanone حول كيفية التَّفريق بين الأزرار الرئيسية والثانوية في مدونته المتخصصة بقوالب واجهات الاستخدام على Dribble. معلومات أكثر تعني قابلية وصول أفضلقد تلاحظ أنّ النماذج في واجهات الاستخدام المُنبسطة الأكثر قابلية للاستخدام تحتوي على نوع من التكرار. لا تحتوي عادةً على مُكون مرئي واحد (كاللّون مثلا) لتوضيح الفرق. عوضًا عن ذلك فإنه قد يتم استخدام اللّون والشّكل معًا أو اللّون والحجم معًا. هذا التكرار يجعل الواجهة أكثر قابلية للوصول لِطيفٍ واسع من المستخدمين، لأن التصميم لا يَفترض بأنّ المستخدم قادر على رؤية أو فهم الاختلاف البصري الوحيد الذي يدلّ على نوعيّة التّفاعل. يُعتبر اللّون مثالًا رائعًا، فهناك نحو 12 بالمئة من البشر من يُعاني من مشاكل مع الألوان. إذا كان اللّون هو الفرق الوحيد بين النص القابل للنَّقر والنص العادي، كما في مثال Klout، فإنك -بهذه الطريقة- تُصعّب المهمّة على نسبة 12 بالمئة من المستخدمين على الأقل. قارن هذا مع التوصيات التي طرحتها أو تلك التي طرحها Luke Wroblewski وآخرون، والتي تنصّ على أنه يجب تعليم الحقول المطلوبة بنجوم حمراء (كما في يسار الصّورة التّالية). في هذا المثال تقوم الألوان والأشكال معًا على إيصال فكرة مُعيّنة للمُستخدم، لهذا يُعد النموذج قابلًا للاستخدام حتّى من قبل المستخدمين الذين لديهم مشاكل مع الألوان (قد يظهر لديهم النموذج كما في الجزء الأيمن من الصورة). خاتمةكمُصمّمين نريد أن ننشئ تجربة استخدام رائعة من خلال البساطة والوضوح. فما هي البساطة وما هو الوضوح؟ هي معرفة المُستخدم ما يجب فعله بالضبط، وكيفية القيام بذلك دون بذل جهد كبير. الحصول على هذا النوع من تجربة الاستخدام يعني إيجاد توازن فعلي، بمعنى أنّ استخدام التّصميم المُنبسط ليس غاية في حدّ ذاته. لمّا نتعامل مع النّماذج فإنّه يجب أن نعلم بأنّ التّقليل ليس بالضرورة تبسيطًا. ترجمة -وبتصرّف- للمقال Flat UI and Forms لصاحبته Jessica Enders