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

يوغرطة بن علي

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

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

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

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

    2

كل منشورات العضو يوغرطة بن علي

  1. أكبر مُشكل قد يواجه المُستقّلين هو تكرار طلبات التّعديل بعد تسليم المشروع. ما هي أفضل طريقة للتّعامل مع ذلك؟
  2. على Archlinux في بعض الحالات يتم تحديث برمجيات/حزم قد تُسبب في توقف برمجيات أخرى تعتمد عليها. هل هناك إمكانية لتعطيل تحديث برمجية بعينها لدى تحديث كل النظام
  3. الآن وبعد أن قررت الانتقال إلى خادوم خاص (أو VPS) وأطلقت تطبيق الويب الذي عملت عليه لأسابيع طويلة، وصلت إلى مرحلة تحتاج فيها إلى استقبال رسائل بريد إلكتروني، لكنك لا ترغب في أن تنشر عنوانك على Gmail أو Yahoo بل تود أن تستخدم عنوان بريد إلكتروني "احترافي" يحتوي اسم النطاق الخاص بك على شاكلة myname@mydomain.com. الحل يكمن في تنصيب خادوم بريد إلكتروني، أو استخدام عميل تمرير البريد الإلكتروني يقوم باستقبال، توصيل وإعادة توجيه رسائل البريد الإلكتروني. تنصيب خادوم بريد إلكتروني كامل باستخدام postfix يتطلب الكثير من الجهد والوقت، وحتى ولو قمت بذلك فإنك لن تحصل على تجربة مُستخدم مُماثلة لتلك التي ألفتها على خدمات البريد الإلكتروني الشهيرة كخدمة Gmail. بإمكانك الجمع ما بين الأمرين (أي استقبال رسائل مُرسلة إليك عبر اسم نطاق موقعك والحصول على تجربة مُستخدم Gmail) عبر استخدام خدمة Google apps مدفوعة الأجر مثلا، لكن بإمكانك أيضا القيام بذلك عبر استقبال الرسائل عبر postfix وتمريرها إلى بريدك الإلكتروني المُفضل. سنقوم في هذا المقال باستعراض الخُطوات اللازمة للقيام بذلك على خواديم Ubuntu / Debian. قم بالتعديل حسبما يُناسبك إن كنت تستخدم توزيعة مُختلفة. تنصيب Postfix تنصيب Postifx سهل وبسيط، حيث يكفي تنفيذ الأمر التالي: $ sudo apt-get install postfix سيتم طرح بعض الأسئلة عليك لدى تنصيب التطبيق، قم بالإجابة عنها وفق ما يتناسب مع مُتطلباتك وبُمجرد أن يتم الفراغ من التنصيب سيتم تشغيل خادوم البريد الإلكتروني بشكل آلي. $ sudo service postfix status * postfix is running بإمكانك التحقق من أن Postix يستمع للمنفذ 25 باستخدام أمر netstat $ sudo netstat -ltnp | grep 25 tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1926/master tcp6 0 0 ::1:25 :::* LISTEN 1926/master العمود الأخير يُظهر pid الخاص بـ postfix تحقق من DNS الخاص باسم النطاق الخاص بك قبل أن نقوم بإعداد Postfix لتمرير الرسائل التي يتم إرسالها إلى اسم النطاق المعني بالأمر يجب أولا أن نتحقق من أن سجلات MX مُوجهة إلى الخادوم المُناسب. بإمكاننا القيام بذلك باستخدام الأمر dig على النحو التالي: $ dig binarytides.com mx ; <<>> DiG 9.9.3-rpz2+rl.13214.22-P2-Ubuntu-1:9.9.3.dfsg.P2-4ubuntu1.1 <<>> binarytides.com mx ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7230 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;binarytides.com. IN MX ;; ANSWER SECTION: binarytides.com. 85100 IN MX 10 mail.binarytides.com. ;; Query time: 74 msec ;; SERVER: 127.0.1.1#53(127.0.1.1) ;; WHEN: Fri Mar 28 08:59:17 IST 2014 ;; MSG SIZE rcvd: 65 مثلما تُلاحظه في قسم 'ANSWER SECTION' فإن mail.binarytides.com هو خادوم البريد الإلكتروني الخاص باسم النطاق binarytides.com. الآن يجب أن نتحقق من سجلات a الخاص بـ mail.binarytides.com والتي يجب أن تُظهر أن عنوان الـ IP صحيح $ dig mail.binarytides.com a ; <<>> DiG 9.9.3-rpz2+rl.13214.22-P2-Ubuntu-1:9.9.3.dfsg.P2-4ubuntu1.1 <<>> mail.binarytides.com a ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43356 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;mail.binarytides.com. IN A ;; ANSWER SECTION: mail.binarytides.com. 85045 IN A 173.255.230.5 ;; Query time: 30 msec ;; SERVER: 127.0.1.1#53(127.0.1.1) ;; WHEN: Fri Mar 28 09:00:19 IST 2014 ;; MSG SIZE rcvd: 65 إعداد Postfix لتحويل رسائل البريد الإلكتروني لتحويل الرسائل التي نستقبلها يجب أولا أن نعرف مسار مُجلد الإعدادات باستخدام الأمر postconf $ postconf | grep config_directory config_directory = /etc/postfix ومن ثم نقوم بتحرير ملف الإعدادات main.cf /etc/postfix/main.cf وإضافة السطرين التاليين: virtual_alias_domains = mydomain.com myanotherdomain.com virtual_alias_maps = hash:/etc/postfix/virtual في السطر الأول نقوم بتحديد كافة النطاقات التي نرغب في أن يقوم postfix باستقبال الرسائل المُرسلة إليها. يجب الفصل ما بين كل اسم نطاق وآخر بمسافة. أما السطر الثاني virtual_alias_mapsفيُبين الملف الذي يحتوي آلية الربط ما بين العناوين المُستقبلة والعناوين المُمرر إليها. الآن يكفي أن تقوم بفتح ملف /etc/postfix/virtual (أو إنشائه إن لم يكن موجودا) وإضافة العناوين التي ترغب فيها على النحو التالي: # تمرير رسائل عنوانين contact@mydomain.com myself@gmail.com sales@mydomain.com myself@gmail.com العنوان الأول في كل سطر هو عنوان الاستقبال والعنوان الثاني هو العنوان الذي سيتم تحويل الرسائل إليه. بإمكان تحويل نفس الرسالة إلى أكثر من عنوان في نفس الوقت على النحو التالي: contact@mydomain.com myself@gmail.com mystaff@gmail.com كما أنه بإمكانك تحويل جميع الرسائل المُرسلة إلى اسم نطاق مُعين: # تحويل جميع الرسائل @mydomain.com myself@gmail.com mystaff@gmail.com بعد الفراغ من إضافة جميع العناوين، احفظ الملف وقم بتنفيذ الأمر التالي لأخذها في الحسبان (تحديث جدول lookup الخاص بـ postfix) $ postmap /etc/postfix/virtual ثم إعادة تحميل إعدادات postfix $ sudo service postfix reload بإمكانك التحقق من أنك قمت بإضافة العناوين بشكل صحيح بتنفيذ الأمر التالي: $ postconf -n | grep virtual virtual_alias_domains = mydomain.com myanotherdomain.com virtual_alias_maps = hash:/etc/postfix/virtual أرسل رسالة تجريبية الآن قم بإرسال رسالة إلى هذه العناوين الجديدة وتحقق من وصولها إلى عناوين التمرير التي اخترتها لا تنس أن تقوم بإعداد Gmail (أو أية خدمة بريد أخرى) لتُرسل الرسائل باستخدام اسم النطاق الخاص بك (ستجد ذلك في إعدادات الخدمة)، وحينها سيكون لديك بريد إلكتروني "احترافي" من دون أن تدفع سنتا إضافيا. ترجمة -وبتصرف- للمقال: Setup mail forwarding in postfix on Ubuntu or Debia
  4. Nginx عبارة عن مشروع مفتوح المصدر، له استخدامات مُختلفة قد يكون أهمها هو استخدامه كخادوم ويب. يُمكن اعتبار Nginx كمنافس قوي لخادوم apache رغم قُوة هذا الأخير. إليكم دليلا سريعا حول كيفية تنصيبه، إعداده واستخدامه كخادوم ويب محلي. سأستعرض آلية تنصيب وإعداد nginx على نظام لينكس (توزيعة Archlinux) ويُمكنك تغيير مسارات الملفات لتتوافق مع مسارات الملفات على توزيعتك المُفضلة للوصول إلى نفس النتيجة. بداية سنحتاج أولا إلى تنصيب nginx عبر الأمر التالي (وفي حال ما إذا كانت مشاريعك مكتوبة بلغة php فإنك ستحتاج أيضا إلى تنصيب php-fpm): sudo pacman -S nginx php-fpm على توزيعة ubuntu سيكون أمر التنصيب هو: sudo apt-get install nginx php5-fpm بعد الفراغ من التنصيب سنقوم بتفعيل الخادوم (وphp-fpm) وتشغيله بالأمرين التاليين: sudo systemctl enable nginx php-fpm sudo systemctl start nginx php-fpm بعد قيامك بذلك ولو استعرضت عنوان localhost فستظهر لك صفحة تؤكد لك بأنه تم تنصيب الخادوم وتشغيله بنجاح. الآن وبحكم أنك ستعمل على أكثر من مشروع ويب في آن واحد على جهازك المحلي سنقوم بإعداد الخادوم لتمكيننا من ذلك. لنبدأ أولا بإلقاء نظرة على ملف nginx.conf الذي يتحكم في الخادوم. ستلاحظ الشفرة التالية المسؤولة عن إظهار صفحة البداية آنفة الذكر server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } وكل ما نحتاجه هو إنشاء خادوم server جديد لكل مشروع تود العمل عليه، لكن ولإبقاء هذا الملف "نظيفا" ولتجنب حصول أية مشاكل بسبب تعديل غير مرغوب فيه سنقوم بإنشاء ملف مُنفصل لكل مشروع جديد. اذهب إلى المُجلد الذي تم تنصيب nginx فيه (/etc/nginx/ ) وقم بإنشاء مُجلدي sites-available وsites-enabled إن لم يكونا موجودين من قبل. لماذا سنحتاج إلى مُجلدين؟ سنضع في الأول المواقع (المشاريع) التي نعمل عليها و"سنضع" في الثاني المواقع (المشاريع) التي نود أن نقوم بتنفيذها. صحيح أن هذه الخُطوة قليلة أو ربما عديمة الفائدة على خادوم محلي، لكن من الأفضل أن تعود نفسك على ذلك قبل أن تقوم برفع مواقعك إلى خادوم فعلي. سنقوم بإنشاء ملف إعدادات لكل مشروع جديد داخل مُجلد site-available ولنسمي كل ملف باسم المشروع متبوعا بـ .dev (يُمكنك تجاهل هذه اللاحقة إن أردت أو استخدام أي لاحقة أخرى) بعبارة أخرى لو كان المشروع الأول الذي نود أن نقوم بتشغيله عبر nginx هو myproject فسيكون اسم الملف هو myproject.dev إليكم مثالا عن إعدادات phpmyadmin (بطبيعة الحال ستحتاج إلى تنصيبه أولا قبل أن تقوم بذلك): server { listen 80; server_name phpmyadmin.dev; location / { root /usr/share/webapps/phpMyAdmin; index index.html index.htm index.php; try_files $uri $uri/ /index.php$is_args$args; autoindex on; } location ~ \.php$ { root /usr/share/webapps/phpMyAdmin; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } في حال ما إذا كان مشروعك داخل مُجلد آخر فيكفي أن تغير قيمة root. لو كان مشروعك متواجدا داخل /srv/http/myproject فيكفي أن تغيير root لتصبح root /usr/share/webapps/myproject; ستحتاج أيضا إلى تغيير قيمة fastcgi_pass لتتوافق مع مسار php-fpm على نظامك، فلو كنت على توزيعة ubuntu مثلا فسيكون المسار unix:/var/run/php5-fpm.sock; بطبيعة الحال يُمكنك إضافة، تعديل أو إزالة أية إعدادات أخرى حسب الحاجة كتفعيل أو تعديل مسار صفحة الخطأ error_page 404 أو تعطيل خاصية autoindex on; التي تسمح باستظهار مُحتوى المُجلدات التي لا تحتوي على ملفات index. الآن وبعد أن أنشأنا على الأقل ملفي إعدادات (واحد للمشروع myproject وآخر لسكربت phpMyAdmin) سنحتاج أن نقوم بنقلهما إلى مُجلد sites-enabled، لكن لن نقوم بنسخهما بل يكفي أن نقوم بإنشاء رابط وهمي. بعبارة أخرى سنقوم بإنشاء رابط وهمي من مُجلد sites-enabled إلى ملفات الإعدادات الموجودة في مجلد sites-available وذلك على النحو التالي: sudo ln -s /etc/nginx/sites-available/myproject.dev /etc/nginx/sites-enabled/myproject.dev sudo ln -s /etc/nginx/sites-available/phpmyadmin.dev /etc/nginx/sites-enabled/phpmyadmin.dev بقيت خُطوة أخيرة، وبحكم أننا سنتحكم في جميع مشاريعنا عبر ملفات فردية فإننا لن نحتاج بعد الآن إلى الإعدادات الموجودة في ملف nginx.conf. هذا من جهة، ومن جهة أخرى سنحتاج إلى تضمين هذه الملفات الفردية في الملف الرئيسي عبر الأمر: include sites-enabled/*; ليصبح الملف على النحو التالي: #user html; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; include sites-enabled/*; } الآن وبعد أن أنهينا إعداد ملفات الخواديم، سنحتاج إلى إعادة تشغيل nginx ليأخذ التغييرات في الحسبان عبر الأمر sudo systemctl restart nginx لكن كيف سنقوم باستعراض المشاريع على المُتصفح؟ بقيت خطوة أخيرة (ألم تقل في الخطوة السابقة أنها الخطوة الأخيرة؟؟:P) سنحتاج إلى تعديل ملف /etc/hosts وإضافة سطر لكل مشروع على النحو التالي: 127.0.0.1 myproject.dev localhost 127.0.0.1 phpmyadmin.dev localhost الآن يكفي أن أكتب في خانة العناوين العنوان phpmyadmin.dev أو myproject.dev لأتمكن من استعراض المشروعين. ملاحظة: هذا دليل سريع حول تنصيب nginx والشروع في استخدامه، قد تحتاج إلى إضافة إعدادات أخرى لتوافق ودعم أفضل لنظام إدارة المُحتوى الذي تعمل عليه أو للغة البرمجية المُفضّلة لديك. ملاحظة2: ستجد في الشفرات السابقة بعض الإعدادات المُعطلة (مسبوقة بمحرف #) تركت لتبيين بعض ما يُمكن إضافته للملف ابحث عن كل واحدة وفعلها حسب الحاجة.
  5. تخيّل معي الوضع التالي. أنت عضو في فريق تطوير تطبيق باستخدام Laravel 4. يستخدم أعضاء الفريق git لإدارة إصدارات التطبيق وفي كل مرة يقوم عضو من أعضاء الفريق بإضافة خصائص أو إدخال تعديلات جديدة على المشروع يقوم بإيداع التغييرات في مُستودع التطبيق. إلى هنا يبدو الوضع عاديا (بل مثاليا) لكن ماذا لو قام أحد أعضاء الفريق بإدخال تعديل يتطلب إضافة جداول جديدة إلى قاعدة البيانات أو تعديل حقول وحذف أخرى، فما الحل هنا؟ هل يستطيع git مثلا أن يفي بالغرض؟ أم أنه سيتم تصدير قاعدة البيانات في كل مرة ويُطلب من كل عضو في الفريق استيرادها؟ ماذا عن البيانات التي تحتويها قاعدة البيانات؟ وهل يجب فعلا أن نتخلص من قاعدة البيانات القديمة واستبدالها بأخرى في كل مرة؟ إن كنت تستخدم إطار عمل لارافل فالحل يكمن في استخدام التهجير migrations والذي يُعتبر نظاما لإدارة الإصدارات الخاصة بقواعد البيانات، حيث أنه لن تعود هناك حاجة إلى إنشاء أي جداول أو إضافة حقول والتعديل عليها بشكل مُباشر/يدوي، وإنما يتم وصف تلك الجداول وحقولها بصيغة تجعل من التعامل مع قواعد البيانات أسهل. قد يبدو الأمر مُعقّدا بعض الشيء، لكنه في حقيقة الأمر بسيط، وبمُجرد أن تفهم آلية عمله وتشرع في استخدامه حتى تستغرب كيف ضيعت كل الوقت السابق في إدارة قواعد البيانات يدويا. خاصية migrations مُفيدة لك حتى ولو كنت تعمل على مشروعك بشكل فردي. بطبيعة الحال ستحتاج إلى إنشاء قاعدة بيانات للمشروع، ومن ثم التعديل على ملف app/config/database.php بما يتوافق مع ذلك. إنشاء ملفات migrationsلإنشاء ملف migration جديد نحتاج إلى استخدام artisan لتنفيذ الأمر migration:make على النحو التالي مع استبدال اسم عملية التهجير بما يتوافق مع ما تقوم به (بطبيعة الحال ستحتاج إلى تنفيذ هذا الأمر بسطر الأوامر لما تكون داخل مُجلد المشروع): php artisan migrate:make create_users_tableسيقوم laravel بإنشاء ملف جديد داخل مُجلد app/database/migrations يحمل الاسم الذي حددته في الأمر السابق ( create_users_table) مسبوقا بترقيم يُمثل تاريخ إنشائه حتى يتسنى لـ laravel معرفة الترتيب الذي يجب اتباعه لدى تنفيذ التهجيرات. يُفضل استخدام أسماء للتهجيرات تدل على ما تقوم به. ففي المثال السابق أردنا إنشاء عملية تهجير جديدة لإنشاء جدول مُستخدمين، وبالتالي كان الاسم create_users_table. ينتج عن تنفيذ الأمر السابق ملف يحتوي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { // } /** * Reverse the migrations. * * @return void */ public function down() { // } } كما هو ظاهر هنا فإن الصنف CreateUsersTable يحتوي على دالتين الأولى up والتي تُبين ما الذي يجب القيام به لدى تنفيذ التهجير، والثانية down والتي نُحدد فيها ما الذي يجب القيام به لدى إلغاء التهجير في حال ما إذا أردنا العودة بقاعدة البيانات إلى الحالة التي كانت عليها قبل تنفيذ التهجير. هذا الملف لا يُحدد أي جدول نعمل عليه أو نرغب في إنشاءه. يُمكن إضافة ذلك يدويا، كما أنه يُمكن القيام بذلك عبر تحديد اسم الجدول لدى تنفيذ أمر إنشاء عملية التهجير وذلك باستخدام --create التي تُحدد اسم الجدول الذي نرغب في إنشاءه أو --table التي تُحدد اسم الجدول الذي نرغب في التعديل عليه. فمثلا لو حذفنا عملية التهجير السابقة ورغبنا في إعادة إنشاء أخرى مع تحديد اسم الجدول فسيكون ذلك على النحو التالي: php artisan migrate:make create_users_table --create=usersوالذي سينتج عنه ملف مثل الملف السابق، لكن هذه المرة نجد أن دالتي up و down تحتويان أوامر أولية: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('user', function(Blueprint $table) { $table->increments('id'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('user'); } } لاحظ هنا أن users هي اسم الجدول المُراد إنشاؤه والذي يكون عادة جمع اسم الـ model الذي تتعامل معه (بمعنى إن كان user هو اسم الـ model فسيكون اسم الجدول الخاص به users) أما لو أردنا التعديل على نفس الجدول السابق وإضافة حقل جديد إليه فيكفي تنفيذ الأمر التالي: php artisan migrate:make add_votes_to_user_table --table=users تنفيذ عمليات التهجيرإلى حد الآن كل ما قمنا به هو إنشاء ملفات التهجير، حيث أنك لو تحققت من قاعدة البيانات لوجدتها فارغة. لتنفيذ عمليات التهجير نستعمل الأمر php artisan migrateوبعد ذلك ستلاحظ ظهور جدول جديد على قاعدة البيانات. أما لو رغبت في التراجع عن آخر عملية تهجير (أو بالأحرى عن آخر جملة تهجيرات تم تنفيذها مع بعض) فإننا نستعمل الأمر: php artisan migrate:rollbackوفي حال ما إذا رغبت في التراجع عن جميع عمليات التهجير والرجوع إلى الحالة الأولى لقاعدة البيانات فإن الأمر التالي كفيل بالقيام بذلك: php artisan migrate:resetويُمكن أيضا استخدام الأمر التالي للتخلص من جميع عمليات التهجير وإعادة تنفيذها من جديد بشكل مُباشر بعد ذلك: php artisan migrate:refreshأنواع الحقولرأينا في الفقرة السابقة بأن عمليات التهجير تسمح لنا بإنشاء معرف autoincrement إضافة إلى حقلي created_at و updated_at بفضل دالة timestamps. يسمح Laravel بإنشاء شتى أنواع الحقول التي قد تحتاجها في مشروعك إلى جانب إضافة خصائص للحقول وإعطائها قِيمًا أوليّة. المثال التالي يُبين بعض هذه الحقول والخصائص: $user->string('name', 64); $user->integer('age')->nullable(); $user->boolean('active')->default(1); $user->integer('role_id')->unsigned(); $user->text('bio');والذي يقوم بإنشاء: حقل name يكون نصيا يكون أقصر من أو يُساوي 64 محرفا.حقل age يكون رقميا، كما أنه يقبل القيمة NULLحقل active يكون منطقيا ويحمل قيمة أولية 1حقل role_id رقميا ويكون موجباحقل bio يكون نصيابإمكان الاطلاع على جميع أنواع الحقول المُمكنة من هنا حذف الحقولستحتاج إلى حذف الحقول في دالة down ويتم ذلك على النحو التالي: Schema::table('users', function($table) { $table->dropColumn('votes'); });بذر قواعد البيانات database seedingالمقصود ببذر قواعد البيانات هو إدخال البيانات الأولية التي نحتاجها لتجربة التطبيق. بالرغم من أن تطبيقك يسمح بإنشاء مُستخدمين جدد فإنك سترغب في استخدام مُستخدمين تجريبيين في كل مرة تُحدث تغييرات في التطبيق، وإنشاء عدد من المُستخدمين يدويا في كل مرة مضيعة للوقت. الحل يكمن في إعلام Laravel بالبيانات الأولية التي ترغب في بذر قاعدة البيانات بها بعد إنشائها ويتم ذلك عبر إنشاء ملفات بذر داخل مُجلد app/database/seeds يحتوي الأوامر التي يجب تنفيذها. مثال على ملف بذر يقوم بإضافة مُستخدم جديد: class UserTableSeeder extends Seeder { public function run() { DB::table('users')->delete(); User::create(array('email' => 'foo@bar.com')); } } لتنفيذ عملية البذر التي قمنا بإنشائها فإننا نستخدم الأمر التالي: php artisan db:seed --class=UserTableSeederوإن كان لديك أكثر من ملف بذر وترغب في تنفيذها كاملة بأمر واحد فإنه يكفي القيام بذلك عبر تحديد أسماء عمليات البذر المُراد تنفيذها في صنف/ملف DatabaseSeeder الذي ستجده داخل مُجلد app/database/seeds على النحو التالي: class DatabaseSeeder extends Seeder { public function run() { $this->call('UserTableSeeder'); $this->call('PostTableSeeder'); } }وبعد ستحتاج إلى تنفيذ الأمر php artisan db:seedالذي سيقوم بقراءة الملف واستدعاء عمليات البذر بشكل مُتوال بإمكانك أيضا تنفيذ عمليات البذر مُباشرة بعد تحديث عمليات التهجير على الشكل التالي: php artisan migrate:refresh --seedتوليد بيانات تجريبية باستخدام Fakerبالرغم من أن هذه الخُطوة ليست ضرورية، إلا أنه في الكثير من الحالات ستحتاج إلى بيانات تجريبية أقرب ما تكون إلى البيانات الحقيقية للتجريب عليها. فمثلا سترغب في استخدام أسماء مُستخدمين "حقيقيين" وعناوين بريد إلكتروني، وعناوين منازل، إضافة إلى أسماء المُدن وأرقام هواتف وما إلى ذلك. بطبيعة الحال فإنه بالإمكان الاكتفاء بملفات البذر وإدخال تلك البيانات بطريقة شبه يدوية، إلا أن هناك حلا آخر يُسهّل عليك ذلك إن استعنت بمكتبة Faker للحصول على هذه البيانات. بداية سنحتاج إلى "تنصيب" Faker وذلك على النحو التالي: قم بالتعديل على ملف composer.json وإضافة التالي: "require-dev":{ "fzaninotto/faker": "1.5.*@dev" },أو قم بإضافة "fzaninotto/faker": "1.5.*@dev" إن كان حقل require-dev مُتوفرا في الملف. بعدها قم بتنفيذ الأمر php artisan update ليقوم artisan بتحميل الملفات المطلوبة. في غالب الأحوال ستحتاج إلى إنشاء مُستخدم غير عشوائي إلى جانب البيانات التجريبية، وعليه يُفضل إنشاؤه أولا قبل توليد البيانات العشوائية. $user = User::create(array( 'username' => 'djug', 'first_name' => 'Youghourta', 'last_name' => 'Benali', 'email' => 'djug@someNewProject.com', 'password' => Hash::make('MySuperPassword') )); $faker = Faker\Factory::create(); for ($i = 0; $i < 25; $i++) { $user = User::create(array( 'username' => $faker->userName, 'first_name' => $faker->firstName, 'last_name' => $faker->lastName, 'email' => $faker->email, 'password' => Hash::make('Password') )); في هذا المثال قمنا بإنشاء 25 مُستخدم يحملون أسماء بشر (وليس مُجرد حروف عشوائية) إضافة إلى عناوين بريد إلكتروني. تسمح مكتبة Faker بتوليد شتى أنواع الحقول التي قد تحتاجها والتي يُمكن الحصول على نُسخ مُوطنة ومُترجمة منها، فمثلا يُمكن توليد أسماء عربية وعناوين فرنسية وما إلى ذلك. للمزيد حول مكتبة Faker قم بإلقاء نظرة على مُستودع المشروع على github وللمزيد حول جميع أنواع العمليات التي يُمكن القيام بها على الهجرات: Schema Builder
  6. تخيل معي الوضع التالي: أنت مُطور PHP، لديك مشروع تود تطويره، قد تختار إطار عمل مُعين لهذه المهمة، لكنك ستحتاج إلى بضعة مكتبات إضافية للقيام بذلك، تخيل بأنك تود أن يقوم تطبيقك بنشر تحديثات مُعينة على حساب المُستخدم على تويتر، وجدت المكتبة التي ترغب في استخدامها لكنها مكتبة تعتمد على مكتبة أخرى. مُطور PHP من العصر الحجري سيقوم بالتالي: سيقوم بتحميل نُسخة من إطار العمل، ومن ثم يقوم بإنشاء مُجلد يضع فيه المكتبات الإضافية التي يحتاجها ومن ثم يُحاول فهم آلية عملها ليربطها ببعضها البعض. قد تؤتي هذه الطريقة أكلها، وقد تسمح لك بتطوير مشروعك "من دون أية مشاكل"، لكن ماذا يحدث مثلا لو تم إطلاق تحديث لأي من المكتبات التي تعتمد عليها؟ هل ستقوم بإعادة تحميلها من جديد واستبدال الإصدار القديم بالجديد؟ هل يُمكن أن تفعل ذلك لو كنت تستخدم أكثر من مكتبة يعتمد بعضها على بعض؟ لست متأكدا من ذلك. لكن ما هو البديل؟ إن سبق لك أن استخدمت لُغات برمجة أخرى كـ javascript مع node.js أو ruby فإنه سبق لك أن تعاملت مع ما يُطلق عليه اسم مدير الحزم Package manager، حيث يتم استخدام npm مع node مثلا لتنصيب حزم وإضافات لـ node. يُمكن القول بأن موضع composer من PHP هو موضع npm من node.js، حيث يُتيح composer تحميل المكتبات التي تحتاجها في مشروعك والإبقاء عليها مُحدثة دون الحاجة إلى تحميلها ونقلها يدويا. رغم كل ذلك يُشير موقع composer الرسمي بأنه لا يُمكن أن نُطلق عليه اسم مُدير حزم بحكم أنه لا يقوم بتنصيب هذه الحزم بشكل عام على النظام global بل تتم إدارة الحزم داخل كل مشروع بشكل محلي، ولهذا يُطلق عليه وصف مُدير الاعتمادات Dependency Manager. تنصيب composer دعونا من الجانب النظري ولنقم بتنصيب composer ولنلق نظرة على كيفية استخدامه. بالرغم من أنه يُمكن تنصيبه بشكل محلي داخل كل مشروع إلا أنه يُفضل تنصيبه بشكل عام على النظام. على أنظمة Linux/Unix يكفي تنفيذ الأمرين التاليين لتنصيب composer: $ curl -sS https://getcomposer.org/installer | php $ mv composer.phar /usr/local/bin/composer قد تحتاج إلى إضافة sudo قبل الأمر الثاني إن احتجت إلى صلاحيات مدير النظام لتنفيذ الأمر. أما على أنظمة Windows فيكفي تحميل وتنصيب التطبيق الرسمي الخاص به. يُمكنك التحقق من إذا ما تم تنصيب composer بشكل صحيح على النظام بتنفيذ أمر composer في سطر الأوامر والذي من شأنه أن يُظهر المساعدة الخاصة به. استخدام Composer الآن وبعد أن قمنا بتنصيب composer سنحتاج إلى إنشاء ملف composer.json نقوم من خلاله بإعلام composer بالحزم التي نود إرفاقها والاعتماد عليها في مشروعنا الجديد، كما أنه يُمكن لهذا الملف أن يحتوي على بيانات أخرى سنحتاجها في بناء المشروع. يكون ملف composer.json في شكله الأبسط على النحو التالي: { "require": { "monolog/monolog": "1.0.*" } } في هذا المثال فإننا نعتمد على الإصدار 1.0.* من مكتبة monolog . بطبيعة الحال يُمكن الاعتماد على أكثر من مكتبة في مشروعنا الحالي، حيث يكفي إضافة سطر جديد لكل مكتبة ما بين حاضنتي require ويتكون كل سطر من اسم المكتبة (الذي عادة ما يحتوي على اسم الجهة المُنتجة لها متبوعة باسمها، وعادة ما يكون نفس الاسم مُكررا مرتين) إضافة إلى رقم الإصدار الذي نرغب فيه. يُمكن إيجاد هذه المكتبات وآليات إضافتها إلى مشروعك الخاص بالبحث على موقع https://packagist.org/. الآن وبعد أن حددنا المكتبات التي نرغب فيها يكفي أن نقوم بتنفيذ الأمر composer install أو php composer.phar install في حال ما إذا لم تقم بنقل composer.phar إلى مُجلد مساره موجود في مُتغير PATH الخاص بالنظام. سيقوم composer بتحميل جميع تلك المكتبات ووضعها داخل مُجلد vendor الذي سيتم إنشاؤه داخل مُجلد المشروع الحالي. Autoloading ولتجنيب المُطور من اللجوء إلى استدعاء هذه المكتبات واحدة واحدة لدى كتابته لمشروعه، يقوم composer بإنشاء ملف vendors/autoloader.php الذي يتولى إدارة ذلك حيث يكفي استدعاء هذا الملف لتتمكن من استخدام المكتبات التي حملتها من دون الحاجة إلى القيام بذلك يدويا: <?php require_once "vendors/autoloader.php"; تحديث المكتبات لدى صدور تحديث جديد للمكتبة التي تعتمد عليها فإنه يكفي تنفيذ الأمر للحصول عليها: composer update بطبيعة الحال إن كنت قد حددت إصدارا مُعينا في ملف composer.json فإنك لن تحصل على الإصدارات الأحدث ما لم تقم بتحديد الإصدار بشكل يسمح بالترقية الآلية. بعبارة أخرى إذا كنت تستعمل مثلا إطار عمل Laravel وقمت بإضافته باستخدام السطر التاليينlaravel/framework": "4.1.* فإنه سيتم التحديث إلى إصدار في التفرع 4.1 ولن يتم المرور إلى الإصدارات 4.2 أو التي تليها. Packagist Packagist عبارة عن موقع يتم تجميع فيه مكتبات PHP مفتوحة المصدر المتوفر للاستعمال من طرف الجميع باستخدام composer. حسب التوثيق الرسمي لـ composer فإنه لا يُشترط في المكتبة أن تكون على Packagist ليتم استدعاؤها من طرف Composer إلا أنه يُفضل إن أردت توفير مكتبتك للجميع أن تُسجلها على هذا الموقع. خلاصة إن كنت مُطور PHP وكنت تود أن تتطور مع تطور هذه اللغة وأن لا تبقى حبيس الإصدارات القديمة منها (الإصدار 4؟) فإنه يجب عليك أن تتبع أسلوبا مُختلفا في التطوير عن أسلوب مُطور PHP من العصر الحجري. من بين أولى الخطوات التي ستخطوها للوصول إلى ذلك هو الاستعانة بـ composer في جميع مشاريعك التي تعمل عليها حيث يُعتبر الغراء الذي يُلصق مُكونات مشروعك بعضها ببعض ويُسهل عليك مهمة التطوير. للمزيد حول composer وحول مُختلف المكتبات التي يُمكن الاستعانة بها في مشروعك قم بزيارة موقعه الرسمي وموقع Packagist.
  7. تحسين أداء المواقع التي نقوم بتصميمها هي عملية مُستمرة، بداية تخلصنا من الجداول، من صور spacer gifs ومن إضافة الأنماط بشكل مُباشرة إلى الصفحات، حيث أننا تخصلنا مثلا من استعمال الوسم <font> وتحويل ما يُمكن تحويله إلى ملفات CSS، كما أننا قلصنا أحجام صفحاتها وفصلنا ما بين الصفحة وما بين أنماط ظهور مُكوناتها. وبعد ذلك أولينا اهتماما بطلبات DNS، وبالتخزين المؤقت caching وبالعدد الكلي للملفات وهو ما نتج عنه استخدام تقنية CSS sprites وذلك عبر تجميع مجموعات من الصور الصغيرة في ملفات مُشتركة. بعد أن استغلينا التقنيات السابقة إلى أقصى حدودها، حان الوقت الآن للولوج إلى عصر جديد من تحسين أداء مواقعنا: خطوط الأيقونات symbol fonts. استخدام خطوط الأيقونات يسمح لنا بنقل تلك الصور الصغيرة التي نستعملها على مواقعنا إلى ملف خاص بالخطوط بدل استخدام خاصية CSS sprite وهو أمر له إيجابيات عديدة، خاصة لما يتعلق الأمر باستعراض هذه المواقع على شاشات عالية الدقة. سنستعرض في هذا المقال جُملة من إيجابيات خطوط الأيقونات وبعض المشاكل التي يُمكن أن تواجهك لدى استخدامك لها. مجموعة من أيقونات خط Foundation Icon Fontsتفاصيل أكثر دقة وتصفح أنعمبحكم أن الخطوط التي تم تصميمها للاستعمال كأيقونات، رموز أو كزخارف في تزايد مُستمر فإن العديد من المواقع الرائدة على الإنترنت شرعت في استبدال الصور التي تستخدمها بهذه الخطوط. أحد أفضل الأمثلة على ذلك هو موقع Github والذي استطاع تحسين سرعة الموقع وتوفير تجربة استخدام أفضل للزوار عبر التخلص من كل الأيقونات الصغيرة التي كان يستخدمها واستبدالها بخط Octicons كبديل عنها. أحد أهم الدوافع وراء التخلص من الأيقونات الصغيرة واستبدالها بخطوط الأيقونات هو التخلص من تلك الصور ذات الملامح "الخشنة" والتي تزداد خشونة وسوءًا لدى تكبيرها، برموز خطوط تُحافظ على نفس الشكل الناعم والسلس مهما تم تغيير حجم الأيقونة، حيث أن الأيقونات الرسومية مُصممة لتعمل في أبهى حُلة لها لدى استخدام دقة شاشة مُعينة، ويظهر الإشكال واضحا مع الشاشات عالية الدقة التي شهدت انتشارا في السنوات القليلة الماضية، حيث أن مُحاولة تكبير تلك الأيقونات لتتوافق معها تجعلها تظهر بشكل مُتدرج الحواف. استخدام وتضمين الرسوم المُوجهة vector graphics في صفحات HTML كان محدودًا فيما سبق. صحيح بأنه بإمكان القيام بذلك عبر PDF وSVG لكن استخدامهما يُسبب عادة مشاكل في التوافقية ما بين المُتصفحات، وبحكم أن الخطوط عبارة عن رسوميات مُوجهة vector وكل المُتصفحات بما فيها IE6 تدعم إمكانية تصيير خُطوط مُضمنة في صفحات HTML فإنه بالإمكان الاعتماد عليها لتوفير أشكال عالية الجودة تكون مدعومة على جميع المُتصفحات، وهو أمر فتح المجال لنا لنمضي قدما في تحسين مواقعنا بشكل أفضل وتوفير تجربة استخدام أرقى للمُستخدم. قابلية الوصوللما يتعلق الأمر بقابلية الوصول فإنه من المُمكن أن تكون خطوط الأيقونات بنفس سوء الصور أو بنفس الأداء العالي للنصوص حسب طريقة استخدامها. العديد من خطوط الأيقونات الأولى التي شُرع في استخدامها كانت تقوم بالربط ما بين أشكالها وبعض حروف ASCII. فعلى سبيل المثال لدى الضغط على مفتاح w ستظهر صورة مُصغرة للكرة الأرضية ولدى الضغط على مفتاح m يظهر ظرف رسالة. هذا الأمر سهل من معرفة أي رمز يُمثل أي شكل وذلك بمُجرد الضغط على ذلك الزر على لوحة المفاتيح. لكن مشاكل هذه التقنية تظهر بُمجرد أن تفشل الصفحة في تحميل ملف الخطوط حيث ينتهي بنا المطاف مع صفحة تحتوي حروفا في أماكن مُتفرقة من الصفحة لا تحمل أية دلالة أو معنى. فعلى سبيل المقال لو كان الخط الذي تستخدمه يهدف إلى إظهار سهم صغير أمام عبارة Next فإنه من المُحتمل أن تستعمله على النحو التالي: <div><span class="icon">L</span> Next</div>لكن لو فشلت الصفحة في تحميل ملفات CSS، JavaScript أو ملف الخطوط فإن ما سيظهر على الصفحة هو حرف L بدل ذلك السهم. حتى ولو وجدت طريقة ما باستخدام JavaScript وCSS (بفضل :before و:after) لإظهار السهم على النحو الذي تريده فإن عناكب مُحركات البحث ستعجز عن فهم ذلك وستظل تُؤرشف مُحتوى صفحتك على الشكل "L Next”، وهو أمر لن ترغب فيه. لكن هناك حل أفضل من الحل السابق. مرت خطوط الأيقونات بعدة مراحل عرفت خلالها مشاكل مُختلفة مكّنتها من الوصول إلى مرحلة نُضج مُتقدمة استطاعت بفضلها حل هذه المشاكل عبر استخدام محارف Unicode ذات استخدام خاص يُطلق عليها اسم Private Use Areas حيث أن محارف هذه المناطق الخاصة لا تملك أية دلالية، كما أنها لا تملك أية صلة بحروف مُختلف الأبجديات. إذا لم يتم تحميل الخط الذي يستخدم هذه المحارف فإنما سيظهر هو مربعات فارغة بدل حروف. سأزيدك من الشعر بيتا، بإمكاننا تحسين هذه التقنية أكثر. تملك الخطوط عادة محارف خاصة يُطلق عليها اسم ligatures، هذه المحارف التي يندر أن تلمحها العين غير المُدربة بشكل جيد، تُستعمل لربط حرفين مُختلفين في حرف واحد لتسهيل قراءتهما. فعلى سبيل المثال لو كتبت حرفي f متتاليين فإنه من المُحتمل جدا – لو كنت تستخدم خطا عالي الجودة- أن تظهر على هيئة حرف ff واحد يربط ما بين الحرفين بلمسة جمالية. هناك عدة محارف مُدمجة شائعة مثل ff، fl أو fi إلا أنه لا يوجد ما يمنعك من إضافة محارفك الخاصة بك، حيث أنه من المُمكن إضافة ذلك في ملف الخط الخاص بك وبمُجرد أن تتم كتابة تلك الحروف بالترتيب الذي ترغب فيه يتم استبدالها بمحرفك الخاص، حتى أنه يُمكنك إضافة محرف جديد يُظهر شعار موقعك لدى كتابتك لجملة أو كلمة متعددة الحروف (كـ webtuts.me مثلا). ما الذي يحدث في هذه الحالة؟ المُتصفحات التي لا تقدر على استظهار المحارف المُدمجة -ونقصد بذلك عناكب مُحركات البحث- ستقوم بأرشفة النص غير المُدمج (اسم موقعك في المثال السابق). أما المُتصفحات التي تقدر على ذلك فستقوم بإظهار الشكل المُوجه الذي قمت بتحديده (شعار موقعك مثلا)، وبالتالي فإننا حللنا المشكل السابق باستخدام أفضل ما يوجد في كلا العالمين (عالم المُتصفحات وعالم عناكب مُحركات البحث) بفضل تقنيات أعلى مما يُمكن القيام به بُمجرد HTML وCSS لوحدهما. بُمجرد أن تفهم آلية عمل الحروف المُدمجة سيُفتح أمامك باب واسع من الخيارات اللامُتناهية. يُمكنك تضمين كل الأيقونات التي ترغب فيها والتي لا تُمثلها محارف فردية وإنما محارف مُدمجة. فعلى سبيل المثال يُمكن أن تُصبح شفرتك على النحو التالي: <ul> <li>Home</li> <li>Contact</li> <li>About</li> <li>Cart</li> </ul>في حين ستكون النتيجة التي تظهر على النحو التالي: أمضى موقع Symbolset الكثير من الوقت في إجراء تجارب على المحارف المُدمجة ما مكنه من تصميم مجموعات مُختلفة من الأيقونات شائعة الاستعمال التي يُمكن شراؤها واستخدامها على موقعك. يُمكن تجربة تلك الأيقونات مُباشرة على نفس الموقع، حيث يكفي أن تكتب بعض الكلمات وبُمجرد أن تفرغ من ذلك تتحول بشكل لحظي إلى أيقونات. ستعجب للكم الهائل من الاحتمالات التي تضعها خاصية دمج المحارف بين يديك. لاستخدام المحارف المُدمجة التي تُستبدل بأيقونات وأشكال عدة استعمالات مُفيدة، فعلى سبيل المثال على موقع شبكة BBC الإخباري كانت تُستخدم ساعة تفاعلية في إحدى زوايا الصفحة الرئيسية. كان بإمكان استخدام Flash لتصميم تلك الساعة أو الاستعانة بـ CSS لإدارة صورة الساعة للحصول على التوقيت المُناسب وتوقيت عمليات التدوير بشيء من JavaScript، لكن خيار BBC وقع على HTML5 وتم استخدام Canvas و JavaScript لتتم إعادة رسم الساعة بشكل مُستمر. كلا الحلين السابقين يعتمدان على صور لا يُمكن لها أن تظهر بشكل جيد على شاشات عالية الدقة. كان بالإمكان أيضا استخدام بعض مكتبات JavaScript مثل مكتبة Raphaeljs والتي ستقوم بإنشاء رسوميات SVG أو كائنات VML جميلة ومُوجهة، لكن بحكم أن كامل العملية سنتم عبر JavaScript فإن ذلك سيمنع مُحركات البحث والمُتصفحات التي لا تستخدم Javascript من رؤيتها. لكن استخدام خطوط الأيقونات كان من شأنه أن يُعطي نتائج أفضل في كلا العالمين: قابلية الوصول وجودة الرسوم. فعلى سبيل المثال يُمكن تصميم خط بمُجرد أن نكتب 12:00 تظهر صورة ساعة تُشير إلى هذا الوقت، وكتابة 12:01 ستُظهر صورة أخرى مُختلفة وهكذا دواليك. بالرغم من أن هذه العملية طويلة وشاقة إلا أن نتائجها ستكون أفضل بكثير، بل هناك بعض الخطوط التي تقوم بتوفير ساعات مُماثلة. قم بزيارة هذا الموقع وألق نظرة على الشفرة المصدرية وستُبهر ببساطتها. فكر في كامل التفاصيل الدقيقة في صفحات الوَب التي تُصممها والتي يُمكنك أن تفعلها باستخدام خطوط الأيقونات، تفاصيل يُمكن أن تتراوح ما بين رؤوس القوائم والأسهم من جهة وما بين أيقونات الشبكات الاجتماعية من جهة أخرى، يُمكن جمع كل ذلك في ملف خطوط واحد قابلة للتصغير وللتكبير وللاستخدام على مُختلف الشاشات ومن دون الحاجة إلى ملفات صُور مُتعددة. إنشاء خط الأيقونات الخاص بكيعاني الكثير من المصممين و المطورين الأمرّين مع تطبيقات التصميم مثيلات Photoshop وfireworks. إن كان الانتقال إلى CSS sprites بسيطا بحكم أنه يتم استخدام نفس الأدوات المُتوفرة في حوزة المُطور للقيام بذلك فإن الأمر سيحتاج إلى خطوة إضافية مع الخطوط وذلك راجع إلى الحاجة إلى تطبيق خاص بتحرير الخطوط. هذه التطبيقات ليست مُعقدة الاستعمال كثيرا، بل هناك من الخدمات من يسعى لجعل العملية في مُنتهى السهولة مثلما هو عليه الحال مع Icomoon حيث يكفي أن تقوم برفع ملفات SVG الخاصة بأيقوناتك، ربط تلك الأيقونات بمحارف unicode ومن ثم تصدير الخط، كل هذا مُباشرة من خلال مُتصفحك. ماذا لو أردت مزيدا من التحكم في الخط؟ هناك عدة أدوات مُتوفرة للقيام بذلك، بعضها تِجاري وبعضها مُتوفر بشكل مجاني مثل تطبيق FontForge. قد يكون هذا التطبيق صعب المراس، لكن يُمكن للباحث إيجاد العديد من الدروس التي ستساعده على ترويضه. مشاكل قد تُواجهك لدى استخدام خطوط الأيقوناتسيخبرك أي مُصمم بارع بأن أي شعار أو أيقونة ستظهر بشكل مُختلف كلما اختلف حجمها، سواء تم استخدام خط أنحف أو أصغر أو حتى تم إهمال بعض التفاصيل الفرعية هنا وهناك. مع خطوط الأيقونات لا يُمكن القيام بذلك حيث أنه لا يُمكنك توفير تصاميم تختلف باختلاف حجم الخط المُستعمل. الأيقونة التي تُصممها ستظهر بنفس الشكل سواء كنت تستخدم حجم الخط 20 نقطة، 120 نقطة أو حتى 6 نقاط فقط. إذا كنت ترغب في الحصول على أشكال مُختلفة لنفس الأيقونة فما عليك سوى نسخها أكثر من مرة وربطها مع أكثر من مُحرف مُختلف، لكن بالرغم من ذلك فإنه يصعب عليك معرفة الطريقة التي ستظهر فيها الأيقونة للمُستخدم أو حجم الخط الذي سيستخدمه، فتكبير الخط أو تصغيره لن يُغير من شكل المحرف وبالتالي سيظهر على نفس الشكل لكن بحجم مُختلف. هذه الحيثية لن تُسبب مُشكلا في أغلب الحالات بحكم أن الأيقونات التي نستعملها حاليا (مثل أيقونات الشبكات الاجتماعية) لا تحتاج فعلا إلى إدخال تغييرات عليها لدى تغيير حجمها. المُشكل الآخر الذي ستواجهه لدى استخدامك لخطوط الأيقونات هو توفر تلك الأيقونات بلون واحد فقط. يُمكنك عمل أيقونات بلونين مُختلفين عبر التحكم في لون الخلفية عن طريق CSS لكن لو احتوى شعارك على أكثر من لونين فإن هذه الخطوط لن تسمح لك بالقيام بذلك. لمُواجهة هذا الإشكال اقترحت Apple خطوطا مُتعددة الألوان وهو ما سيسمح بإنشاء رسوم مُوجهة مُتعددة الألوان وإظهارها على صفحات الويب مثلما هو عليه الحال مع خط Apple Color Emoji المُتوفر على نظام OSX Lion، إلا أن هذا الحل يبقى محدودا جدًا بحكم أن توفير خط مُتعدد الألوان يحتاج إلى دعم المُتصفحات له كما سنحتاج إلى أدوات جديد لإنشائها وهو ما سيُؤخر من أية جهود تسعى لتعميم هذه الخطوط الجديدة. أهلا بكم في عصر جديدخطوط الأيقونات هي الخطوة القادمة لتحسين أداء وتصميم مواقعنا وتحتاج إلى فهم مبدأ عملها إن أردت استخدامها في مشاريعك. لن تحتاج سوى إلى بعض ٍمن التدريب لتتمكن من إنشاء خطك الخاص الذي يُمكنك من جمع كامل أيقوناتك وشعاراتك في ملف خط واحد لتضمينه في موقعك. لن تساعدك هذه الخطوط على إبهار زوار موقعك فحسب وإنما ستزيد من أدائه وسرعته. حان الوقت لنا جميعا لنشرع في استخدام هذه الخطوط وللمساعدة في تحسين أداء الأدوات التي تقوم بإنشائها، والمعايير التي تحكم ذلك والتقنيات المُتبعة خلال هذه العملية. ترجمة -وبتصرف- للمقال: The Era of Symbol Fonts لصاحبه Brian Suda (بموافقة من موقع A List Apart وكاتب المقال).
  8. تُعتبر بساطة CSS إحدى أهم الخواص المُميزة والمرغوبة فيه، حيث أن أوراق أنماط CSS ما هي سوى قوائم طويلة من الأوامر والتي تُحدد كل واحدة منها مُنتقيا selector وبعضا من الأنماط التي يجب تطبيقها عليه. لكن وبحكم أن مواقعنا وتطبيقاتنا أصبحت تكبر أكثر فأكثر وزادت درجة تعقيدها مع ذلك، كما أنها أصبحت تستهدف أجهزة وأحجام شاشات مُختلفة، فإن البساطة التي تُميز CSS سرعان ما تُصبح ثقلا على كاهل المُبرمجين بحكم أن الأمر لم يعد مُتعلقا فقط ببعض الخواص القاعدية. في حين أن البعض قد اقترح حلولا لمشاكل CSS عبر إضافة المُتغيرات والثوابت إليها مثلا إلا أن المُتصفحات امتنعت عن استخدامها ودعمها. وحتى ولو قام أي من المُتصفحات بدعم نسخة جديدة أكثر تطورا من CSS، فإن الأمر سيحتاج إلى سنوات ليتم تعميم الأمر على جميع المُتصفحات مما يجعل من الاعتماد عليه فكرة غير صائبة. لكن لحسن الحظ اقترح منذ بضعة سنين المُطوران Hampton Catlin وNathan Weizenbaum طريقة أفضل للتعامل مع أوراق الأنماط المعقدة. بما أن المُتصفحات ليست مُستعدة لاعتماد إصدار جديد من CSS وجد المُطوران بأنه بإمكانهما تصميم تراكيب (syntax) جديدة لأوراق الأنماط تجعل من مهمة كتابة وصيانة تلك الأوراق أسهل، حيث يكفي استخدام مُعالج قبلي preprocessor لترجمة التركيب الجديد إلى التركيب القديم المُعتمد في أوراق CSS التي نعرفها. تم إطلاق اسم Sass على التركيب الجديد والذي هو اختصار لـ syntactically awesome style sheets. الإصدارات الأولى من Sass كان مُختلفة جدا عن CSS الكلاسيكي، فعلى سبيل المثال لم يكن هناك وجود لأي حاضنات curly braces، كما أنه وجب تسنين indent الخواص على نحو مُعين وبعدد مُحدد من المسافات لتجنب ظهور أخطاء لدى ترجمة الملف. لم يمنع الأمر المُبرمجين الذين اعتادوا على تعلم لغات برمجة جديدة والاستمتاع بذلك من التعامل مع هذه اللغة ولم يجدوا مُشكلا مع التراكيب الجديدة التي أتت بها Sass.، لكن الأمر كان مُختلفا مع المُصممين الذين رأوا أن البنية اللغوية لـ Sass كانت مُختلفة جدا عن الـ CSS الذي ألفوه ولذلك لم يرغبوا في استخدامه. المُشكل الآخر هو أن الاختلاف في البُنية اللغوية مع CSS الكلاسيكية جعل من مهمة الاستفادة من Sass في المشاريع الحالية أمرا مستحيلا من دون إمضاء الكثير من الوقت لترجمة ملفات CSS الحالية إلى Sass. ولدرء هذه المشاكل عمد المُطورون في الإصدار 3.0 من Sass إلى إضافة بُنية لغوية جديدة أقرب ما تكون من بنية CSS والتي أطلقوا عليها اسم SCSS أو Sassy CSS. يوصف SCSS عادة بأنه "مُجمع صارم" Strict Superset أو لغة مُترفعة مشتقة من CSS وهو الأمر الذي يعني بأن أي ملف يُعتبر صحيح البُنية في CSS سيكون صحيح البُنية في SCSS أيضا. بعبارة أخرى يُمكنك استخدام ملفات CSS الحالية مع معالج Sass القبلي من دون أية مشاكل، مما سيسمح لك بتعلم واستخدام بعض خواص Sass دون الحاجة إلى تعلم جميع الخواص لاستخدامه. عكس ما هو الحال مع CSS العادي فإنه يُمكن اعتبار Sass/ SCSS لغة برمجية scripting language بكل ما تحمله الكلمة من معنى، حيث أنه يدعم العديد من خواص لغات البرمجة مثل: expressions،functions، variables، conditional logic، و loops. بطبيعة الحال أنت في غنى عن استعمال كل هذه الخواص دفعة واحدة، لكنها قيد إشارتك لما تكون في حاجة إليها، بل وستجعل من مهمة كتابة أوراق أنماط مُعقدة -والتي عادة ما تحتوي على شفرات مُكررة- أمرا في غاية السهولة. سنستعرض في هذا المقال جُملة من قواعد Sass/SCSS لإعطائك فكرة واضحة عما يُمكنك القيام به باستخدام هذه اللغة الجديدة، وسنختم بجُملة من الروابط والكتب إن رغبت في الذهاب بعيدا معها. ولإبقاء الأمر بسيطا قدر الإمكان فإننا سنركز في أغلب الأمثلة التي سنستعرضها هنا على شفرة SCSS فقط وليس شفرة CSS التي تنتج عنها بعد ترجمتها. بطبيعة الحال فإن أفضل طريقة لتعلم Sass هي أن تقوم تجربها بنفسك وتكتب بعض الشفرات ثم تلاحظ ملفات CSS التي تنتج عن ذلك. يُمكن إيجاد جميع الأمثلة المعروضة هنا إضافة إلى ملفات CSS التي تنتج عنها على هذا المُستودع على Github. البدايةتمت كتابة Sass بلغة روبي، ويتم توزيعها عبر مدير الحزم الخاص بها والمعروف باسم RubyGems. سيكون بإمكان الذين يستعملون روبي أو الذين لا يجدون صعوبة في التعامل مع سطر الأوامر تنصيب Sass بسهولة باتباع التعليمات الموجودة على موقع Sass، أما من يجب صعوبة في ذلك أو لم يسبق له التعامل مع روبي فإنه بإمكانه الاعتماد على تطبيق Scout على نظامي Windows وmac والذي يأتي مجهزا بروبي وبـ Sass (إن كنت على نظام لينكس فإنه يفترض بك أن تكون مرتاحا مع سطر الأوامر وبالتالي... ). سواء نصبت Sass عبر سطر الأوامر أو عبر تطبيق Scout فإن مبدأ العمل يبقى نفسه، حيث تتم مراقبة ملفات SCSS الخاصة بك وفي كل مرة يتم إدخال تحديثات عليها وحفظها تتم ترجمة ذلك إلى ملف CSS كلاسيكي. نطلق اسم مجلد المُدخلات Input Folder على المُجلد الذي يحتوي ملفات Sass ويتم حفظ ملفات CSS الناتجة في مُجلد يُطلق عليه اسم مجلد المخرجات Output Folder. يُمكن لأحد هذه المُجلدين أن يكون داخل الآخر، بل من الشائع أن يكون مجلد المُدخلات والذي يُمكن أن نسميه بـ scss داخل مجلد أوراق الأنماط الخاصة بمشروعك والذي نسميه css على النحو التالي: my_project/ index.html css/ main_style.css scss/ main_style.scss _mixins.scss _colors.scssفي المثال السابق، يُطلق على الملفات التي تبدأ أسماؤها بمحرف _ داخل مُجلد scss وصف partials وتوصف بذلك لأنها عبارة عن أوراق أنماط جزئية يتم استيرادها في ملفات SCSS الرئيسية. استخدم الملفات الجزئية لتنظيم شفرتكيوفر CSS تعليمة @import لاستيراد ملفات css إضافية، وعادة ما يعمد المُطورون إلى استخدام هذه التعليمة لتقسيم المشاريع الكبيرة إلى ملفات صغيرة الحجم لتسهيل مهمة صيانتها. فعلى سبيل المثال يُمكن لملف main_style.css الرئيسي أن لا يحتوي سوى على مجموعة من تعليمات @import على النحو التالي: @import url('/shared/global.css'); @import url('/pages/home.css'); @import url('/pages/blog.css');بطبيعة الحال فإنه لا يُنصح بالقيام بذلك نظرا للآثار التي ستترتب عن ذلك، حيث أن كل سطر عبارة عن ملف إضافي يجب على المُتصفح تحميله مما قد يسبب ثقلا في تحميل موقعك وبالتالي تراجعا في تقييمي Yslow وgoogle Page Speed الخاصين بموقعك. يسمح Sass بتقسيم الملفات إلى ملفات جزئية Partials بنفس الطريقة السابقة واستيرادها باستعمال نفس التعليمة @import، لكن لدى ترجمة ملفات Sass إلى CSS فإنه سيتم تضمين كامل الشفرة في ملف واحد. @import 'shared/global'; @import 'pages/home'; @import 'pages/blog';ينتج عن الكود السابق ملف CSS واحد فقط. يُمكن لـ Sass القيام بعملية minification لملف CSS الناتج والتخلص من كل المسافات الزائدة وذلك لتحسين أداء الموقع لدى وتقليص زمن تحميله. هناك أمر يجب أخذه بالحسبان وهو أن الملفات الجزئية هي ملفات من نوع خاص خاصة بـ SCSS ليست مُعدة لتُستعمل كملفات CSS كلاسيكية، ويجب القيام باستيرادها باستخدام تعليمة @import لأخذها بالحسبان. كما تبدأ أسماء الملفات الجزئية بالمحرف "_”، حيث أن pages/home في المثال السابق تقوم باستيراد ملف pages/_home.scss . يسمح مُحرف _ لـ Sass بمعرفة أن الملف عبارة عن ملف جزئي وبالتالي يتجنب ترجمته إلى ملف CSS مستقل بذاته. لا تكرر ما تقوم بهبعد أن أصبحت أوراق الأنماط خاصتنا أكثر تنظيما يتوجب علينا الآن التخلص من التكرار الموجود في محتواها. إحدى أهم خواص Sass هي خاصية القواعد المُضمنة Nested rules. في ملفات CSS الكلاسيكية تأتي مُختلف القواعد بعضها تلو الأخرى، وعلى مُحدد كل قاعدة أن يشمل جميع عناصره: body.home .media-unit { border: 1px solid #ccc; background-color: #fff; } body.home .media-unit .right { border-left: 1px solid #ccc; } body.home .media-unit .right h1 { font-size: 24px; }علاوة على أن هذه الشفرة تحتوي على الكثير من التكرار فإنها لا تساعدنا لفهم العلاقة الموجودة ما بين العناصر التي نقوم بإضافة أنماط عرض إليها. لكن بفضل القواعد المُضمنة فإنه بإمكاننا كتابة شفرة SCSS لا تتجنب التكرار فحسب، وإنما تجعل من معرفة العلاقة ما بين العناصر أوضح وأسهل للفهم: body.home { .media-unit { border: 1px solid #ccc; background-color: #fff; .right { border-left: 1px solid #ccc; h1 { font-size: 24px; } } } }بعد ترجمة هذه الشفرة فإننا سنحصل على نفس الشفرة السابقة. للأسف فإن الحجم الصغير لشفرة SCSS لا تنتج عنه بالضرورة شفرة CSS صغيرة الحجم أيضا أو سريعة التحميل، لكن استخدام القواعد المُضمنة من شأنه أن يبقي الشفرة أنظف، أكثر منطقية وأكثر تنظيما، وهي مزايا ستسهل من مهمة إدارة وصيانة هذه الشفرة مع مرور الوقت. تسمح القواعد المُضمنة أيضا بتضمين media queries داخل قواعد أخرى، مما يجعل من السهل معرفة أي نمط يتم تنفيذه على أي من عناصر صفحتك: .container { width: 940px; // If the device is narrower than 940px, switch to // a fluid layout @media screen and (max-width:940px) { width: auto; } }لدى ترجمة هذه الشفرة يقوم Sass بتحويله إلى شفرة CSS كلاسيكية وذلك عبر نسخ مُحدد .container داخل media query على النحو التالي: .container { width: 940px; }@media screen and (max-width:940px) { .container { width: auto; } }المتغيراتمتغيرات Sass مفيدة جدا لسببين: أولها وأكثرها أهمية هو تسهيل مهمة تعديل الشفرة وتجنيب التكرار، وثانيها هو تمكين المُطور من إعطاء أسماء خاصة لبعض الخواص خاصة الألوان مما يزيد من مقروئية الشفرة ويسهل فهمه. على موقع Typekit مثلا نجد أن العديد من العناصر تستخدم اللون #99CC00 أو ما يُطلق عليه مطورو الموقع اسم Typekit green اختصارا. وبما أنه يتم استخدام هذا اللون في جميع أجزاء الموقع بدءا بالأزرار ووصولا بالعناوين الرئيسية، فإنه، وفي حالة أردنا تغيير هذا اللون الأخضر إلى لون آخر يجب علينا استبداله هذه القيمة بقيمة أخرى أينما ظهرت على ملف CSS. لكن في حال استخدام متغيرات Sass بدل القيمة الست عشرية آنفة الذكر فإنه يكفي تغيير قيمة المتغير المعني بهذا اللون (والذي يُمكن تعريفه في بداية الملف أو حتى في الملفات الجزئية) حتى يتم تغييره في جميع عناصر الصفحة بشكل آني وآلي. يُمكن أيضا استخدام المتغيرات لإعطاء قيم لمتغيرات أخرى مما يسهل من الحفاظ على أنماطك أكثر تنظيما: $typekit-green: "#99cc00"; $typekit-link-color: $typekit-green;a { color: $typekit-link-color; }بإمكانك أيضا أن تعطي هذه المتغيرات تقريبا أي قيمة ترغب فيها، وتماما مثلما أفادتنا هذه المُتغيرات مع الألوان فإنها ستفيدنا أيضا مع الخطوط: $sans-serif-font: 'ff-dagny-web-pro', 'Helvetica Neue', Arial, Helvetica, 'Liberation Sans', sans-serif; $serif-font: 'ff-tisa-web-pro', Georgia, Times, serif;.banner h1 { font-family: $sans-serif-font; } MIXINS Mixins عبارة عن مجموعة من القواعد أو الخواص التي يُمكنك تضمينها أو "دمجها' مع قواعد أخرى. نقوم بتعريف هذه المجموعات باستخدام التعليمة @mixin ونقوم بتضمينها في قواعد أخرى باستخدام @include. في المثال التالي نطلب من Sass أن يقوم بتنفيذ جميع الخواص الموجودة في مجموعة خواص highlighted-bold-text على عناصر span الموجودة داخل result-with-highlights: $highlight-color: #ffa;@mixin highlighted-bold-text { font-weight: bold; background-color: $highlight-color; }.result-with-highlights { span { @include highlighted-bold-text; } }يكفي أن تقوم بتعريف الـ mixin مرة واحدة حتى يُصبح بإمكانك استخدامه أينما شئت في نفس الملف. في المثال التالي تتم إضافة جميع خواص الـ mixin الذي قمنا بتعريفه سابقا إلى الصنف الذي يحمل الاسم highlighted: .highlighted { @include highlighted-bold-text; }هذا الأمر مفيد خاصة لدى القيام بإضافة خواص CSS3 على بعض العناصر مع الرغبة في ضمان ظهور هذه العناصر على نفس الشكل على جميع المُتصفحات وذلك باستخدام البادئات prefixes الخاصة بكل متصفح إضافة إلى توفير تراجع رشيق للمتصفحات التي لا تدعم تلك الخواص. عادة ما يكون التعامل مع مختلف البادئات في ملفات CSS الكلاسيكية أمرا مُزعجا نظرا لطولها وللحاجة إلى نسخها ولصقها في كل مرة. لكن مع mixins فإنه بالإمكان القيام بذلك بشكل أسرع ومن دون الوقوع في الأخطاء ومن دون الحاجة إلى كتابة الكثير من الشفرات. في المثال التالي، نقوم بإضافة الحواف الدائرية بقيمة 4px على عنصر وذلك باستخدام بادئات كل من Webkit، Firefox وIE مع إضافة خاصية border-radius الخاصة بـ CSS3. كما أننا نقوم بتحديد قيمة الدوران في مُتغير وذلك لتسهيل مهمة تعديلها لاحقا: @mixin rounded-corners { $rounded-corner-radius: 4px; -webkit-border-radius: $rounded-corner-radius; -moz-border-radius: $rounded-corner-radius; -ms-border-radius: $rounded-corner-radius; border-radius: $rounded-corner-radius; }.button { @include rounded-corners; }يُمكن للـ mixins احتواء قواعد مُضمنة كاملة وليس مجرد خواص. المثال التالي يُوضح كيف يُمكن كتابة clearfix CSS باستخدام Sass mixin: @mixin clearfix { // For modern browsers &:before, &:after { content:""; display:table; } &:after { clear:both; } // For IE 6/7 (trigger hasLayout) & { zoom:1; } }.group { @include clearfix; }رمز & في Sass يرمز إلى "العنصر الحالي"، حيث أنه ولدى ترجمة الملف يتم استبداله بـ المُحدد Selector الحالي. في المثال السابق سيتم استبداله بـ .group أوراق أنماط أكثر ذكاءاستخدام mixins لتنفيذ أنماط مُعينة على بعض العناصر أمر مفيد جدا، لكن الأفيد والأروع هو إمكانية استخدام المتغيراتarguments تماما مثلما هو عليه الحال مع لغات البرمجة المُختلفة كـ JavaScript وPHP، كما يُمكن استخدامها مع خواص أخرى أكثر تقدما مثل التعابير expressions والدوال functions وذلك بغية الذهاب أبعد من مُجرد تنظيم أوراق الأنماط وتنفيذ أنماط أكثر تعقيدا. تُعتبر Grid Layout systems إحدى أشهر استعمالات Sass. هناك العديد من أنظمة 960px الجاهزة لكن أغلبها يتطلب إضافة أسماء أصناف غير دلالية إلى شفرتك، هذا إلى جانب حاجتك إلى تحميل كامل النظام في مشروعك قبل استخدامه حتى ولو لم تكن ترغب في استخدام سوى جزء يسير منه. في مثالنا الأخير في هذا المقال سنقوم بإنشاء نظام Grid Layout من 12 وحدة باستخدام Sass. بدل استخدام اسم خاص لكل وحدة سنوليmixin مهمة تحديد العرض والهوامش الأنسب لكل عنصر لتحويله إلى وحدة في النظام الشبكي الذي نقوم بإعداده. بداية نحتاج إلى تحديد عرض كل عمود وهوامشه: $column-width: 60px; // 12 columns = 720px $gutter-width: 20px; // 11 gutters =ومن ثم نطلب من Sass أن يقوم بحساب عرض كل وحدة بالنيابة عنا، حيث أن عرض كل وحدة يساوي مجموع أعراض الأعمدة التي يغطيها إضافة إلى الهوامش التي تتخللها، وبالتالي يُمكن حسابه على النحو التالي: width: ($column-width * $span) + ($gutter-width * ($span – 1));وعليه فإننا سنكتب mixin يقبل متغيرا واحدا (والمتمثل في عدد الأعمدة span)، سيتم محاذاة كل وحدة إلى اليسار، وإضافة هامش 20px بين الوحدات، كما أنه ستتم إضافة هامش على يمين كل وحدة بنفس القيمة: @mixin grid-unit($span) { float: left; margin-right: $gutter-width; width: ($column-width * $span) + ($gutter-width * ($span - 1)); }بالرغم من بساطة الشفرة السابقة فإنها في غاية القوة، حيث أنه بإمكاننا مثلا تنفيذ نمط قاعدي متكون من عمود يحتوي ثلثي المساحة وعمود آخر يحتوي الثلث الباقي على النحو التالي: .container { @include clearfix; @include grid-unit(12); float: none; margin: 0 auto; }.main-content { @include grid-unit(8); }.sidebar { @include grid-unit(4); margin-right: 0; }وما هذا إلا جزء يسير مما يُمكن القيام به باستخدام Sass. دعم Sass للعمليات الحسابية القاعدية يجعل من مهمة العمل على تصاميم مُتكيفة adaptive fluid-width layouts أسهل. في المثال التالي نستخدم "الوصفة" الخاصة بـ Ethan Marcotte لتحويل التصميم السابق إلى تصميم مُتكيف. بما أن Sass لا يقوم بالتحويل ما بين الوحدات ما لم يتم طلب ذلك بشكل صريح فإننا نقوم باستخدام الدالة percentage() للقيام بذلك: .container { // result = target / context width: percentage(940px / 960px); .main-content { // This is nested inside of .container, so its context is 940px width: percentage(620px / 940px); } .sidebar { width: percentage(300px / 940px); } }يتوفر Sass أيضا على دوال للتحكم في الألوان كالسطوع والدكانة والشفافية وما إلى ذلك على النحو التالي: $base-link-color: #00f; a { color: $base-link-color; } a:visited { // This reduces the lightness of the color (in HSL terms) // by 50%, leaving hue and saturation alone color: darken($base-link-color, 20%); }figcaption { // Generates an rgba() color value with 50% opacity background-color: transparentize(#fff, 50%); }إذا لم تكن هذه الدوال كافية في نظرك فإنه بإمكانك إضافة دوال أخرى و تشاركها وإعادة استخدامها ما بين مختلف مشاريعك عبر الملفات الجزئية. ألق نظرة على القائمة الكاملة لدوال Sass لتأخذ فكرة عما يُمكن لهذه الدوال أن تقوم به. هل من مزيد؟موقع Sass الرسمي يحتوي الكثير من المعلومات المهمة والمفيدة للراغب في تعلم Sass ويحتوي دليلا شاملا لكل خواص ومزايا SCSS. أما لو كنت تفضل قراءة الكتب، فقد ترغب في قراءة كتاب Pragmatic Guide to Sass والذي شارك في تأليفه Hampton Catlin مطور Sass. أما لو أردت الذهاب إلى أبعد من ذلك فقد ترغب في إلقاء نظرة على مكتبة Compass والتي تحتوي مجموعة كبيرة من دوال أنماط SCSS والتي تدعم كلا من ورقة التصفير CSS reset الخاصة بـ Eric Meyer، نظام الشبكات Blueprint Grid system، إضافة إلى العديد من خواص وتأثيرات CSS3، والتي يصفها مطورها بأنها “jQuery for stylesheets”. إن كنت تستخدم تطبيق scout فإنك ستجد Compass متوفرة فيه بشكل مباشر، كما يُمكنك تنصيبه باتباع التعليمات المتوفرة على موقع المكتبة. ترجمة -وبتصرف- للمقال Getting Started with Sass لصاحبه David Demaree
  9. عادة ما يرتكب القادم الجديد إلى عالم HTML5 أخطاء عديدة ترجع إما لعدم فهمه للعناصر الجديدة أو الإفراط في استخدامها مكان العناصر القديمة. سنحاول في هذا المقال تسليط الضوء على أكثر الأخطاء شيوعا وكيفية تجنب الوقوع فيها. لا تستخدم <section> كأداة للتغليف بدل <div>أحد أكثر الأخطاء شيوعا هو الاستبدال المفرط لكل عناصر <div> بعناصر <section> في شفرات HTML5 وخاصة لما يتعلق الأمر بعناصر <div> المستخدمة لأغراض تنسيقية styling. سابقا لدى استخدامنا لـ XHTML و HTML4 كنا نكتب الشفرات على النحو التالي: <!-- HTML 4-style code --> <div id="wrapper"> <div id="header"> <h1>My super duper page</h1> <!-- Header content --> </div> <div id="main"> <!-- Page content --> </div> <div id="secondary"> <!-- Secondary content --> </div> <div id="footer"> <!-- Footer content --> </div> </div>بعض ظهور HTML5 أصبح العديد يكتبونها على النحو التالي: <!-- Don’t copy this code! It’s wrong! --> <section id="wrapper"> <header> <h1>My super duper page</h1> <!-- Header content --> </header> <section id="main"> <!-- Page content --> </section> <section id="secondary"> <!-- Secondary content --> </section> <footer> <!-- Footer content --> </footer> </section>وهو أمر خاطئ لأنه وبكل بساطة لا يعتبر عنصر <section> أداة تغليف wrapper، حيث أنه يتم استخدام هذا العنصر مع الأجزاء الدلالية للصفحة لبناء مخطط واضح المعالم لها، كما أنه من الواجب أن يحتوي على ترويسة heading. إن كان كل ما ترغب في القيام به هو إضافة نمط style لصفحتك فحاول أن تنفذه مباشرة على عنصر <body> ، أما لو احتجت عناصر إضافية للنمط الذي تود تنفيذه فعليك استخدام <div> في هذه الحالة وهو العنصر الأنسب لما يكون كل ما تحتاجه هو أداة لتنفيذ الأنماط. بناء على ما سبق ذكره فإن الطريقة الصحيحة لكتابة الشفرة السابقة باستخدام HTML5 وبعض وظائف ARIA (ملاحظة: قد تحتاج إلى عنصر <div> واحد فقط بناء على التصميم الذي ترغب فيه) هو على النحو التالي: <body> <header> <h1>My super duper page</h1> <!-- Header content --> </header> <div role="main"> <!-- Page content --> </div> <aside role="complementary"> <!-- Secondary content --> </aside> <footer> <!-- Footer content --> </footer> </body>إذا لم تكت تعلم ما هي العناصر التي يجب عليك استخدامها فيُمكنك الاستعانة بالصورة التالية التي ستسهل عليك الاختيار لا تستخدم عنصر header ما لم يكن هناك حاجة إليهملاحظة: في المقال الأصلي تم الحديث عن عنصري header و hgroup، وبما أنه تم التخلص من هذا الأخير من مواصفات HTML5 فلم أقم بتضمينه في الترجمة. لا توجد أية معنى لإضافة عناصر إضافية إلى صفحتك ما لم يكن هناك حاجة لها، لكن رغم ذلك عادة ما نلحظ استخدام عنصر <header> لما لا تكون هناك أية حاجة إلى استخدامه. يُمكنك معرفة كيفية استخدام هذا العنصر بقراءتك لهذا المقال والذي يُمكن تلخيصه في أن العنصر <header> يلعب دور عنصر مساعد أو مقدم لمحتوى الجزء الذي يحتويه. وبما أنه يُمكن استخدام عنصر <header> أكثر من مرة واحدة في نفس الصفحة فإنه عادة ما تتم إساءة استخدامه على النحو التالي: <!-- Don’t copy this code! No need for header here --> <article> <header> <h1>My best blog post</h1> </header> <!-- Article content --> </article>إن كان عنصر header الذي تستخدمه لا يحتوي سوى على عنصر رأسي heading element واحد فمن الأفضل تجنب استخدامه، حيث أن عنصر article سيضمن تضمين هذا العنصر الرأسي في مُخطط الصفحة document outline. وبما أنه سيحتوي عنصرا واحدا فقط (عكس ما تشير إليه مواصفات العنصر) فإنه من الأفضل كتابة الشفرة بشكل مبسط على النحو التالي: <article> <h1>My best blog post</h1> <!-- Article content --> </article>لا تُغلف كل قوائم الروابط باستخدام navلم يعد من السهل -مع كل العناصر الجديدة التي تمت إضافتها إلى HTML5- اختيار العنصر الأنسب لكثرة الاختيارات المتاحة، لكنه في المقابل لا يجب علينا أن نُفرط في استخدام العناصر الدلالية الجديدة وهو أمر عادة ما نلاحظه مع العنصر nav والذي تنص مواصفاته على التالي: يُمثل عنصر nav قسما من الصفحة تقوم بالربط إلى صفحات أخرى أو إلى أجزاء أخرى من نفس الصفحة. ملاحظة: لا يجب أن تكون كل مجموعات الروابط داخل عناصر <div>، يجب اقتصار استعمال هذا العنصر على كتل التصفح Navigation blocks الرئيسية فقط. فعلى سبيل المثال عادة ما يحتوي أسفل الصفحات footers على قوائم قصيرة لروابط لمختلف صفحات الموقع مثل قواعد استخدام المواقع، صفحة البداية وصفحة حقوق الملكية الفكرية. في مثل هذه الحالات يكفي استخدام عنصر footer لكنه يبقى استخدام عنصر nav ممكنا رغم أنه غير ضروري. WHATWG HTML spec الكلمة المفتاحية في هذه المواصفات هي "الرئيسية"، قد نختلف فيما تعنيه هذه الكلمة على وجه التحديد، لكنه عادة ما يُقصد بها: روابط تصفح الموقع الرئيسيةمحرك بحث الموقعروابط تصفح الموقع الثانويةروابط التنقل داخل الصفحة الواحدة (خاصة في الصفحات والمقالات الطويلة).بالرغم من أنه يصعب تمييز الصحيح من الخطأ في الكثير من الحالات إلا أنه يبدو بأنه من الأفضل تجنب استخدام nav في الحالات التالية: ترقيم الصفحاتالروابط الاجتماعية (قد يكون لهذا الأمر استثناءات خاصة إذا ما كانت هذه الروابط جزءا أساسيا في الصفحة مثلما هو الحال مع موقعي about me و flavours)الوسوم أو التصنيفات في التدويناتالروابط الثانويةأسفل الصفحات (footers)إن لم تعرف ما إذا كان بإمكانك استخدام عنصر nav اسأل نفسك، هل الروابط التي تنوي تغليفها داخل عنصر nav هي وسيلة أساسية للانتقال داخل الصفحة أو داخل الموقع؟ يمكنك الاستعانة بالنقطتين التاليتين للإجابة على هذا السؤال: لا تستخدم nav ما لم تعتقد بأنه يُمكن استبدال الأمر بعنصر <section> باستخدام عنصر hxهل كنت ستضيف عنصر "اذهب مباشرة إلى" للوصول إليها لتحسين قابلية وصول الموقع؟إن كانت إجابتك بالنفي فإنه من الأجدر بك عدم استخدام عنصر nav. أخطاء شائعة مع عنصر figureليس من السهل إتقان استخدام عنصر figure (وعنصر figcaption الذي يلازمه). إليكم بعض الأخطاء الشائعة التي يقع الكثيرون لدى استعمالهما. لا تستعمل figure مع جميع الصوركما سبق وأن أشرنا إليه ، لا توجد أية فائدة من كتابة شفرات إضافية ما لم يكن هناك داع لها، وهو نفس الأمر الذي يتكرر مع هذا العنصر أيضا. هناك من يقوم بتحويل جميع الصور إلى figure رغم أننا في غنى عن تغليف كل صورة في هذا العنصر، كلما تقوم به لدي قيامك بهذا الأمر هو إضافة شفرات إضافية لا تقدم أية إضافة للصفحة. تحدد مواصفات HTML5 عنصر figure على النحو التالي: بعبارة أخرى figure عبارة عن محتوى قائم بذاته يحتوي وصفا يتم إضافته إلى محتوى الصفحة رغم أنه ليس جزءا أساسيا فيها. وهنا يبرز جمال عنصر figure حيث أنه بالإمكان تغيير مكانه في الصفحة إلى القائمة الجانبية sidebar مثلا دون الإخلال بمحتوى الصفحة. إن كان ما تحاول وضعه داخل figure عبارة عن محتوى جمالي فقط لا يقدم أية إضافة للمحتوى، وإن لم يكن بالإمكان الإشارة إليه في محتوى صفحتك فإنه من المحتمل جدا أن لا يكون العنصر الواجب استخدامه هو figure. يُمكنك أيضا أن تسأل نفسك "هل هذه الصورة (أو غيرها) أساسية لفهم محتوى الصفحة" إن لم يكن جوابك بالإيجاب فقد لا يكون figure هو العنصر الأنسب لك (فكر في استخدام aside حينها). أما لو أجبت بالإيجاب فاسأل نفسك "هل يمكنني تغيير مكان هذه الصورة إلى ملف ملحق appendix ؟" إن كانت إجابتك بالنفي هنا أيضا فقد لا يكون عنصر figure هو الأنسب لك أيضا. لا تستخدم figure مع شعار موقعكلا يصح أيضا استخدام figure مع شعارات المواقع أيضا. عادة ما نشاهد مثل هذه الشفرات الخاطئة في بعض المواقع: <!—Don't copy this code! It's wrong! --> <header> <h1> <figure> <img src="/img/mylogo.png" alt="My company" /> </figure> My company name </h1> </header> <!—Don't copy this code! It's wrong! --> <header> <figure> <img src="/img/mylogo.png" alt="My company" /> </figure> </header>ليس لدينا ما نقوله هنا سوى أن استخدام figure للشعارات هو استخدام خاطئ. يجب عليك تجنب استخدام figure ما لم تتم الإشارة إلى المحتوى المراد تغليفه في هذا العنصر داخل الصفحة. وبما أنه من السهل أن نجزم بأنه لن تتم الإشارة إلى شعار موقعك في أي جزء من أجزاء صفحتك، فإن كل ما تحتاجه هو: <header> <h1>My company name</h1> <!-- More stuff in here --> </header>لا يقتصر استخدام figure على الصور فقطالاعتقاد السائد هو أن استخدام عنصر figure يقتصر على الصور فقط وهو اعتقاد خاطئ حيث أنه من المُمكن استخدام figure مع الفيديوهات، الملفات الصوتية، الرسوم البيانية (على هيأة SVG مثلا)، الاقتباسات، الجداول، الشفرات المصدرية وغيرها. يعني أي محتوى يساعد على فهم المحتوى الرئيسي للصفحة وإعطاء تفاصيل إضافية حوله يصلح أن يكون داخل عنصر figure. يُمكن معرفة المزيد حول عنصر figure بقراءتك لهذا المقال. استخدام خاصية type غير الضروريةاستخدام خاصية type شائعة جدا ما بين المبرمجين، رغم أنه ليس خطأ في حد ذاته، إلا أنه من الأفضل تجنبه. ليس من الضروري لدى استخدام HTML5 التصريح بنوع عنصري script و style. قد لا يكون من السهل التخلص من الأمر خاصة إن كان إضافة هذه الخاصية يتم بشكل آلي خاصة لدى استخدام أنظمة إدارة المحتوى إلا أنه لا توجد أية حاجة ماسة لاستخدامها لما تقوم بكتابة كامل شفرة تطبيقك بشكل يدوي لأنه وبكل بساطة تتوقع جميع المتصفحات أن تكون السكربتات التي تستخدمها من نوع javascript وكل الأنماط من نوع css، وعليه فإنك لن تحتاج إلى كتابة التالي: <!-- Don’t copy this code! It’s attribute overload! --> <link type="text/css" rel="stylesheet" href="css/styles.css" /> <script type="text/javascript" src="js/scripts.js"></script>بل كل ما تحتاجه هو <link rel="stylesheet" href="css/styles.css" /> <script src="js/scripts.js"></script>كما أننا لم نعد في حاجة إلى كتابة الكثير للإشارة إلى نوعية الترميز المستخدم في الصفحة character set إضافة إلى أمور أخرى لم يعد هناك حاجة إليها ستجدها مشروحة بشكل مفصل في هذا المقال. استخدامات خاطئة لبعض خصائص النماذجكما سبق وأن أشرنا إليه، يوفر HTML5 خصائص عديدة للنماذج، ويرافق استخدام هذه الخصائص أخطاء يجب تجنبها: الخصائص المنطقيةالعديد من الخصائص الجديدة في نماذج HTML5 هي خصائص منطقية، ونعني بذلك بأنه تتم إضافة سلوك معين للنموذج أو لعنصر ما بمجرد إضافة هذا العنصر إليه، ومن بين هذه الخصائص المنطقية نجد كلا من autofocus، autocomplete و required. قد لا يكون هذه المشكل كثير الشيوع، إلا أن هناك من يستخدم هذه الخصائص المنطقية (عنصر required مثلا) على النحو التالي: <!-- Don’t copy this code! It’s wrong! --> <input type="email" name="email" required="true" /> <!-- Another bad example --> <input type="email" name="email" required="1" />لكن ماذا لو أردت "العبث" بالشفرة السابقة قليلا وأعطيت قيمة false لخاصية required، ما الذي تتوقع أن يقوم به المتصفح في هذه الحالة؟ <!-- Don’t copy this code! It’s wrong! --> <input type="email" name="email" required="false" />على غير ما تتوقع فإن المتصفح وبمجرد أن يلاحظ وجود خاصية required فإنه يقوم بجعل العنصر الذي تمت إضافته إليه ضروريا رغم أنك أعطيت الخاصية قيمة false. هناك 3 صيغ لاستخدام الخصائص المنطقية مع HTML5 (يتم استخدام الصيغتين الثانية والثالثة مع XHTML): required required="" required="required"وأفضل طريقة لكتابة الشفرة السابقة هي على النحو التالي: <input type="email" name="email" required />خلاصةاستعرضنا في هذا المقال بعضا من الأخطاء الأكثر شيوعا مع HTML5. بطبيعة الحال فإنه يستحيل حصر كل هذه الأخطاء، وبالتالي إن كانت هناك أخطاء أخرى سبق وأن شاهدتها أكثر من مرة فلا تتردد في مشاركتها معنا في التعليقات. ترجمة -وبتصرف- للمقال Avoiding common HTML5 mistakes لصاحبه Richard Clark
  10. أكثر الإثارة التي تصحب عادة الحديث حول HTML5 تدور عادة حول الواجهات البرمجية الجديدة ويتعلق الأمر بكل من Local Storage، Application Cache، WebWorkers، الرسم ثنائي الأبعاد وما شابه. لكن يجب علينا أن لا نتجاهل بأن HTML5 يحمل في طياته 30 عنصرا جديدا لتعليم mark up المُستندات والتطبيقات مما يرفع عدد العناصر المتوفرة بشكل كلي إلى أكثر من 100 عنصر. باستثناء بعض الأمثلة والعروض الجوفاء، فإن أغلب التطبيقات المبنية بشكل أساسي على Javascript أو حتى التطبيقات المُغالية في مبادئ Web 2.0 ستحتوي على نصوص تحتاج أن يتم تعليمها بشكل حساس. دعونا نلقي نظرة على بعض العناصر الجديدة لتضمن بأن مشاريعك القادمة ستكون دلالية Sementic مثلما ستكون تفاعلية interactive. ما ستلاحظه طيلة هذا المقال هو أنه تم تصميم دلالية HTML5 لتقوم بتمديد ما يستطيع HTML القيام به، مع إتاحة مستخدمي المتصفحات القديمة الوصول إلى المُحتوى . سنرى أيضا بأن التعليمات الدلالية Sementic Markup ليس أمرا "من الجيد القيام به" فحسب وإنما يُعتبر حجز الزاوية لما يتعلق الأمر بتطوير تطبيقات الويب لأنها الآلية التي تسمح بتعزيز قابلية الوصول (Accessibility)، القابلية للبحث (searchability)، التدويل (internationalization) والتشغيل البيني (interoperability). اللغات البشرية كالإنجليزية وبالرغم من مفرداتها التي تُعد بالملايين فإنه لا يُمكنها أن تُعبر عن جميع الأفكار دون أن يكون هناك لُبس فيها، وبالتالي فإنه مع 100 مُفردة التي يُمكننا استخدامها في HTML فإننا سنجد أنفسها في حالات لا نعرف فيها على وجه اليقين أي عُنصر يجب علينا استخدامه لأي جزء من المُحتوى، في هذه الحالة كل ما عليك القيام به هو اختيار واحد واستخدامه بشكل متناسق في كامل الموقع. بعض عناصر العرض لم يعد لها وجود بعض عناصر العرض مثل center، font أو big أصبحت مهجورة في وقتنا الحاضر، حيث أنه تم استبدال أدوارها بـ CSS، لكن ذلك لا يعني بأنه يجب عليك أن تُسارع لإعادة كتابة كل تلك الصفحات القديمة التي كانت تستخدمها لأنه وبالرغم من كونها مهجورة ستقوم المُتصفحات بعرضها بشكل صحيح، حيث أن HTML5 دائما ما تهدف إلى توفير حلول جديدة دون أن تخل بالحلول الحالية. ولنفس الأسباب تم التخلص من بعض خصائص العرض التي كانت متوفرة من قبل في بعض العناصر مثلما هو عليه الحال مع خاصية align في عنصري img وtable ، خاصية background في عنصر body وخاصية bgcolor في عنصر table. العنصر "الشرير" frame أيضا مُغيب في HTML5 حيث أنه كان يُسبب مشاكل في قابلية الاستخدام وقابلية الوصول، لكن لو كانت لديك حاجة ماسة إلى استخدامه فكل ما عليك القيام به هو استخدام DOCTYPE أقدم لتبقى صفحاتك صحيحة من حيث البنية. يُمكنك أن تجد قائمة كاملة بكل العناصر والخواص التي تم حذفها على موقع W3C. تمت إعادة تعريف بعض عناصر العرض لتصبح دلالية لم يتم التخلص من جميع عناصر العرض، خضع بعضها لبرنامج إعادة تأهيل شامل وخرجت منه بخواص دلالية جديدة. فعلى سبيل المثال لم يعد عنصر small يعني "استخدم حجم خط أصغر" رغم أنه سيتم عرضه على هذا النحو في ملفات الأنماط الخاصة بالمتصفحات، حيث أنه أصبح يُمثل تعليقات جانبية، مثل تعليقات Small Print: يتم استخدام Small print في كل من تصريحات إخلاء المسؤولية، المحاذير، القيود القانونية وحقوق الملكية الفكرية، كما تستخدم أيضا لنسب الأعمال إلى أصحابها أو فيما يتعلق بالتراخيص. بعض عمليات إعادة التعريف قد تبدو مبالغا فيها، فإن كان بإمكان تفهم إعادة تعريف عنصر <b>(أو عنصر <i>) والذي تم بشكل في غاية الدقة (والذي تشوبه بعض الغرابة)، إلا أن إعادة تعريف بعض العناصر كعنصر <u> قد تصيبك بالدوار: The u element [now] represents a span of text with an unarticulated, though explicitly rendered, non-textual annotation, such as labeling the text as being a proper name in Chinese text (a Chinese proper name mark), or labeling the text as being misspelt. يُمكن قراءة المزيد حول العناصر والخصائص التي تم تحديثها على موقع W3C. عناصر دلالية جديدة وجذابة كلنا سمعنا عن عنصري video و audio الشهيرين. عنصر canvas أيضا شهير خاصة بسبب سماحه بتصميم رسوم ثلاثية الأبعاد بالاستعانة بـ WebGL والتي تسمح لمصممي الألعاب بنقل ألعابهم إلى الويب. ومثل عناصر img فإن هذه العناصر الجديدة تقوم بتضمين مُحتوى من مصادر أخرى سواء كانت ملفات، بيانات أو JavaScript. لكن على خلاف img فإن هذه العناصر لديها وسوم فتح وإغلاق مما يسمح بتوفير نوع من التراجع Fallback، وعليه فإنه سيكون بالإمكان توفير محتوى بديل للمتصفحات التي لا تدعم canvas ، ويُمكن لصورة مثلا أن تلعب دور التراجع لعنصر canvas، كما يُمكن لملف Flash أن يلعب دور التراجع لعنصر video وهذه التقنية تُسمى بتقنية "الفيديو للجميع". عنصرا source و track هما عنصران فارغان (من دون أي وسم إغلاق) ويأتيان كذرية (children) لعنصري video أو audio. يتم إعطاء عنصر source ملفات بتراميز مُختلفة، ويستعمل كل عنصر منها ملفا مختلفا (WebM، MP4، Ogg Theora) وسيقوم المتصفح بتشغيل أول هذه الملفات التي يُحسن التعامل معها: <audio controls> <source src=bieber.ogg type=audio/ogg> <source src=bieber.mp3 type=audio/mp3> <!-- fallback content: --> Download <a href=bieber.ogg>Ogg</a> or <a href=bieber.mp3>MP3</a> formats. </audio> في هذا المثال، سيقوم كل من Opera، Firefox وChrome بتحميل وتشغيل ملف Ogg ، في حين سيفضل Internet Explorer و Safari ملف MP3. يُمكن لمتصفح Chrome أن يُشغل كلا من Ogg وMP3 لكن المتصفحات ستقوم بتشغيل أول ملف تُحسن التعامل معه حسب الترتيب الذي وردت عليه. التراجع الذي نوفره هنا والذي يظهر قبل وسم الإغلاق يُوفر رابطا لتحميل الملف وتشغيله على جهازك باستخدام قارئ الصوتيات المُفضل لديك، كما أنه لا يظهر شوى على المُتصفحات التي لا يُمكنها قراءة الوسائط المُتعددة بشكل مُباشر. أما فيما يخص الفيديوهات فإنه بإمكانك تضمين ملف Flash على Youtube كنوع من التراجع: <video controls> <source src=best-video-ever.webm type=video/webm> <source src=best-video-ever.mp4 type=video/mp4> <!-- fallback content: --> <iframe width="480" height="360" src="http://www.youtube.com/embed/xzMUyqmaqcw?rel=0" frameborder="0" allowfullscreen> </iframe> </video> بهذه الطريقة سيصبح بإمكان مستخدمي المُتصفحات القديمة مثل IE6-8 أن يُشاهدوا الفيديو على Youtube (إن كانت مُتصفحاتهم تدعم Flash)، وسيكون بمقدورهم الوصول إلى تلك الفيديو. في حين سيحصل مستخدمو المتصفحات الأحدث على النسخة المُضمنة في الموقع من الفيديو، وبالتالي سيحصل الجميع على المحتوى الذي قدموا من أجله إلى موقعك. يُعتبر عنصر track إضافة جديدة إلى عائلة HTML5 وهو مدعوم على كل من Opera، Chrome وIE. يقوم هذا العنصر بالربط إلى ملف نصي يحتوي نصا وتوقيتا، يتم استخدامها لعرض الترجمة الفورية للفيديو وهي خاصية مفيدة جدا ليس فقط للذين يُعانون من مشاكل في السمع، بل أيضا للذين لا يتقنون اللغة التي تُعرض فيها الفيديو. الدلالية والتدويل قد يبدو هذا الأمر أقل أهمية من الوسائط المُتعددة لكن الأمر ليس كذلك بحكم أن الشبكة العنكبوتية العالمية ليس مُجرد محتويات باللغة الإنجليزية، بل أنها تستعمل أيضا أنظمة كتابة مُختلفة عن نظام الكتابة في اللغة الانجليزية. فبعض اللغات كالعربية والعبرية هي لغات تكتب من اليمين إلى اليسار على عكس اللغات الأوروبية والتي تُكتب من اليسار إلى اليمين. قد لا يشكل هذا الأمر أي إشكال على الصفحات التي تحتوي نظام كتابة واحد، لكن الأمر مُختلف على الصفحات التي تحتوي نظامي الكتابة في آن واحد، حيث أنه يجب على المُتصفح أن يقرر أين يتوجب عليه أن وضع علامات التنقيط، أزرار القوائم وأرقامها وما إلى ذلك. عادة ما تُبلي المُتصفحات بلاء حسنا باستخدامها للخوارزميات ثنائية الاتجاه الخاصة بـ Unicode لكنها تخطئ في بعض الحالات، وهو ما يصعب من مهمة فهم المحتوى. يوفر HTML5 عنصر bdi والذي يسمح للكتاب أن يقوموا بتجاوز الخوارزمية ثنائية الاتجاه آنفة الذكر لجعل نصوصهم أكثر سهولة للفهم. لوصف أوفى للمشكل ولمعرفة الطريقة التي يقوم العنصر bdi بحلها ألق نظرة على هذا المقال HTML5’s New bdi Element لكاتبه Richard Ishida المسؤول عن التدويل لدى W3C. بعض اللغات لا تملك أبجديات تقليدية بالمرة، والتي تُعبر عن أفكار بدل الأصوات، في بعض الحالات سيحتاج الكاتب بهذه اللغات إلى إضافة تنبيهات لتسهيل قراءة الكلمات خاصة مع الكلمات الشاذة أو الأحرف الغريبة، ويتم ذلك عادة بتوفير نص موازٍ بخص صغير فوق الحرف المعني بالأمر. عادة ما كان يتم القيام بذلك في المطبوعات باستخدام خط صغير ذي حجم 5 نقاط يُسمى « ruby » ، ولهذا يُوفر HTML5 على 3 عناصر جديدة للقيام بذلك، ويتعلق الأمر بكل من ruby، rt وrp. للمزيد من المعلومات حول الأمر، أقرأ المقال التالي: The HTML5 ruby Element in Words of One Syllable or Less الدلالية الهيكلية أغلب المُطورين على علم بأن HTML5 يوفر العديد من العناصر التي تسمح بوصف أجزاء مُختلفة من صفحات الويب مثل header، footer، nav، section، article، aside وغيرها. تم إنشاء هذه العناصر لأن المُطورين أمثالنا رغبوا في وجودها. قد تتساءل كيف عرف مطورو HTML5 العناصر التي نرغب فيها؟ كل ما في الأمر أن Google قامت سنة 2005 بتحليل مليار صفحة لمعرفة ما هي المُعرفات id والأصناف class التي كان المُطورون يستخدمونها مع عناصر div في تلك الصفحات. كما قامت Opera MAMA سنة 2008 بتحليل 3 ملايين URL لمعرفة أكثر أسماء الأصناف انتشارا والمعرفات الأكثر شيوعا على الإنترنت. كشفت هذه التحليلات بأن المطورين رغبوا في تعليم بعض أجزاء صفحاتهم لكن لم يكن لديهم خيار سوى استخدام عنصر div والذي أضافوا إليها أصنافا أو مُعرفات. كما سبق ذكره فإننا لن نتعمق في جميع هذه العناصر في هذا المقال، لكن يُمكنكم أن تجدوا تفاصيل كثيرة حولها على موقع HTML5Doctor. تم تصميم هذه العناصر الدلالية الجديدة لتوفر مبدأ التراجع الرشيق، فعلى سبيل المثال انظروا كيف يتم وصف عنصر figure في مواصفات HTML5: لم يأت هذا العنصر بأية أفكار جديدة حيث سبق لـ HTML3 أن اقترح عنصر fig لكنه لم يتم قبوله في مواصفات HTML3.2 والذي كان يُستعمل على النحو التالي: <FIG SRC="nicodamus.jpeg"> <CAPTION>Ground dweller: <I>Nicodamus bicolor</I> builds silk snares</CAPTION> <P>A small hairy spider. <CREDIT>J. A. L. Cooke/OSF</CREDIT></P> </FIG> هناك مُشكل كبير مع هذه الطريقة، حيث أنه وعلى المُتصفحات التي لا تدعم fig (ولا يوجد أي متصفح يدعمها) لن يتم عرض الصورة لأن المتصفحات ستقوم بتجاهل عنصر fig بشكل كامل، بل كل ما سيتم عرضه هو مُحتوى عنصر credit لأنه عبارة عن نص، وبالتالي ستحصل على وصف دون الصورة في المتصفحات القديمة. لكن مع HTML5 الوضع مُختلف، حيث أننا سنقوم بكتابة نفس المثال على النحو التالي: <figure> <img src="nicodamus.jpeg"> <figcaption> <p>Ground dweller: <i>Nicodamus bicolor</i> builds silk snares.</p> <p>A small hairy spider. <small>J. A. L. Cooke/OSF</small&gt</p> </figcaption> </figure> على خلاف عنصر HTML3 الذي لم يتم قبوله فإن الطريقة التي نكتب بها المثال باستخدام HTML5 متوافقة مع الإصدارات القديمة من المُتصفحات، حيث أن المتصفحات التي لا "تعرف" عنصر figure ستقوم بعرض الصورة والنص الموجود في العنصر figcaption (مثلما كان سيتم عرض مُحتوى عنصر credit). لاحظوا بأننا نستخدم في هذا المثال عنصر small الذي تمت إعادة تعريفه بدل استحداث عنصر credit جديد. تذكروا دائما أنه يتم استعمال عنصر small لنسب الأعمال إلى أصحابها. يُوفر HTML5 عنصر figcaption جديدا. بداية كانت هناك رغبة لإعادة استخدام عنصر caption مثلما تم اقتراحه في HTML3، لكن كانت هناك مشاكل "إرثية" (Legacy problems) بحكم أن caption كانت تُستخدم سابقا كأحد ذرية عنصر table فقط. أحد مبادئ التصميم التي بُني عليها HTML5 هو أنه يجب على كل خاصية جديدة أن توفر تراجعا رشيقا، وإن لم يكن بإمكان العنصر القيام بذلك فإنه يجب عليه أن يسمح بتوفير محتوى تراجعي Fallback content، حيث أنه يتم تفضيل استخدام عناصر موجودة بدل استحداث عناصر جديدة، لكنه بحكم أن HTML5 لغة برمجية عملية فإنه لما يكون استحداث عنصر جديد أمرا ضروريا فإنها تقوم بذلك. دلالية تفاعلية لا تؤثر العناصر الهيكلية لـ HTML5 على مظهر الصفحات في المتصفحات كثيرا، إلا أن التطبيقات التي تُبنى على المتصفحات (خاصة تطبيقات قراءة الشاشات) قد شرعت في استخدامها (للمزيد حول الأمر: " HTML5, ARIA Roles, and Screen Readers in March 2011" و " JAWS, IE and Headings in HTML5.") بعض العناصر الأخرى لديها تأثير على شكل الصفحات، فعلى سبيل المثال العنصر details عبارة عن عنصر تفاعلي والذي يلعب دور نافذة صغيرة يحصل المستخدم لدى النقر عليها على بيانات أو خواص إضافية. ستقوم أغلب المُتصفحات إظهار هذا العنصر كصندوق قابل للتوسع، بعبارة أخرى لما يقوم المُستخدم بالنقر على أيقونة يقوم المُتصفح بتوليدها (كمثلث أو كسهم تحميل) أو حتى على كلمة "تفاصيل" (والتي سيكون بإمكان المُطور استبدالها في العنصر summary الذي سيكون ابنا مُباشرا للعنصر details)، وسيتم فتح الصندوق بشكل منسدل مظهرا التفاصيل التي يحتويها. من المُمكن أن يكون المحتوى عبارة عن وصف كامل للصورة أو للرسم البياني، وصفا لجدول مركب، خصائص للتحكم في نموذج بحث، أو أية معلومات أخرى. تُعتبر هذه الخاصية إحدى الخصائص الضرورية للويب الحديث، وبفضل HTML5 أصبح بالإمكان القيام بذلك من دون الحاجة إلى أي JavaScript. أغلبنا سبق لك أن شاهد مُختلف الخواص الدلالية الجديدة لنماذج HTML5 (تعرف على العناصر والخصائص الجديدة لنماذج HTML5)، والتي أغلبها عبارة عن خصائص للعنصر input والتي توفر تراجعا رشيقا إلى <input type=text> في المتصفحات الأقدم. من بين العناصر الجديدة نجد أيضا كلا من datalist، output، progress و meter. هل نملك العناصر الدلالية الأنسب؟ كما رأينا فإننا نملك عناصر دلالية جديدة عديدة، لكن السؤال الذي يجب أن نطرحه هو: هل فعلا نملك العناصر الدلالية الأنسب لاستعمالاتنا؟ مثلما رأينا فإن دراسة Google التي بُني عليها الأمر تعود إلى عدة سنوات خلت (2005)، ومن المُحتمل أن تكون الدلالية التي نعمل عليها متأخرة بعدة سنوات عن احتياجاتنا الحقيقية، كما لاحظنا فإن هذه العناصر تدور كلها هو مفهوم المُستند ومحتوياته document-centric وليست مبنية حول التطبيقات application-centric. هل نحتاج إلى عناصر دلالية تدول حول التطبيقات مثل login أو share، أو حتى Modal. ليس من السهل الإجابة على هذا السؤال، لكن كون HTML معيارا حيا living standard فإنه من المُمكن إضافة مثل هذه العناصر لاحقا لو تم اقتراح حالات استخدام قوية للـ Working Group. من دون شك سيرحب أغلب المُطورين بطرق جديدة لتضمين الصور والتي تتماشى مع مختلف الأجهزة التي يتم عليها. يُمكن مثلا أن نقتبس من عنصر video والذي يقوم بعرض الفيديو من المصدر الذي يتوافق مع المتصفح، يُمكن مثلا تخيل عنصر picture يكون على النحو التالي: <picture alt="angry pirate"> <source src=hires.png media="min-width:800px"> <source src=midres.png media="min-width:480px"> <source src=lores.png> <!-- fallback for browsers without support --> <img src=midres.png alt="angry pirate"> </picture> هذا العنصر سيعرض hire.png على الشاشات الكبيرة، midres.png على الشاشات التي يتراوح عرضها ما بين 480 و800 بكسل، و lores.png لباقي الشاشات. وهو ما قد يجيب أيضا على التساؤل الذي يطرحه عادة المصممون على أنفسهم: "هل يجب علي أن أطلب من جميع المتصفحات تحميل صورة عالية الجودة ومن ثم أقوم بتصغيرها للشاشات الصغيرة مما يعني بأنني سأقوم بتحميل بيانات زائدة، أم أقوم بتحميل صورة منخفضة الجودة ومن ثم أقوم بتكبيرها على الشاشات الكبيرة وبالتالي فإنني سأضحي بجودة الصور". وقياسا على ما سبق وأن رأيناه من عناصر دلالية شائعة فإنه يُمكن أيضا أن نوفر تراجعا رشيقا، والذي سيكون في هذه الحالة عنصرا من نوع img وبالتالي سيحصل الجميع على المحتوى الأصح. لا يزال إرسال الصورة بالحجم الأنسب أحد أعقد المشاكل فيما يتعلق بالتصاميم العبارة للأجهزة cross-device design وللتصاميم المتجاوبة responsive design. قد نجد حلا لها مع HTML6، لكن إلى غاية ذلك الحين تبقى أفضل الحلول -والتي من ضمنها حلا Adaptive Images و Responsive Images- تحتاج إلى JavaScript وإلى بعض التعديلات على ملف htaccess من جانب الخادوم. لكن أسوأ الحلول الحالية تتطلب تقنيات عفا عنها الزمن، كـ" اشتمام المتصفحات" Browser-sniffing، والذي تم تغيير اسمه ليصبح "اكتشاف الأجهزة" device detection رغم أنها تستعمل نفس التقنيات القديمة المتعلقة بالتحقق من user-agent والتي هي عبارة عن تقنية هشة جدا، لا تصلح مع التقنيات المستقبلية، كما أنها غير قابلة للتحجيم Scalable، دون أن ننسى بأنها تُذكرنا بالأيام التي كنا نشاهد فيها "لأفضل عرض استخدم متصفح netscape بدقة 800x600" على صفحات المواقع. متى، أين ومن؟ تحتاج الكثير من البيانات إلى المعلومات التالية: متى، أين ومن. يُوفر HTML5 عنصرtime (والذي أسال الكثير من الحبر) والذي يسمح لك بإرفاق التواريخ التي يُمكن لنا أن نقرها من دون صعوبة human-readable بتواريخ على هيأة قابلة للتحليل بشكل آلي machine-readable. لا يهم النص الذي تضعه ما بين وسمين الفتح والإغلاق، لأن ذلك النص هو الذي سيظهر للقراء، وبالتالي فإنه يُمكن استخدام أي من الصيغتين التاليتين: <time datetime="1982-07-18">The day the woman I love was born</time> <time datetime="1982-07-18">Priyanka Chopra’s birthday</time> أيا كانت الصيغة التي تختارها فإنه يمكن للآلة قراءة التاريخ بشكل صحيح مادام تم توفير التاريخ على شكل YYYY-MM-DD. إن أردت إضافة الوقت فإنه يمكنك ذلك لكن يجب عليك أن تفصله عن التاريخ بـ T وأن تستخدم وقتا من 24 ساعة (وليس من 12 ساعة) وتختمه بـ Z إضافة إلى أي اختلاف في الحزمة الزمنية. وبالتالي 2011-11-13T20:00Z تُمثل الساعة 8 مساء من يوم 13 نوفمبر سنة 2011 بالتوقيت العالمي UTC، في حين 2011-11-13T23:26.083Z-05.00 تُمثل الساعد 11 ليلا و26 دقيقة و83 جزء من الألف من الثانية في الحزمة الساعية التي تتواجد 5 ساعات قبل التوقيت العالمي. يُمكن مثلا لمتصفح في سيريلانكا أن يقوم بتحويل هذه المعلومة بشكل آلي إلى توقيت حسب التوقيت البوذي، كما أن مُحركات البحث قادرة على استخدام timestamps لتحديد مدى طزاجة نتائج البحث. رغم الانتشار الكبير لخدمات تحديد الأماكن الجغرافية geolocation إلا أننا لا نملك أي عنصر لتمثيلها والذي يقبل 3 خصائص: خطوط الطول، دوائر العرض، إضافة إلى الارتفاع (بشكل اختياري). وسيكون رائعا لو كان بإمكاننا كتابة شيء مثل التالي: <location lat=51.502064 long=-0.131981>London SW1A 4WW</location> وسيكون حينها بإمكان المتصفحات أن تقترح عليك خريطة فيما جملة من التوجيهات إلى المكان الذي تود أن تصل إليه اعتمادا على إحداثياتك الجغرافية الحالية. احتوى HTML3 على عنصر person تم استخدامه لأسماء الأفراد وذلك للتمكن من استخراجها بشكل آلي من طرف تطبيقات الأرشفة، لكنه لم يتم استخدامها. في HTML4 كان بالإمكان استخدام العنصر cite لتغليف أسماء الأشخاص، لكنه تم التخلص منه في HTML5 بشكل مثير للجدل، وبالتالي فإنه مع HTML5 لا نملك أية وسيلة لتحديد أسماء الأفراد بشكل واضح لا لُبس فيه. في المقابل فإن أسماء الأفراد يُعتبر مشكلا في غاية التعقيد، فإن كان للأوقات والتواريخ صيغ قياسية للتعبير عنها (YYYY-MM-DD للأولى و HH :MM :SS,mmm للثانية) وإن كان يتم تمثيل الأماكن الجغرافية دائما بخطوط الطول ودوائر العرض، فإن الأسماء أصعب للتحليل وللتقسيم إلى وحدات صغيرة يسهل التعامل معها، فعلى سبيل المثال هناك أسماء العائلات الروسية، الأسماء الإندونيسية أحادية الكلمات، الأسماء التي تحتوي على عدة أسماء للعائلة، دون أن ننسى الألقاب التايلاندية. يُمكنكم الاطلاع على مدى تعقيد الأمر بقراءة هذا المقال: Personal Names Around the World. يملك عنصر date الجديد -والذي استبدل عنصر time- خاصية تحدد قيمة الوقت الذي يُمكن قراءته بشكل آلي (machine-readable information)، لكنه لا يتطلب أو يتضمن صيغة خاصة للقيام بذلك، وبالتالي فإنه لا يُمكن لمحركات البحث مثلا أن تعلم إن كان 1936-10-19 تاريخا، جزءا من رقم، أو حتى رمزا بريديا. Microdata HTML5 تماما مثل سابقه HTML4 عبارة عن معيار قابل للتمديد extensible (لكنه ليس قابلا للتمديد على طريقة XML التي يذمها الـ Working Group). بإمكانك أن تستخدم الـ microformat التي سبق وأن تمت تجربتها واختبارها والتي تستعمل أصناف HTML (HTML classes) أو مواصفات RDFa الكاملة والتي لا يُمكنها أن تتجاوز اختبارات التحقق validation في كل من HTML4 أو HTML5. يتم اعتبار RDFa صعبة المراس، حيث أن Google أجرت بحثا بين بأنه يتم ارتكاب 30% أكثر من الأخطاء لدى استخدام RDFa مقارنة بغيرها من الصيغ). أما microdata فعبارة عن آلية لإضافة طبقة دلالية إضافية باستخدام مجموعة من الوسوم التي تم التفاهم عليها مُسبقا. يُمكنكم إيجاد المزيد حول الأمر على موقع HTML5doctor. مثلما هو عليه الحال مع microformat و RDFa، فإن الوسوم الدلالية التي نضيفها لن يكون لديها أي معنى ما لم يكن لدينا "وثيقة" تدلنا على المعنى الذي يحمله كل وسم. بعبارة أخرى هذه البيانات تحتاج إلى أن تربط إلى قاموس مفردات تُخبر التطبيقات الزاحفة crawler بأي طريقة يجب عليه أن يفسر البيانات التي يجدها. ولمن أراد استخدام microdata هناك موقع schema.org والذي يجمع مخططات/وسوم HTML يُمكن للمطورين استخدامها بطريقة تتعرف عليها كبريات مُحركات البحث. هل للويب الدلالي أي فائدة؟ بما أنه توليد الكثير من الوسوم أصبح يتم بشكل آلي عبر JavaScript فإن هناك من يعتقد بأن الدلالية لم يعد لها فائدة، عادة ما نُشاهد منتجات يتم التسويق لها على أساس أنها مُنتجات HTML5 لكنها بكل بساطة عبارة عن تطبيقات تقوم بجعل مجموعة من عناصر div "تطير" من مكان إلى آخر من الصفحة باستخدام JavaScript بنفس الطريقة المُتبعة مع DHTML منذ عشرية. بل أصبح هناك العديد من المُطورين الذين يطلقون تطبيقات لا تحتوي على أية وسوم، وهناك بعض أطر العمل التي تنتج هياكل HTML تحتوي على وسم body فارغ ومن ثم تقوم بحقنه بوسوم HTML باستخدام JavaScript. إن كنت ممكن يقومون بالقيام بذلك فأنت أقرب ما تكون من Flash منك إلى الويب. ومثلما أن هناك من يعتقد بأن قضاء 47 دقيقة (والتي قد يبدو بأنها مُدة طويلة) لبناء تصميم CSS هي مدة طويلة جدا ويتجهون مباشرة إلى استخدام الجداول في صفحاتهم، فإن هناك أيضا من يعتقد بأن قضاء بعض الوقت في التفكير في أي عنصر يجب استخدامه هو أيضا مضيعة وقت. هناك حجة أفضل والتي تقول بأنه لا يوجد أية تطبيقات تهتم أو تستهلك المحتويات الدلالية، فلماذا الاهتمام بها؟ رغم أن هذه الحجة ليس صحيحة لأن العمل جار على ربط تقنيات قابلية الوصول accessibility مع الدلالية الحديثة. لكن حتى لو كانت هذه الحجة صحيحة فإنها تتجاهل بأن المشكل الحالي هو مشكل مشابه لمشكل من أتى أولى، الدجاجة أم البيضة؟ لأنها تفترض بأنه لن تظهر أية محركات بحث جديدة يكون بمقدورها استخدام العناصر الجديدة، أو أن المتصفحات لن تطلق أية إصدارات جديدة تقوم باستغلال الدلالية فيها، أو أن المطورين لن يكتبوا أية إضافات للمتصفحات للقيام بذلك. باختصار هذه الحجة تفترض بأن دورة تطور الويب قد اكتملت. للويب الدلالي فائدة، لأن الدلالية تحمل معنى وبمجرد أن يتم اعتماد ذلك فإنه يُمكن للآلات أن تقوم باستغلال تلك البيانات من دون الحاجة إلى كتابة أو تطوير خوارزميات لتخمن معناها. سيكون بإمكان إضافة للمتصفح أن تسمح للمستخدم بالانتقال مباشرة إلى nav بنقرة زر واحدة لأنها ستقوم بالبحث عن nav مباشرة بدل البحث في كامل عناصر div وتخمن ما إذا كان المعرف id أو الصنف class الذي تحمله يوحي بأنها عبارة عن nav، هذا إن افترضنا أن المطور سيسمي هذا العنصر بأسماء لها معنى كـ nav، navigation، sidebar أو menu. كما أنه على موقع مطعم مثلا فإن div يحمل المعرف menu قد يحتوي على قائمة المأكولات المتوفرة بدل أمر آخر، وهو ما يذكرنا من جديد في مقدار الغموض الذي يلتبس لغاتنا الحية. وسيصبح مثلا بإمكان تطبيق زاحف crawler أن يجمع المقالات حسب ترتيبها الزمي مثلا. باختصار هناك الكثير من الحالات التي يُمكن التفكير فيها بناء على ذلك. تم بناء الويب اعتمادا على تقنيات بسيطة تم دمجها مع بعض لتعطينا نتائج مُذهلة وهي النتائج التي تجاوزت كل نوايا وتوقعات مطوريها الأوائل، وسيواصل الويب إبهارنا على هذا النحو. الأمر الذي جعل الويب مذهلا بهذه الطريقة والأمر الذي جعله مرنا وفي غاية القوة هو توفر المحتوى على شكل صيغ مفتوحة وبإمكاننا تحليله ودمجه بطرق مذهلة. يمكن لهذا أن يحدث لو تم وسم المحتوى من أجل إعطاء معنى له، ولو كان للغة وسوم يُمكن استخدامها كجزء من مفرداتنا. ما يقوم به HTML5 هو توسيع لدائرة المفردات التي نستعملها، بطبيعة الحال سنحتاج إلى مفردات إضافية والتي ستأتي مع HTML6. إذا كنت تعتقد بأن الويب عبارة عن نظام وجب عليه أن يعمل بنفس الطريقة على مختلف المتصفحات، وعلى مختلف أنظمة التشغيل وعلى مختلفة الأجهزة وباختلاف اللغات، وإن كنت تظن بأن شيفرته يجب أن تكون متوفرة للقراءة، وبأننا يجب أن يكون بمقدورنا القيام بمختلف العمليات عليه (القدرة على التغيير، والدمج، والقابلية للوصول، والقابلية للأرشفة ولإعادة الاستخدام) فإنه يجب علينا أن نضمن بأننا نستخدم الأدوات الدلالية التي في حوزتنا بشكل صحيح، وهو ما يضمن بأننا سنستفيد جميعا من الأمر. ترجمة –وبتصرف- للمقال HTML5 Semantics لصاحبه Bruce Lawson. اقرأ أيضًا دليل تعلم لغة HTML دليل تعلم البرمجة
  11. تطرقنا في المقال السابق إلى نبذة عن تاريخ نماذج HTML5 إضافة إلى جُملة من خصائصها الجديدة. سنتطرق في هذا المقال إلى أنواع الحقول الجديدة التي أضافتها HTML5 إلى النماذج. مثلما سنلاحظه طيلة هذا المقال أيضا فإن هذه المميزات الجديدة ستُسهل المهمة على المُطورين وستقدم تجربة أفضل للمستخدم. وكما سبق وأن أشرنا إليه في المقال السابق فإنه يُمكن الشروع في استخدام كل هذه الميزات منذ الآن. أنواع الحقول الجديدةأضافت HTML5 13 نوعا جديدًا من الحقول، سنقوم باستعراضها أولا ومن ثم سنشرح لماذا يجب عليك الشروع في استخدامها في مشاريعك. لاستخدام هذه الحقول الجديدة فائدتان، أولاهما هو تقليص زمن التطوير الذي تحتاجه لإنهاء تطبيقك، وثانيهما هو تقديم تجربة استخدام أفضل. الحقول الجديدة التي سنستعرضها في هذا المقال هي كالتالي: searchemailurltelnumberrangedatemonthweektimedatetimedatetime-localcolorsearchلا يوجد أفضل من هذا الحقل للشروع في استعراض خواص هذه الحقول الجديدة. ليس المقصود بالبحث هنا المحركات الشهيرة كـ Google، Yahoo أو Bing، بل نقصد حقل البحث الذي استعملته على أحد مواقع التجارة الإلكترونية، على ويكيبيديا أو على مُدونتك الشخصية. وقد تكون هذه الحقول (حقول البحث بشكل عام) هي الحقول الأكثر استعمالا على الويب، إلا أننا نستعملها بشكل لا يدل فعليا على وظيفتها، حيث أننا ألفنا إنشاء حقول البحث على النحو التالي: <input type="text" name="search"> لكن ماذا لو كان بإمكاننا القيام كتابتها على النحو التالي: <input type="search" name="search"> وهو ما يُمكن فعلا القيام به باستخدام HTML5، وهو ما يبدو أفضل بكثير، أليس كذلك؟ تظهر المُتصفحات حقول البحث بنفس مظهر الحقول النصية إلى غاية أن تشرع في الكتابة فيها، وحينها ستظهر علامة x صغيرة على الجانب الأيمن للحقل، والذي يسمح لك بمسح الحقل بمجرد النقر عليه، وهو أمر مماثل لما يحدث مع حقل البحث في مُتصفح Safari. حقل البحث كما يظهر على مُتصفح Safari على نظام Windows.الوضع على الهواتف الذكية أفضل بكثير، ألق نظرة على الصورة التالية والتي تُظهر حقل بحث على هاتف iPhone. لدى انتقال التركيز Focus إلى خانة البحث فإن لوحة مفاتيح خاصة تظهر، لاحظ زر search في الزاوية اليُمنى أسفل الشاشة، والتي تُعوض زر Go لما يكون الحقل نصيا فقط. حقل البحث على هاتف iPhoneكما سبق وأن لاحظناه مع الخصائص الجديدة في المقال السابق فإن المُتصفحات التي لا تفهم/تدعم هذا الحقل تُوفر تراجعا رشيقا له graceful degradation، وهو ما يحدث مع جميع الحقول التي سنتطرق إليها في هذا المقال. إذا لم يستطع المُتصفح فهم type="search" فإنه سيقوم بتعويضه بـ type="text"، وهو ما يعني بأنك لن تخسر أي شيء باستخدامك لهذا الحقل، بل العكس كل العكس، حيث أنك تُوفر تحسينا تدريجيا progressive enhancement وتُوفر لزوار موقعك تجربة مُستخدم أفضل. كما نعلم جميعا فإن ملء حقول نموذج ليس بالأمر المُمتع وبالتالي فإن أي تحسين يُمكن أن ندخله عليها مُرحب به. emailمن حيث المظهر لا يملك التفريق ما بين حقل email وما بين الحقول النصية العادية، ويستعمل هذا الحقل لإدخال عنوان بريد إلكتروني (أو أكثر). لكن من حيث الاستخدام ولدى إضافة خاصية required إلى هذا الحقل فإن المُتصفح سيقوم حينها من التحقق من أن النص الذي تم إدخاله هو فعلا عُنوان بريد إلكتروني صحيح من حيث بُنيته. بطبيعة الحال التحقق الذي يقوم به المُتصفح هو مُجرد تحقق بدائي حيث يتحقق من وجود كل من @ و النقطة في العنوان كما أنه لا يسمح بوجود المسافات. يدعم هذه الخاصية كل من Opera 9.5+، Firefox 4+، IE10 وChrome 5+، وتُظهر المُتصفحات رسالة خطأ إن كان العنوان الذي تم إدخاله غير صحيح البُنية. بإمكانك التحكم في مظهر الحقل بعد ملئه وذلك باستخدام أشباه الفئة :valid و :invalid أو :required مثلما يشرحه هذا المقال. <input type="email" name="email" required>رسالة خطأ في حقل email كما يظهر على مُتصفح Opera.تُشير مواصفات HTML5 إلى أنه يُمكن إدخال أكثر من عنوان بريد إلكتروني في هذا الحقل، مما يعني بأن يُمكنك استخدام خاصية multiple مع حقول البريد الإلكتروني (type="email") أيضا، وهو ما يذكرك بمقدار شفرات JavaScript التي كان يتوجب عليك كتابتها بنفسك لو كنت تقوم بعمليات التحقق هذه بنفسك. لمزيد من التفاصيل حول التحكم في مظهر حقول النماذج بالاستعانة بأشباه الأصناف pseudo-classes يُرجى الاطلاع على هذا المقال على موقع A List Apart. ملاحظة: لدى كتابة هذه السطور لا تزال بعض المُتصفحات تُعاني من نقائص لدى التحقق من عناوين البريد الإلكتروني التابعة لأسماء نطاقات تستعمل حروفا غير لاتينية (كبعض أسماء النطاقات اليابانية)، حيث أن بعض المُتصفحات تعتبرها غير صحيحة البُنية. خذ على سبيل المثال التالي: <input type="email" name="email" value="gordo@日本.jp">والتي تعتبرها كل من متصفحات Firefox (تم تصحيح الوضع في Firefox)، Safari، IE أو Chrome غير صحيحة البُنية (يقبل مُتصفح Opera هذا العنوان)، إلا أن Kyle Barrow وجد طريقة لحل هذا المُشكل وذلك باستخدام حقل نصي عادي والاستعانة بخاصية pattern على النحو التالي: <input type="text" name="email" value="gordo@日本.jp" pattern="[^ @]*@[^ @]*">هناك حل آخر إن أردت الإبقاء على type="email" وذلك باستخدام formnovalidate مع زر إرسال النموذج على النحو التالي (هذه الطريقة ستضمن بأن المُتصفح لن يقوم بالتحقق مما يتم إدخاله في حقل البريد الإلكتروني وهو ما أمر قد لا ترغب فيه): <form action="process.php"> <label for="email">Email:</label> <input type="email" name="email" value="gordo@日本.jp"> <input type="submit" formnovalidate value="Submit">كما يُمكن استخدام خاصية novalidate مع النموذج على النحو التالي: <form action="process.php" novalidate> <label for="email">Email:</label> <input type="email" name="email" value="gordo@日本.jp"> <input type="submit" value="Submit">دعونا من هذه المشكل ولنعد إلى ما سبق وأن تحدثنا عنه بخصوص منافع حقول HTML5 الجديدة، والتي هي –كما سبق ذكره أيضا- تقليص وقت التطوير وتحسين تجربة المُستخدم. ألقوا نظرة على المثال السابق لكن باستخدام iPhone مثلا، سيظهر لك أمر مماثل للصورة التالية: يُظهر iPhone لوحة مفاتيح خاصة مع حقول البريد الإلكترونيهل لاحظت الاختلاف هذه المرة؟ ركز على السطر السُفلي في لوحة المفاتيح ستجد بأن هناك زرا خاصا بـ @ وآخر خاصا بالنقطة . وهما زران ستحتاجهما لدى كتابة عناوين بريد إلكتروني. وكما سبق ذكره مع حقول search فإنه لا يوجد أي جانب سلبي لاستخدام هذا الحقل (type="email") من الآن، حيث أن المُتصفحات التي لا تدعمه ستقوم بتعويضه بحقل نصي عادي (type="text")، وفي باقي المُتصفحات سيحصل الزائر على تجربة مستخدم أفضل. urlتُخصص حقول url مثلما قد تتوقعه لعناوين الويب. تقبل هذه الحقول استخدام خاصية multiple معها للسماح بإدخال أكثر من عنوان واحد. ومثلما هو الحال مع حقول البريد الإلكتروني فإن المُتصفحات تقوم بعملية تحقق بسيطة من مُحتوى هذا الحقل، ومن ثم تعرض رسالة خطأ إن كان بُنية العنوان غير صحيحة، ويتم ذلك عبر التحقق من وجود بعض المحارف الخاصة كـ / ، النقاط، المسافات مع إمكانية التحقق من لاحقة العنوان top-level domain كـ .com مثلا. يتم استخدام حقول url على النحو التالي: <input type="url" name="url" required>ومن جديد سنلقي نظرة على نتيجة صفحة تحتوي هذا الحقل باستخدام iPhone. مثلما تلاحظونه في الصورة التالية فإن المُتصفح يُظهر لوحة مفاتيح خاصة ليسهل مهمة الكتابة على المُستخدم، حيث تم استبدال زر المسافة بأزرار لكل من الـ /، النقطة و زر خاص بـ .com (يكفي الضغط مطولا عليه لتظهر لواحق أُخرى كـ .org أو .net). يُظهر iPhone لوحة مفاتيح خاصة مع حقول عناوين الويبtelتختلف حقول tel عن حقول email أو url بكونها لا تعتمد أي نمط مُعين بحكم أن أرقام الهواتف تختلف باختلاف بلدانها وهو ما يجعل من مهمة التحقق من الأرقام في غاية الصعوبة، عدى السماح باستخدام الأرقام فقط مع إمكانية استخدام مُحرف +. بطبيعة الحال يبقى بإمكانك التحقق من رقم الهاتف إن أردت إن كنت تعرف بأن الأرقام التي سيتم إدخالها تتبع نمطا مُعينا، لكن يجب عليك القيام بذلك على جانب الخادوم من تطبيقك. يتم استخدام حقول tel على النحو التالي: <input type="tel" name="tel" id="tel" required>من جديد فإن هواتف iPhone تتعرف على حقول أرقام الهواتف لكن هذه المرة يستعرض المُتصفح لوحة مفاتيح مُختلفة كُلية، حيث يتم استخدام لوحة أرقام الهواتف، وهو ما يحدث أيضا على بعض هواتف Android (مثل هاتف HTC Desire والذي يظهر في الصورة أدناه). ظهور لوحة أرقام الهاتف ستمكن المُستخدم من إدخال رقم هاتفه بشكل أسرع. يقوم iPhone وبعض هواتف Android بتغيير لوحة المفاتيح بشكل كبير لدى استخدام حقول أرقام الهواتف.numberمثلما هو ظاهر من اسمه، يتم استخدام حقل number مع الأرقام. ومثلما هو عليه الحال مع أغلب هذه الحقول الجديدة فلقد كان مُتصفح Opera السباق في دعمها. يظهر هذا الحقل على كل من Opera، Safari وChrome على هيئة spinbox حيث أنه يمكن النقر على سهمي فوق وتحت لتغيير قيمة الحقل. أما على Firefox وIE10 فيظهر الحقل كمجرد حقل نصي عادي. حقل number كما يظهر على مُتصفح Operaيُمكن استخدام خصائص min، max وstep مع الحقول الرقمية ما يسمح بالتحكم في القيم القصوى والدنيا للحقل إضافة إلى "الخطوة" التي يتم الانتقال بها لدى النقر على زري فوق وتحت، إضافة إلى إمكانية التحكم في القيمة القياسية عبر استخدام خاصية value. المثال التالي يُوضح كيفية القيام بذلك: <input type="number" min="5" max="18" step="0.5" value="9" name="shoe-size">في هذا المثال يُمثل min القيمة الدنيا المُمكنة التي يُمكن للحقل قبولها، max تُمثل القيمة القصوى المُمكنة. لدى الوصول إلى هاتين القيميتن فإنه سيتم تعطيل السهم المسؤول عن ذلك وبالتالي فإنه لا مجال للذهاب أعلى القيمة القُصوى أو أدنى من القيمة الدنيا*. أما step فهي الخُطوة التي يتم الانتقال بها لدى النقر على السهمين والتي تأخذ 1 كقيمة قياسية، وهو ما يعني بأنه يمكن استخدام قيم سالبة أو استخدام خطوات مثل 0.5 أو5**. أما value فهي خاصية ألفنا استخدامها مع HTML4. كل هذه الخواص ليست إجبارية. *: لم يتم تعطيل الأسهم لدى تجربتي للحقل على كل من Safari وOpera. **: لدى تجربتي لقيم سالبة قام كل من Opera وSafari باستخدام القيمة القياسية 1 للخطوة بدل القيمة السالبة. في مقابل طريقة عرض Opera للحقول الرقمية، لا يقوم كل من iPhone و بعض هواتف Android بعرضها سوى كحقول نصية عادية، لكن يقوم كلاهما باستخدام لوحة مفاتيح خاصة. حقل number كما يظهر على كل من iPhone وHTC Desireلجعل iPhone يستخدم لوحة أرقام الهواتف مثلما رأينا مع حقول الهواتف، اكتشف Chris Coyier صاحب موقع CSS Tricks خدعة تساعد في القيام بذلك، حيث أنه بدل استخدام type="number" فإنه يكفي استخدام حقل نصي type="text" وإضافة خاصية pattern بحيث نجعله لا يقبل سوى الأرقام مثلما هو موضح في المثال التالي. هذا الحل ليس مثاليا، لكنه يحل الُمشكل. يُمكنكم الإطلاع على نتيجة ذلك في هذه الفيديو القصيرة. <input type="text" pattern="[0-9]*" name="shoe-size">هذه التقنية من شأنها أن تصبح "مهجورة" obsolete بعد اعتماد خاصية inputmode والتي تمت إضافتها مؤخرا إلى مواصفات HTML5. هذه الخاصية من شأنها أن تُحدد طريقة ملء الحقل الأنسب للمستخدم. لدى استخدام هذه الخاصية فإنه سيصبح بالإمكان الاختيار ما بين الأرقام، الحروف اللاتينية، عناوين البريد الإلكتروني أو Kana (والتي يبدو بأنها خاصة باللغة اليابانية). rangeحقل range مُشابه لحقل number مع نكهة إضافية، حيث أنه يُمثل قيمة عددية محصورة ضمن نطاق مُعين (range). قد تتساءل عن الفرق ما بين هذين الحقلين، الفرق بسيط وهو أن قيمة الحقل ليست بتلك الأهمية التي هي عليها قيمة الحقل مع number، كما أن المُتصفح يوفر آلية أكثر سهولة في التحكم فيه. يتم إظهار حقل range على كل من مُتصفحات Opera، Safari، IE10 وChrome على هيئة slider (انظر الصورة أدناه). يُظهر مُتصفح IE10 لدى تحريك زر الحقل القيمة التي تم اختيارها. يقوم مُتصفح Opera بإظهار الـ slider بشكل عمودي إن تم إعطاء قيمة للطول أكبر من قيمة العُرض له في ملف CSS. المثال التالي يُوضح كيفية استخدام حقل rang للقيام مثلا بتحديد مدى مهارة المُستخدم في مجال مُعين على سُلم من 1 إلى 100، حيث نقوم بتحديد القيم الدنيا والقُصوى من خلال الخاصيتين min وmax. بإمكاننا أيضا تحديد قيمة قياسية لهذا الحقل بالاستعانة بخاصية value. <input id="skill" type="range" min="1" max="100" value="0">حقل range على مُتصفح Chromeملاحظة: إن كنت تبحث عن طريقة لتوفير تراجع رشيق لحقول rang على المُتصفحات التي لا تدعمها، فيُمكنك القيام بذلك باستخدام هذه الطريقة التي أتى بها Remy Sharp. dates و timesإن سبق لك أن حجزت أو اشتريت تذاكر على الإنترنت فإنك من دون شك قد تعاملت مع data picker لاختيار التاريخ الذي توده، وربما قد سبق لك وأن استخدمت ذلك في أحد مشاريعك. عادة ما يتم توفير ذلك باستخدام JavaScript وبالتحديد مكتبة jQuery، Dojo أو YUI. قد يكون تحميل مكتبة بأكملها وإحدى إضافاتها من أجل القيام بذلك قرارًا غير صائب، لكن مع HTML5 فإنه يُمكن القيام بذلك من دون أية إضافات. ليس هذا فحسب فما تُقدمه HTML5 لا تسمح باختيار التاريخ فقط، بل يُمكن أيضا اختيار الأسبوع، الشهر، الوقت، التاريخ، وحتى التاريخ التابع لمنطقة زمنية مُعيّنة. يُمكن القيام بذلك على النحو التالي: <input id="dob" name="dob" type="date">يُمكنك الذهاب إلى أبعد من ذلك باستخدام خاصيتي min وmax لتضمن بأن التاريخ الذي يختاره المُستخدم يقع ضمن نطاق تقوم بتحديده. <input id="startdate" name="startdate" min="2012-01-01" max="2013-01-01" type="date">وكما حول الحال مع العديد من أنواع الحقول فإن مُتصفح Opera يتميز عن غيره بدعمها لهذا الحقل بشكل جيد. دعونا نلقي نظرة على الكيفية التي تظهر فيها هذه الحقول على مُتصفح Opera: dateالصورة التالية تُبين الحالة التي يظهر عليها حقل date على الإصدار 10.5 من مُتصفح Opera لا يقتصر استخدام هذا الحقل على الأجهزة المكتبية فقط، تقوم أجهزة BlackBerry ومتصفح Chrome على نظام Android باستخدام date pickerالخاص بها لدى استخدام حقل date. monthالصورة التالية توضح كيف تظهر حقول month على مُتصفح Opera والتي يُمكن استخدامها مثلا لإدخال شهر انتهاء صلاحية بطاقة دفع إلكتروني. يُمكن استخدام حقل month على النحو التالي: <input id="expiry" name="expiry" type="month" required> weekيُمكن أيضا تمكين المُستخدم من اختيار أسبوع مُعين في الشهر على النحو التالي: <input id="vacation" name="vacation" type="week">لاحظوا في الصورة التالية كيف يقوم مُتصفح Opera بإبراز/تظليل الأسبوع الذي يتم اختياره. timeالصورة التالية تُبين الحالة التي يظهر عليها حقل time على متصفح Opera والذي يُمكن استخدامه على النحو التالي: <input id="exit-time" name="exit-time" type="time"> datetimeيُمكن دمج كلا من حقلي date وtime لينتج لنا حقل datetime والذي يُستعمل لتحديد التاريخ والوقت معا على النحو التالي: <input id="entry-day-time" name="entry-day-time" type="datetime"> datetime-local وأخيرا وليس آخرا، تظهر الصورة التالية كيف يسمح HTML5 لنا بالتحكم بشكل أدق في آلية اختيار التاريخ والوقت ضمن المنطقة الزمنية المحلية باستخدام datetime-local على النحو التالي: <input id="arrival-time" name="arrival-time " type="datetime-local"> مشاكل مع date و timeهناك على الأقل مشكلان رئيسيان مع حقول الوقت والتاريخ. الأول يخص عدم التمكن من كتابة التاريخ يدويا بشكل مباشر (على المتصفحات التي تدعمها) رغم أنه يمكن التحكم في هذه الحقول باستخدام لوحة المفاتيح، حيث أنه وفي الحالات التي يقوم المستخدم بملء نفس النموذج عدة مرات فإنه هذه العملية ستكون أسرع لو تم تمكينه من كتابة التواريخ يدويا. المشكل الثاني يكمن في عدم مقدرتنا في التحكم في مظهر الـ data Picker. الاعتقاد السائد هو أن هذا الأمر محمود، حيث سيحصل المستخدم على نفس تجربة المستخدم ونفس المظهر على جميع المواقع التي يزورها، إلا أن الشركات -ومن دون شك- سترغب في توفير Data Picker خاص بها. قامت كل من Safari5 و Chrome5 بدعم هذه الحقول إلا أن مظهرها ليس جيدا. يجب أن تكون حقول date على الشكل التالي: YYYY-MM-DD وحقول datetime على الشكل الغريب التالي: YYYYMM-DDT00:00Z. ومثلما هو عليه الحال مع باقي أنواع الحقول الأخرى تقوم المتصفحات التي لا تدعم هذه الحقول بتجاهلها وتعويضها بحقول نصية عادية type="text". colorتسمح حقول color باختيار لون مُعين وإرجاع قيمته الست عُشرية Hex value. من المفترض أن يكون المُستخدم قادرا على إدخال قيمة اللون الذي اختاره أو أن يقوم باختيار اللون من لوحة Color Picker والتي يمكن أن تكون إما لوحة اختيار الألوان الخاصة بنظام التشغيل أو لوحة اختيار الألوان الخاصة بالمُتصفح. قام مُتصفح Opera 11 بدعم حقل الألوان بتوفيره جملة من الألوان القياسية إضافية إلى زر يوفر إمكانية اختيار ألوان أخرى، والذي -بمجرد النقر عليه- يُظهر لوحة اختيار الألوان الخاصة بنظام التشغيل. <input id="color" name="color" type="color">حقل الألوان على مُتصفح Opera على اليسار ونتيجة النقر على زر other على اليمين.في المقابل توفر بعض أجهزة BlackBerry دعما لحقول color حيث تقوم بإظهار لوحة اختيار الألوان المُبنية في الصورة التالية: خلاصةباستخدامك للحقول الجديدة الخاصة بـ HTML5 فأنت تقدم تجربة مستخدم أفضل لزوار موقعك، تحضر موقعك للعمل حسب معايير المستقبل، وتسهل من مهمة التطوير عليك. بطبيعة الحال ليس من المُمكن أن نتجاهل المُتصفحات التي لا تدعم هذه الخواص، إلا أنه من الممكن توفير دعم لها باستخدام JavaScript (ستجد تفاصيل حول الأمر بقراءتك للفصل السادس من كتاب Beginning HTML5 and CSS3). يُمكن لك أن تجد نموذجا تجريبيا يستخدم بعضا من الأمثلة التي استعرضناها في هذا المقال هنا. أشرنا خلال هذا المقال إلى المتصفحات التي تدعم كل من الحقول التي استعرضناها، لكن مع الإصدارات الجديدة لكل متصفح والتي يتم إطلاقها بوتيرات متسارعة فإنه من الصعب معرفة ما الذي يدعمه هذا المتصفح وما الذي لا يدعمه ذاك المتصفح، لكن إن أردت البقاء على اطلاع على ذلك فإنه يُمكنك ذلك عبر المواقع التالية: can I use …، FindMeByIP ومحرك بحث Wufoo الخاص بالـ HTML5. إذا فاتتك قراءة المقال السابق الذي يتحدث عن مختلف الخصائص الجديدة في نماذج HTML5 فيُمكن إيجاده هنا. ترجمة –وبتصرف- للمقال HTML5 forms input types لصاحبه Richard Clark.
  12. مما لا شك فيه هو أنك تتعامل على الأقل مع نموذج واحد على الويب كل يوم، سواء كان ذلك خلال استخدامك لمحرك بحثك المُفضل، تسجيلك للدخول إلى بريدك الإلكتروني، أو حتى الدخول إلى فيس بوك. يُعتبر التعامل مع النماذج Forms إحدى المهمات الأكثر شيوعا على الإنترنت. بحُكم أننا مصممون أو مطورون فإن تعاملنا مع النماذج يحوم حوله نوع من الرتابة والتكرار خاصة لما يتعلق الأمر بكتابة سكريبتات للتحقق من قيم الحقول. أضافت HTML5 العديد من أنواع المُدخلات، الخواص والعديد من العناصر إلى هذه النماذج. سنركز في هذا المقال على الخواص الجديدة التي أضافتها HTML5 فقط، وسنفرد مقالا آخر لأنواع المدخلات الجديدة لاحقا. كما سنلاحظه طيله هذا المقال، ستسهل عليك هذه الخواص الجديدة مهمتك وستقدم تجربة أمتع للمستخدم، وفوق كل هذا يُمكنك الشروع في استخدامها من الآن. لكن دعونا نبدأ باستعراض سريع لتاريخ النماذج. نبذة عن تاريخ نماذج HTML5قبل أن تصبح نماذج HTML5 على النحو الذي نعرفه الآن كانت في السابق مُجرد مواصفات specification أُطلق عليها اسم Forms 2.0 والتي أضافت جُملة من العناصر والمُدخلات الجديدة إلى النماذج. هذه المواصفات أطلقتها Opera وتولى تحريرها Ian Hickson الذي كان يعمل لديها حينها، قبل أن يتم تقديمها إلى W3C بداية 2005. تم الشروع في العمل على هذه المواصفات تحت مظلة W3C ثم تم دمجها مع مواصفات Web Applications 1.0 لإنشاء قواعد ما أصبح يُعرف لاحقا بمواصفات HTML5 التابعة لـ WHATWG. استخدام مبادئ تصميم HTML5أحد أفضل ميزات النماذج الخاصة بـ HTML5 تتعلق بكونها قابلة للاستعمال ابتداءًا من الآن، ولا حاجة لك للاستعانة بأية حيل، Shivs أو طرق مُلتوية للقيام بذلك، لكن ذلك لا يعني بأنها مدعومة الآن، حيث أنها تعطي نتائج رائعة على المتصفحات الحديثة التي تدعمها وتوفر "تراجعا رشيقا" (graceful degradation) على المتصفحات التي لا تفهمها، وهذا راجع بشكل أساسي إلى مبادئ تصميم HTML5، ونقصد هنا بالتحديد التراجع الرشيق وهو ما يعني بأنه لا يوجد أي دافع لعدم استخدام هذه الخواص في مشاريعك الحالية. خواص نماذج HTML5 الجديدةهناك 14 خاصية جديدة مُتعلقة بنماذج HTML5 والتي سنقوم باستعراضها في هذا المقال وهي كالآتي: placeholderautofocusautocompleterequiredpatternlistmultiplenovalidateformnovalidateformformactionformenctypeformmethodformtargetplaceholderأول هذه الخواص هي placeholder والتي تسمح لنا بإضافة نص توضيحي بنفس الطريقة التي كنا نعملها مع خاصية value في نماذج HTML4. يجب استخدام هذه الخاصية مع النصوص التوضيحية القصيرة فقط، ويُفضل الاستعانة بخاصية title لكل النصوص التوضيحية الأطول. الاختلاف الحاصل مُقارنة بالطريقة المُتبعة مع نماذج HTML4 هو أنه لا يتم استعراض النص إلا في حالة ما إذا كان الحقل فارغا ولم يستقبل "التركيز" Focus (يعني لم يتم اختياره بالنقر عليه مثلا أو بالانتقال إليه عبر Tab من حقل آخر)، وبُمجرد أن يستقبل الحقل التركيز فإن النص يختفي، وهو أمر مُشابه لحقل البحث الموجود على مُتصفح Safari مثلا. حقل البحث على متصفح Safari مع وبدون التركيز focusدعونا نُلقي نظرة على طريقة استخدام placeholder: <input type="text" name="user-name" id="user-name" placeholder="at least 3 characters">هذا كل ما في الأمر. قد يقول قائل: "وما الرائع في هذا الأمر؟ ألِفتُ القيام بنفس الأمر عبر استخدام JavaScript طيلة السنوات الماضية" وذلك أمر صحيح، لكن مع HTML5 تأتي هذه الخاصية مدعومة بشكل مُضمن في المُتصفح، مما يعني أنها ستعمل من دون أية سكربتات إضافية، وتعمل على جميع المتصفحات حتى ولو كان JavaScript مُعطلا عليها. دعم خاصية placeholder على متصفح Chrome مع ظهوره في الصورة الأولى واختفائه في الثانيةستقوم المتصفحات التي لا تدعم placeholder بتجاهله بكل بساطة، وبالتالي فإنها لن تقوم بإظهاره. باستخدامك لهذه الخاصية فإنك ستقدم تجربة مستخدم مُحسنة لزوار موقعك والذين تدعم مُتصفحاتهم هذه الخاصية، كما أنها تُعد موقعك للعمل وفق معايير المستقبل، بحكم أن كل المُتصفحات الحديثة تدعمها. ملاحظة: حاليا لا وجود لأية pseudo-class رسمية للتحكم في مظهر placeholder رغم ذلك فإن كلا من Mozilla (مُطورة متصفح Firefox) و WebKitتوفران آليات للتعامل مع ذلك (vendor prefixed properties) ويتعلق الأمر بكل من -mozplaceholder و –webkit-input-placeholder، وهو ما يُعطي الانطباع بأنه سيتم اعتماد pseudo-class للتحكم في مظهر placeholder في المُستقبل. لمعلومات أوفى حول الأمر يُمكنكم مُراجعة هذه الصفحة على القائمة البريدية الخاصة بـ WHATWG. autofocusتقوم autofocus تماما بالوظيفة الظاهرة من اسمها. إضافة هذه الخاصية لأي حقل من الحقول تُمكنه من الحصول على "التركيز" (Focus) بمجرد أن يتم تحميل الصفحة. ومثلما هو الحال مع placeholder فإنه كان بإمكاننا في السابق الوصول إلى نفس النتيجة التي نحصل عليها لدى استخدام autofocus إن نحن استعملنا بعض الـ JavaScript. إلا أن الطرق المُستعملة مع JavaScript تُعاني بعض النقائص، فعلى سبيل المثال لو شرع المُستخدم في ملء حقول النموذج قبل أن يتم تحميل السكربت فإنه سيتم إرجاعه (أو تحويل التركيز إلى الحقل الأول) بُمجرد أن يتم الفراغ من تحميل السكربت، وهذا ما يُرجح الكفة لصالح autofocus حيث أن هذه الخاصية (أي حصول أحد الحقول على التركيز) يتم بمُجرد الفراغ من تحميل الصفحة دون الحاجة إلى انتظار تحميل أي سكربتات إضافية. في المُقابل ننصح باستعمال خاصية autofocus بشكل حصري على الصفحات التي يكون النموذج محتواها الرئيسي فقط (مثل صفحة بداية مُحرك Google) وذلك لتفادي المشاكل التي قد تترتب عن ذلك والمُتعلقة بقابلية الاستخدام usability. بما أن الأمر هنا يتعلق بخاصية منطقية boolean attribute (إن كان المُستند الذي تكتبه متوافقا مع XHTML5 فاقرأ الملاحظة أدناه) فإننا نستعملها على النحو التالي: <input type="text" name="first-name" id="first-name" autofocus>كل المتصفحات الحديثة تدعم خاصية autofocus ومثلما هو الحال مع placeholder فإنه لا يحدث أي شيء على المتصفحات التي لا تدعمها حيث أنها تقوم بتجاهله. ملاحظة: العديد من خواص HTML5 الجديدة هي خواص منطقية (Boolean attribute)، وهو ما يعني بأنها خواص يتم أخذها بالحسبان إن كانت حاضرة ويتم تجاهلها إن لم تحضر. إلا أنه من المُمكن كتابتها بعدة طرق في HTML5 على النحو التالي: autofocus autofocus="" autofocus="autofocus"في المُقابل إن كان مُستندك متوافقا مع XHTML5 فإنه يجب عليك استعمال الصيغة التالية: autofocus="autofocus" autocomplete تُساعد خاصية autocomplete المُستخدِمَ على ملء حقوله بناء على ما قام بإدخاله من قبل في نفس الحقل. هذه الخاصية ليست بالجديدة حيث كان بالإمكان استخدامها منذ IE5.5 وقد تم اعتمادها مؤخرا بشكل رسمي ضمن HTML5. الحالة القياسية (default state) لهذه الخاصية هو on وهو ما يعني بأنك لست في حاجة إلى استخدامها بشكل صريح في حقولك. في المُقابل إن أردت أن يقوم المُستخدم بملء حقوله بنفسه في كل مرة يتعامل فيها مع نموذجك (يعني أنك ترغب في أن لا يتم ملء الحقول بشكل آلي) فإنه يجب عليك استخدام الخاصية على النحو التالي: <input type="text" name="tracking-code" id="tracking-code" autocomplete="off">إن توفرت خاصية autocomplete في حقل ما فإن المتصفح سيأخذ حالتها في الحسبان عوض حالة هذه الخاصية في عنصر form الذي يحتوي الحقل (بعبارة أخرى خاصية autocomplete في أي حقل تقوم بعمل override لنفس الخاصية إن كان form يستخدمها). requiredلا يبدو بأننا في حاجة لشرح ما الذي تقوم به هذه خاصية required حيث أنها تقوم تماما بالوظيفة التي نفهمها من اسمها. لدى إضافة هذه الخاصية لأي حقل من الحقول فإن المُتصفح سيطلب من المُستخدم ملء الحقل قبل أن يتمكن من إرسال النموذج، وهذا ما يسمح باستبدال آلية التحقق من الحقول التي عادة ما نقوم بها باستخدام JavaScript، وهو ما يُحسن من تجربة المُستخدم قليلا كما أنه يُجنبنا عناء التحقق من الحقول بأنفسنا. خاصية required هي خاصية منطقية ويتم استخدامها بنفس طريقة استخدام autofocus على النحو التالي: <input type="text" id="given-name" name="given-name" required>لا يدعم خاصيةَ required سوى المتصفحات التالية: Opera 9.5+، Firefox 4+، Safari 5+، IE10 و Chrome5+، وعليه فإنك قد تحتاج إلى كتابة سكربت للتحقق من المدخلات على المُتصفحات/الإصدارات التي لا تدعمها (خاصة IE). تُظهر كلا من متصفحات Opera، Chrome وFirefox رسالة خطأ في حال جرب المُستخدم إرسال النموذج من دون ملء الحقول المطلوبة، وتظهر رسائل الخطأ هذه مكتوبة بنفس اللغة التي يستخدمها المُستخدم على المتصفح (يعني إن كنت تستخدم الإصدار الفرنسي من متصفحك المُفضل فتسظهر رسالة الخطأ بالفرنسية). لا يقوم مُتصفح Safari بإظهار رسالة خطأ، وإنما ينقل التركيز Focus إلى الحقل المعني بالخطأ. حقل يملك خاصية required ورسالة الخطأ التي تطالب بملئه على مُتصفح operaيتحكم كل مُتصفح في مظهر رسالة الخطأ وبالتالي فإن شكلها يختلف من مُتصفح إلى آخر، لكنه من غير المُمكن حاليا التحكم في هذا المظهر عبر CSS، إلا أن Chrome تُوفر آلية للقيام بذلك والتي يُمكن التعرف عليها بقراءة هذا المقال. يبقى التحكم في مظهر الحقل المعني برسالة الخطأ مُمكنا باستخدام شبه الفئة required: إضافة إلى إمكانية تغيير رسالة الخطأ ومظهرها بالاستعانة بـ setCustomValidity الخاصة بـ JavaScript. هناك أمر واحد يجب أخذه بالحسبان وهو أن عملية التحقق التي يقوم بها المُتصفح لدى استخدامك لهذه الخاصية لا تُغنيك من القيام بعملية تحقق على جانب الخادم من تطبيقك. للمزيد حول التحكم في مظهر نماذج HTML5: HTML5 Form Validation On the styling of forms patternهذه الخاصية من شأنها أن تثير اهتمام الكثير من المُطورين. تقوم خاصية pattern بالتحقق من توافق قيمة الحقل مع تعبير قياسي (regular expression) خاصة بـ Javascript. تسمح هذه الخاصية من التحقق من أنماط مُعينة مما يتيح مثلا التدقيق في معرفات مُنتجات، أرقام فواتير، أرقام هواتف وما إلى ذلك. يُمكنك استخدام pattern للتحقق من أي نمط تريده. إليكم مثالا حول كيفية استخدامها: <label>Product Number: <input pattern="[0-9][A-Z]{3}" name="product" type="text" title="Single digit followed by three uppercase letters."/> </label>النمط المُبين في هذا المثال ينص على أن مُعرف كل منتج يجب أن يبدأ برقم واحد متبوع بثلاث حروف كبيرة (uppercase letters). يُمكنك أن تجد قائمة بأكثر الأنماط شيوعا على موقع HTML5 Pattern. مثلما هو الحال مع required فإن المتصفحات الوحيدة التي تدعم pattern هي: Opera 9.5+، Firefox4+ ،Safari5+، IE10 وChrome5+، لكن مع التطور السريع لسوق المتصفحات فإنه من المحتمل أن تدعمها باقي المتصفحات لاحقا. خاصية list والعنصر datalistتسمح خاصية list بربط حقل مُعين بقائمة من الخيارات. يجب أن تكون قيمة الخاصية list متطابقة مع خاصية ID المُتعلقة بالعنصر datalist الموجود في نفس الصفحة. تُعتبر datalist عنصرا جديدا في HTML5 والتي تُمثل قائمة من الخيارات التي يُمكن ربطها بأحد عناصر النموذج، والتي تُعطي نتيجة مشابهة لما يحدث لدى استخدامك لخانة البحث على مُتصفحك، حيث يتم عرض خيارات لدى كتابة الكلمات المُراد البحث عنها. اقتراحات محرك بحث Google على متصفح Safariالمثال التالي يُبين كيفية استخدام كلا من list وdatalist: <label>Your favorite fruit: <datalist id="fruits"> <option value="Blackberry">Blackberry</option> <option value="Blackcurrant">Blackcurrant</option> <option value="Blueberry">Blueberry</option> <!-- … --> </datalist> If other, please specify: <input type="text" name="fruit" list="fruits"> </label>يُمكن توفير تراجع أكثر رشاقة (superior graceful degradation) من مُجرد توفير عنصر option وذلك عبر إضافة عنصر select داخل الـ datalist. هذه الطريقة التي ابتكرها Jeremy Keith تتوافق بشكل مثالي مع مبادئ تصميم HTML5 التي تحدثنا عنها من قبل: <label>Your favorite fruit: <datalist id="fruits"> <select name="fruits"> <option value="Blackberry">Blackberry</option> <option value="Blackcurrant">Blackcurrant</option> <option value="Blueberry">Blueberry</option> <!-- … --> </select> If other, please specify: </datalist> <input type="text" name="fruit" list="fruits"> </label>المتصفحات التي تدعم List وdatalist هي: Opera 9.5+ (الصورة المُبينة أسفله)، Chrome 20+، IE10، وFirefox4+. عُنصر datalist كما يظهر على مُتصفح Operamultipleيُمكننا أن نُحسن المثال السابق عبر الاستعانة بخاصية multiple والتي تسمح للمستخدم باختيار أكثر من قيمة واحدة من الـ datalist، ليصبح المثال السابق كالتالي: <label>Your favorite fruit: <datalist id="fruits"> <select name="fruits"> <option value="Blackberry">Blackberry</option> <option value="Blackcurrant">Blackcurrant</option> <option value="Blueberry">Blueberry</option> <!-- … --> </select> If other, please specify: </datalist> <input type="text" name="fruit" list="fruits" multiple> </label>لا يقتصر استخدام multiple مع datalist فقط، بل يُمكن استخدامها مع عدة حالات أخرى خاصة إذا ما تعلق الأمر مثلا بإدخال عناوين بريد إلكتروني أو لدى رفع أكثر من ملف كما هو مُبين في المثال التالي: <label>Upload files: <input type="file" multiple name="upload"></label>يدعم multiple المُتصفحات التالية: Firefox3.6+، Safari4+، Opera11.5+، Internet Explorer 10 وChrome4+. تعليق المُترجم: لم يتسن لي تجربة آلية عمل multiple مع غير الملفات (يعني الحقول النصية فقط)، إن كنت تعلم كيف يتم القيام بذلك فاترك تعليقا حول الأمر تُبين فيها ذلك. novalidate وformnovalidateتُشير الخاصيتان novalidate وformnovalidate بأنه يجب على المُتصفح أن لا يقوم بالتحقق من محتويات حقول النموذج لدى إرساله. كلا الخاصيتين منطقيتان boolean. يُمكن استخدام formnovalidate مع كل من أزرار الإرسال submit أو حقول الصور، أما خاصية novalidate فلا يُمكن استخدامها سوى مع العنصر form. قد تتساءل ما هي الفائدة المرجوة من عدم التحقق من محتويات الحقول لدى إرسال النموذج، يُمكن استخدام formnovalidate على زر لحفظ بيانات نموذج مُعين دون الحاجة إلى التحقق من محتوياته (لإكمال النموذج لاحقا على سبيل المثال)، في هذه الحالة سنتمكن من حفظ النموذج بالرغم من أنه غير مُكتمل الحقول رغم أن هذه الحقول مطلوبة required لدى القيام بإرسال النموذج للمعالجة النهائية. أما فيما يخص novalidate فُيمكن استخدامها مثلا في الحالات التي نود أن لا يتم التحقق من حقول النموذج لكننا نود الاستفادة من التحسينات الخاصة بتجربة المُستخدم والتي تقدمها خواص HTML5 الجديدة (نود مثلا أن يتم إظهار لوحة مفاتيح رقمية للمستخدمين عبر الهواتف الذكية لدى انتقالهم إلى حقل مُعين لكن لا نود أن يتم اقتصار ما يقومون بإدخاله على الأرقام فقط). المثال التالي يُبين كيفية استخدام formnovalidate: <form action=”process.php”> <label for=”email”>Email:</label> <input type=”email” name=”email” required> <input type=”submit” formnovalidate value=”Submit”> </form>المثال التالي يخص حول استخدام novalidate: <form action=”process.php” novalidate> <label for=”email”>Email:</label> <input type=”email” name=”email” required> <input type=”submit” value=”Submit”> </form>form يتم استخادم خاصية form لربط كل من input ،select أو textarea بنموذج مُعين (النموذج الذي تتبعه). استخدام خاصية form يسمح للمكونات سابقة الذكر أن لا تكون ذُرّية مباشرة (direct children) للنموذج الذي تنتمي إليه، مما يسمح بوضعه في مكان آخر داخل نفس الصفحة. قد يكون الاستخدام الأكثر شيوعا لهذه الخاصية هو ربط الأزرار الموجودة داخل جداول بالنماذج. <input type="button" name="sort-l-h" form="sort"> formaction، formenctype، formmethod وformtargetلدى كل من Formaction، formenctype، formmethod وformtarget ما يُقابلها من خصائص form والتي سبق لك أن تعاملت معها في HTML4. تم استحداث هذه الخصائص بشكل أساسي لأنه من المُمكن أن نحتاج في نماذجنا actions مختلفة تختلف باختلاف الأزرار التي نقوم بإرسال النموذج من خلالها بدل أن نقوم بإنشاء أكثر من نموذج للقيام بذلك. إليكم وصفا سريعا لهذه الخصائص الجديدة: formactionتحدد خاصية formaction الملف أو التطبيق الذي سيتولى مهمة استقبال النموذج لدى إرساله حيث أنها تشغل نفس الوظيفة التي تشغلها خاصية action التي نضيفها إلى العنصر form. يقتصر استخدامها على الأزرار فقط سواء كانت submit أو صورا (type="submit" أو type="image"). لدى إرسال النموذج يقوم المُتصفح بالتحقق أولا من وجود خاصية formaction وفي حال ما إذا لم يجدها يقوم بالبحث حينها على الخاصية action. <input type="submit" value="Submit" formaction="process.php">formenctypeتُحدد خاصية formenctype الطريقة التي يتم ترميز البيانات باستخدام POST. لهذه الخاصية نفس مفعول خاصية enctype الخاصة بالعنصر form ويقتصر استخدامها على الأزرار فقط سواء كانت submit أو صورا (type="submit" أو type="image"). إذا لم يتم تضمين هذه الخاصية فإنه يتم اعتماد قيمتها القياسية application/x-www-formurlencoded . <input type="submit" value="Submit" formenctype="application/x-www-form-urlencoded">Formmethodتُحدد خاصية formmethod فعل HTTP المُستخدم لإرسال النموذج (GET، POST، PUTأو DELETE)، لهذه الخاصية نفس مفعول خاصية method الخاصة بالعُنصر form، ويقتصر استخدامها على الأزرار فقط سواء كانت submit أو صورا (type="submit" أو type="image"). <input type="submit" value="Submit" formmethod="POST">Formtargetتُحدد خاصية formtarget النافذة التي ستظهر نتيجة النموذج، لهذه الخاصية نفس مفعول خاصية target الخاصة بالعُنصر form، ويقتصر استخدامها على الأزرار فقط سواء كانت submit أو صورا (type="submit" أو type="image"). <input type="submit" value="Submit" formtarget="_self">خلاصةاستعرضنا في هذا المقال جُملة من الخصائص الجديدة التي تساعد على توفير تجربة مُستخدم أفضل للزائر وتساعدك على تقليص زمن كتابة نماذجك، لا تزال هناك بعضٌ من الخصائص الجديدة والتي سنتسعرضها في مقال قادم مع جُملة من أنواع المُدخلات الجديدة. يُمكنك أن تجد نموذجا تجريبيا يستخدم بعضا من الأمثلة التي استعرضناها في هذا المقال هنا. أشرنا خلال هذا المقال إلى المتصفحات التي تدعم الخواص التي استعرضناها، لكن مع الإصدارات الجديدة لكل متصفح والتي يتم إطلاقها بوتيرات متسارعة فإنه من الصعب معرفة ما الذي يدعمه هذا المتصفح وما الذي لا يدعمه ذاك المتصفح، لكن إن أردت البقاء على اطلاع فعليك زيارة المواقع التالية: can I use …، FindMeByIP ومحرك بحث Wufoo الخاص بالـ HTML5. ترجمة –وبتصرف- للمقال HTML5 forms introduction and new attributes لصاحبه Richard Clark هذا المقال عبارة عن مُقتطف من الفصل السادس من كتاب Beginning HTML5 and CSS3: The Web Evolved. تعليق المترجم: قد تكون ترجمة بعض المُصطلحات التقنية في هذا المقال غير دقيقة، أو أن هناك ترجمات أفضل لها، إن لاحظت أيا منها فلا تتردد في مراسلتي أو الإشارة إليها في التعليقات.
  13. Modernizr هي مكتبة JavaScript تقوم باكتشاف ميزات HTML5 وCSS3 التي يدعمها متصفح الزائر. قيامها بذلك بُتيح للمطور معرفة الخواص والتقنيات الجديدة المدعومة بشكل مُضمن في المتصفح والتي بإمكانه استخدامها بشكل مُباشر إضافة إلى تلك التي لا يدعمها، والتي يجب عليه أن يدعمها بطريقة تراجعية Fallback. يُطلق على هذه التقنية اسم اكتشاف الميزات (الخاصة) والتي تُعتبر تقنية أنجح بكثير من تقنية "التعرف على المتصفح" (browser sniffing). تُعتبر Modernizr في غاية الأهمية لدى استكشاف خواص CSS3 المدعومة على المتصفح، لكننا سنركز في هذا المقال على HTML5 فقط، رغم أن مبدأ عمل المكتبة هو نفسه مع كلي الأمرين. تجدر الإشارة إلى أن Modernizr لا تقوم بتعويض النقص الناتج عن عدم دعم المتصفح لبعض الخواص أو ما يُعرف بالـ Polyfills، كل ما تقوم بها المكتبة هو استكشاف إن كان المتصفح يدعم خاصية مُعينة من عدمه، لكنه يبقى بإمكانك استخدام Modernizr كجزء من آلية تعويض ذلك النقص. لا يدعم الإصدار الثامن من متصفح Internet Explorer والإصدارات التي تسبقه الخواص الجديدة للـ HTML5 بشكل قياسي، ولهذا إن احتجت دعم هذه المتصفحات فإنه يجب عليك تعويض هذا النقص ببعض الـ JavaScript. يُمكنك القيام بذلك باستخدام الشفرة التي سيلي استعراضها، كما يُمكنك القيام بذلك باستخدام HTML5 Shiv الخاصة بـ ‎@rem والتي تشمل جميع الخواص الجديدة. يساعدك Modernizr في القيام بذلك، وبالتالي فإن المرور عبر تضمين الـ Shiv غير ضروري. البداية بداية سنحتاج إلى ملف HTML: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Hello Modernizr</title> <script src="modernizr.js"></script> </head> <body> </body> </html> كما هو ظاهر في هذه الشفرة فإننا سنحتاج إلى ملف modernizr.js والذي يُمكنك بناء نسخة منه ومن ثم تحميله بناء على الخواص التي ترغب من التحقق من دعمها. يُمكنك القيام بذلك عبر اختيار Production (الصورة الأولى) ومن ثم اختيار تلك الخواص مثلما هو ظاهر في الصورة الثانية. هذا الأمر يسمح باستخدام ملف صغير الحجم لأننا لا نقوم بتضمين جميع الخواص التي يُمكن لـ Modernizr استكشافها. يُوفر الموقع نسخة تطوير خاصة بالمكتبة، لكنه قبل أن ترفع موقعك إلى خادمك الخاص فإنك ستحتاج إلى ملف Production الذي يستكشف الخواص التي تحتاج استكشافها فقط. خيارا تحميل Modernizr اختيار خواص ومن ثم بناء ملف Modernizr لاحظ أيضا في السطر الثاني في ملف HTML آنف الذكر وجود صنف no-js في وسم <html>. يقوم Modernizr باستبدال هذا الصنف بصنف js والذي يُمكن أن يكون له فائدة في ملف CSS الخاص بك. إلى جانب صنف js يُضيف Modernizr أصنافا لكل الخواص التي يدعمها المتصفح، وللخواص التي لا يدعمها يُضيف أصنافا تُسبق أسماؤها بـ no-. إليك مثالين عن الأصناف التي يُضيفها Modernizr على كل من متصفحي Chrome 16 و IE9: <html class="js flexbox canvas canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths"> <html class="js no-flexbox canvas canvastext no-webgl no-touch geolocation postmessage no-websqldatabase no-indexeddb hashchange no-history draganddrop no-websockets rgba hsla multiplebgs backgroundsize no-borderimage borderradius boxshadow no-textshadow opacity no-cssanimations no-csscolumns no-cssgradients no-cssreflections csstransforms no-csstransforms3d no-csstransitions fontface generatedcontent video audio localstorage sessionstorage no-webworkers no-applicationcache svg inlinesvg smil svgclippaths"> استكشاف العناصر يقوم Modernizr بإنشاء كائن جافاسكربت عام (Global Object) تحت اسم Modernizr مما يسمح لنا بالقيام باستعلامات حول مختلف خواص properties المتعلقة به وذلك عبر مناداة Modernizr.featurename (أين featurename هي اسم الخاصية المراد التأكد من دعمها على المتصفح). وبالتالي إن أردنا مثلا التأكد إن كان المتصفح يدعم canvas فإننا نكتب التالي: <script> if (Modernizr.canvas) { alert("This browser supports HTML5 canvas!"); } </script> جرب هذه الشيفرة على متصفح حديث وستظهر لك رسالة تُخبرك بأنه يدعم Canvas. بطبيعة الحال يُمكن أيضا التحقق ما إذا كان المتصفح لا يدعم خاصية مُعينة على النحو التالي: <script> if (Modernizr.canvas) { alert("This browser supports HTML5 canvas!"); } else { alert("no canvas :("); } </script> أو اختصار الأمر على النحو التالي: <script> if (!Modernizr.canvas) { alert("No canvas here"); } </script> استكشاف الخواص وتعويض النقائص باستخدام YepNope استعرضنا في المثال السابق أبسط طريقة لاستكشاف خواص المتصفح. الآن ماذا لو أردت التحقق من دعم المتصفح لخاصية مُعينة ثم أردت الاستعانة بالـ polyfill لجعل المتصفح يعمل بشكل أفضل؟ هذا ما يُمكنك القيام به لدى استخدامك لـ YepNope. YepNope عبارة عن أداة تحميل شرطية conditional loader، مما يعني بأنها لن تقوم بتحميل سوى السكربتات التي يحتاجها المُتصفح. تم تضمين YepNope مُباشرة ضمن Modernizr وبالتالي لا حاجة لك للتفكير أو القيام بتحميل أو الربط مع مكتبة Javascript أُخرى. لكن كيف نستعملها؟ سنقوم باستخدام Canvas كمثال هنا أيضا. يرغب المطورون عادة بدعم (القيام بـ Fallback لـ) المتصفحات التي لا تدعمها مثل IE8 أو الإصدارات السابقة له. الطريقة التقليدية للقيام بذلك هو ربط صفحة الـ HTML خاصتك بسكربت Polyfill يقوم بذلك كـ FlashCanvas مثلا: <script src="http://flashcanvas.net/bin/flashcanvas.js"></script> المشكل مع هذا الحل هو أن كل المتصفحات ستقوم بتحميل هذا السكربت، رغم أن ذلك غير مطلوب ولا فائدة تُرجى منه. هناك من يرى أن وضع السكربت في تعليق شرطي conditional comment يحل هذا المشكل، لكن إن كان بإمكاننا إبقاء السكربت خارج شفرة الصفحة بشكل كامل فسيكون ذلك أفضل بكثير، وهنا يأتي دور Modernizr.load()‎ كما سبق ذكره فإنه تم تضمين YepNope داخل Modernizr وبالتالي فإنه من الممكن التحقق من خاصية مُعينة ومن ثم توفير Polyfill خاصة بها إن لم تكن مدعومة. تجدر الإشارة إلى أنه لا يتم تضمين ()load. بشكل قياسي في ملف development، وبالتالي فإنه يجب عليك تضمينه لدى قيامك بـ'بناء' (build) الملف. الاستعمال القاعدي للدالة ()load. يخص التحقق من خاصية مُعنية إن كانت مدعومة (yep) أو لا(nope). في المثال التالي سيقوم Modernizr بالتحقق من دعم Canvas وفي حال ما إذا لم تكن مدعومة، يقوم بتحميل FlashCanvas: Modernizr.load({ test: Modernizr.canvas, nope: 'http://flashcanvas.net/bin/flashcanvas.js' }); إن كنت تملك IE8 على جهازك، الق نظرة على لسان تبويب Network في الـ Developer tools، ستلاحظ أن المتصفح يقوم بتحميل وتهيئة flashcanvas.js. تحميل FlashCanvas في IE8 إليكم الآن مثالا أكثر فائدة والذي يقوم بالتحقق من دعم <input type="date"> ومن ثم تحميل ملفي jQuery وملف CSS لإنشاء مختار للتواريخ Data picker: <script src="modernizr.js"></script> <script>Modernizr.load({ test: Modernizr.inputtypes.date, nope: ['http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js', 'jquery-ui.css'], complete: function () { $('input[type=date]').datepicker({ dateFormat: 'yy-mm-dd' }); } }); </script> كما هو ظاهر من هذا السكربت، ستقوم الصفحة بالتحقق من دعم <input type="date"‎>، وفي حالة ما إذا لم تكن مدعومة، ستقوم بتحميل ملفي jQuery وملف CSS (في هذا المثال يُفترض بملف CSS أن يكون محليا). بعد الفراغ من ذلك (on complete) تتم مناداة الإضافة مع كل <input type="date"‎> الموجودة في الـ DOM. سيتم تحميل ملفات jQuery في العديد من المتصفحات، لكنه لن يتم ذلك على Opera (أو على أحدث إصدارات Chrome). عنصر منتقي التاريخ من jQuery في متصفح فيرفوكس عنصر منتقي التاريخ الأصلي في متصفح أوبرا نعتظهر الصورتان السابقتان الاختلافات الناتجة عن تحميل المتصفح لإضافة jQuery في الأول ودعمه للخاصية في الثاني. ويظهر الأمر أيضا بشكل واضح في قائمة الملفات التي يقوم كل متصفح بتحميلها: تحميل موارد عنصر منتقي التاريخ في متصفح فيرفوكس تحميل عنصر منتقي التاريخ في متصفح أوبرا لاحظوا هنا أن المتصفح يقوم بتحميل ملفي jQuery مرتين، وهو سلوك طبيعي لمكتبة YepNope، ولذلك لا تقلق من الأمر فهو طبيعي. يُمكنك القيام بأكثر مما قُمنا به في هذين المثالين مع مكتبة YepNope. إليك المثال التالي والمأخوذ مباشرة من موقع المكتبة والذي سيتعرض كافة الخواص الممكنة لها (كل الخواص ليست مطلوبة): yepnope([{ test : /* boolean(ish) - Something truthy that you want to test */, yep : /* array (of strings) | string - The things to load if test is true */, nope : /* array (of strings) | string - The things to load if test is false */, both : /* array (of strings) | string - Load everytime (sugar) */, load : /* array (of strings) | string - Load everytime (sugar) */, callback : /* function ( testResult, key ) | object { key : fn } */, complete : /* function */ }, /* ... */ ]); الخلاصة Modernizr عبارة عن مكتبة استكشافية في غاية القوة، تسمح لك بالتحقق من إن كان المتصفح يدعم الخواص التي ترغب في استعمالها على صفحاتك، وبناء على ذلك تقوم الصفحات باستخدام تلك الخواص كما تدعمها تلك المتصفحات أو تقوم بالاستعانة بـ polyfill لتعويض النقص الناجم عن قصور المتصفح المستخدم في استعراض تلك الصفحات. قمنا في هذا المقال باستعراض كيفية إنشاء ملف Modernizr ومن ثم استخدامه بطريقتين مختلفين: استخدام كائن Modernizr بشكل مباشر (Modernizr.<featurename>) أو الاستعانة بـ YepNope. ترجمة –وبتصرف- للمقال: Using Modernizr to detect HTML5 features and provide fallbacks لصاحبه: Tom Leadbetter
  14. منذ سنوات بدأت عدد من الشركات، كما الأفراد، تقديم خدمات تسميها بخدمات تحسين الظهور في محركات البحث. لكن كل الشركات التي صادفتها تخدع عملاءها بخدمات من نوعية إدراج الموقع في عدد كبير من محركات البحث وأدلة المواقع، مع شراء الروابط في المواقع الأخرى. وتقول إن ذلك كل ما يلزم لتحسين ظهور الموقع في محركات البحث! في الحقيقة عمليات الـ SEO بسيطة جدا. إنها أبسط مما يدعيه أي شخص. بل المصطلح نفسه مجرد تضخيم تسويقي، أريد به خلق سوق جديدة، كما تم لاحقا مع مصطلح ويب 2. لكن رغم بساطته هو ليس سهلا ولا متوفرا دون بذل جهد حقيقي. ترتكز معايير SEO الحقيقية على مبدأين: المحتوى، والتوصيف الدلالي للمحتوى. أما باقي الأمور الأخرى التي تحشر ضمن ”الباقات التجارية“ لـ SEO فهي تندرج في الأصل ضمن الخدمات التسويقية. لكن يمكن تنفيذها كخدمات فرعية (وليست أساسية) ضمن SEO. ما يفعله الأغلبية الآن هو التركيز على التسويق (أو الدعاية لو شئت الدقة) مع التقليل من أهمية المحتوى وتجاهل كامل للتوصيف الدلالي. المحتوى (نصوص، صور، فيديو…) هو ما يبحث عنه المستخدم. لذلك هو جوهر عملية النشر الإلكتروني. تحسين المحتوى يعتمد على جودة المضمون وحسن الصياغة. يمكن للشركات التجارية توظيف فريق محررين أو شركات استشارية لصياغة المحتوى بالشكل المطلوب لإيصال المعلومة بشكل سليم. أما المواقع الشخصية والمدونات فيمكن لأصحابها تحسين مهاراتهم اللغوية وتحسين معرفتهم بالمجال الذي يكتبون عنه. أما مسألة التوصيف الدلالي للمحتوى فهي عملية تقنية محضة تعتمد على استخدام الرموز المناسبة من لغة HTML لتوصيف كل جزء من المحتوى بشكل سليم ومنطقي، بحيث تتعامل محركات البحث مع المحتوى حسب أهميته الحقيقية وتعرف كيف تعرضه بالشكل المناسب والمتوافق مع استعلامات البحث. إذن، كل المطلوب للوصول إلى الصفحات الأولى لمحركات البحث هو: (أ) تحسين المحتوى من حيث جودة المضمون وسلامة الصياغة، (ب) واستخدام رموز التوصيف الدلالي HTML المناسبة للتعبير بشكل سليم عن المحتوى بشكل يساعد محركات البحث على فهم المحتوى. النقطة الأولى تشمل أيضا فهم الفئة المستهدفة من القراء وتوقع عمليات البحث الممكن إجراؤها من الباحثين للوصول إلى ذلك النوع من المحتوى. وهو ما يعني ضرورة صياغة المحتوى بشكل يتناسب مع القراء المستهدفين والتركيز على الكلمات المفتاحية التي يكثر من البحث عنها. لكن دون الوقوع في فخ ”الكتابة لمحركات البحث“ بدل الكتابة للبشر، حيث أن التركيز المبالغ فيه على الكلمات المفتاحية المهمة قد ينتج عنه صياغة ركيكة لغويا للمحتوى. لذلك يجب الاحتراس والتوازن في صياغة المحتوى، بحيث تكون الكلمات المفتاحية المهمة بارزة -لتسهيل تحسين الظهور في محركات البحث- وفي نفس الوقت يبقى الأسلوب اللغوي سلسا محفزا على القراءة.
×
×
  • أضف...