<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: HTML</title><link>https://academy.hsoub.com/programming/html/page/3/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: HTML</description><language>ar</language><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x645;&#x648;&#x627;&#x635;&#x641;&#x627;&#x62A; ARIA: &#x625;&#x639;&#x637;&#x627;&#x621; &#x639;&#x646;&#x627;&#x635;&#x631; HTML &#x62F;&#x644;&#x627;&#x644;&#x627;&#x62A; &#x62E;&#x627;&#x635;&#x629; &#x644;&#x62A;&#x633;&#x647;&#x64A;&#x644; &#x627;&#x644;&#x648;&#x635;&#x648;&#x644;</title><link>https://academy.hsoub.com/programming/html/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%85%D9%88%D8%A7%D8%B5%D9%81%D8%A7%D8%AA-aria-%D8%A5%D8%B9%D8%B7%D8%A7%D8%A1-%D8%B9%D9%86%D8%A7%D8%B5%D8%B1-html-%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%AE%D8%A7%D8%B5%D8%A9-%D9%84%D8%AA%D8%B3%D9%87%D9%8A%D9%84-%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-r1327/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_10/615e832f66d18_--ARIA-------ARIA---ARIA---ARIA---.png.0d53be6a404d20d867974617e9d3b07c.png" /></p>

<p>
	شجعنا سابقًا على استخدام عناصر HTML الأساسية native لأنها توفر كل من إمكانية التركيز focus و دعم لوحة المفاتيح والدلالات المبنية مسبقًا built-in semantics. إلا أنه يوجد العديد من الحالات التي لا يكفي فيها استخدام عناصر HTML الأساسية مع نسق layout بسيط للوصول للمطلوب. مثلًا: لا يتوفر حاليًا عنصر HTML قياسي لإنشاء قائمة منبثقة pop-up menu رغم أنها شائعة الاستخدام. كما أنه لا يوجد عنصر HTML يوفر خاصية دلالية مثل "يحتاج المستخدم إلى معرفة ذلك بأسرع ما يمكن".
</p>

<p>
	نستكشف في هذه المقالة كيفية التعبير عن الدلالات التي لا تستطيع عناصر HTML التعبير عنها بمفردها وذلك بالاعتماد على مواصفات ARIA.
</p>

<h2>
	مقدمة إلى ARIA
</h2>

<p>
	تُعدّ المواصفات المُقدّمة من "مبادرة الوصول للويب لتطبيقات الإنترنت الغنية سهلة الوصول" <a href="https://www.w3.org/TR/wai-aria/" rel="external nofollow">Web Accessibility Initiative's Accessible Rich Internet Applications specification</a> (WAI-ARIA أو فقط ARIA) مفيدة في الحالات التي لا يُمكن معالجتها باستخدام عناصر HTML الأساسية. تسمح هذه المواصفات بتحديد الخصائص التي تُعدّل طريقة ترجمة عنصر إلى شجرة الوصول accessibility tree. نبدأ أولًا بمثال بسيط.
</p>

<p>
	نستخدم في مقطع الشيفرة التالي عنصر قائمة <code>li</code> كنوع من مربع اختيار مخصص. يوفر الصف "checkbox" خصائص العنصر المرئية المطلوبة:
</p>

<pre class="ipsCode">
&lt;li tabindex="0" class="checkbox" checked&gt;
  Receive promotional offers
&lt;/li&gt;
</pre>

<p>
	لن يتمكن قارئ الشاشة من إعطاء أي إشارة للمستخدم بأن العنصر السابق يُعامل كمربع اختيار، وبذا لن يكون هذا العنصر واضحًا إلا للمستخدمين المبصرين أما بالنسبة لضعاف البصر (الذين يستخدمون قارئ الشاشة) فسيكون هذا العنصر مخفيًا تمامًا عنهم.
</p>

<p>
	تسمح خصائص ARIA بتوفير المعلومات الناقصة لهذا العنصر مما يُمكّن قارئ الشاشة من فهمه بشكل صحيح. تُبين الشيفرة التالية إضافة خاصية الدور role وخاصية حالة الاختيار aria-checked (من ARIA) للتصريح الواضح بأن العنصر هو مربع اختيار وحالته الافتراضية "مُحدّدًا". ستُضاف قائمة هذا العنصر إلى شجرة الوصول المستخدمة من قبل قارئ الشاشة الذي سيُعرّف هذا العنصر للمستخدم بشكل صحيح بعد الآن.
</p>

<pre class="ipsCode">
&lt;li tabindex="0" class="checkbox" role="checkbox" checked aria-checked="true"&gt;
  Receive promotional offers
&lt;/li&gt;
</pre>

<p>
	ملاحظة: نعرض خصائص ARIA لاحقًا.
</p>

<p>
	تُعدّل ARIA شجرة الوصول الناتجة عن شجرة DOM وفق ما يلي: تسمح ARIA بتعديل شجرة الوصول (جزئيًا أو كليًا) لأي عنصر في الصفحة، إلا أنها لا تزيد على أي من السلوكيات الأصيلة في العنصر. فهي، مثلًا، لن تُغيّر من إمكانية التركيز على العنصر ولن تُضيف له مستمع لحدث من لوحة المفاتيح. تبقى هذه الأمور من مهام المطور.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78297" href="https://academy.hsoub.com/uploads/monthly_2021_09/001acctree1.jpg.a33168bf4e965bebffb6e7cd652b5f1f.jpg" rel=""><img alt="001acctree1.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78297" data-unique="l7hmr1q26" src="https://academy.hsoub.com/uploads/monthly_2021_09/001acctree1.jpg.a33168bf4e965bebffb6e7cd652b5f1f.jpg"></a>
</p>

<p>
	يجب الانتباه جيدًا إلى أننا لا نحتاج لإعادة تعريف الدلالات الضمنية للعناصر. مثلًا: لا يحتاج مربع الاختيار القياسي <code>&lt;"input type="checkbox&gt;</code> لأن نُضيف له دور <code>"role="checkbox</code> ليٌعامله قارئ الشاشة بشكل صحيح.
</p>

<p>
	تجدر الإشارة أيضًا إلى أن لبعض عناصر HTML قيود على إضافة أدوار وخصائص ARIA إليها. مثلًا: لا يسمح عنصر مربع النص القياسي في HTML بإضافة أي دور أو خاصية عليه <code>&lt;"input type = "text&gt;</code>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78298" href="https://academy.hsoub.com/uploads/monthly_2021_09/002acctree2.jpg.d381cf8cecc9ab7c36b7d9ecee7d4912.jpg" rel=""><img alt="002acctree2.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78298" data-unique="uzrkjnqd4" src="https://academy.hsoub.com/uploads/monthly_2021_09/002acctree2.jpg.d381cf8cecc9ab7c36b7d9ecee7d4912.jpg"></a>
</p>

<p>
	يُمكن استعراض مواصفات ARIA من خلال  <a href="https://www.w3.org/TR/html-aria/#sec-strong-native-semantics" rel="external nofollow">ARIA in HTML spec</a>. وسنعرض فيما يلي بعض الإمكانات الأخرى التي توفرها ARIA.
</p>

<h2>
	ما الذي يمكن أن تفعله ARIA؟
</h2>

<p>
	يُمكن أن تُعدّل ARIA من دلالات العناصر أو تُضيف إليها دلالات جديدة غير موجودة في دلالاتها الأساسية كما عرضنا في مثال مربع الاختيار السابق. يُمكن لها أيضًا التعبير عن نماذج دلالات غير موجودة على الإطلاق في HTML، مثل قائمة menu أو تبويب في لوحة panel. تسمح ARIA غالبًا بإنشاء عناصر جديدة لواجهة المستخدم لا يُمكن بنائها باستخدام HTML القياسية.
</p>

<p>
	مثلًا، يُمكن أن تُضيف ARIA عنوان label إضافي لوضع نص توصيفي يُعامل فقط في واجهة برمجة التطبيقات للتقنية المساعدة.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9216_6" style="">
<span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">aria-label</span><span class="pun">=</span><span class="atv">"screen reader only label"</span><span class="tag">&gt;&lt;/button&gt;</span></pre>

<p>
	يُمكن باستخدام ARIA التعبير عن العلاقات الدلالية بين العناصر التي تعمل على توسيع العلاقة القياسية أب/ابن، مثل شريط تمرير مخصص custom scrollbar يتحكم في منطقة معينة.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9216_8" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">role</span><span class="pun">=</span><span class="atv">"scrollbar"</span><span class="pln"> </span><span class="atn">aria-controls</span><span class="pun">=</span><span class="atv">"main"</span><span class="tag">&gt;&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"main"</span><span class="tag">&gt;</span><span class="pln">
. . .
</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	يُمكن باستخدام ARIA جعل أجزاء من الصفحة "مباشر" live، بحيث تُعلّم التقنية المساعدة عند حدوث أي تغيير فيها فورًا .
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9216_11" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">aria-live</span><span class="pun">=</span><span class="atv">"polite"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;span&gt;</span><span class="pln">GOOG: $400</span><span class="tag">&lt;/span&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	من أهم الميزات المُقدّمة من ARIA هو مجموعة الأدوار التي يُمكن تعريفها للعناصر. إذ يسمح إسناد دور معين لعنصر بتعريف سلوك هذا العنصر مباشرًة. توفر ARIA مجموعة معينة من نماذج الأدوار التي يُمكن إسنادها لعناصر HTML.
</p>

<p>
	مثلًا: يُخبر استخدامنا للدور <code>"role="checkbox</code> التقنية المساعدة بأن سلوك هذا العنصر يجب أن يُماثل سلوك مربع اختيار checkbox. أي أنه يجب أن يكون له حالة الاختيار (مُحدّد أم لا)، وبأن هذه الحالة يُمكن قلبها باستخدام الفأرة أو شريط المسافة من لوحة المفاتيح (تمامًا مثل أي مربع اختيار من HTML).
</p>

<p>
	تلعب أحداث لوحة المفاتيح دورًا أساسيًا عند استخدام قارئ الشاشة، ولذا فمن المهم جدًا التأكد عند إنشاء عنصر مخصص من تطبيق خاصية الدور <code>role</code> في نفس مكان تطبيق خاصية ترتيب الجدولة <code>tabindex</code> مما يضمن ذهاب أحداث لوحة المفاتيح إلى المكان الصحيح وتطبيق الدور بدقة عندما يُصبح التركيز على عنصر.
</p>

<p>
	تُقدّم مواصفات <a href="https://www.w3.org/TR/wai-aria/" rel="external nofollow">ARIA</a> مجموعة المفردات للقيم الممكنة لخاصية الدور ولخصائص ARIA التي يُمكن استخدامها مع الأدوار جنبًا إلى جنب بطريقة تدعمها المستعرضات والتقنيات المساعدة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78299" href="https://academy.hsoub.com/uploads/monthly_2021_09/003aria-roles.jpg.73c83f05c8cd4f8f020d7f613d07e612.jpg" rel=""><img alt="003aria-roles.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78299" data-unique="e2jlgswzj" src="https://academy.hsoub.com/uploads/monthly_2021_09/003aria-roles.thumb.jpg.aa578583857de7866128f4e24ff6f832.jpg" style="width: 600px; height: auto;"></a>
</p>

<p>
	نظرًا للعدد الكبير للمواصفات، يُمكن البدء من وثيقة ممارسات التأليف <a href="https://www.w3.org/TR/wai-aria-practices-1.1/" rel="external nofollow">ARIA Authoring Practices document</a> التي تعرض أفضل الممارسات لاستخدام أدوار وخصائص ARIA المتاحة.
</p>

<p>
	توفر ARIA أيضًا أدوارًا مميزة توسع الخيارات المتاحة في HTML5. يُمكن العودة إلى نماذج تصميم الأدوار <a href="https://www.w3.org/TR/wai-aria-practices-1.1#kbd_layout_landmark_XHTML" rel="external nofollow">Landmark Roles Design Patterns</a> لمزيد من المعلومات.
</p>

<h2>
	العناوين في ARIA
</h2>

<p>
	توفر ARIA العديد من الآليات لإضافة عناوين labels أو وصف للعناصر. في الواقع، تُعدّ الخاصية <code>aria-label</code> الطريقة الوحيدة لإضافة مساعدة سهلة الوصول أو نص يصف للعنصر. نعرض فيما يلي الخصائص المستخدمة لإنشاء عناوين سهلة الوصول.
</p>

<h3>
	عنوان aria-label ARIA  
</h3>

<p>
	تسمح الخاصية <code>aria-label</code> بتحديد سلسلة نصية لاستخدامها كعنوان سهل الوصول. تُلغي هذه الخاصية أي عنوان مُمكن آخر مُحدّد باستخدام طريقة أساسية كاستخدام العنصر <code>label</code>. مثلًا: إذا تضمن زر كل من خاصية النص text وخاصية <code>aria-label</code> فستُستخدم خاصية <code>aria-label</code> فقط.
</p>

<p>
	يُمكن استخدام الخاصية <code>aria-label</code> عندما يوفر العنصر نوعًا من المؤثرات المرئية لتوضيح الغرض من العنصر كوضع صورة مُعبّرة على زر عوضًا عن النص إلا أنه مازال ضروريًا توفير توضيح عن هذا العنصر لأي شخص غير قادر على إدراك المؤثر المرئي الموجود (مشاهدة الصورة الموضوعة على الزر).
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78300" href="https://academy.hsoub.com/uploads/monthly_2021_09/004aria-label.jpg.ec7bfe0a1038b3b26475e53782e4833f.jpg" rel=""><img alt="004aria-label.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78300" data-unique="tmbyrs6xu" src="https://academy.hsoub.com/uploads/monthly_2021_09/004aria-label.jpg.ec7bfe0a1038b3b26475e53782e4833f.jpg"></a>
</p>

<h3>
	معنون باستخدام aria-labelledby
</h3>

<p>
	تسمح الخاصية <code>aria-labelledby</code> بتحديد مُعرّف ID عنصر آخر في شجرة DOM كعنصر يوفر العنوان.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78301" href="https://academy.hsoub.com/uploads/monthly_2021_09/005aria-labelledby.jpg.f174e065433c3b5eca6d3463b9a8d076.jpg" rel=""><img alt="005aria-labelledby.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78301" data-unique="f3rmtaowk" src="https://academy.hsoub.com/uploads/monthly_2021_09/005aria-labelledby.jpg.f174e065433c3b5eca6d3463b9a8d076.jpg"></a>
</p>

<p>
	يشبه هذا السلوك إلى حد كبير استخدام عنصر العنوان <code>label</code>، مع بعض الاختلافات الرئيسية:
</p>

<ol>
<li>
		يُمكن استخدام <code>aria-labelledby</code> مع أي عنصر، وليس فقط مع العناصر القابلة للعنونة.
	</li>
	<li>
		يُشير عنصر العنوان <code>label</code> إلى الشيء الذي يُعنونه، تنعكس العلاقة في حالة <code>aria-labelledby</code> إذ أن الشيء المُعنون يشير إلى الشيء الذي يُعنونه.
	</li>
	<li>
		يُمكن ربط عنصر عنوان <code>label</code> واحد فقط بعنصر قابل للعنونة، أما الخاصية aria-labelledby فيُمكن أن تأخذ قائمة من المُعرّفات IDREFs لتكوين عنوان من عناصر متعدّدة. يكون العنوان النهائي حصيلة ضمّ نصوص العناصر وفق ترتيبها ضمن IDREFs.
	</li>
	<li>
		يُمكن استخدام <code>aria-labelledby</code> للإشارة إلى عناصر مخفية والتي لن تكون ضمن شجرة إمكانية الوصول. مثلًا: يُمكن إضافة امتداد span مخفي جانب العنصر المطلوب عنونته والإشارة إليه باستخدام <code>aria-labelledby</code>.
	</li>
	<li>
		لا تمنح الخاصية aria-labelledby سلوك النقر المألوف على عنصر العنوان <code>label</code> إذ أن ARIA لا يؤثر إلا على شجرة الوصول.
	</li>
</ol>
<p>
	يجب ملاحظة أن عنوان <code>aria-labelledby</code> له الأولوية الأولى أي أنه يتجاوز جميع مصادر العناوين الأخرى. مثلًا: في حال كان لعنصر كل من الخاصيتين <code>aria-labelledby</code> و <code>aria-label</code> أو كل من الخاصيتين <code>aria-labelledby</code> و <code>label</code> الأساسية من HTML، فسيكون العنوان المُعتمد هو العنوان المُحدّد من الخاصية <code>aria-labelledby</code>.
</p>

<h2>
	العلاقات في ARIA
</h2>

<p>
	تُنشئ الخصائص العلائقية علاقات Relationships دلالية بين عناصر الصفحة وذلك بغض النظر عن علاقتهم في شجرة DOM. مثلًا: الخاصية <code>aria-labelledby</code> هي مثال عن خاصية العلاقة "العنصر مُعنون بهذا العنصر". تُحدّد مواصفات ARIA ثمان خصائص علائقية [eight relationship attributes، ستٌ منها تُشير إلى عنصر أو أكثر على الصفحة وتُستخدم لإنشاء علاقات جديدة بين هذه العناصر: 
</p>

<ul>
<li>
		<code>aria-activedescendant.</code>
	</li>
	<li>
		<code>aria-controls.</code>
	</li>
	<li>
		<code>aria-describedby.</code>
	</li>
	<li>
		<code>aria-labelledby.</code>
	</li>
	<li>
		<code>aria-owns.</code>
	</li>
</ul>
<p>
	يكمن الفرق في كل حالة بمعنى العلاقة وكيفية عرضها للمستخدمين.
</p>

<h3>
	التملك aria-owns
</h3>

<p>
	تُعدّ خاصية التملك <code>aria-owns</code> من أكثر علاقات ARIA استخدامًا. تسمح هذه الخاصية بإعلام التقنية المساعدة بأن عنصر ما منفصل في شجرة DOM يجب أن يُعامل كابن للعنصر الحالي، أو أنه يجب إعادة ترتيب العناصر الأبناء بشكل مختلف. مثلًا: في حال وضع قائمة جزئية منبثقة pop-up sub-menu أمام القائمة الأب لها مع عدم إمكانية وضع هذه القائمة المنبثقة ابنًا للقائمة الأب في شجرة DOM لأن ذلك يؤدي إلى تغيير مظهر العرض المرئي المطلوب. يُمكن في هذه الحالة استخدام <code>aria-owns</code> لتقديم القائمة الفرعية المنبثقة كابن للقائمة الأب لقارئ الشاشة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78302" href="https://academy.hsoub.com/uploads/monthly_2021_09/006aria-owns.jpg.ed1b2e860df92e461061bbb4b672448d.jpg" rel=""><img alt="006aria-owns.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78302" data-unique="4y1qdn70y" src="https://academy.hsoub.com/uploads/monthly_2021_09/006aria-owns.thumb.jpg.e3290eac2de044818d9e4387324aff4f.jpg"></a>
</p>

<h3>
	الابن النشط aria-activedescendant
</h3>

<p>
	تلعب الخاصية <code>aria-activedescendant</code> دور الوصل بين العناصر. مثلًا: تُعلّم هذه الخاصية التقنية المساعدة بأنه عند وصول التركيز على عنصر (الذي أسندنا قيمة لهذه الخاصية فيه) فيجب إعلام المستخدم بحصول التركيز على عنصر آخر. مثلًا: يُمكن أن يكون المطلوب عند استخدام مربع قائمة listbox ترك التركيز على حاوية مربع القائمة مع تحديث الخاصية <code>aria-activedescendant</code> إلى العنصر الحالي المُحدّد من القائمة مما يجعل هذا العنصر يظهر للتقنية المساعدة فيما لو كان العنصر الحاصل على التركيز.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78303" href="https://academy.hsoub.com/uploads/monthly_2021_09/007aria-activedescendant.jpg.fbf4d9ad10d0c446509f2710fc5f93d8.jpg" rel=""><img alt="007aria-activedescendant.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78303" data-unique="sh83avsoz" src="https://academy.hsoub.com/uploads/monthly_2021_09/007aria-activedescendant.thumb.jpg.b5b49227bd051891dcba514c90ca6e89.jpg"></a>
</p>

<h3>
	الوصف باستخدام aria-describedby
</h3>

<p>
	توفر الخاصية <code>aria-describedby</code> وصفًا سهل الوصول بنفس الطريقة التي توفر بها الخاصية aria-labelledby العنوان. يُمكن لهذه الخاصية الإشارة إلى عناصر مخفية سواًء في شجرة الوصول أو في شجرة DOM. تُقدّم هذه الخاصية آلية مفيدة لتقديم شرحًا إضافيًا لكل من المستخدمين العاديين ولمستخدمي التقنية المساعدة.
</p>

<p>
	من الأمثلة الشهيرة على استخدام هذه الخاصية هي حالة حقل إدخال كلمة السر والمصحوب بنص يشرح متطلبات كلمة السر. على خلاف العنوان، يُمكن عرض هذا النص التوضيحي أم لا للمستخدم الذي يكون له الخيار في الوصول إليه أو قد يأتي بعد كل المعلومات الأخرى أو يُمكن استباقه بشيء آخر. مثلًا: إذا كان المستخدم يُدخل بعض المعلومات فيُمكن لهذه المعلومات أن تُظهر مرة أخرى مقاطعًة وصف العناصر.
</p>

<p>
	وبهذا يكون الوصف طريقة رائعة لتوصيل معلومات إضافية غير أساسية ولن يقف في طريق الحصول على معلومات أكثر أهمية مثل دور العنصر.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78304" href="https://academy.hsoub.com/uploads/monthly_2021_09/008aria-describedby.jpg.8010b493a1279c1c9fa7bc4b95ee2fac.jpg" rel=""><img alt="008aria-describedby.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78304" data-unique="nbyguklhv" src="https://academy.hsoub.com/uploads/monthly_2021_09/008aria-describedby.thumb.jpg.03e0de9ffa77a43f1367258223c5f441.jpg"></a>
</p>

<h3>
	المكان والحجم aria-posinset &amp; aria-setsize
</h3>

<p>
	تعمل الخصائص المتبقية معًا (والمختلفة قليلًا عن الخصائص السابقة). تُعرّف الخاصيتان <code>aria-posinset</code> (المكان في المجموعة) و <code>aria-setsize</code> (حجم المجموعة) العلاقة بين العناصر الأخوة في مجموعة، مثل حالة القائمة list.
</p>

<p>
	عند تعذر تحديد قياس المجموعة باستخدام العناصر الموجودة في شجرة DOM، مثل حالة التصيير الكسول lazy rendering المستخدمة عادًة لتجنب وجود قائمة ضخمة في شجرة DOM دفعة واحدة. تُحدّد الخاصية <code>aria-setsize</code> الحجم الفعلي للمجموعة، أما الخاصية <code>aria-posinset</code> فتُحدّد مكان العناصر في المجموعة. مثلًا: يُمكن في مجموعة تحوي 1000 عنصر من تعيين العنصر ذو الترتيب 857 ليكون الإظهار الأول في شجرة DOM واستخدام تقانات HTML الديناميكية للتأكد من تمكّن المستخدم من استكشاف كامل عناصر القائمة عند الحاجة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78305" href="https://academy.hsoub.com/uploads/monthly_2021_09/009aria-posinset.jpg.cfa174c9ec8821e138addd8c1a3463d9.jpg" rel=""><img alt="009aria-posinset.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78305" data-unique="n7rq0z2ii" src="https://academy.hsoub.com/uploads/monthly_2021_09/009aria-posinset.thumb.jpg.5907528e09292cbd95153b1da96e718a.jpg"></a>
</p>

<h2>
	إظهار وإخفاء المحتوى
</h2>

<p>
	تُعدّ عملية عرض الأجزاء المناسبة من الصفحة للتقنية المساعدة من الآليات المهمة في صقل تجربة مستخدمي التقنية المساعدة. يوجد العديد من الطرق للتأكد من عدم عرض جزء ما من شجرة DOM لواجهة برمجة تطبيقات شجرة الوصول.
</p>

<h3>
	الإخفاء aria-hidden
</h3>

<p>
	أولًا، لا يُضمّن في شجرة الوصول أي شيء مخفي بشكل صريح في شجرة DOM. وبالتالي، فإن أي نمط CSS يتعلق بالإخفاء مثل <code>visibility: hidden</code> أو <code>display: none</code> أو الخاصية <code>hidden</code> في HTML5 سيكون مخفيًا أيضًا لمستخدمي التقنية المساعدة.
</p>

<p>
	ومع ذلك، فإن أي عنصر لم يُعرض على الصفحة إلا أنه غير مخفي بشكل صريح سيبقى موجودًا في شجرة الوصول. من الطرق الشائعة تضمين "نص لقارئ الشاشة فقط" في عنصر موضوع خارج الشاشة بشكل مطلق absolute.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9216_15" style="">
<span class="pln">.sr-only {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}</span></pre>

<p>
	يُمكن، كما عرضنا سابقًا، توفير نص لقارئ الشاشة فقط باستخدام <code>aria-label</code> أو <code>aria-labelledby</code> أو <code>aria-describedby</code> مع الإشارة إلى عنصر مخفي، كما يُمكن العودة إلى مقالة منظمة WebAIM حول تقانات إخفاء العناصر <a href="https://webaim.org/techniques/css/invisiblecontent/#techniques" rel="external nofollow">Techniques for hiding text</a> للمزيد من المعلومات عن توفير "نص لقارئ الشاشة فقط".
</p>

<p>
	توفر ARIA آلية لاستبعاد المحتوى غير المخفي باستخدام الخاصية <code>aria-hidden</code> والتي يؤدي تطبيقها على عنصر إلى حذفه مع جميع أبناءه من شجرة الوصول مع استثناء العناصر المشار إليها بإحدى الخاصيتين <code>aria-labelledby</code> و <code>aria-describedby</code>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9216_17" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"deck"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"slide"</span><span class="pln"> </span><span class="atn">aria-hidden</span><span class="pun">=</span><span class="atv">"true"</span><span class="tag">&gt;</span><span class="pln">
    Sales Targets
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"slide"</span><span class="tag">&gt;</span><span class="pln">
    Quarterly Sales
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"slide"</span><span class="pln"> </span><span class="atn">aria-hidden</span><span class="pun">=</span><span class="atv">"true"</span><span class="tag">&gt;</span><span class="pln">
    Action Items
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	مثلًا: يُمكن استخدام الخاصية <code>aria-hidden</code> في حال إنشاء واجهة مستخدم شرطية modal والتي تمنع المستخدم من الوصول إلى الصفحة الرئيسية. في مثل هذه الحالة يرى المستخدم المبصر نوعًا من التراكب شبه الشفاف والذي يُفهمه بأنه لا يستطيع الوصول إلى عناصر الصفحة الأساسية أما مستخدم قارئ الشاشة فيبقى قادرًا على الوصول إلى جميع أجزاء الصفحة. يُمكن هنا إضافًة لقفل لوحة المفاتيح التأكد من أن جميع أجزاء الصفحة المطلوب إخفائها عن المستخدم لها الخاصية aria-hidden.
</p>

<p>
	يٌمكن الآن بعد فهم أساسيات ARIA وكيف تتعامل مع دلالات عناصر HTML الأساسية وآلية استخدامها لإجراء تعديلات في شجرة إمكانية الوصول، الانتقال إلى مسألة إيصال المعلومات الهامة بشكل فوري للمستخدم.
</p>

<h3>
	الجزء الحي aria-live
</h3>

<p>
	تسمح الخاصية <code>aria-live</code> للمطور بتحديد جزء من الصفحة على أنه "حي" live بمعنى أنه يجب إعلام المستخدم بأي تحديث في هذا الجزء فورًا وبغض النظر عن موضع المستخدم في الصفحة، أي دون أن يقوم المستخدم باستكشاف هذا الجزء من الصفحة. عندما يكون لعنصر الخاصية <code>aria-live</code>، يُدعى الجزء من الصفحة الذي يحوي هذا العنصر وأبناءه بالمنطقة الحية أو الآنية live region.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78306" href="https://academy.hsoub.com/uploads/monthly_2021_09/010aria-live.jpg.df6cfd0ea64f092a9da8d4c85fb7ba1d.jpg" rel=""><img alt="010aria-live.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78306" data-unique="0ey38zzj0" src="https://academy.hsoub.com/uploads/monthly_2021_09/010aria-live.thumb.jpg.2a9fb03b0ef5526b5c75d814a8004bfe.jpg"></a>
</p>

<p>
	مثلًا: إذا كانت المنطقة الحية عبارة عن رسالة حالة تُظهر نتيجة إجراء ما للمستخدم، وكانت الرسالة هامة كفاية لجذب أنظار المستخدمين المبصرين فإنه من الضروري بمكان تنبيه مستخدم التقنية المساعدة إليها وذلك بضبط الخاصية <code>aria-live</code>.
</p>

<p>
	يُمكن مقارنة حالة هذا القسم div العادي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9216_19" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"status"</span><span class="tag">&gt;</span><span class="pln">Your message has been sent.</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	مع نظيره "الآني":
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9216_22" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"status"</span><span class="pln"> </span><span class="atn">aria-live</span><span class="pun">=</span><span class="atv">"polite"</span><span class="tag">&gt;</span><span class="pln">Your message has been sent.</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	يُمكن أن يكون للخاصية <code>aria-live</code> إحدى القيم الثلاث التالية: <code>polite</code> و <code>assertive</code> و <code>off</code>.
</p>

<ul>
<li>
		القيمة <code>aria-live="polite"</code>: تُعلّم هذه القيمة التقنية المساعدة لتنبيه المستخدم بالتغيير الحاصل حال انتهائه مما يعمل حاليًا. تُستخدم هذه القيمة عندما يكون هنالك أمرًا هامًا إلا أنه غير مستعجل جدًا وهي الحالة العامة لاستخدام <code>aria-live</code>.
	</li>
	<li>
		القيمة <code>aria-live="assertive"</code>: تُعلّم هذه القيمة التقنية المساعدة لتنبيه المستخدم بالتغيير الحاصل فورًا وبغض النظر عما يقوم به حاليًا. تُستخدم هذه القيمة عندما يكون هنالك أمرًا هامًا ومستعجلًا مثل "حصل خطأ على الخادم ولم تُحفظ تعديلاتك، يُرجى إعادة تحميل الصفحة"، أو كتعديل على حقل إدخال نتيجة إجراء مستخدم كالنقر على أزرار عنصر تحديد خطوة stepper widget.
	</li>
	<li>
		القيمة <code>aria-live="off"</code>: تُعلّم هذه القيمة التقنية المساعدة بإيقاف مقاطعات <code>aria-live</code> بشكل مؤقت.
	</li>
</ul>
<p>
	من الإرشادات الذكية للتأكد من أن المناطق المباشرة تعمل بشكل صحيح:
</p>

<ul>
<li>
		أولًا، قد تُحدّد المنطقة المباشرة <code>aria-live</code> خلال التحميل الأول للصفحة. لا يُعدّ هذا الأمر قاعدة مؤكدة إلا أنه قد يكون هذا سبب مشكلة المنطقة المباشرة.
	</li>
	<li>
		ثانيًا، يُمكن أن يكون تعامل برامج قراءة الشاشة مختلفًا مع أنواع التحديثات الممكنة. مثلًا: يُمكن إطلاق تنبيه في بعض برامج قراءة الشاشة لمجرد قلب حالة عنصر من مخفي إلى ظاهر أو بالعكس باستخدام النمط <code>hidden</code>.
	</li>
</ul>
<p>
	يُمكن للخصائص الأخرى التي تعمل مع <code>aria-live</code> المساعدة في الضبط الدقيق لما يُعرض للمستخدم حال حصول تحديثات في المنطقة المباشرة.
</p>

<p>
	تُحدّد الخاصية <code>aria-atomic</code>، والتي تأخذ إحدى القيمتين <code>true</code> أو <code>false</code> (القيمة الافتراضية)، فيما إذا كان من الواجب اعتبار كامل المنطقة المباشرة عند الإعلام بالتحديثات أم لا. مثلًا: في حال استخدام عنصر التاريخ والذي يتألف من اليوم والشهر والسنة، فإن تغيير المستخدم لقيمة الشهر فقط يؤدي إلى إعادة قراءة التاريخ فيما لو كانت <code>aria-atomic=true</code> و <code>aria-live=true</code>.
</p>

<p>
	تُحدّد الخاصية <code>aria-relevant</code> أنواع التغييرات الواجب إعلام المستخدم بها. يوجد بعض الخيارات التي يُمكن استخدامها بشكل منفصل أو بشكل قائمة:
</p>

<ul>
<li>
		الإضافات additions: تعني أن أي إضافة إلى المنطقة المباشرة يجب إعلام المستخدم بها. مثلًا: في حال إضافة امتداد span لسجل رسائل الحالة يُمكن أن يعني أنه من الأنسب إعلام المستخدم بهذا الامتداد الجديد (بافتراض أن قيمة <code>aria-atomic</code> هي <code>false</code>).
	</li>
	<li>
		النص text: تعني أن النص المُضاف لأي عقدة تابعة descendant node هو نصًا مناسبًا لإعلام المستخدم به. مثلًا: يُمكن عند تحديث الخاصية textContent لحقل نص مخصص إعادة قراءة النص للمستخدم.
	</li>
	<li>
		الحذف removals: تعني وجوب إعلام المستخدم بحذف أي نص أو عقدة تابعة.
	</li>
	<li>
		الكل all: تعني أن جميع التغييرات مناسبة لإعلام المستخدم بها. تكون القيمة الافتراضية للخاصية هي التسلسل <code>additions text</code> مما يعني أنه في حال عدم تحديد الخاصية <code>aria-relevant</code> فسيُعلم المستخدم بأي إضافة إلى العنصر وهو المطلوب في معظم الأحيان.
	</li>
</ul>
<p>
	أخيرًا، تطلب الخاصية <code>aria-busy</code> من التقنية المساعدة إهمال جميع التحديثات على العنصر بشكل مؤقت، مثلًا: خلال فترة التحميل يُمكن إسناد القيمة <code>true</code> لهذه الخاصية وعند الانتهاء نعاود إسناد القيمة <code>false</code> لها للعودة للوضع الطبيعي لقارئ الشاشة.
</p>

<p>
	ترجمة -وبتصرف- لمجموعة المقالات:
</p>

<ul>
<li>
		<a href="https://developers.google.com/web/fundamentals/accessibility/semantics-aria" rel="external nofollow">Introduction to ARIA</a>
	</li>
	<li>
		<a href="https://developers.google.com/web/fundamentals/accessibility/semantics-aria/aria-labels-and-relationships" rel="external nofollow">ARIA Labels and Relationships</a>
	</li>
	<li>
		<a href="https://developers.google.com/web/fundamentals/accessibility/semantics-aria/hiding-and-updating-content" rel="external nofollow">Hiding and Updating Content </a>
	</li>
</ul>
<p>
	للمؤلفين: Meggin Kearney وDave Gash وAlice Boxhall.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/html/%D8%A7%D9%84%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B6%D9%85%D9%86%D8%A9-%D9%84%D8%B9%D9%86%D8%A7%D8%B5%D8%B1-%D8%B5%D9%81%D8%AD%D8%A9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%88%D8%AF%D9%88%D8%B1%D9%87%D8%A7-%D9%81%D9%8A-%D8%AA%D8%B9%D8%B2%D9%8A%D8%B2-%D8%B3%D9%87%D9%88%D9%84%D8%A9-%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-r1325/" rel="">الدلالات المضمنة لعناصر صفحة الويب ودورها في تعزيز سهولة الوصول </a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/html/%D8%B3%D9%87%D9%88%D9%84%D8%A9-%D9%88%D8%B5%D9%88%D9%84-%D8%AC%D9%85%D9%8A%D8%B9-%D8%A7%D9%84%D8%B2%D9%88%D8%A7%D8%B1-%D9%84%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r1323/" rel="">سهولة وصول جميع الزوار لمواقع وتطبيقات الويب</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/html/%D8%A7%D9%84%D8%AA%D8%B1%D9%83%D9%8A%D8%B2-%D8%B9%D9%84%D9%89-%D8%B9%D9%86%D8%A7%D8%B5%D8%B1-%D8%B5%D9%81%D8%AD%D8%A9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r1324/" rel="">التركيز على عناصر صفحة الويب</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">نحو فهم أعمق لتقنيات HTML5</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1327</guid><pubDate>Mon, 27 Sep 2021 15:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62F;&#x644;&#x627;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x636;&#x645;&#x646;&#x629; &#x644;&#x639;&#x646;&#x627;&#x635;&#x631; &#x635;&#x641;&#x62D;&#x629; &#x627;&#x644;&#x648;&#x64A;&#x628; &#x648;&#x62F;&#x648;&#x631;&#x647;&#x627; &#x641;&#x64A; &#x62A;&#x639;&#x632;&#x64A;&#x632; &#x633;&#x647;&#x648;&#x644;&#x629; &#x627;&#x644;&#x648;&#x635;&#x648;&#x644;</title><link>https://academy.hsoub.com/programming/html/%D8%A7%D9%84%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B6%D9%85%D9%86%D8%A9-%D9%84%D8%B9%D9%86%D8%A7%D8%B5%D8%B1-%D8%B5%D9%81%D8%AD%D8%A9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%88%D8%AF%D9%88%D8%B1%D9%87%D8%A7-%D9%81%D9%8A-%D8%AA%D8%B9%D8%B2%D9%8A%D8%B2-%D8%B3%D9%87%D9%88%D9%84%D8%A9-%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-r1325/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_09/6155c47b40925_--------------------HTML----------And.png.0838e1bb8cd33a2d5ffcb3f54ab4e914.png" /></p>

<p>
	عرضنا في مقالة سابقة مسائل <a href="https://academy.hsoub.com/programming/html/%D8%B3%D9%87%D9%88%D9%84%D8%A9-%D9%88%D8%B5%D9%88%D9%84-%D8%AC%D9%85%D9%8A%D8%B9-%D8%A7%D9%84%D8%B2%D9%88%D8%A7%D8%B1-%D9%84%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r1323/" rel="">سهولة الوصول</a> أو ما نطلق عليها بالشمولية (شمل مختلف المستخدمين والزائرين سواء كانت لديهم مشاكل وإعاقات أم لا) وإتاحة جميع عمليات التفاعل مع صفحات الموقع باستخدام لوحة المفاتيح فقط، لاسيما للأشخاص الذين لا يستخدمون الفأرة أو أجهزة التأشير لأسباب متعددة مثل الإعاقات الجسدية أو بسبب مشكلة تقنية أو لمجرد تفضيلاتهم الشخصية. لا يتطلب تحقيق هذه السهولة الكثير من الجهد والوقت فيما لو خُطّط لها بشكل صحيح منذ البداية. مع التنويه إلى أن تحقيق هذه السهولة يُفضي في نهاية المطاف إلى صفحات سهلة الوصول وجذابًة للمستخدمين.
</p>

<p>
	نبدأ أولًا، في هذه المقالة، بعرض بعض المعلومات الأساسية عن التقنية المساعدة assistive technology وهو المصطلح المُستخدم للإشارة إلى الأدوات المساعدة، كقارئ الشاشة مثلًا، للأشخاص الذين يعانون من إعاقات تمنعهم من الوصول للمعلومات بشكل اعتيادي.
</p>

<p>
	ننتقل بعد ذلك لعرض بعض تجارب الاستخدام العامة، ونتعمق بعدها في تجارب مستخدمي التقنيات المساعدة.
</p>

<p>
	وفي النهاية، نعرض كيفية استخدام لغة HTML بفعالية لتحقيق تجربة استخدام لهؤلاء المستخدمين وكيفية تداخل ذلك مع مسألة <a href="https://academy.hsoub.com/programming/html/%D8%A7%D9%84%D8%AA%D8%B1%D9%83%D9%8A%D8%B2-%D8%B9%D9%84%D9%89-%D8%B9%D9%86%D8%A7%D8%B5%D8%B1-%D8%B5%D9%81%D8%AD%D8%A9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r1324/" rel="">التركيز</a> التي تعرضنا لها في مقالة سابقة.
</p>

<h2>
	التقنية المساعدة
</h2>

<p>
	يشمل مصطلح التقنية المساعدة جميع الأجهزة والبرمجيات والأدوات التي تُساعد أي شخص يعاني من إعاقة ما من إكمال مهمة معينة بنجاح. بشكل عام، يُمكن أن تكون الأداة شيئًا بسيطًا مثل عكاز المشي أو عدسة التكبير للقراءة، أو شيئًا ذو تقنية عالية مثل ذراع جسمال robot أو برنامج التعرف على الصور في هاتف ذكي.
</p>

<p style="text-align: center;">
	<img alt="001assistive-tech.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78294" data-unique="lgicfuwzu" src="https://academy.hsoub.com/uploads/monthly_2021_09/001assistive-tech.png.b3cd499cb7e22e918e29a9abb57a4b9b.png"></p>

<p>
	يُمكن أن تتضمن التقنية المساعدة شيئًا عامًا مثل تكبير/تصغير zoom المتصفح، أو خاصًا مثل وحدة تحكم مصممة خصيصًا للألعاب. كما يُمكن أن تكون جهازًا منفصلًا مثل شاشة برايل braille display (للكفيف) أو مُضمّنه بشكل كامل في برنامج ما مثل التحكم بالصوت. كما يُمكن أن تكون التقنية المساعدة مبنية مسبقًا built-in في نظام التشغيل، أو عبارة عن إضافة add-on ما مثل امتدادات المتصفح Chrome.
</p>

<p style="text-align: center;">
	<img alt="002assistive-tech2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78283" data-unique="bnlh2cegk" src="https://academy.hsoub.com/uploads/monthly_2021_09/002assistive-tech2.png.2e437bc9d14689aedf19dcd32fb9617a.png"></p>

<p>
	لا يُمكن الفصل بين التقنية عمومًا والتقنية المساعدة بشكل واضح، إذ تهدف التقنية بجميع أشكالها، في النهاية، إلى مساعدة الناس للقيام بمهامهم. يُمكن لنفس التقنية أن تُعدّ أحيانًا ضمن فئة التقنية المساعدة وأحيانًا خارجها.
</p>

<p>
	مثلًا: كانت الآلة الحاسبة الناطقة للمكفوفين من أقدم المنتجات التجارية لتركيب الكلام. أما اليوم، فقد أصبح تركيب الكلام موجودًا في كل مكان: بدءًا من برمجيات توجيه الاتجاهات driving directions إلى المساعدين الافتراضيين virtual assistants. على النقيض من ذلك، نجد اليوم العديد من التقنيات العامة تُستخدم لأغراض مساعدة مثل استخدام ضعاف البصر زوم zoom كاميرا هواتفهم الذكية لإلقاء نظرة أفضل على شيء صغير في العالم الحقيقي.
</p>

<p>
	يجب أن يأخذ مطور صفحات الويب بعين الاعتبار مجموعة متنوعة من التقنيات الممكنة. إذ قد يتفاعل الأشخاص مع موقع الويب باستخدام قارئ الشاشة screen reader أو عارض برايل braille display أو مكبر الشاشة screen magnifier أو متحكم الصوت voice control أو جهاز تبديل switch device أو أي شكل آخر من أشكال التقنيات المساعدة والتي تُكيّف واجهات الصفحات الافتراضية لإنشاء واجهات مُخصصة يُمكن استخدامها من قبل هؤلاء الأشخاص مع اختلاف أدوات الوصول المستخدمة.
</p>

<p>
	تعتمد العديد من هذه التقنيات المساعدة على الدلالات المُعبّر عنها برمجيًا programmatically expressed semantics لإنشاء تجربة استخدام سهلة الوصول. نتطرق أولًا إلى الإمكانات affordances قبل شرح الدلالات المعبر عنها برمجيًا.
</p>

<h2>
	الإمكانات الدالة على كيفية الاستخدام
</h2>

<p>
	يُمكن لنا، في أغلب الأحيان، بمجرد النظر على شكل أداة أو جهاز أن نُكوّن فكرة عن عمل هذا الجهاز وكيفية استخدامه. يُساهم التصميم الجيد للإمكانات Affordances (المهام المعينة التي توفرها الأغراض المختلفة) في توضيح آلية استخدامها للعموم بسهولة.
</p>

<p>
	مثلًا يُدرك أي شخص بمجرد النظر لغلاية ماء أو إبريق شاي أن الإبريق يُحمل من مقبضه وليس من فوهته حتى لو كانت المرة الأولى التي يرى فيها إبريق الشاي.
</p>

<p style="text-align: center;">
	<img alt="003teapot.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78284" data-unique="jcmpjdcid" src="https://academy.hsoub.com/uploads/monthly_2021_09/003teapot.png.1a9ea7b2208dbf5da8ebb94a70f4639d.png" style="width: 500px; height: auto;"></p>

<p>
	يُمكن تفسير ذلك بأن الإمكانات المُقدّمة من الإبريق تُشابه الإمكانات المُقدّمة من أغراض أخرى شبيهة به مثل أواني الري وأباريق المشروبات وأكواب القهوة وغيرها. بالطبع، يُمكنك مسك الإبريق من فوهته إلا أن تجارب المستخدم السابقة مع أغراض أخرى شبيهة بالإبريق تؤكد له بأن المقبض هو الخيار الأنسب.
</p>

<p>
	بشكل مماثل، تُعدّ إمكانات واجهات المستخدم البيانية الإجراءات التي يُمكن للمستخدم القيام بها، إلا أن هذه الإجراءات يُمكن أن تكون غامضة نظرًا لعدم وجود أي كائن مادي للتفاعل معه. تُصمّم واجهات المستخدم البيانية لتكون إمكاناتها واضحة دون أي لبس فيها باستخدام الأزرار buttons ومربعات الاختيار check boxes وأشرطة التمرير scrol bars بحيث يكون استخدامها واضحًا دون الحاجة لتدريب طويل للتعامل معها.
</p>

<p>
	مثلًا، يُمكن التعبير عن بعض عناصر التحكم الشائعة (إمكانات العناصر) كما يلي:
</p>

<ul>
<li>
		أزرار الانتقاء Radio buttons "يُمكن انتقاء واحدًا من الخيارات المتاحة".
	</li>
	<li>
		مربع الاختيار Check box "يُمكن اختيار نعم أو لا من هذا الخيار".
	</li>
	<li>
		حقل نصي Text field "يُمكن كتابة أي نص في هذه المساحة".
	</li>
	<li>
		قائمة منسدلة Dropdown "يُمكن فتح هذا العنصر لعرض الخيارات المتاحة".
	</li>
</ul>
<p>
	يُمكن الوصول للاستنتاجات السابقة حول عناصر التحكم بمجرد رؤيتها، إلا أن السؤال المطروح هو: ما وضع الشخص غير القادر على رؤية هذه العناصر وبالتالي لا يستطيع إدراك إمكاناتها بديهيًا؟. يجب على المطور إذًا التأكد من التعبير عن المعلومات بمرونة كافية للوصول إليها باستخدام التقنية المساعدة والتي يُمكن لها إنشاء واجهة بديلة لتناسب احتياجات المستخدم الخاصة.
</p>

<p>
	يُدعى هذا العرض غير المرئي من إمكانات الاستخدام بالدلالات semantics.
</p>

<h2>
	قارئ الشاشة
</h2>

<p>
	يُعدّ قارئ الشاشة screen reader من أكثر التقنيات المساعدة شيوعًا، وهو عبارة عن برنامج يقرأ النص المكتوب على الشاشة بصوتٍ عالٍ مُولدٍ تلقائيًا مما يُمكّن الأشخاص ذوي الإعاقة البصرية من استخدام الحواسيب.
</p>

<p>
	يُمكن مشاهدة هذا <a href="https://www.youtube.com/watch?v=QW_dUs9D1oQ" rel="external nofollow">الفيديو</a> لفيكتور تساران (الكفيف ومدير البرنامج الفني في شركة Google) وهو يتصفح الويب باستخدام قارئ الشاشة المدعو VoiceOver في نظام التشغيل OS X.
</p>

<p>
	لمعايشة تجربة الكفيف الفعلية مع قارئ الشاشة، يُمكن القيام بالتمرين التالي: فتح صفحة الويب التالية (باستخدام المتصفح Chrome) <a href="http://udacity.github.io/ud891/lesson3-semantics-built-in/02-chromevox-lite/" rel="external nofollow">ChromeVox lite demo page</a> والتي هي عبارة عن صفحة بسيطة مكتوبة بلغة جافا سكريبت تُخفى النصوص فيها لمحاكاة تجربة ضعف البصر ولإرغام المستخدم على استخدام قارئ الشاشة.
</p>

<p>
	يُمكن استخدام لوحة التحكم الموجودة أسفل الشاشة للتحكم في قارئ الشاشة والذي يحتوي على الحد الأدنى من الوظائف الضرورية. يتم التنقل في المحتوى باستخدام الزرين السابق <code>Previous</code> والتالي <code>Next</code>، كما يُمكن النقر على أي شيء باستخدام الزر <code>Click</code>.
</p>

<p>
	تُستخدم الصفحة السابقة بعد تمكين ChromeVox lite لاستخدام قارئ الشاشة. وفي الحقيقة، يوفر قارئ الشاشة (أو أي تقنية مساعدة أخرى) تجربة استخدام بديلة كاملة اعتمادًا على الدلالات المُعبّر عنها برمجيًا. فعوضًا عن الواجهة المرئية، يوفر قارئ الشاشة واجهة مسموعة.
</p>

<p>
	يُعلَم قارئ الشاشة ببعض المعلومات حول كل عنصر من عناصر الواجهة. يجب أن نتوقع من قارئ شاشة مصمم جيدًا أن يُخبر المستخدم بجميع، أو على الأقل بمعظم، المعلومات التالية حول عناصر الواجهة:
</p>

<ul>
<li>
		دور العنصر role أو نوعه type، إذا كان موصّفًا (يجب أن يكون).
	</li>
	<li>
		اسم العنصر name، إذا كان له اسم (يجب).
	</li>
	<li>
		قيمة العنصر value، إذا كان له قيمة (قد تكون أو لا تكون).
	</li>
	<li>
		حالة العنصر state، مثلًا: فيما إذا كان مُمكّنًا أو معطلاً (إن أمكن).
	</li>
</ul>
<p>
	يستطيع قارئ الشاشة إنشاء واجهة المستخدم البديلة لأن العناصر الأصلية native تحوي مسبقًا بيانات تعريف إمكانية الوصول. كما يستخدم المتصفح الشيفرة الأساسية native code لإظهار الواجهة الرسومية يستخدم قارئ الشاشة البيانات الوصفية metadata في عقد شجرة DOM لإنشاء إصدار سهل الوصول كما يُبين المثال التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78295" href="https://academy.hsoub.com/uploads/monthly_2021_09/004nativecodetoacc.png.ffa355aa950fa3b1b0836328d44e23a0.png" rel=""><img alt="004nativecodetoacc.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78295" data-unique="jxnxarztu" src="https://academy.hsoub.com/uploads/monthly_2021_09/004nativecodetoacc.thumb.png.768dea5365671cec02575743040ad45c.png" style="width: 600px; height: auto;"></a>
</p>

<h2>
	شجرة الوصول
</h2>

<p>
	لا نحتاج إلى إنشاء أي واجهة مرئية على الإطلاق في حال أردنا إنشاء واجهات لمستخدمي قارئ الشاشة فقط، وإنما يجب توفير المعلومات الكافية لقارئ الشاشة ليُنشئ الواجهة المسموعة الموافقة لاحتياجات هؤلاء المستخدمين.
</p>

<p>
	أي أنه يجب إنشاء نوع من واجهات برمجة التطبيقات <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> تصف بنية صفحة الويب على غرار DOM <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> مع معلومات وعقد أقل مما تحتاجه الواجهة المرئية. يُبين الشكل التالي مثالًا:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78287" href="https://academy.hsoub.com/uploads/monthly_2021_09/005treestructure.jpg.77bca3cd2e771ad65ae97acf5cbb200e.jpg" rel=""><img alt="005treestructure.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78287" data-unique="qkf1gktdt" src="https://academy.hsoub.com/uploads/monthly_2021_09/005treestructure.thumb.jpg.4294d04c52d771180d7eb60d93cbe9e4.jpg" style="width: 600px; height: auto;"></a>
</p>

<p>
	يُظهر المثال السابق ما يُمكن أن يُقدّم المتصفح لقارئ الشاشة. يٌعدّل المتصفح شجرة DOM إلى شكل قابل للاستخدام من قبل التقنية المساعدة. ندعو الشجرة المُعدّلة بشجرة الوصول Accessibility Tree.
</p>

<p>
	يُمكن تشبيه شجرة الوصول بصفحة ويب قديمة من التسعينيات مع بضعة صور والكثير من الروابط مع حقل وزر كما يُظهر الشكل التالي:
</p>

<p style="text-align: center;">
	<img alt="006google1998.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78288" data-unique="yg8ev445s" src="https://academy.hsoub.com/uploads/monthly_2021_09/006google1998.png.8e8540073bd408d95ea134d0141fcbc2.png"></p>

<p>
	يُمكن التمعن في صفحة الشكل السابق لتخيل تجربة مماثلة لما سيحصل عليه قارئ الشاشة، ومع ملاحظة بساطة الصفحة إلا أنها تُشبه إلى حدّ كبير شجرة الوصول.
</p>

<p>
	تتفاعل معظم التقنيات المساعدة مع شجرة الوصول، ويكون التدفق شبيهًا بما يلي:
</p>

<ol>
<li>
		يُقدّم التطبيق (المتصفح أو أي تطبيق آخر) إصدارًا دلاليًا من واجهة المستخدم إلى التقنية المساعدة عبر واجهة برمجة تطبيقات معينة <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>.
	</li>
	<li>
		تستخدم التقنية المساعدة المعلومات التي تصلها عبر واجهة برمجة التطبيقات لإنشاء عرضًا بديلًا لواجهة المستخدم. مثلًا: يُنشئ قارئ الشاشة واجهة يسمع فيها المستخدم تمثيلًا منطوقًا للتطبيق.
	</li>
	<li>
		يُمكن أن تسمح التقنية المساعدة للمستخدم بالتفاعل مع التطبيق بطرق مختلفة. مثلًا: توفر معظم قارئات الشاشة إمكانية محاكاة النقر بالفأرة أو بالإصبع.
	</li>
	<li>
		تُخبر التقنية المساعدة التطبيق برغبة المستخدم القيام بإجراء ما (مثل "النقر") عبر واجهة برمجة التطبيقات.
	</li>
	<li>
		يتحمل التطبيق بعد ذلك مسؤولية تفسير الإجراء بشكل مناسب ضمن واجهة المستخدم .
	</li>
</ol>
<p>
	أما مع متصفح الويب (منصة تشغيل تطبيق الويب)، فسيكون هنالك خطوة إضافية في كل اتجاه لأن المتصفح يحتاج لترجمة تطبيق الويب إلى شجرة وصول والتأكد من إطلاق الأحداث events المناسبة في جافا سكريبت والموافقة لأفعال المستخدم والتي تُمرر للمتصفح من التقنية المساعدة.
</p>

<p>
	يجب على مطور الويب التأكد من السلوك السابق (والذي هو من مسؤولية المتصفح) وتطوير صفحات ويب تستفيد من هذا السلوك لإنشاء تجارب استخدام سهلة الوصول.
</p>

<p>
	لتحقيق الهدف السابق (سهولة الوصول)، يجب التأكد من التعبير عن دلالات الصفحات بشكل صحيح مثل: التأكد من سهولة الوصول لأدوار roles وحالات states وخصائص properties جميع العناصر الهامة، مع تحديد أسماء هذه العناصر ووصفها. وبالتالي يُمكن للمتصفح بعد ذلك السماح للتقنية المساعدة بالوصول إلى هذه المعلومات لإنشاء تجربة مخصصة.
</p>

<h2>
	الدلالات في عناصر لغة HTML الأساسية
</h2>

<p>
	يُمكن للمتصفح تحويل شجرة DOM إلى شجرة الوصول لأن لمعظم عناصر HTML دلالة ضمنية. تستخدم شجرة DOM عناصر HTML الأساسية والتي تعمل بشكل قياسي موحد على مختلف المنصات. تُعالَج مسألة الوصول للعناصر الأساسية مثل الروابط والأزرار تلقائيًا. يُمكن الاستفادة من الدلالات المبنية مسبقًا built-in بكتابة تعليمات HTML التي تٌعبّر عن دلالات عناصر الصفحة.
</p>

<p>
	يُمكن أن يستخدم المطور أحيانًا عناصر شبيهة بالعناصر الأساسية إلا أنها ليست كذلك. مثلًا العنصر الشبيه بالزر في الصورة التالية ليس زرًا على الإطلاق:
</p>

<p style="text-align: center;">
	<img alt="007Button.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78289" data-unique="0iautmerg" src="https://academy.hsoub.com/uploads/monthly_2021_09/007Button.png.e357aedf91a981c08d0a64867dd64629.png"></p>

<p>
	يُمكن إنشاء العنصر السابق في HTML بعدة طرق مثلًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1308_7" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"button-ish"</span><span class="tag">&gt;</span><span class="pln">Give me tacos</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	لن يتمكن قارئ الشاشة من التعرف على العنصر السابق (ليس زرًا) عند الوصول إليه. كما يجب إضافة خاصية ترتيب الجدولة <code>tabindex</code> للعنصر السابق ليتمكن مستخدمو لوحة المفاتيح من الوصول إليه إذ لا يُمكن الوصول إليه (كما هو مُصمم حاليًا) إلا عن طريق الفأرة.
</p>

<p>
	يُمكن تجاوز المشكلة السابقة باستخدام عنصر زر عادي عوضًا عن <code>div</code>. يوفر استخدام عنصر أصلي للمطور معالجة مسائل الوصول باستخدام لوحة المفاتيح إذ يُعالجها العنصر الأصلي بمفرده. لا يجب التردد في استخدام العناصر الأصلية بحجة مظهرها البسيط الأساسي إذ يُمكن للمطور إضافة المظهر المرئي المناسب لها مع حفاظها على دلالاتها الضمنية وسلوكها الاعتيادي.
</p>

<p>
	لاحظنا سابقًا أن قارئ الشاشة يُعلن عن دور العنصر واسمه وحالته وقيمته. يسمح استخدام الدلالات الصحيحة بالوصول إلى الدور والحالة والقيمة إلا أنه يجب التأكد من سهولة العثور على اسم العنصر.
</p>

<p>
	يوجد عمليًا نوعين من الأسماء:
</p>

<ul>
<li>
		العناوين المرئية Visible labels والتي يربط المستخدمون من خلالها المعنى بالعنصر.
	</li>
	<li>
		البدائل النصية Text alternatives والتي تُستخدم عندما لا يكون هنالك حاجة لتسمية مرئية.
	</li>
</ul>
<p>
	لا نحتاج لعمل أي شيء مع العناصر النصية لأن محتواها النصي يُعرّف عنها، أما بالنسبة لبقية عناصر التحكم أو الإدخال أو العناصر ذات المحتوى المرئي، كالصور مثلًا، فيجب التأكد من وجود اسمها. عمليًا، يكون التحقق من الاسم على رأس قائمة التحقق من سهولة الوصول المعتمدّة من قبل المنظمة WebAIM (منظمة غير ربحية تُعنى بتقديم حلول سهولة الوصول منذ عام 1999).
</p>

<p>
	من الطرق المستخدمة اتباع التوصية: "يجب أن يكون لجميع عناصر الإدخال في النموذج عناوين نصية". يوجد طريقتين لربط عنوان label مع عنصر على النموذج مثل مربع الاختيار، تؤدي كل منهما إلى جعل نص التسمية هدفًا لنقر مربع الاختيار والذي يكون مساعدًا أيضًا لمستخدمي الفأرة أو شاشة اللمس. يُمكن لربط عنوان مع عنصر إما:
</p>

<ul>
<li>
		وضع عنصر الإدخال داخل عنصر عنوان كما تُبين الشيفرة التالية:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1308_9" style="">
<span class="tag">&lt;label&gt;</span><span class="pln">
  </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"checkbox"</span><span class="tag">&gt;</span><span class="pln">Receive promotional offers?
</span><span class="tag">&lt;/label&gt;</span></pre>

<p>
	حيث يكون مظهر مربع الاختيار مع إمكانية النقر على العنوان أو على مربع الاختيار لاختيار/إزالة الاختيار من مربع الاختيار:
</p>

<p style="text-align: center;">
	<img alt="008checkbox.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78290" data-unique="p0bc9rkre" src="https://academy.hsoub.com/uploads/monthly_2021_09/008checkbox.png.4ee5016e58782e7766b7ccd1a687feed.png"></p>

<p>
	أو:
</p>

<ul>
<li>
		استخدام الخاصية for لعنصر العنوان مع إسناد مُعرّف مربع الاختيار لها كما توضح الشيفرة التالية:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1308_11" style="">
<span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"promo"</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"checkbox"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"promo"</span><span class="tag">&gt;</span><span class="pln">Receive promotional offers?</span><span class="tag">&lt;/label&gt;</span></pre>

<p>
	يُمكن لقارئ الشاشة إظهار المعلومات التالية عندما يكون مربع الاختيار معنونًا بشكل صحيح: العنصر هو مربع اختيار بحالة الاختيار ويُدعى "Receive promotional offers?‎" كما يُبين الشكل التالي:
</p>

<p style="text-align: center;">
	<img alt="009checkboxreading.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78291" data-unique="a75vaxz5m" src="https://academy.hsoub.com/uploads/monthly_2021_09/009checkboxreading.png.599b43f55c413a36ea0a626a99262d27.png"></p>

<p>
	يُمكن استخدام قارئ الشاشة للعثور على التسميات غير المرتبطة مع العناصر بشكل صحيح عن طريق التنقل عبر الصفحة باستخدام مفتاح الجدولة <code>tab</code> والتحقق من الأدوار والحالات والأسماء المنطوقة.
</p>

<h2>
	النصوص البديلة للصور
</h2>

<p>
	تُعدّ الصور من أهم مكونات صفحات الويب، وهي بالطبع نقطة شائكة خاصًة للمستخدمين ضعاف البصر. ولذا يجب الآخذ بعين الاعتبار لدور الصورة في الصفحة عند تحديد النص البديل لها. لنعاين الصورة التالية مثلًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1308_13" style="">
<span class="tag">&lt;article&gt;</span><span class="pln">
  </span><span class="tag">&lt;h2&gt;</span><span class="pln">Study shows 9 out of 10 cats quietly judging their owners as they sleep</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
  </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"imgs/160204193356-01-cat-500.jpg"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/article&gt;</span></pre>

<p style="text-align: center;">
	<img alt="010cats.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78292" data-unique="uj52zaeyx" src="https://academy.hsoub.com/uploads/monthly_2021_09/010cats.jpg.07e5124e6f6447eeb6008b6275baf2f3.jpg"></p>

<p>
	تظهر صورة قطة في الصفحة في مقال عن سلوك القطط المعروف في حكمهم على الآخرين. يقوم قارئ الشاشة في هذا المثال بنطق اسم الصورة <code>"/160204193356-01-cat-500.jpg"</code> بشكل صحيح إلا أن هذا غير مفيد للمستخدم على الإطلاق.
</p>

<p>
	يُمكن استخدام الخاصية <code>alt</code> لتوفير نص بديل ذو معنى مفيد لهذه الصورة مثل "قطه تُحدّق في الفضاء بشكل متوعد"
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1308_15" style="">
<span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"/160204193356-01-cat-500.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"A cat staring menacingly off into space"</span><span class="tag">&gt;</span></pre>

<p>
	يُظهر قارئ الشاشة الوصف الموجز للصورة في الشريط الأسود VoiceOver، ويُمكن للمستخدم بعدها اختيار الانتقال للمقالة.
</p>

<p style="text-align: center;">
	<img alt="011funioncat2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78293" data-unique="g6yep7f16" src="https://academy.hsoub.com/uploads/monthly_2021_09/011funioncat2.png.433ce550a631dcbf6144d6a44078cd7e.png"></p>

<p>
	يُمكن أن نشير إلى الملاحظتين التاليتين عن الخاصية <code>alt</code>:
</p>

<ul>
<li>
		تسمح الخاصية <code>alt</code> بتحديد نص بسيط لعرضه في أي وقت لا تكون فيه الصورة متاحة، مثل حالة الفشل في تحميلها أو التعامل معها من قبل زاحف الويب crawler أو المرور عليها من قبل قارئ الشاشة.
	</li>
	<li>
		تختلف الخاصية <code>alt</code> عن خاصية العنوان <code>title</code> أو أي نوع من التسميات التوضيحية في أنها تُستخدم فقط عند تعذر توفير الصورة للمستخدم.
	</li>
</ul>
<p>
	تُعدّ كتابة نصًا بديلًا مفيدًا عملًا فنيًا إذ يجب أن يعكس النص مفهوم الصورة بشكل واضح وضمن سياق استخدامها.
</p>

<p>
	يُمكن مثلًا وضع النص البديل المناسب التالي لصورة شعار موقع الصفحة السابقة The Funion logo.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1308_17" style="">
<span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"logo"</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"logo.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"The Funion logo"</span><span class="tag">&gt;</span></pre>

<p>
	قد يكون إعطاء الشعار نصًا بديًلا بسيطًا مثل "الصفحة الرئيسية" أمرًا جاذبًا أكثر للمطور (لأن الشعار موضوع في الصفحة الرئيسة) إلا أن هذا قد يُربك كلًا من ضعاف البصر وجيدي النظر على وجه السواء.
</p>

<p>
	تؤدي القيمة "الصفحة الرئيسية" إلى إرباك مستخدم قارئ الشاشة الذي يريد تحديد موقع الشعار الموجود في رأس الصفحة، كذلك سيواجه المستخدم المبصر نفس السؤال: ماذا يؤدي النقر على الشعار؟
</p>

<p>
	وبالمقابل، لا يكون مفيدًا دومًا وصف الصورة. لنأخذ مثلًا حالة صورة العدسة المكبرة التي توضع داخل زر البحث الذي له النص "بحث". بالتأكيد لو لم يكن النص موجودًا، لكان من المفيد إعطاء الخاصية <code>alt</code> للصورة القيمة "بحث" إلا أنه مع وجود النص سيقرأ قارئ الشاشة هذا النص بصوتٍ عالٍ وسيكون من التكرار قراءة قيمة الخاصية <code>alt</code> للصورة.
</p>

<p>
	يؤدي عدم وضع قيمة للخاصية <code>alt</code> للصورة إلى قراءة اسم الملف من قبل قارئ الشاشة في أغلب الأحيان، والذي يكون أمرًا مربكًا وغير مفيد. يُمكن اللجوء في مثل هكذا حالات إلى وضع قيمة فارغة للخاصية <code>alt</code> وبالتالي سيتخطى قارئ الشاشة الصورة بشكل كامل.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1308_19" style="">
<span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"magnifying-glass.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">""</span><span class="tag">&gt;</span></pre>

<p>
	والخلاصة، يجب أن تحتوي جميع الصور على الخاصية <code>alt</code>، إلا أنه ليس بالضرورة أن تكون قيمتها نصًا. إذ يجب أن تحتوي الصور الهامة على نص بديل يصف الصورة بإيجاز، أما الصور الموضوعة بهدف الزخرفة فقط، فيجب وضع قيمة فارغة للخاصية <code>alt</code> أي <code>alt=""‎</code>
</p>

<h2>
	الدلالات والتنقل في المحتوى
</h2>

<p>
	تعرفنا فيما سبق على الإمكانات والدلالات وكيفية استخدام التقنيات المساعدة لشجرة الوصول بهدف إنشاء تجربة استخدام بديلة لمستخدمي هذه التقنيات. يُمكن تحقيق سهولة الوصول بجهد بسيط في حال كتابة عناصر HTML بطريقة مُعبرّة عن دلالاتها إذ يوفر الكثير من عناصر HTML الدلالات والسلوك الداعم المطلوب بشكل مبني مسبقًا built-in.
</p>

<p>
	نعرض فيما يلي بعض الدلالات الأقل وضوحًا والتي تُعدّ هامة جدًا لمستخدمي قارئ الشاشة لا سيما مسائل التنقل في محتوى الصفحات. من السهولة معاينة صفحة مليئة بعناصر التحكم والعثور بسرعة على المطلوب إلا أنه سيكون من الأصعب قراءة محتوى الصفحات الزاخرة بالمحتوى مثل صفحات الويكيبيديا وصفحات الأخبار من الأعلى للأسفل، وهنا تبرز الحاجة الماسة لطرق تنقل في المحتوى بفعالية أكبر.
</p>

<p>
	يحمل مطوري الويب بعض الأفكار الخاطئة حول برامج قراءة الشاشة بأنها مملة وبطيئة وأن كل شيء موجود على الشاشة يجب أن يتمكن المستخدم من وضع التركيز عليه. هذا ليس هو الحال في الكثير من الأحيان.
</p>

<p>
	يعتمد مستخدمو قارئ الشاشة على قائمة الترويسات headings لتحديد موقع المعلومات في أغلب الأحيان. كما تمتلك معظم برامج قراءة الشاشة طرقًا سهلة لإيجاد قائمة ترويسات الصفحة وهي ميزة هامة تُدعى الدوّار rotor. نعرض فيما يلي كيفية استخدام العناوين في HTML بشكل فعّال لدعم هذه الميزة.
</p>

<h3>
	استخدام العناوين بفعالية
</h3>

<p>
	نُعيد التذكير أولًا بأن ترتيب العناصر في شجرة DOM أمرًا هامًا سواءً بالنسبة لترتيب التركيز focus أو بالنسبة لترتيب قارئ الشاشة. يُمكن باستخدام برامج قراءة الشاشة مثل VoiceOver و NVDA و JAWS و ChromeVox استنتاج أن قائمة الترويسات headings list تتبع ترتيب شجرة DOM وليس ترتيب ظهورها على الشاشة.
</p>

<p>
	يعود هذا الأمر إلى أن قارئ الشاشة يتعامل مع شجرة الوصول accessibility tree والتي هي بدورها ناتجة عن شجرة DOM أي أن الترتيب المُعتمد من قبل قارئ الشاشة هو ترتيب شجرة DOM في نهاية المطاف. يدّل ذلك على أن تنظيم بنية الترويسات المناسبة أصيح أمرًا هامًا وضروريًا أكثر مما مضى.
</p>

<p>
	توضع مستويات الترويسات heading levels، في الصفحات المُنظّمة جيدًا، بشكل هرمي لضمان علاقة أب/ابن بين أقسام المحتوى. تُشير توصيات WebAIM إلى هذه التقنية مرارًا وتكرارًا. نعرض فيما يلي بعض الروابط التي تُشير إلى:
</p>

<ul>
<li>
		استخدام الترميز الدلالي لتعيين العناوين <a href="https://webaim.org/standards/wcag/checklist#sc1.3.1" rel="external nofollow">1.3.1</a>.
	</li>
	<li>
		استخدام العناوين كتقنية لتجاوز كتل المحتوى <a href="https://webaim.org/standards/wcag/checklist#sc2.4.1" rel="external nofollow">2.4.1</a>.
	</li>
	<li>
		بعض التفاصيل حول كتابة عناوين مفيدة <a href="https://webaim.org/standards/wcag/checklist#sc2.4.6" rel="external nofollow">2.4.6</a>.
	</li>
	<li>
		تحديد الأقسام الفردية من المحتوى باستخدام العناوين عندما يكون ذلك مناسبًا <a href="https://webaim.org/standards/wcag/checklist#sc2.4.10" rel="external nofollow">2.4.10</a>
	</li>
</ul>
<p>
	ليس بالضرورة أن تكون كل العناوين مرئية على الشاشة. مثلًا: تضع صفحات الويكيبيديا بعض العناوين عمدًا خارج الشاشة وتُتيحهم فقط لقارئات الشاشة وللتقنيات المساعدة الأخرى.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1308_21" style="">
<span class="tag">&lt;style&gt;</span><span class="pln">
  </span><span class="pun">.</span><span class="pln">sr</span><span class="pun">-</span><span class="pln">only </span><span class="pun">{</span><span class="pln">
    position</span><span class="pun">:</span><span class="pln">absolute</span><span class="pun">;</span><span class="pln">
    left</span><span class="pun">:-</span><span class="lit">10000px</span><span class="pun">;</span><span class="pln">
    top</span><span class="pun">:</span><span class="kwd">auto</span><span class="pun">;</span><span class="pln">
    width</span><span class="pun">:</span><span class="lit">1px</span><span class="pun">;</span><span class="pln">
    height</span><span class="pun">:</span><span class="lit">1px</span><span class="pun">;</span><span class="pln">
    overflow</span><span class="pun">:</span><span class="pln">hidden</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="tag">&lt;/style&gt;</span><span class="pln">

</span><span class="tag">&lt;h2</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"sr-only"</span><span class="tag">&gt;</span><span class="pln">This heading is offscreen.</span><span class="tag">&lt;/h2&gt;</span></pre>

<p>
	يُمكن العودة لمقالة المنظمة WebAIM حول <a href="https://webaim.org/techniques/css/invisiblecontent/" rel="external nofollow">المحتوى خارج الشاشة</a> للمزيد من المعلومات.
</p>

<p>
	يُمكن، في بعض التطبيقات المعقدة، أن تكون هذه الطريقة جيدة لاستيعاب العناوين عندما لا تتسع المساحة المتاحة لعرضها أو لا يكون لها دورًا هامًا في سياق العرض الحالي.
</p>

<p>
	تحذير: من المهم عدم المبالغة في استخدام هذه الطريقة (إخفاء العناوين). يجب الانتباه إلى أن مستخدمي التقنية المساعدة قد يكونوا قادرين أيضًا على رؤية الشاشة بأنفسهم، لذا فإن التركيز فقط على إنشاء محتوى يُناسب "قارئ الشاشة فقط" قد يؤدي في الواقع إلى تدهور تجربة الاستخدام لبعض المستخدمين، كما يُمكن أن يؤدي لكثير من الإرباك أثناء صيانة التطبيق من قبل المطور.
</p>

<h3>
	خيارات التنقل الأخرى
</h3>

<p>
	يوجد العديد من العناصر الأخرى التي يُمكن استخدامها للتنقل في الصفحة بما فيها الروابط links وعناصر النموذج controls والعلامات landmarks إضافًة إلى الترويسات.
</p>

<p>
	يُمكن لقارئ الصفحة استخدام ميزة الدوّار rotor (طريقة سهلة لتحديد قائمة الترويسات في صفحة) للوصول إلى قائمة روابط في الصفحة. قد تحتوي الصفحة، مثل صفحات الويكيبيديا، على الكثير من الروابط التي غالبًا ما يبحث المستخدم عن تعريف لمصطلح ما ضمنها. يؤدي هذا إلى الاقتصار على زيارة الروابط التي تحوي المصطلح بدلًا من كل ظهور لمصطلح على الصفحة.
</p>

<p>
	يُمكن أن تكون هذه الميزة مفيدة في حال عثور قارئ الشاشة على الرابط وكان لنص الرابط معنى واضح. نعرض فيما يلي بعض الممارسات السيئة والتي تُعطي روابط صعبة الوصول:
</p>

<ul>
<li>
		استخدام الروابط <code>&lt;a&gt;</code> دون تحديد قيمة للخاصية <code>href</code> (لاسيما في التطبيقات ذات صفحة واحدة) مما يوقع قارئات الشاشة في مشاكل عديدة.
	</li>
	<li>
		استخدام الأزرار مع الروابط مما يجعل قارئ الشاشة يُعامل المحتوى كرابط ويُهمل وظيفة الزر. يجب في مثل هذه الحالة استبدال الرابط بزر حقيقي واستخدام تنسيق مناسب له.
	</li>
	<li>
		استخدام الصور كمحتوى للروابط. يُمكن في بعض الأحيان أن تكون مثل هذه الصور غير قابلة للاستخدام من قبل قارئ الشاشة. لضمان وصول التقنية المساعدة للرابط يجب التأكد من وضع الخاصية <code>alt</code> للصورة.
	</li>
</ul>
<p>
	يجب الانتباه لتوفير نصًا واضحًا يُعطي معلومات مفيدة حول المكان الذي ينقلنا الرابط إليه. مثلًا لا يوفر النص "معرفة المزيد" أو "انقر هنا" أي معلومات دلالية، على خلاف النصوص مثل "تعرّف على المزيد حول التصميم سريع الاستجابة" أو "مشاهدة البرنامج التعليمي" والتي تُساعد برامج قراءة الشاشة في توفير سياق مفيد حول الروابط.
</p>

<p>
	يُمكن للدوّار أيضًا استرداد قائمة التحكم في النموذج والتي تُمكّن القراء من البحث عن عناصر مُحدّدة والانتقال إليها مباشرًة.
</p>

<p>
	ترتكب برامج قارئات الشاشة العديد من أخطاء التهجئة أو النطق مثل قراءة رقم الهاتف كعدد صحيح كبير أو قراءة النص المكتوب بحروف كبيرة كاختصار أو قراءة اسم "Hsoub" مثل "saub". من حسن الحظ، يعتاد المستخدمون على مثل هذه الأخطاء ويألفونها ويأخذوها بالحسبان.
</p>

<p>
	يحاول بعض المطورين توفير النص مُهجًأ صوتيًا لقارئ الشاشة. مثلًا: لنأخذ التهجئة البسيطة التالية: "<strong>don't do it</strong>" والتي ستُفاقم المشكلة! مثلًا إذا كان المستخدم يستخدم شاشة برايل للعرض فستُكتب الكلمات بشكل غير صحيح مما سيؤدي لمزيد من الالتباس. بما أن قارئات الشاشة تقرأ الكلمات بصوت مرتفع يُمكن ترك الأمر لقارئ النص للتحكم في تجربته وقرار متى يكون ذلك ضروريًا.
</p>

<p>
	يُمكن للقارئ استخدام الدوّار rotor لمعاينة قائمة العلامات landmarks list لمساعدته في إيجاد المحتوى الأساسي ومجموعة علامات التنقل navigational landmarks التي توفرها عناصر العلامات في HTML.
</p>

<p>
	توفر HTML5 مجموعة من العناصر الجديدة التي يُمكن لها أن تُساعد في تحديد البنية الدلالية للصفحة بما فيها الترويسة <code>header</code> والتذييل <code>footer</code> والتنقل <code>nav</code> والمقال <code>article</code> والقسم <code>section</code> والجزء الرئيسي <code>main</code> والجزء الجانبي <code>aside</code>. توفر هذه العناصر أدلة على هيكلية الصفحة دون فرض أي تصميم مبني مسبقًا (وهو ما يجب فعله باستخدام CSS). تحل هذه العناصر الهيكلية الدلالية مكان كتل <code>div</code> المتعدّدة والمتكررة وتوفر طريقة وصفية أوضح للتعبير عن بنية الصفحة بشكل حدسي سواء للمطورين أو للمتصفحين.
</p>

<p>
	ترجمة -وبتصرف- لمجموعة المقالات: <a href="https://developers.google.com/web/fundamentals/accessibility/semantics-builtin" rel="external nofollow">Introduction to Semantics</a> <a href="https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree" rel="external nofollow">The Accessibility Tree</a> <a href="https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/text-alternatives-for-images" rel="external nofollow">Text Alternatives for Images</a> <a href="https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/navigating-content" rel="external nofollow">Semantics and Navigating Content</a>
</p>

<p>
	للمؤلفين: Meggin Kearney وDave Gash وAlice Boxhall.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">تعلم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%B9%D9%84%D9%88%D9%85-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8/" rel="">المدخل الشامل لتعلم علوم الحاسوب</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1325</guid><pubDate>Fri, 24 Sep 2021 15:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x631;&#x643;&#x64A;&#x632; &#x639;&#x644;&#x649; &#x639;&#x646;&#x627;&#x635;&#x631; &#x635;&#x641;&#x62D;&#x629; &#x627;&#x644;&#x648;&#x64A;&#x628;</title><link>https://academy.hsoub.com/programming/html/%D8%A7%D9%84%D8%AA%D8%B1%D9%83%D9%8A%D8%B2-%D8%B9%D9%84%D9%89-%D8%B9%D9%86%D8%A7%D8%B5%D8%B1-%D8%B5%D9%81%D8%AD%D8%A9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r1324/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_09/6155bddff23f5_.png.043bce576978572e8c41db6db5328e86.png" /></p>

<p>
	نُناقش مسألة التركيز Focus في القسم الأول من هذه المقالة التعليمية، كما نشرح آلية ترتيب عناصر شجرة DOM في القسم الثاني منها، ونُنهي المقالة بشرح استخدام فهرس الجدولة tabindex.
</p>

<h2>
	مقدمة في التركيز
</h2>

<p>
	نبدأ أولًا بشرح عملية التحكم بالتركيز على العناصر وآليات إدارته، وحيث يختص التركيز بعناصر التحكم (عناصر الإدخال مثل الحقول وصناديق التحقق والأزرار والروابط) التي تتلقى حاليًا الدخل من لوحة المفاتيح أو من الحافظة عند إجراء عملية لصق. يُعدّ التركيز نقطة الانطلاق الأولى لتعلم مسائل إمكانية الوصول لاسيما أننا جميعًا نتعامل مع لوحة المفاتيح بسهولة، كما سيستفيد جميع المستخدمين من نتائج إعداد التركيز المناسب.
</p>

<p>
	قد يعتمد المستخدمون الذين يعانون من إعاقات حركية، والتي تتراوح من التواء الرسغ إلى الشلل الدائم، على لوحة مفاتيح أو جهاز تبديل للتنقل في صفحة الويب، مما يستلزم توفير تجربة استخدام جيدة ووضع استراتيجية تركيز ملائمة لهم. تُساهم عملية التنقل في الموقع بسرعة في رفع انتاجية المستخدمين لاسيما المحترفين منهم والذين يستخدمون اختصارات لوحة المفاتيح بسهولة.
</p>

<p>
	وبالمحصلة، تضمن استراتيجية التركيز المُنفذّة جيدًا تمتع كل مستخدم بتجربة أفضل. سنرى لاحقًا أن الجهد الذي قد يبذله المطور ضروري للسماح لذوي الإعاقات المختلفة باستخدام الأدوات المساعدة كما أنه يُساعد في إغناء تجارب تعامل كل المستخدمين مع صفحات الويب المطورة.
</p>

<h3>
	ما هو التركيز
</h3>

<p>
	يُحدّد التركيز عنصر التحكم الحالي الذي يتلقى الإدخالات من لوحة المفاتيح ويعرض الأحرف التي يكتبها المستخدم، كما يستقبل هذا العنصر بيانات أي عملية لصق من الحافظة.
</p>

<p style="text-align: center;">
	<img alt="001TextBox.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78276" data-unique="0mu642jil" src="https://academy.hsoub.com/uploads/monthly_2021_09/001TextBox.png.e640895a60a3dbf069142ccb57c5168d.png" style=""></p>

<p>
	يُميّز العنصر الحاصل على التركيز بواسطة إطار لوني حوله يعتمد نمطه على المستعرض أو على أسلوب التنسيق المُحدّد من قبل مطور صفحة الويب. يقوم المستعرض Chrome مثلًا بوضع إطار أزرق، بينما يقوم Firefox بوضع إطار متقطع.
</p>

<p style="text-align: center;">
	<img alt="002Button.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78277" data-unique="7t5gpg0ul" src="https://academy.hsoub.com/uploads/monthly_2021_09/002Button.png.6ef752ce8f63e6bbe42b6984f08de965.png" style=""></p>

<p>
	يتعامل بعض المستخدمين مع حاسوبهم حصرًا باستخدام لوحة المفاتيح وبالتالي يكون التركيز بالنسبة لهم أمرًا هامًا جدًا فهو وسيلتهم للوصول إلى أي كائن في صفحة الويب. تنص قائمة التحقق من مجموعة إمكانية الوصول Web AIM (اختصارًا إلى Web Accessibility In Mind) في الفقرة السابقة منها على أن جميع وظائف صفحة الويب يجب أن تكون ممكنة الوصول عن طريق لوحة المفاتيح (إلا في حالات خاصة لا يُمكن القيام بها باستخدام لوحة المفاتيح كالرسم اليدوي مثلًا).
</p>

<p>
	يُمكن نقل التركيز من عنصر لآخر باستخدام مفتاح الجدولة <code>Tab</code> أو التركيب <code>Shift+Tab</code> أو باستخدام مفاتيح الأسهم. يختلف هذا الأسلوب قليلًا في نظام التشغيل Mac OSX. يسمح لك المتصفح Chrome بالتنقل باستخدام المفتاح Tab بينما يجب استخدام <code>Option+Tab</code> في المتصفح Safari. يُمكن تغيير إعدادات نقل التركيز باستخدام لوحة المفاتيح عن طريق نافذة لوحة المفاتيح من تفضيلات النظام:
</p>

<p style="text-align: center;">
	<img alt="003Preferences.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78278" data-unique="zo3qklyyr" src="https://academy.hsoub.com/uploads/monthly_2021_09/003Preferences.png.384aa333a4c8eed43679fe9e117876a5.png" style=""></p>

<p>
	يُدعى ترتيب نقل التركيز من عنصر لآخر للأمام أو للخلف بترتيب الجدولة، وهو من الأمور التي يجب على مطور صفحة الويب أن يأخذها بالحسبان فيتحقق من وجود ترتيب انتقال ملائم بين العناصر في الصفحة.
</p>

<h3>
	تعريف إمكانية التركيز
</h3>

<p>
	يُمكن التركيز على أي عنصر من عناصر HTML التي تسمح للمستخدم بالتفاعل معها (تغيير قيمها أو حالتها) مثل صناديق النصوص والأزرار والقوائم، وتدخل تلقائيًا في ترتيب الجدولة وتتفاعل مع أحداث لوحة المفاتيح دون أي تدخل من قبل مطور الصفحة.
</p>

<p style="text-align: center;">
	<img alt="004focusable (1).png" class="ipsImage ipsImage_thumbnailed" data-fileid="78264" data-unique="o3u8bmfso" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155bde2e6bdf_004focusable(1).png.e69a405358f0700cc4d2a04e3cbdd258.png" style=""></p>

<p>
	أما العناصر التي لا يتفاعل المستخدم معها مثل الفقرات والحاويات div فلا ينتقل التركيز عليها ولا تدخل في ترتيب الجدولة.
</p>

<p style="text-align: center;">
	<img alt="005notfocusable (1).png" class="ipsImage ipsImage_thumbnailed" data-fileid="78263" data-unique="085rx2fgn" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155bde252caa_005notfocusable(1).png.2af0e81b801cdd716ed7aeb4781a0855.png" style=""></p>

<h3>
	تجربة التركيز
</h3>

<p>
	نعرض في المثال التالي تقانات التركيز التي شرحناها سابقًا: افتح المستعرض Chrome وانتقل للرابط <a href="http://udacity.github.io/ud891/lesson2-focus/01-basic-form/" rel="external nofollow">airline site mockup page</a> واطلب تذكرة سفر باستخدام <strong>لوحة المفاتيح حصرًا</strong> (لا تتفاعل الصفحة بأي حال مع الفأرة).
</p>

<p style="text-align: center;">
	<img alt="006airlinesite.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78265" data-unique="8qq9d5dt9" src="https://academy.hsoub.com/uploads/monthly_2021_09/006airlinesite.png.816e222019f96617a4542e9bb15cc216.png" style=""></p>

<p>
	عليك ملء المعلومات التالية:
</p>

<ul>
<li>
		اتجاه واحد للسفر oneway
	</li>
	<li>
		إلى مدينة Arrival ملبورن Melbourne
	</li>
	<li>
		تاريخ المغادرة Depart Date 12/10/2017
	</li>
	<li>
		تاريخ العودة Return Data 23/10/2017
	</li>
	<li>
		مقعد جانب النافذة Preferred seat type
	</li>
	<li>
		لا تطلب تلقي إشعارات العروض الترويجية Receive promotional offers
	</li>
</ul>
<p>
	بمجرد أن تنتهي من إتمام عملية إدخال البيانات دون أي خطأ ومن ثم نقر زر البحث، سيتم مسح البيانات وإعادة تهيئة نموذج إدخال جديد (قم بالتجربة المطلوبة ومن ثم أتمم القراءة).
</p>

<p>
	لنعاين الآن كيف يتفاعل نموذج الصفحة السابق مع إدخالات لوحة المفاتيح. يؤدي الضغط على مفتاح الجدولة <code>Tab</code> في البداية إلى إضاءة الروابط أعلى النموذج (الرحلات Flights، الفنادق Hotels، سيارات الأجرة Rental Cars)، وإذا استمريت بضغط مفتاح الجدولة مرارًا ستنتقل إلى مجموعة أزرار الانتقاء والتي عليك الآن استخدام مفاتيح الأسهم للتنقل فيما بينها (نوع الرحلة). اخرج من مجموعة أزرار الانتقاء باستخدام مفتاح الجدولة <code>Tab</code> لتنتقل إلى حقل الاسم ومن ثم إلى حقل العنوان للكتابة فيهما. عند وصولك للقائمة المنسدلة للمدن، يُمكنك اختيار عنصر منها عن طريق مفاتيح الأسهم أو عن طريق البدء بكتابة الأحرف الأولى من اسم المدينة ليتم ملء الحقل بالمدينة المناسبة. عند وصولك لقائمة نوع الكرسي يُمكن اختيار عنصر من القائمة باستخدام مفاتيح الأسهم أو بكتابة أحد الأحرف w أو a أو n لتحديد عنصر القائمة الموافق (لا تفضيل No preference، ممر Aile، نافذة Window). يُمكنك إلغاء تحديد صندوق التحقق (لطلب عدم تلقي إشعارات الحملات الترويجية) بالضغط على مفتاح المسافة عند وصول التركيز لصندوق التحقق. ضع أخيرًا التركيز على زر البحث Search وانقر المفتاح <code>Enter</code> لإرسال بيانات النموذج.
</p>

<p>
	يبدو أن التفاعل مع النموذج باستخدام لوحة المفاتيح فقط أسهل وأسرع من استخدام الفأرة ولوحة المفاتيح معًا (وضياع الوقت بالتنقل بينهما)، وهو أمر سهل التحقيق من قبل المطور لأن ما عليه سوى استخدام <a href="https://wiki.hsoub.com/HTML" rel="external">عناصر HTML الأساسية</a> ولن يحتاج إلى كتابة أي شيفرة إضافية لإدارة عمليات التركيز.
</p>

<h2>
	أهمية ترتيب العناصر في شجرة DOM
</h2>

<p>
	يؤدي استخدام عناصر HTML الأساسية إلى الحصول على ترتيب انتقال تركيز ملائم إذ أن ترتيب الانتقال بين العناصر يكون وفق ترتيبها في نموذج كائن الوثيقة DOM.
</p>

<p>
	يكون ترتيب انتقال التركيز بين الأزرار في المثال التالي وفق ترتيبها في DOM أي الزر "I Should" أولًا ومن ثم الزر "Be Focused" و أخيرًا الزر "Last":
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6370_15" style="">
<span class="tag">&lt;button&gt;</span><span class="pln">I Should</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;button&gt;</span><span class="pln">Be Focused</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;button&gt;</span><span class="pln">Last!</span><span class="tag">&lt;/button&gt;</span></pre>

<p>
	<iframe allow="clipboard-write https://developers-dot-devsite-v2-prod.appspot.com" allowfullscreen="" data-ss1637657846="1" data-ss1637657940="1" data-ss1637662916="1" name="goog_1785065003" src="https://developers.google.com/web/fundamentals/accessibility/focus/dom-order-matters_864297fc9cc5b1ee3e45307e66bfb7da497a8d08c4fc4014e46928b952a11e18.frame"></iframe>يجب الانتباه إلى بعض المشاكل التي قد تنجم عند استخدام تنسيق CSS لاسيما إذا كان ذلك يؤثر على أمكنة تموضع العناصر. فمثلًا إذا وضعت الخاصية (عائم إلى اليمين) للزر الأول "float: right" فسيظهر هذا الزر أقصى اليمين إلا أن ترتيبه في الجدولة سيبقى الأول لأنه الأول في ترتيب العناصر ضمن DOM. بالتأكيد، سيُسبب هذا إرباكًا للمستخدم إذ سيقفز بزر الجدولة <code>Tab</code> من الزر أقصى اليمين "I Should" إلى الزر أقصى اليسار "Be Focused" بعده.
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_6370_17" style="">
<span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">style</span><span class="pun">=</span><span class="atv">"</span><span class="kwd">float</span><span class="pun">:</span><span class="pln"> right</span><span class="atv">"</span><span class="tag">&gt;</span><span class="pln">I Should</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;button&gt;</span><span class="pln">Be Focused</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;button&gt;</span><span class="pln">Last!</span><span class="tag">&lt;/button&gt;</span></pre>

<p>
	<iframe allow="clipboard-write https://developers-dot-devsite-v2-prod.appspot.com" allowfullscreen="" data-ss1637657846="1" data-ss1637657940="1" data-ss1637662916="1" name="goog_1785065004" src="https://developers.google.com/web/fundamentals/accessibility/focus/dom-order-matters_0b57b953097e534b3c7800bac5f2fc8a0d875beac58184beaa1014ea737da48c.frame"></iframe>تنص قائمة التحقق من مجموعة إمكانية الوصول Web AIM اختصارًا Web Accessibility In Mind على أن الترتيب المرئي (ترتيب القراءة) يجب أن يكون متوافقًا مع ترتيب الجدولة كي لا نُربك المستخدم الذي يعتمد على لوحة المفاتيح.
</p>

<h3>
	المحتوى غير الظاهر
</h3>

<p>
	يجب الانتباه إلى انتقال التركيز على عناصر غير ظاهرة مما يُربك المستخدم الذي سيشعر عندها بفقدان أو ضياع مؤشر التركيز وسيبدأ بضغط مفتاح الجدولة مرارًا ليكتشف أن مؤشر التركيز يظهر ويختفي! يُمكن أن تظهر هذه المشكلة مثلًا عند استخدام لوحة تنقل جانبية متجاوبة responsive side navigation panel وعندها يجب أن نمنع التركيز من الانتقال للوحة عندما لا تكون ظاهرة، ونسمح له بالانتقال لها فقط عندما يكون المستخدم في حالة تفاعل معها.
</p>

<p style="text-align: center;">
	<img alt="009navpanel.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78267" data-unique="5jfpb3ups" src="https://academy.hsoub.com/uploads/monthly_2021_09/009navpanel.png.6d867f8bc5d920b3fc3994c26aee1617.png" style=""></p>

<p>
	قد يتوجب عليك أحيانًا البحث عن موضع التركيز باستخدام خاصية العنصر النشط <code>document.activeElement</code> لمعرفة العنصر النشط حاليًا، ومن ثم إظهاره باستخدام <code>display: none</code> أو <code>visibility: hidden</code> أو إخفائه باستخدام <code>display: block</code> أو <code>visibility: visible</code> حسب الحالة.
</p>

<p style="text-align: center;">
	<img alt="010visiblehidden.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78268" data-unique="8bt9ttm3r" src="https://academy.hsoub.com/uploads/monthly_2021_09/010visiblehidden.png.fe83fb89fcdf1d8d7aefa1e0dd320c01.png" style=""></p>

<p>
	نؤكد أخيرًا على ضرورة قيام المطور بتجريب عملية التنقل مرارًا وتكرارًا في صفحته المطورة قبل نشرها للعموم ليتأكد من عدم وجود أي خلل في التركيز كاختفائه أو وجود ترتيب غير ملائم، وفي حال وجود أي خلل فيُمكن تصحيحه عن طريق إعادة ترتيب العناصر في نموذج كائن الوثيقة DOM أو عن طريق إخفاء العناصر عندما تكون غير ظاهرة في الشاشة ومن ثم إظهارها عندما يتفاعل المستخدم معها.
</p>

<h2>
	استخدام فهرس الجدولة tabindex
</h2>

<p>
	يُلائم الترتيب الافتراضي للجدولة والذي يُحدّده ترتيب العناصر في شجرةDOM السلوك المنطقي المطلوب للانتقال، إلا أنه قد تتطلب صفحتك المطورة تغيير هذا الترتيب الافتراضي. يُمكن القيام بذلك بتغيير مكان توضع العنصر في الوثيقة إلا أن ذلك قد لا يكون ممكنًا في بعض الحالات مما يجعلنا نتوجه لاستخدام سمة فهرس الجدولة tabindex في HTML.
</p>

<p>
	يُمكن تحديد ترتيب الجدولة لأي عنصر باستخدام السمة <code>tabindex</code> والتي تكون قيمتها عدد صحيح يُحدّد ترتيب العنصر. علاوةً على ذلك، يُمكن استخدام هذه السمة لإضافة كائن لا يتمتع بإمكانية التركيز (مثل الحاويات div) إلى ترتيب الجدولة، كما يُمكن حذف عناصر من ترتيب الجدولة.
</p>

<p>
	يؤدي إسناد القيم 0 إلى السمة <code>tabindex</code> لإضافة العنصر إلى الترتيب الطبيعي للجدولة أي يُمكن الانتقال له باستخدام مفتاح الجدولة <code>Tab</code> كما يُمكن وضع التركيز عليه برمجيًا باستخدام الطريقة <code>focus</code>. يُظهر المثال التالي عنصر مخصص يُمكن الانتقال له باستخدام المفتاح <code>Tab</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6370_19" style="">
<span class="tag">&lt;custom-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"0"</span><span class="tag">&gt;</span><span class="pln">Press Tab to Focus Me!</span><span class="tag">&lt;/custom-button&gt;</span></pre>

<p>
	<iframe allow="clipboard-write https://developers-dot-devsite-v2-prod.appspot.com" allowfullscreen="" data-ss1637657846="1" data-ss1637657940="1" data-ss1637662916="1" src="https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex_b98a1a4d11a69c31224bdc5a3046e5ef683d020f29945e81fe48810d87bc917f.frame"></iframe>يؤدي إسناد القيم -1 إلى السمة <code>tabindex</code> إلى إزالة العنصر من الترتيب الطبيعي للجدولة أي لن يعود بالإمكان الانتقال له بمفتاح الجدولة <code>Tab</code> إلا أنه يُمكن وضع التركيز عليه برمجيًا باستخدام الطريقة <code>focus</code>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6370_21" style="">
<span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"foo"</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"-1"</span><span class="tag">&gt;</span><span class="pln">I'm not keyboard focusable</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">onclick</span><span class="pun">=</span><span class="atv">"</span><span class="pln">foo</span><span class="pun">.</span><span class="pln">focus</span><span class="pun">();</span><span class="atv">"</span><span class="tag">&gt;</span><span class="pln">Focus my sibling</span><span class="tag">&lt;/button&gt;</span></pre>

<p>
	لا يُمكن الآن الانتقال للزر الأيسر بمفتاح الجدولة <code>Tab</code> وإنما يُمكن وضع التركيز عليه بالنقر على الزر الأيمن:
</p>

<p>
	<iframe allow="clipboard-write https://developers-dot-devsite-v2-prod.appspot.com" allowfullscreen="" data-ss1637657846="1" data-ss1637657940="1" data-ss1637662916="1" name="goog_1931073422" src="https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex_d2fe3e213f308dd8177eb8432eafff0e1d2fb257b91b29a69d37245342fd1f49.frame"></iframe>يؤدي إسناد قيمة صحيحة أكبر من الصفر (مثلًا 5) إلى وضع العنصر الموافق في مقدمة ترتيب الجدولة. أما إذا وجد أكثر من عنصر لهم قيمة أكبر من الصفر فيتم الانتقال بدءًا من العنصر ذو القيمة الأدنى (أكبر من الصفر) إلى القيمة الأعلى التالية وهكذا. تُعدّ عملية إسناد قيم أكبر من الصفر مخالفة للنموذج النمطي الطبيعي <strong>anti-pattern</strong>.
</p>

<p>
	ليكن لدينا مثلًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6370_24" style="">
<span class="tag">&lt;button&gt;</span><span class="pln">I should be first</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"6"</span><span class="tag">&gt;</span><span class="pln">And I should be second</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"5"</span><span class="tag">&gt;</span><span class="pln">But I jumped to the front!</span><span class="tag">&lt;/button&gt;</span></pre>

<p>
	سيكون الزر الأخير (الأيمن) أول الأزرار في الجدولة ومن ثم الزر الثاني(الأوسط) وأخيرًا الزر الأول.
</p>

<p>
	<iframe allow="clipboard-write https://developers-dot-devsite-v2-prod.appspot.com" allowfullscreen="" data-ss1637657846="1" data-ss1637657940="1" data-ss1637662916="1" src="https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex_859762173e05b63413b13ce13a87bd0df45d2983001fe7794a76c65a96c3e167.frame"></iframe>بالطبع، لا معنى لتغيير ترتيب الجدولة للعناصر التي لا يتفاعل معها المستخدم مثل العناوين والصور. كما أنه من المستحسن تنظيم ترتيب الجدولة وفق ترتيب العناصر في DOM وعدم اللجوء لاستخدام <code>tabindex</code> إلا عند الضرورة القصوى مقتصرًا على عناصر التحكم التفاعلية مثل صناديق النص والأزرار والقوائم.
</p>

<p>
	لا تقلق بشأن مستخدمي قارئ الشاشة أن يفوتهم محتوى هامًا بسبب أن ليس له ترتيب جدولة <code>tabindex</code>، فحتى لو كان المحتوى مهمًا مثل الصور لا داع أن تضع له ترتيب جدولة لأن المستخدم لن يتفاعل معها أصلًا. ركّز على وضع عبارات توصيفية للصور في الخاصية <code>Alt</code> كي يستفيد منها مستخدمي قارئ الشاشة كما سنعرض لاحقًا.
</p>

<h3>
	إدارة التركيز على مستوى الصفحة
</h3>

<p>
	يُمكن أن يكون استخدام السمة ضروريًا في بعض الحالات. مثلًا: إذا احتوت صفحة على عدة أقسام لا تُعرض جميعها بنفس الوقت أي أن النقر على رابط قد يؤدي إلى تغيير المحتوى الظاهر دون إعادة تحميل الصفحة. يجب إذًا في هذه الحالة إسناد القيمة -1 لترتيب الجدولة لكل قسم كي لا ننتقل بمفتاح الجدولة <code>Tab</code> للقسم وإنما حصرًا باستخدام الطريقة <code>focus</code>. يحافظ هذا الأسلوب، المدعو بإدارة التركيز، على تزامن المحتوى المرئي مع سياق تفاعل المستخدم مع الصفحة.
</p>

<h3>
	إدارة التركيز للعناصر المخصصة
</h3>

<p>
	يُمكن أيضًا أن تحتاج لإدارة التركيز للتحكم بعنصر مخصص. مثلًا نعلم أنه يُمكن استخدام مفاتيح الأسهم لتحديد خيار من عنصر قائمة الاختيار الأساسية <code>select</code>. إذا أنشأت عنصرًا مخصصًا مشابه للقائمة، فسترغب بأن يكون له نفس أسلوب الاختيار لتراعي مستخدمي لوحة المفاتيح والذين يستخدمون الأسهم لاختيار عنصر من القائمة.
</p>

<p>
	نقوم في الشيفرة التالية باستخدام عنصر القائمة الأساسي مما يُعطي قائمة يُمكن التنقل والاختيار منها باستعمال مفاتيح الأسهم:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6370_26" style="">
<span class="com">&lt;!-- يُمكن نقل التركيز باستخدام مفتاح الجدولة أو مفاتيح الأسهم--&gt;</span><span class="pln">
</span><span class="tag">&lt;select&gt;</span><span class="pln">
  </span><span class="tag">&lt;option&gt;</span><span class="pln">Aisle seat</span><span class="tag">&lt;/option&gt;</span><span class="pln">
  </span><span class="tag">&lt;option&gt;</span><span class="pln">Window seat</span><span class="tag">&lt;/option&gt;</span><span class="pln">
  </span><span class="tag">&lt;option&gt;</span><span class="pln">No preference</span><span class="tag">&lt;/option&gt;</span><span class="pln">
</span><span class="tag">&lt;/select&gt;</span></pre>

<p style="text-align: center;">
	<select><option>Aisle seat</option>
<option>Window seat</option>
<option>No preference</option></select></p>

<p>
	قد لا يكون من السهل دائمًا معرفة سلوك لوحة المفاتيح الواجب تنفيذها مما يتوجب العودة إلى دليل تطوير تطبيقات الإنترنت الغنية سهلة الوصول <a href="https://www.w3.org/TR/wai-aria-practices/" rel="external nofollow">Accessible Rich Internet Applications Authoring Practices</a> التي تختصر إلى ARIA، لمعاينة قائمة أنواع عناصر التحكم وأحداث لوحة المفاتيح التي تتجاوب معها. نستخدم هذا الدليل لدعم لوحة المفاتيح في عنصر مخصص جديد. ليكن مثلًا العنصر المخصص Custom Elements الجديد التالي والذي يُماثل مجموعة أزرار الانتقاء إنما يُمكن أن نُخصص له مظهرًا وسلوكًا جديدين:
</p>

<pre class="ipsCode">
&lt;radio-group&gt;
  &lt;radio-button&gt;Water&lt;/radio-button&gt;
  &lt;radio-button&gt;Coffee&lt;/radio-button&gt;
  &lt;radio-button&gt;Tea&lt;/radio-button&gt;
  &lt;radio-button&gt;Cola&lt;/radio-button&gt;
  &lt;radio-button&gt;Ginger Ale&lt;/radio-button&gt;
&lt;/radio-group&gt;
</pre>

<p>
	بمراجعة القسم الثاني من دليل <a href="https://www.w3.org/TR/wai-aria-practices/" rel="external nofollow">ARIA</a> لتحديد نوع التفاعل مع لوحة المفاتيح المطلوب، نجد ضمن قائمة نماذج التصميم المقترحة جدول مواصفات مجموعة أزرار الانتقاء <a href="https://www.w3.org/TR/wai-aria-practices/#radiobutton" rel="external nofollow">characteristics table for radio groups</a> والتي تُعدّ الأقرب للعنصر المخصص الذي نقوم بتطويره. يُبين هذا الجدول ضرورة تجاوب العنصر مع مفاتيح الأسهم أعلى/أسفل/يمين/يسار. لإضافة هذا التفاعل مع العنصر المخصص الجديد سنستخدم تقنية تُدعى ترتيب الجدولة المتنقل roving tabindex.
</p>

<p style="text-align: center;">
	<img alt="015ARIA.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78273" data-unique="g0clswh0b" src="https://academy.hsoub.com/uploads/monthly_2021_09/015ARIA.png.deb6d66701286d98a334543db71156ee.png" style=""></p>

<p>
	تتمحور تقنية ترتيب الجدولة المتنقل على إسناد القيمة -1 لجميع العناصر ما عدا العنصر المُحدّد حاليًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6370_28" style="">
<span class="tag">&lt;radio-group&gt;</span><span class="pln">
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"0"</span><span class="tag">&gt;</span><span class="pln">Water</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln">
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"-1"</span><span class="tag">&gt;</span><span class="pln">Coffee</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln">
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"-1"</span><span class="tag">&gt;</span><span class="pln">Tea</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln">
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"-1"</span><span class="tag">&gt;</span><span class="pln">Cola</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln">
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"-1"</span><span class="tag">&gt;</span><span class="pln">Ginger Ale</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln">
</span><span class="tag">&lt;/radio-group&gt;</span></pre>

<p>
	يستخدم العنصر المخصص الجديد مستمع listener لمعرفة المفتاح الذي يضغطه المستخدم وعندها تُسندّ قيمة ترتيب الجدولة -1 إلى العنصر المُحدّد حاليًا ومن ثم تُسندّ القيمة 0 لترتيب الجدولة للعنصر الجديد الذي سيُحدّد باستخدام الطريقة <code>focus</code>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6370_30" style="">
<span class="tag">&lt;radio-group&gt;</span><span class="pln">
  // Assuming the user pressed the down arrow, we'll focus the next available child
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"-1"</span><span class="tag">&gt;</span><span class="pln">Water</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln">
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"0"</span><span class="tag">&gt;</span><span class="pln">Coffee</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln"> // call .focus() on this element
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"-1"</span><span class="tag">&gt;</span><span class="pln">Tea</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln">
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"-1"</span><span class="tag">&gt;</span><span class="pln">Cola</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln">
  </span><span class="tag">&lt;radio-button</span><span class="pln"> </span><span class="atn">tabindex</span><span class="pun">=</span><span class="atv">"-1"</span><span class="tag">&gt;</span><span class="pln">Ginger Ale</span><span class="tag">&lt;/radio-button&gt;</span><span class="pln">
</span><span class="tag">&lt;/radio-group&gt;</span></pre>

<p>
	عندما يصل المستخدم إلى الخيار الأخير (أو الأول، وفق الاتجاه الذي يتحرك به باستخدام مفاتيح الأسهم)، نعاود وضع التركيز على الخيار الأول (أو الأخير).
</p>

<p>
	<iframe allow="clipboard-write https://developers-dot-devsite-v2-prod.appspot.com" allowfullscreen="" data-ss1637657846="1" data-ss1637657940="1" data-ss1637662916="1" src="https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex_bad4f2a29d2cab4e1b9619684d779b01ec36e113018ee8e921bd57c72cebb64b.frame"></iframe>
</p>

<p>
	يُمكن العودة إلى مستودع GitHub للحصول على الشيفرة المتاح للعموم وتجريب العنصر الجديد المخصص.
</p>

<h3>
	النوافذ الشرطية وقفل لوحة المفاتيح
</h3>

<p style="text-align: center;">
	 
</p>

<p>
	يُمكن في بعض الأحيان، أثناء إدارة التركيز، الوقوع في ورطة لا يُمكن الخروج منها. من الأمثلة على ذلك حالة عنصر الإكمال التلقائي autocomplete الذي يحاول إدارة التركيز ومتابعة ترتيب الجدولة إلا أنه يمنع التركيز من الخروج منه حتى إكمال النص مما يؤدي إلى حجز لوحة المفاتيح والذي يُمكن أن يضايق المستخدم إلى حد كبير. تنص الفقرة 2.1.2 من دليل ARIA على أنه لا يجوز بأي حال من الأحوال <a href="https://webaim.org/standards/wcag/checklist#sc2.1.2" rel="external nofollow">حجز لوحة المفاتيح أو حصر التركيز في عنصر ما</a> إذ أن المستخدم يجب أن يكون قادرًا على التنقل ضمن جميع عناصر الصفحة بحرية كاملة.
</p>

<p>
	يُمكن أن يكون هذا السلوك مطلوبًا في بعض الحالات مثل حالة النافذة الشرطية modal التي تمنع المستخدم من الوصول لعناصر الصفحة الخلفية. يُمكن وضع غطاء داكن شفاف لتغطية الصفحة الخلفية إلا أن ذلك لن يمنع خروج التركيز خارج النافذة الشرطية بشكل أكيد.
</p>

<p style="text-align: center;">
	<img alt="017Modal.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78275" data-unique="y4055tzho" src="https://academy.hsoub.com/uploads/monthly_2021_09/017Modal.png.03569f555539c7bc3c3002d31019dec9.png" style=""></p>

<p>
	يُمكن في مثل هذه الحالات تنفيذ حجز مؤقت للوحة المفاتيح لحصر التركيز ضمن النافذة الشرطية عندما تكون مفتوحة ومن ثم العودة للعنصر الذي كان عليه التركيز في الصفحة الخلفية عند إغلاق النافذة الشرطية.
</p>

<p>
	يوجد العديد من المقترحات لتسهيل المعالجة السابقة مثل استخدام العنصر الجديد <code>&lt;dialog&gt;</code> إلا أنه مازال غير متوافق مع بعض المتصفحات. يُمكن العودة <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog" rel="external nofollow">للمقالة</a> للتزود بمعلومات أكثر عن <code>&lt;dialog&gt;</code> كما يُمكن تفحص هذا <a href="https://github.com/gdkraus/accessible-modal-dialog" rel="external nofollow">المثال</a> من مستودع GitHub.
</p>

<p>
	نعرض فيما يلي الخطوات الأساسية اللازمة لتنفيذ قفل لوحة المفاتيح بشكل مؤقت وذلك لحالة نافذة شرطية (حاوية div لبعض العناصر) مع حاوية ثانية للغطاء الداكن.
</p>

<ol>
<li>
		استخدم التابع <code>document.querySelector</code> لحفظ مرجع لحاوية النافذة الشرطية ومرجع للحاوية الثانية.
	</li>
	<li>
		احفظ فور فتح النافذة الشرطية مرجع للعنصر الذي كان عليه التركيز في النافذة الخلفية (وبهذا ستتمكن من الرجوع إليه لاحقًا).
	</li>
	<li>
		استخدم مستمع لحدث ضغط مفتاح للأسفل keydown. يجب أيضًا استخدام مستمع لحدث النقر على الحاوية الثانية.
	</li>
	<li>
		احصر مجموعة العناصر القابلة للتركيز في النافذة الشرطية إذ سيلعب العنصر الأول والأخير دور الحارس للدوران ضمن مجموعة العناصر مع مفتاح الجدولة لضمان البقاء ضمن النافذة الشرطية.
	</li>
	<li>
		أظهر النافذة الشرطية وضع التركيز على أول عنصر فيها.
	</li>
	<li>
		انقل التركيز من عنصر لآخر للأمام عندما يقوم المستخدم بضغط مفتاح الجدولة <code>Tab</code> أو للخلف عندما يقوم المستخدم بضغط <code>Shift+Tab</code> مع مراعاة الدوران عند أول وآخر عنصر.
	</li>
	<li>
		أغلق النموذج حال ضغط المستخدم لمفتاح الهروب <code>Esc</code> (هذا أمر ضروري يسمح للمستخدم بإغلاق النافذة دون البحث عن زر الإغلاق ومفيد بالأخص للمستخدمين الذين لا يستعملون الفأرة).
	</li>
	<li>
		أخف النافذة الشرطية وحاوية الغطاء عند طلب الإغلاق وأعد التركيز على عنصر الصفحة الذي قمت بحفظ مرجع له.
	</li>
</ol>
<p>
	يُمكن، باتباع الخطوات السابقة، إدارة نافذة شرطية مريحة التعامل لجميع فئات المستخدمين.
</p>

<p>
	يُمكن الحصول على <a href="https://github.com/udacity/ud891/tree/gh-pages/lesson2-focus/07-modals-and-keyboard-traps/solution" rel="external nofollow">الشيفرة</a> المتاح للجميع واختبار <a href="http://udacity.github.io/ud891/lesson2-focus/07-modals-and-keyboard-traps/solution/index.html" rel="external nofollow">المثال</a> كاملًا.
</p>

<p>
	ترجمة -وبتصرف- للمقالات الثلاث التالية:
</p>

<ul>
<li>
		<a href="https://developers.google.com/web/fundamentals/accessibility/focus" rel="external nofollow">Introduction to Focus</a>
	</li>
	<li>
		<a href="https://developers.google.com/web/fundamentals/accessibility/focus/dom-order-matters" rel="external nofollow">DOM Order Matters</a>
	</li>
	<li>
		<a href="https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex" rel="external nofollow">Using tabindex</a>
	</li>
</ul>
<p>
	للمؤلفين الثلاثة: Meggin Kearney, Dave Gash, Rob Dodson.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/html/%D8%B3%D9%87%D9%88%D9%84%D8%A9-%D9%88%D8%B5%D9%88%D9%84-%D8%AC%D9%85%D9%8A%D8%B9-%D8%A7%D9%84%D8%B2%D9%88%D8%A7%D8%B1-%D9%84%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r1323/" rel="">سهولة وصول جميع الزوار لمواقع وتطبيقات الويب</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/workflow/vuejs/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-vuejs-%D9%84%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-dom-r990/" rel="">استخدام Vue.js للتعامل معDOM</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/html/html5/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%AF%D8%B9%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%B5%D9%81%D8%AD%D8%A7%D8%AA-%D9%84%D9%85%D9%8A%D8%B2%D8%A7%D8%AA-html5-r340/" rel="">اكتشاف دعم المتصفحات لميزات HTML5</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">تعلم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%B9%D9%84%D9%88%D9%85-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8/" rel="">المدخل الشامل لتعلم علوم الحاسوب</a>
	</li>
</ul>
<style type="text/css">
p iframe {
    border: 1px solid #e7e5e3 !important;
}</style>
]]></description><guid isPermaLink="false">1324</guid><pubDate>Sun, 12 Sep 2021 15:00:00 +0000</pubDate></item><item><title>&#x633;&#x647;&#x648;&#x644;&#x629; &#x648;&#x635;&#x648;&#x644; &#x62C;&#x645;&#x64A;&#x639; &#x627;&#x644;&#x632;&#x648;&#x627;&#x631; &#x644;&#x645;&#x648;&#x627;&#x642;&#x639; &#x648;&#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x648;&#x64A;&#x628;</title><link>https://academy.hsoub.com/programming/html/%D8%B3%D9%87%D9%88%D9%84%D8%A9-%D9%88%D8%B5%D9%88%D9%84-%D8%AC%D9%85%D9%8A%D8%B9-%D8%A7%D9%84%D8%B2%D9%88%D8%A7%D8%B1-%D9%84%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r1323/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_09/6155b93713b85_-.png.303d4de6b8f1f625ead2b7489491bcd1.png" /></p>

<p>
	نعرض في هذه المقالة أساسيات ومبادئ سهولة الوصول accessibility وذلك بالاعتماد على محتوى إحدى الدورات التدريبية في Udacity وفق الترتيب التالي:
</p>

<ul>
<li>
		تعريف مسألة سهولة الوصول لاسيما في مسائل <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8/" rel="">تطوير الويب</a>.
	</li>
	<li>
		آليات تحقيق سهولة الوصول وجعل مواقع الويب شاملة الاستخدام usable من قبل الجميع.
	</li>
	<li>
		كيفية تحقيق سهولة الوصول بأقل جهد ممكن خلال مرحلة التطوير.
	</li>
	<li>
		استخدام الميزات التي توفرها لغة HTML لتحسين سهولة الوصول.
	</li>
	<li>
		عرض الآليات المتقدمة التي تسمح بالوصول لتفاعل سلس للمستخدمين مع صفحات الويب.
	</li>
</ul>
<p>
	تعرض هذه المقالة جميع الآليات المتاحة لتطوير مواقع ويب سهلة الاستخدام من قبل الجميع مما سيرفع، بالتأكيد، من مستواك في التطوير. لن يكون الأمر صعبًا إذ يُمكنك القيام ببعض الممارسات البسيطة أثناء استخدامك لغة HTML لتحسين سهولة الوصول (إضافًة لبعض التقانات المتقدمة والتي سنعرضها في هذه المقالة). ستصل، باتباعك للإرشادات المُقدّمة إلى واجهات سهلة الاستخدام لجميع شرائح المستخدمين بما فيهم ذوي الاحتياجات الخاصة.
</p>

<p>
	قد يوجد لدى الكثير من المطورين تصور أو فهم خاطئ لما يعنيه سهولة الوصول (شيء له علاقة بالعقود الحكومية أو صناديق التحقق أو قارئات الشاشات؟)، أو لربما يظن البعض أن سيكون عليهم الاختيار بين واجهات جميلة وجذابة وأخرى غير أنيقة إنما سهلة الوصول. بما أن الأمر ليس ذلك على الإطلاق فلنبدأ أولًا بشرح ماذا نقصد بسهولة الوصول وما سنتعلم في هذه المقالة.
</p>

<h2>
	ما هي سهولة الوصول؟
</h2>

<p>
	نصف، عادًة، موقع ويب بأنه سهل الوصول عندما يتمكن جميع المستخدمين بمختلف شرائحهم من الوصول إليه واستثمار وظائفه بسهولة. من البساطة لك كمطور ويب أن تفترض أن جميع المستخدمين قادرين على التفاعل والتعامل مع موقعك بنفس الطريقة التي تقوم بها أنت بنفسك وذلك باستخدام لوحة المفاتيح أو الفأرة أو شاشة اللمس. يُمكن أن تكون فرضيتك هذه صحيحة مع الكثير من المستخدمين إلا أنه قد تبرز في العديد من الحالات مشاكل في التعامل مع الموقع تتراوح من المضايقات البسيطة إلى التوقف عن التصفح والاستخدام.
</p>

<p>
	يُعنى تسهيل الوصول بتفقد تجربة المستخدمين غير النمطيين والذين يُمكن أن يكون لهم أسلوب مختلف وغير متوقع في التواصل والتعامل مع محتوى الويب لاسيما الأشخاص الذين يعانون من مشاكل معينة أو إعاقات مختلفة.
</p>

<p>
	لا يعني تركيزنا في مسألة سهولة الوصول على الأشخاص الذين يعانون من إعاقات جسدية إهمال مشاكل الوصول التي قد تظهر عند أي مستخدم. فمن منا لم يعان من مشاكل في استخدام التطبيقات على جواله المحمول أو لم يتمكن من الوصول لقائمة معينة على حاسوبه اللوحي أو تفاجأ بظهور عبارة "هذا المحتوى غير متاح لك في منطقتك"؟
</p>

<p>
	تُساعد معالجة مسائل سهولة الوصول بهذا المعنى الأوسع والأعم على تحسين تجربة جميع المستخدمين في التعامل مع المنتج البرمجي كما سنرى لاحقًا. لنبدأ مثلًا بإلقاء نظرة على المثال التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78256" href="https://academy.hsoub.com/uploads/monthly_2021_09/001FormExample.jpg.8f7170d4d44eb7350961f5074b2fef82.jpg" rel=""><img alt="001FormExample.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78256" data-unique="3zdpf07s2" src="https://academy.hsoub.com/uploads/monthly_2021_09/001FormExample.jpg.8f7170d4d44eb7350961f5074b2fef82.jpg"></a>
</p>

<p>
	من الواضح أن الواجهة السابقة تعاني من المشاكل التالية:
</p>

<ul>
<li>
		للنص المكتوب تباين منخفض وبالتالي سيصعُب على ضعاف النظر قراءته.
	</li>
	<li>
		يوجد مسافات كبيرة بين العناوين (على اليسار) والحقول (على اليمين) مما سيجعل عملية الربط بينهما شاقة لاسيما لمن يتعامل مع هذا النموذج على الجوال ويقوم بتكبير النموذج لمعاينته مما سيُضطره أيضًا للتحريك يمنى ويسرى.
	</li>
	<li>
		لا يرتبط عنوان صندوق التحقق معه (تذّكر التفاصيل Remember details) وبالتالي سيكون على المستخدم النقر حصرًا على صندوق التحقق الصغير عوضًا عن النقر على العنوان. علاوًة على ذلك، لن يتمكن المستخدم الكفيف مثلًا والذي يستخدم قارئ شاشة من الربط بين العنوان وصندوق التحقق.
	</li>
</ul>
<p>
	إذا أصلحنا هذه المشاكل كلها بتطبيق حلول سهولة الوصول التالية: زيادة تباين النصوص بجعله أغمق وتعديل التصميم لتقريب التسميات من حقولها وربط عنوان خانة الاختيار معها، نحصل على النموذج المُحسّن التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78257" href="https://academy.hsoub.com/uploads/monthly_2021_09/002EnhancedForm.jpg.bb5e6a22660feea2d764298e5e67d74e.jpg" rel=""><img alt="002EnhancedForm.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78257" data-unique="p0jgb3rid" src="https://academy.hsoub.com/uploads/monthly_2021_09/002EnhancedForm.jpg.bb5e6a22660feea2d764298e5e67d74e.jpg"></a>
</p>

<p>
	إذا كنت تفضل النموذج الثاني على الأول فأنت، بالتأكيد، فهمت الهدف من هذا الدليل الإرشادي! وتذكر أنه غالبًا ما يكون الأمر الذي يمنع البعض من الوصول والتعامل مع منتجك يُسبب إرباكًا كبيرًا للآخرين.
</p>

<h2>
	إرشادات تطوير محتوى الويب سهل الوصول
</h2>

<p>
	نتبع في هذا الدليل الإرشادي الإرشادات التي يُقدّمها الدليل Web Content Accessibility Guidelines (WCAG) 2.0 وهي مجموعة من التوصيات والممارسات الجيدة التي وضعها خبراء سهولة الوصول لحل مسائل "سهولة الوصول" بطريقة منهجية.
</p>

<p>
	يتمحور الدليل الإرشادي WCAG حول أربعة مبادئ يُطلق عليها غالبًا الاختصار POUR الأجنبي:
</p>

<ul>
<li>
		قابل للإدراك Perceivable: هل يُمكن للمستخدم إدراك المحتوى؟ مع الآخذ بعين الاعتبار أن ما نُدركه بحاسة واحدة مثل البصر لا يعني، بالضرورة، أن جميع المستخدمين يُمكن لهم أن يدركوه.
	</li>
	<li>
		قابل للتشغيل Operable: هل يتمكن المستخدم من التعامل مع الواجهات والتنقل عبر المحتوى؟ مثلًا إذا كان أمرًا في الواجهة يتطلب تحريك الفأرة فلن يتمكن الأشخاص الذين لا يقدرون على استخدام الفأرة أو شاشات اللمس من القيام به.
	</li>
	<li>
		مفهوم Understandable: هل يفهم المستخدم الواجهات دون أي غموض أو التباس؟
	</li>
	<li>
		مرن Robust: هل يُمكن عرض المحتوى على متصفحات مختلفة وباستخدام أدوات مساعده؟
	</li>
</ul>
<p>
	نظرًا لضخامة الإرشادات العامة التي يُقدّمها دليل WCAG، قامت مجموعة سهولة الوصول على الويب WebAIM (اختصارًا إلى Web Accessibility In Mind) باستخلاص مجموعة الإرشادات الخاصة بمحتوى الويب ووضعها في قائمة واحدة تُعطي المختصر المفيد مع تسهيل العودة لتفصيلات WCAG إن لزم الأمر. سيُحقق التزامك بهذه الإرشادات تطوير محتوى ويب يتمتع بسهولةالوصول من قبل كافة شرائح المستخدمين.
</p>

<h2>
	فهم تنوع المستخدمين
</h2>

<p>
	من المفيد البدء أولًا بفهم احتياجات المستخدمين بمختلف شرائحهم والمشاكل التي قد تواجه البعض منهم عند تعاملهم مع محتوى الويب. للمزيد من التوضيح نعرض فيما يلي جلسة أسئلة/أجوبة مفيدة مع فيكتور تسارن Victor Tsaran مدير البرنامج الفني في شركة Google وهو شخص كفيف لا يرى شيئًا على الإطلاق.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78258" href="https://academy.hsoub.com/uploads/monthly_2021_09/003VictorTsaran.jpg.8198c442994f0c981b26480f7c0c7d6e.jpg" rel=""><img alt="003VictorTsaran.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="78258" data-unique="tu7ni2j4k" src="https://academy.hsoub.com/uploads/monthly_2021_09/003VictorTsaran.jpg.8198c442994f0c981b26480f7c0c7d6e.jpg"></a>
</p>

<ul>
<li>
		السؤال: ما هي طبيعة عملك في Google؟
		<ul>
<li>
				الجواب: أعمل على التأكد من أن منتجات Google تلائم جميع المستخدمين بما فيهم ذوي الإعاقات مهما كان نوعها.
			</li>
		</ul>
</li>
	<li>
		السؤال: ما هي أنواع الإعاقات التي يعاني المستخدمون منها بشكل عام؟
		<ul>
<li>
				الجواب: يأتي فقدان البصر في مقدمة الإعاقات التي قد تجعل من الصعوبة، وأحيانًا من المستحيل، التفاعل مع الكثير من مواقع الويب لاسيما أن العديد من تقانات الويب المتقدمة لا تأخذ بعين الاعتبار الأدوات المختلفة التي يستخدمها المكفوفون في تصفح محتوى الويب. وبشكل عام يُمكن تقسيم إعاقات المستخدمين إلى أربع مجموعات: البصرية والحركية والسمعية والإدراكية.
			</li>
		</ul>
</li>
	<li>
		السؤال: لنعرض هذه الإعاقات واحدًة تلو الأخرى ولنبدأ أولًا ببعض الأمثلة عن الإعاقة البصرية
		<ul>
<li>
				الجواب: تُقسم الإعاقات البصرية إلى عدة فئات أولها المستخدمون الكفيفون، مثلي، والذين يتوجب عليهم استخدام قارئ شاشة أو قارئ برايل أو تركيبة من الاثنين.
			</li>
		</ul>
</li>
</ul>
<p style="text-align: center;">
	<img alt="004braille eader.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78259" data-unique="jh359pjng" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155b920a25dc_004brailleeader.png.45e98ba92dc4763f3a57f449579d27f5.png"></p>

<p>
	إضافًة إلى الكفيفين الذين لا يرون على الإطلاق، هنالك عدد كبير من المستخدمين الذين يعانون من ضعف البصر والذين يكون لهم في الغالب نظارات طبية سميكة. يوجد الكثير من الحلول لهؤلاء الأشخاص مثل استخدام قارئ الشاشة أو قارئ برايل أو استخدام تقنية تحويل النص إلى كلام، كما يُمكن لهم تكبير الشاشة وزيادة التباين وتكبير حجم الخطوط وغيرها من التقانات المساعدة والتي ربما يقوم بها الأشخاص العاديون للحصول على مظهر أريح للعين.
</p>

<p style="text-align: center;">
	<img alt="005high-contrast.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78260" data-unique="8ib6c7z9x" src="https://academy.hsoub.com/uploads/monthly_2021_09/005high-contrast.png.9bb59178f17826da65c264878d913521.png"></p>

<p>
	ومع ملاحظة أن النظر يضعف مع تقدم العمر وأنه في لحظات معينة يُمكن لأي شخص أن تحصل له مشاكل في البصر (بعد عملية ليزر جراحية في العين مثلاً أو بوجود أشعة الشمس القوية على شاطئ البحر مثلًا). أطلب من مطوري الويب أخذ هذا الأمر بعين العطف لمراعاة أصحاب هذه الإعاقات. كما أُذكّر أيضًا بأن 9% من الذكور و1% من الإناث لديهم مشاكل بصرية في تمييز الألوان (الأحمر مع الأخضر مثلًا أو الأصفر مع الأزرق) مما يتطلب من مطوري نماذج الويب مراعاة ذلك أيضًا.
</p>

<ul>
<li>
		السؤال: ماذا عن الإعاقات الحركية؟
		<ul>
<li>
				الجواب: يُمكن أن تتراوح الإعاقات الحركية من أشخاص لا يستطيعون الحركة أبدًا إلى أشخاص لا يُمكنهم تحريك الفأرة لسبب أو لآخر مثل الأشخاص الذين يعانون من إصابات الإجهاد المتكرر RSI مثلًا. يُمكن حسب درجة الإعاقة الحركية التفاعل مع الحاسوب باستخدام لوحة المفاتيح أو جهاز تبديل أو حتى جهاز متابعة العين كما يُمكن لمثل هؤلاء الأشخاص إعطاء الأوامر للحاسوب صوتيًا.
			</li>
		</ul>
</li>
</ul>
<p style="text-align: center;">
	<img alt="006eyetracking.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78261" data-unique="ih2edzs66" src="https://academy.hsoub.com/uploads/monthly_2021_09/006eyetracking.png.f4f011faad04d3c219b4e888cc7e041b.png"></p>

<p>
	على غرار ضعف البصر، يُمكن أن تكون الإعاقة الحركية مؤقتة كأن تكون راكبًا في قطار يهتز بقوة أو أنك كسرت يدك أو غيرها من الحالات. وبجميع الأحوال، يجب أن نلبي احتياجات ذوي الإعاقات الدائمة والمؤقتة.
</p>

<ul>
<li>
		السؤال: لنتكلم الآن عن الإعاقات السمعية.
		<ul>
<li>
				الجواب: يتراوح الأشخاص في هذه المجموعة أيضًا من الأصم إلى ضعيف السمع. وعلى غرار البصر، يضعُف السمع مع التقدم بالعمر ويلجأ الأشخاص عادًة إلى وسائل تقوية السمع.
			</li>
		</ul>
</li>
</ul>
<p style="text-align: center;">
	<img alt="007Screencaptions.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78262" data-unique="d824g17g5" src="https://academy.hsoub.com/uploads/monthly_2021_09/007Screencaptions.png.20ac46e32c4331056a30a7477cd17f16.png"></p>

<p>
	يجب، أثناء تطوير الواجهات، التأكد من أننا لا نعتمد على الصوت فقط بل نوفر بدائل مثل التعليقات والنصوص. وكما هو الحال مع الإعاقات البصرية والحركية، فمن السهل حقًا تخيل موقف يستفيد فيه شخص تعمل أذنيه جيدًا من هذه البدائل أيضًا. ففي مكتب عمل يتشاركه العديدون، يُمكن حضور فلم فيديو بدون صوت إذا كان الحوار مكتوبًا على الفلم.
</p>

<ul>
<li>
		السؤال: هل يُمكن أن تخبرنا قليلًا عن الإعاقات الإدراكية؟
		<ul>
<li>
				الجواب: تختلف هذه الإعاقات حسب الحالة فهنالك حالات عسر القراءة وحالات التوحد وحالات التشتت وغيرها من الحالات التي يتطلب معظمها إيجاد تصميمات بسيطة لواجهات التفاعل مع المستخدم. بالطبع، يُمكن لهؤلاء الأشخاص استخدام وظائف التكبير/التصغير لتسهيل القراءة أو زيادة التركيز. بالتأكيد، إذا ابتكرنا ما يُمكن أن يجده الشخص الذي يعاني من ضعف إدراكي مفيدًا فسيكون ممتعًا ومفيدًا لجميع الآخرين.
			</li>
		</ul>
</li>
	<li>
		السؤال: هل يُمكن لك في النهاية تلخيص وجهة نظرك بخصوص سهولةالوصول؟
		<ul>
<li>
				الجواب: إن تصميم وبناء منتجات تتوجه فقط للأشخاص الذين لا يعانون من أي مشكلة سيجعل جمهور هذا المنتج ضيقًا جدًا نظرًا لوجود الإعاقات، ولو بشكل جزئي أو مؤقت، عمليًا عند الجميع.
			</li>
		</ul>
</li>
</ul>
<p>
	قام فيكتور خلال هذه المقابلة بتصنيف الإعاقات ضمن أربع مجموعات: البصرية والحركية والسمعية والإدراكية، كما نوه إلى أن هذه الإعاقات يُمكن أن تكون ظرفية أو مؤقتة أو دائمة.
</p>

<p>
	يُعطي الجدول التالي بعض الأمثلة الواقعية لمختلف أنواع الإعاقات (لاحظ أن بعض الإعاقات قد تندرج في أكثر من تصنيف):
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<table>
<thead><tr>
<th>
				 
			</th>
			<th>
				ظرفية
			</th>
			<th>
				مؤقتة
			</th>
			<th>
				دائمة
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				بصرية
			</td>
			<td>
				 
			</td>
			<td>
				ارتجاج في المخ
			</td>
			<td>
				العمى
			</td>
		</tr>
<tr>
<td>
				حركية
			</td>
			<td>
				حمل طفل
			</td>
			<td>
				ذراع مكسور، إصابات الإجهاد المتكررة
			</td>
			<td>
				إصابات الإجهاد المتكررة
			</td>
		</tr>
<tr>
<td>
				سمعية
			</td>
			<td>
				ضجيج مكتب
			</td>
			<td>
				 
			</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				إدراكية
			</td>
			<td>
				 
			</td>
			<td>
				ارتجاج في المخ
			</td>
			<td>
				 
			</td>
		</tr>
</tbody>
</table>
<p style="text-align: center;">
	من الأمثلة على إصابات الإجهاد المتكررة: متلازمة النفق الرسغي carpal tunnel syndrome، مرفق التنس tennis elbow، إصبع الزناد trigger finger.
</p>

<h2>
	الخطوات الموالية
</h2>

<p>
	عرضنا في هذه المقالة أساسيات سهولة الوصول:
</p>

<ul>
<li>
		تعريف مسألة سهولة الوصول ومدى أهميتها.
	</li>
	<li>
		قوائم إرشادات تحقيق سهولة الوصول WCAG و WebAIM.
	</li>
	<li>
		الأنواع المختلفة من الإعاقات التي يجب مراعاتها أثناء تصميم محتوى الويب.
	</li>
</ul>
<p>
	نعرض في بقية هذا الدليل الإرشادي الجوانب العملية للوصول إلى موقع ويب ذو سهولة وصول جيدة وحيث سنُركّز العمل حول ثلاثة جوانب أساسية:
</p>

<ul>
<li>
		التركيز Focus: نعرض كيفية الاستعاضة عن الفأرة بلوحة المفاتيح مما يسمح للمستخدمين الذين يعانون من إعاقات حركية من التعامل مع الواجهات المختلفة كما يضمن هذا الأمر تحقيق واجهات سهلة الاستخدام ولجميع المستخدمين.
	</li>
	<li>
		الدلالات Semantics: يجب أن نضمن أن واجهاتنا المطورة تعمل بشكل جيد مع أدوات الوصول المختلفة التي يُمكن أن تُستخدم من قبل ذوي الإعاقات.
	</li>
	<li>
		التصميم Styling: يجب أن يُحقق تصميم الوجهات سهولة الاستخدام إلى أكبر قدر ممكن عبر استخدام التقانات المناسبة.
	</li>
</ul>
<p>
	يحتاج كل محور من هذه المحاور إلى دورة تدريبية كاملة لذا لن نغطي كل المواضيع بشكل كامل وإنما سنزودك بنقاط البدء ونوجهك إلى العديد من المراجع المفيدة.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://developers.google.com/web/fundamentals/accessibility" rel="external nofollow">Accessibility</a> للكتّاب الأربعة: Meggin Kearney, Dave Gash, Alice Boxhall, Rob Dodson.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">تعلم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%B9%D9%84%D9%88%D9%85-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8/" rel="">المدخل الشامل لتعلم علوم الحاسوب</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/workflow/cordova/%D9%86%D8%B8%D8%B1%D8%A9-%D8%B9%D8%A7%D9%85%D8%A9-%D8%B9%D9%86-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AC%D9%87%D8%B2%D8%A9-%D8%A7%D9%84%D9%85%D8%AD%D9%85%D9%88%D9%84%D8%A9-%D8%B9%D8%A8%D8%B1-%D9%83%D9%88%D8%B1%D8%AF%D9%88%D9%81%D8%A7-r1261/" rel="">نظرة عامة عن تطويرتطبيقات الأجهزة المحمولة عبر كوردوفا</a>
	</li>
	<li>
		النسخة الكاملة لكتاب <a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">نحو فهم أعمق لتقنيات HTML5</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1323</guid><pubDate>Thu, 09 Sep 2021 15:00:00 +0000</pubDate></item><item><title>&#x62F;&#x644;&#x64A;&#x644;&#x643; &#x644;&#x62A;&#x62D;&#x631;&#x64A;&#x643; &#x627;&#x644;&#x631;&#x633;&#x648;&#x645; &#x627;&#x644;&#x645;&#x62A;&#x62C;&#x647;&#x629; SVG &#x648;&#x641;&#x642;&#x64B;&#x627; &#x644;&#x645;&#x648;&#x627;&#x635;&#x641;&#x627;&#x62A; SMIL</title><link>https://academy.hsoub.com/programming/html/%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D9%84%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D9%87%D8%A9-svg-%D9%88%D9%81%D9%82%D9%8B%D8%A7-%D9%84%D9%85%D9%88%D8%A7%D8%B5%D9%81%D8%A7%D8%AA-smil-r868/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_04/5e8fffe4b20b3_-----.jpg.45390fc2ed94e5c5312043e46f67887c.jpg" /></p>

<p>
	<em>في الوقت الذي ستُلقي فيه نظرة على هذا المقال قد تكون معايير SMIL أصبحت شيئًا من الماضي، لكن مهلًا! <a href="https://academy.hsoub.com/programming/html/%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A7%D8%AA-smil-%D8%A7%D9%84%D9%85%D8%AA%D8%AD%D8%B1%D9%83%D8%A9-%D9%82%D8%AF-%D8%A7%D9%86%D8%AF%D8%AB%D8%B1%D8%AA-%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D8%AF%D8%A7%D8%A6%D9%84-r863/" rel="">في هذا المقال</a> ستجد دليلًا لاستبدال بعض الميزات وتطويرها.</em>
</p>

<h2>
	لمحة عامة
</h2>

<p>
	يمكن تحريك الرسوم المتجهة <strong>(SVG graphics)</strong> باستخدام <strong>عناصر التحريك</strong> المعرفة في مواصفات لغة التكامل المتزامن للوسائط المتعدّدة <a href="https://www.w3.org/TR/2001/REC-smil-animation-20010904/" rel="external nofollow"><strong>SMIL</strong></a>، تشمل تلك العناصر ما يلي:
</p>

<ul>
<li>
		<code>&lt;animate&gt;</code>: يسمح لك هذا العنصر بتحريك خاصيات HTML وخاصيات الكائنات على مدى فترة زمنية محددة.
	</li>
	<li>
		<code>&lt;set&gt;</code>: وهو اختزال مناسب للتحريك، فهو يفيد في تعيين قيم التحريك لخاصيات HTML وخاصيات الكائنات مثل خاصية الظهور والرؤية.
	</li>
	<li>
		<code>&lt;animateMotion&gt;</code>: يعمل على تحريك العنصر على امتداد مسار الحركة.
	</li>
	<li>
		<code>&lt;animationColor&gt;</code>: تستطيع من خلال هذا العنصر تعديل القيم اللونية لخاصيات HTML وخاصيات الكائنات مع مرور الوقت. لاحظ إهمال العنصر <code>&lt;animateColor&gt;</code> لمجرد استخدام عنصر التحريك لاستهداف خصائص من الممكن أن تمتلك قيم لونية. بالرغم من ذلك لا يزال ذلك العنصر متاحًا في مواصفات SVG1.1، على العكس من SVG2 فهو مهمل ومحذوف بالكامل.
	</li>
</ul>
<p>
	بالإضافة إلى عناصر التحريك المعرفة في مواصفات SMIL تحتوي الرسوم المتجهة SVG ملحقات متوافقة مع مواصفات SMIL والتي تحتوي على خاصيات توسع نطاق عمل العنصر <code>&lt;animateMotion&gt;</code> وعناصر إضافية أخرى. تشمل ملحقات الرسوم المتجهة SVG ما يلي:
</p>

<ul>
<li>
		<code>&lt;animateTransform&gt;</code>: يتيح لك تحريك إحدى خاصيات الرسوم المتجهة مع مرور الوقت، مثل خاصية <code>transform</code>.
	</li>
	<li>
		<code>path</code> <em>(خاصية HTML)</em>: تسمح بتحديد أي خاصية من صيغ بيانات مسار الرسوم المتجهة SVG في خاصية المسار لعنصر <code>animateMotion</code>، (التحريك اعتمادًا على SMIL فقط يسمح بتفرع صيغ بيانات الرسوم المتجهة خلال مسار). سنتطرق بالحديث أكثر عن <code>animateMotion</code> في الفقرات القادمة.
	</li>
	<li>
		<code>&lt;mpath&gt;</code>: يستخدم بالاقتران مع عنصر <code>animateMotion</code> للإشارة إلى مسار حركة الذي سيستخدم كمسار لتحريك العناصر. مع العلم أن عنصر <code>mpath</code> مضمن داخل عنصر <code>animationMotion</code> قبل علامة الإغلاق.
	</li>
	<li>
		<code>&lt;keypoints&gt;</code> <em>(خاصية HTML)</em>: تستخدم كخاصية لـ <code>animateMotion</code> لتوفير تحكم دقيق في سرعة حركة العناصر في مساراتها.
	</li>
	<li>
		<code>&lt;rotate&gt;</code> <em>(خاصية HTML)</em>: تستخدم أيضًا كخاصية لـ <code>animateMotion</code> للتحكم في ما إذا كان الكائن يستجيب للدوران تلقائيًا بحيث يشير المحور السيني له في نفس الاتجاه (أو الاتجاه المعاكس) مثل متجه الظل الاتجاهي لمسار الحركة. هذه الخاصية هي مفتاح نجاح تحريك العناصر على امتداد مسار ما كما تتوقع للحركة أن تكون. مزيدًا من التوضيح في الجزئية الخاصة بشرح <code>animationMotion</code>.
	</li>
</ul>
<p>
	حركة رسوم SVG من الممكن أن تكون مشابهة لرسوم CSS والانتقالات عبرها حسب طبيعتيهما. مفاتيح الحركة تُضبط وبالتالي تتحرك العناصر وتتغير الألوان …إلخ. مع ذلك بإمكان رسوم SVG القيام بأمور لا تستطيع رسوم CSS القيام بها وهذا ما سنتطرق له لاحقًا.
</p>

<h2>
	لماذا قد تستخدم الرسوم المُتجهة (SVG Animation)؟
</h2>

<p>
	<a href="http://slides.com/sarasoueidan/styling-animating-svgs-with-css--2#/" rel="external nofollow">من الممكن تصميم وتحريك الرسوم المتجهة (SVG) باستخدام CSS</a>. بشكل أساسي التأثيرات الحركية التي تطبق على عناصر HTML من الممكن أيضًا تطبيقها على عناصر SVG. ولكن هناك بعض الخصائص التي يمكن تطبيقها على SVG ليست فعالة على CSS. مسار SVG على سبيل المثال يأتي مع مجموعة من البيانات (<code>d=""‎</code> خاصية HTML) التي تعطي للمسار شكلًا. تلك البيانات يمكن تعريفها وتحريكها خلال SMIL ولكن الأمر لا ينطبق على CSS. ذلك لأن عناصر SVG تتصف بمجموعة من خاصيات HTML تُعرف بخاصيات للعرض. بعض تلك الخاصيات من الممكن معايرتها والتحكم فيها وتحريكها باستخدام CSS وهذا لا ينطبق على الخاصيات جميعها.
</p>

<p>
	وهكذا ترى أن العديد من تأثيرات الحركة يمكن تطبيقها حاليًا باستخدام CSS. وأما الفجوات في استخدام SVG CSS من الممكن تجاوزها عند استخدام JavaScript أو SVG المستمدة من SMIL.
</p>

<p>
	إذا كنت تفضل استخدام JavaScript فيستحسن أن تجرب <a href="http://snapsvg.io/" rel="external nofollow">snap.svg</a> بواسطة Dmitry Baranovsky الذي يعد كمكتبة حافلة بالكثير من النصوص البرمجية الخاصة بـ SVG. <a href="https://codepen.io/collection/edpyJ/" rel="external nofollow">ويمكنك الاطلاع على العديد من الأمثلة</a> على ذلك. أما إذا كنت تفضل الخوض في مسار تعريفي أكثر بإمكانك استخدام عناصر التحريك التي سيتطرق لها هذا الدليل.
</p>

<p>
	ميزة أخرى تميز SMIL عن JS هي أن رسوم JS لا تعمل عند تضمين رسوم SVG كصور <code>img</code> أو استعمالها كصورة خلفية (<code>background-image</code>) في CSS. رسوم SMIL تعمل في كلا الحالتين أو هكذا ينبغي. وهذه ميزة عظيمة. لربما ستجد نفسك قد اخترت SMIL عن غيرها من الخيارات بسبب تلك الميزة. ومن هنا فهذا الدليل سيؤدي دور المساعد لتتعلم كيف تستخدم SMIL بدءًا من اليوم.
</p>

<h2>
	دعم المتصفح والنسخ الاحتياطية
</h2>

<p>
	دعم المتصفح لرسوم SMIL لائق للغاية. حيث أنه يعمل في جميع المتصفحات باستثناء Internet Explorer و Opera Mini. للحصول على نظرة شاملة حول دعم المتصفح، يمكنك الرجوع إلى <a href="https://caniuse.com/#feat=svg-smil" rel="external nofollow">جدول التوافق</a>.
</p>

<p>
	إذا كنت بحاجة إلى توفير نسخة احتياطية لحركة الرسوم لـ SMIL، يمكنك اختبار دعم المتصفح أثناء التنقل باستخدام <a href="https://modernizr.com/" rel="external nofollow">Modernizr</a>. إذا لم يكن SMIL مدعومًا ، فيمكنك تقديم نوع من الاستعاضة (رسوم JavaScript متحركة، تجربة بديلة، …إلخ).
</p>

<h2>
	تحديد الهدف من الحركة باستخدام <code>xlink: href</code>
</h2>

<p>
	بغض النظر عن أي من عناصر التحريك الأربعة التي تختارها، فأنت بحاجة إلى تحديد هدف الحركة المحدد بواسطة هذا العنصر.
</p>

<p>
	لتحديد الهدف يمكنك استخدام خاصية <code>xlink: href</code>. تعطي خاصية HTML هذه مرجع URI للعنصر المستهدف في التحريك والذي سيجري تعديله بمرور الوقت. <strong>يجب أن يكون العنصر المستهدف جزءًا من مستند SVG الحالي.</strong>
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_6" style="">
<span class="tag">&lt;rect</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"cool_shape"</span><span class="pln"> ... </span><span class="tag">/&gt;</span><span class="pln">

</span><span class="tag">&lt;animate</span><span class="pln"> </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#cool_shape"</span><span class="pln"> ... </span><span class="tag">/&gt;</span></pre>

<p>
	إذا واجهت عناصر التحريك في SVG من قبل، فمن المحتمل أنك رأيتها متداخلة مع العنصر المفترض تحريكه. هذا ممكن تبعًا لمحددات:
</p>

<ul>
<li>
		إذا لم تتوفر خاصية xlink: href<code>HTML</code>، فسيكون العنصر المستهدف هو العنصر الأصل المباشر لعنصر الحركة الحالي.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_8" style="">
<span class="tag">&lt;rect</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"cool_shape"</span><span class="pln"> ... </span><span class="tag">&gt;</span><span class="pln">

  </span><span class="tag">&lt;animate</span><span class="pln"> ... </span><span class="tag">/&gt;</span><span class="pln">

</span><span class="tag">&lt;/rect&gt;</span></pre>

<p>
	لذلك إذا كنت تريد "تضمين" الرسم المتحرك في العنصر الذي ينطبق عليه، فبإمكانك القيام بذلك. وإذا كنت تريد أن تبقي الرسم المتحرك منفصل في مكان آخر في المستند، فيمكنك القيام بذلك أيضًا، وحدّد الهدف من كل حركة باستخدام <code>xlink: href</code>. كلا الطريقتين تعملان بشكل جيد.
</p>

<h2>
	تحديد الخاصية المستهدفة للحركة باستخدام <code>attributeName</code> و<code>attributeType</code>
</h2>

<p>
	تشترك جميع عناصر التحريك أيضًا في خاصية HTML أخرى وهي <code>attributeName</code>. تُستخدم <code>attributeName</code> لتحديد اسم خاصية HTML التي تقوم بتحريكها.
</p>

<p>
	على سبيل المثال، إذا كنت ترغب في تحريك موضع مركز الدائرة <code>&lt;circle&gt;</code> على المحور السيني (x-axis)، حدد <code>cx</code> كقيمة لخاصية <code>attributeName</code>.
</p>

<p>
	تأخذ <code>attributeName</code> قيمة واحدة فقط، ولا تقبل قيم متعددة، لذلك يمكنك تنشيط خاصية HTML واحدة فقط في كل مرة. إذا كنت ترغب في تحريك أكثر من خاصية HTML واحدة فأنت بحاجة إلى تعريف أكثر من تحريك واحد للعنصر. لربما لا توجد طريقة أخرى ولهذا لـ CSS أفضلية عن SMIL. ولكن مرة أخرى، نظرًا للقيم المحتملة لخاصيات الحركة الأخرى (والتي سنتطرق لها بعد ذلك)، فمن المنطقي تحديد اسم خاصية HTML واحد فقط في المرة الواحدة، وإلا فقد تصبح قيم الخاصيات الأخرى معقدة للغاية بحيث لا يمكن التعامل معها.
</p>

<p>
	عند تحديد اسم خاصية HTML، يمكنك إضافة البادئة <code>XMLNS</code> (اختصار namespace XML) للإشارة إلى مجال اسم خاصية HTML. يمكن أيضًا تحديد مجال الاسم باستخدام الخاصية <code>attributeType</code>. على سبيل المثال، تعد بعض الخاصيات جزءًا من مساحة اسم CSS (مما يعني أنه يمكن العثور عليها كخاصية CSS أيضًا) والبعض الآخر XML فقط. يمكن العثور على جدول يوضح هذه الخاصيات <a href="http://slides.com/sarasoueidan/styling-animating-svgs-with-css#/10" rel="external nofollow">هنا</a>. خاصيات HTML في الجدول ليست كلها من خاصيات SVG إنها فقط تلك التي يمكن ضبطها باستخدام CSS. بعضها متاح بالفعل كخصائص CSS.
</p>

<p>
	إذا لم تُعيّن قيمة <code>attributeType</code> بشكل صريح أو عُيّنت على "تلقائي"<code>auto</code>، يجب أن يبحث المتصفح أولاً من خلال قائمة خصائص CSS عن اسم خاصية مطابق، وإذا لم يُعثر على أي منهما سيبحث في مجال اسم XML الافتراضية للعنصر.
</p>

<p>
	على سبيل المثال، يوضح المقتطف التالي التحكم في تحريك شفافية مستطيل SVG. نظرًا لأن خاصية HTML للشفافية <code>opacity</code> متوفرة أيضًا كخاصية CSS، تُعين <code>attributeType</code> على مجال اسم CSS:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_10" style="">
<span class="tag">&lt;rect&gt;</span><span class="pln">
  </span><span class="tag">&lt;animate</span><span class="pln"> </span><span class="atn">attributeType</span><span class="pun">=</span><span class="atv">"CSS"</span><span class="pln"> </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"opacity"</span><span class="pln"> 
           </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"1"</span><span class="pln"> </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"0"</span><span class="pln"> </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"5s"</span><span class="pln"> </span><span class="atn">repeatCount</span><span class="pun">=</span><span class="atv">"indefinite"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
</span><span class="tag">&lt;/rect&gt;</span></pre>

<p>
	سنتجاوز خاصيات الحركة الأخرى في الأمثلة التالية أدناه. جميع خاصيات التحريك متعارف عليها ما بين جميع عناصر التحريك ما لم يذكر خلاف ذلك.
</p>

<h2>
	تحريك خاصية HTML لعنصر من قيمة لأخرى على مدار فترة زمنية وتحديد الحالة النهائية: <code>from</code> و<code>by</code> و<code>to</code> و<code>dur</code> و<code>fill</code>
</h2>

<ul>
<li>
		ابدأ بتحريك دائرة من موقع إلى آخر عن طريق تغيير قيمة الخاصية <code>cx</code> الخاصة بها (والتي تحدد قيمة x لمركزها).
	</li>
	<li>
		عنصر <code>&lt;animate&gt;</code> سيتيح لك القيام بذلك حيث يستخدم لتحريك خاصية واحدة في كل مرة. عادةً ما تتحرك الخاصيات التي تأخذ قيم رقمية ولونية باستخدام هذا العنصر. تفقد <a href="https://www.w3.org/TR/SVG2/animate.html#AnimationAttributesAndProperties" rel="external nofollow">الجدول</a> للتعرف على الخاصيات التي يمكن تحريكها.
	</li>
	<li>
		للتغيير من قيمة إلى أخرى خلال فترة زمنية يمكنك استخدام الخاصيات <code>From</code> و<code>to</code> و<code>dur</code>. ستحتاج أيضًأ إلى تحديد بداية الحركة عن طريق خاصية <code>begin</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_12" style="">
<span class="tag">&lt;circle</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"my-circle"</span><span class="pln"> </span><span class="atn">r</span><span class="pun">=</span><span class="atv">"30"</span><span class="pln"> </span><span class="atn">cx</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">cy</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"orange"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

  </span><span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#my-circle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"cx"</span><span class="pln">
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"450"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"1s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"click"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	يوضح المثال السابق طريقة تعريف دائرة وتحريكها من مركزها من الموضع الأولي عند 50 وحدة ثم إلى الموضع الجديد 450 وحدة على امتداد محور السينات (x-axis).
</p>

<p>
	تتحدد قيمة البداية <code>begin</code> بالنقر <code>click</code> أي أن الدائرة سوف تتحرك عند النقر عليها. ويمكنك أيضًا قيمة البداية كقيمة زمنية. على سبيل المثال، تعيين القيمة <code>"begin="0s</code> يعني أن حركة العنصر ستبدأ بمجرد تحميل الصفحة. بإمكانك <strong>تأخير</strong> حركة العنصر عند تحديد قيمة موجبة، مثلًا <code>"begin="2s</code> تعني أن حركة العنصر ستبدأ بعد ثانيتين من تحميل الصفحة.
</p>

<p>
	الأكثر إثارةً هو أنه بإمكانك تعيين قيمة البداية <code>begin</code> مثل <code>s1+click</code> لتبدأ حركة العنصر <strong>خلال ثانية واحدة بعد النقر عليه</strong>! علاوةً على ذلك بإمكانك استخدام قيم أخرى تسمح لك بمزامنة العنصر بدون حساب المدة الزمنية وزمن التأخير للعناصر المتحركة الأخرى. ستعرف المزيد لاحقًا.
</p>

<ul>
<li>
		خاصية <code>dur</code> تكافئ <code>animation-duration</code> في CSS.
	</li>
	<li>
		الخاصيتان <code>from</code> و<code>to</code> تشبهان الإطارين المفتاحيين (keyframes)‏ from وto في قاعدة <code>‎</code>@keyframe الخاصة بـ CSS:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_3117_14" style="">
<span class="lit">@keyframes</span><span class="pln"> moveCircle </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">from</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* start value */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
  to </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* end value */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أما خاصية HTML التعبئة <code>fill</code> (والتي تحمل نفس اسم خاصية HTML "التعبئة" التي تحدد لون العنصر لسوء الحظ) فهي تشبه خاصية وضع ملء الرسوم <code>fill-mode property</code> والتي تحدد ما إذا كان على العنصر أن يعود لحالته الأولية بعد انتهاء عملية التحريك. تتشابه قيم SVG مع تلك الموجودة في CSS، باستثناء اختلاف التسميات:
</p>

<ul>
<li>
		<code>freeze</code>: يُعني هذا التأثير بتجميد قيمة التأثير لآخر قيمة في الفترة النشطة. يبقى التأثير مجمدًا للفترة الزمنية المتبقية في المستند أو حتى إعادة تشغيل الحركة.
	</li>
	<li>
		<code>remove</code>: يقوم هذا التأثير بإزالة تأثير الحركة (أي أنه لم يعُد مُطبقًا) عند انتهاء المدة النشطة للحركة. بعد انتهاء زمن الحركة لم يعد الهدف متأثرًا بالحركة ما لم يُعاد تشغيل الحركة من جديد.
	</li>
</ul>
<p>
	حاول تغيير القيم في العرض الحي المباشر لترى كيف تتأثر الحركة:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="200" id="cp_embed_e883265849147a0a4b712c5960c448a8" name="cp_embed_1" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 360px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/e883265849147a0a4b712c5960c448a8?height=200&amp;theme-id=1&amp;slug-hash=e883265849147a0a4b712c5960c448a8&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_1"></iframe>
</p>

<p>
	تستخدم خاصية <code>by</code> لتعيين إزاحة نسبية للحركة. كما يوحي الاسم فبإمكانك استخدام الخاصية HTML لتحديد مقدار الإزاحة التي تريد للحركة أن تتقدم بها. يكون تأثير الخاصية <code>by</code> مرئيًا عند تقدمك خلال مدة الحركة في خطوات منفصلة، على غرار الطريقة المعمول بها في <code>CSS عبر</code> steps()<code>‎</code>. المكافئ لدالة steps()<code>‎ في CSS</code> هو <code>"calcMode="discrete </code>في SVG، وسنتطرق لخاصية <code>calcMode</code> لاحقًا في المقالة.
</p>

<p>
	الحالة الأخرى عندما يكون تأثير <code>by</code> أكثر وضوحًا عند تحديد خاصية <code>to</code>. سيأتي مثال على ذلك لاحقًا. وأخيرًا وليس آخرًا، تأتي <code>by</code> بفائدة أخرى عند العمل مع الحركة المضافة والتراكمية.
</p>

<h3>
	إعادة تشغيل الحركة باستخدام <code>restart</code>
</h3>

<p>
	قد يكون من المفيد وقف إعادة تشغيل الحركة أثناء نشاطها. للقيام بذلك تمنح SVG خاصية <code>restart</code> المزودة بخيارات ثلاثة:
</p>

<ul>
<li>
		<code>always</code>: تمكنك من إعادة تشغيل الحركة في أي وقت حيث أنها القيمة الافتراضية.
	</li>
	<li>
		<code>whenNotActive</code>: يمكن إعادة تشغيل الحركة فقط عندما لا تكون نشطة (أي بعد النهاية النشطة). أما محاولات إعادة تشغيل الحركة خلال المدة النشطة فيتم تجاهلها.
	</li>
	<li>
		<code>never</code>: لا يمكن إعادة تشغيل العنصر لما تبقى من المدة البسيطة الحالية لحاوية الزمن. (في حالة SVG نظرًا لأن حاوية الوقت الأصلية هي جزء من مستند SVG، فلا يمكن إعادة تشغيل الحركة للفترة المتبقية من مدة المستند).
	</li>
</ul>
<h3>
	تسمية الحركة ومزامنتها
</h3>

<p>
	افترض أننا نريد تحريك موضع ولون دائرة، بحيث يتغير اللون في نهاية الحركة. بإمكانك القيام بذلك عن طريق تحديد قيمة <code>begin</code> لحركة تغيير اللون لتكون مساوية لمدة الحركة <code>dur</code>، هذه هي الطريقة التي نفعلها عادة في CSS.
</p>

<p>
	SMIL مع ذلك، لديها ميزة لطيفة التعامل مع الأحداث. لقد ذكرنا قبل ذلك أن الخاصية <code>begin</code> تقبل قيمًا مثل <code>click + 5s</code>. تسمى هذه القيمة "قيمة الحدث (event value)، وتتكون في هذه الحالة من مرجع حدث متبوعًا بـ "قيمة الساعة". الجزء المثير للاهتمام هنا هو تسمية الجزء الثاني: <a href="https://www.w3.org/TR/SVG2/animate.html#ClockValueSyntax" rel="external nofollow">"قيمة الساعة"</a>. لماذا ليست مجرد "قيمة زمنية"؟ حسنًا، الجواب هو أنه يمكنك استخدام قيمة الساعة حرفيًا مثل "10min" أو "01:33" أي ما يعادل "دقيقة و 33 ثانية"، أو حتى "02:30:03" (ساعتان، 30 دقيقة، و 3 ثوان). في وقت كتابة هذا التقرير، لم تُطبق قيم الساعة بالكامل في أي متصفح.
</p>

<p>
	لذا، إذا أردنا العودة إلى العرض الحي السابق واستخدمت <code>click + 01:30</code>، إذا بدأ متصفح يدعمه، ستبدأ الحركة خلال دقيقة و 30 ثانية بعد النقر فوق الدائرة.
</p>

<p>
	نوع آخر من القيم التي يمكن أن يقبلها هو معرف رسوم متحركة أخرى يتبعها مرجع حدث. إذا كان لديك حركتان (أو أكثر) (سواء طبقت على نفس العنصر أم لا!) وتريد مزامنتهما بحيث تبدأ إحداهما نسبة إلى الأخرى، يمكنك القيام بذلك دون الحاجة إلى معرفة مدة الحركة المتبقية.
</p>

<p>
	على سبيل المثال، في العرض الحي التالي، يبدأ المستطيل الأزرق في التحرك لمدة ثانية واحدة بعد بدء حركة الدائرة. و ذلك عن طريق إعطاء معرف كل حركة <code>ID</code>، ثم استخدام هذا المعرف مع الحدث <code>begin</code> كما هو موضح في التعليمات البرمجية التالية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_16" style="">
<span class="tag">&lt;circle</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"orange-circle"</span><span class="pln"> </span><span class="atn">r</span><span class="pun">=</span><span class="atv">"30"</span><span class="pln"> </span><span class="atn">cx</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">cy</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"orange"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

</span><span class="tag">&lt;rect</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"blue-rectangle"</span><span class="pln"> </span><span class="atn">width</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">height</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">x</span><span class="pun">=</span><span class="atv">"25"</span><span class="pln"> </span><span class="atn">y</span><span class="pun">=</span><span class="atv">"200"</span><span class="pln"> </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"#0099cc"</span><span class="tag">&gt;&lt;/rect&gt;</span><span class="pln">

  </span><span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#orange-circle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"cx"</span><span class="pln">
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"450"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"5s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"click"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">d</span><span class="pun">=</span><span class="atv">"circ-anim"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

  </span><span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#blue-rectangle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"x"</span><span class="pln"> 
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"425"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"5s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"circ-anim.begin + 1s"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"rect-anim"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	البداية <code>"begin="circ-anim.begin + 1s</code> هي الجزء الذي يخبر المتصفح ببدء الحركة للمستطيل بعد ثانية واحدة من بداية الدائرة. تفقد العرض التوضيحي التالي:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="550" id="cp_embed_55195eee8647f438525b852000504c7a" name="cp_embed_2" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/55195eee8647f438525b852000504c7a?height=550&amp;theme-id=1&amp;slug-hash=55195eee8647f438525b852000504c7a&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_2"></iframe>
</p>

<p>
	يمكنك أيضًا بدء الحركة للمستطيل بعد انتهاء حركة الدائرة باستخدام حدث النهاية <code>end</code> بتتبع الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_18" style="">
<span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#blue-rectangle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"x"</span><span class="pln"> 
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"425"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"5s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"circ-anim.end"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"rect-anim"</span><span class="tag">/&gt;</span></pre>

<p>
	يمكنك حتى بدء تشغيله قبل نهاية حركة الدائرة باستخدام الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_20" style="">
<span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#blue-rectangle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"x"</span><span class="pln"> 
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"425"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"5s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"circ-anim.end - 3s"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"rect-anim"</span><span class="tag">/&gt;</span></pre>

<h3>
	تكرار الحركة باستخدام <code>repeatCount</code>
</h3>

<p>
	إذا كنت ترغب في تشغيل الحركة أكثر من مرة، فيمكنك القيام بذلك باستخدام خاصية <code>repeatCount</code>. يمكنك تحديد عدد المرات التي ترغب في تكرارها، أو استخدام الكلمة المفتاحية الأساسية غير المحددة لجعلها تتكرر إلى ما لا نهاية <code>infinite</code>. لذلك، إذا أردنا تكرار الحركة للدائرة مرتين، ستكون الشيفرة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_22" style="">
<span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#orange-circle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"cx"</span><span class="pln">
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"450"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"5s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"click"</span><span class="pln">
    </span><span class="atn">repeatCount</span><span class="pun">=</span><span class="atv">"2"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"circ-anim"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	يمكنك التحقق من العرض الحي هنا. في المثال الحي، عين عدد التكرار ليكون 2 على الدائرة، وبشكل غير نهائي في المربع <code>infinite</code>.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="550" id="cp_embed_d8e38406a5a90f4392a4bb85f6aadd78" name="cp_embed_3" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/d8e38406a5a90f4392a4bb85f6aadd78?height=550&amp;theme-id=1&amp;slug-hash=d8e38406a5a90f4392a4bb85f6aadd78&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_3"></iframe>
</p>

<p>
	لاحظ طريقة إعادة تشغيل الحركة من القيمة الأولية <code>from</code> من القيمة بدلاً من القيمة التي وصلت إليها في نهاية الحركة. لسوء الحظ، لا تتضمن SMIL طريقة للرجوع إليها بين قيم البداية والنهاية مثل CSS التي تتيح لنا القيام بذلك. في CSS، تحدد خاصية اتجاه الحركة <code>animation-direction</code> ما إذا كانت الحركة يجب أن تنفذ بشكل معاكس على بعض أو كل الدورات أو التكرارات. <code>Animation-direction: alternate</code>: تعني القيمة البديلة أن عمليات تكرار دورة الحركة ذات القيم الفردية يتم تشغيلها في الاتجاه الطبيعي، وأما القيم الزوجية فتكون في اتجاه عكسي. هذا يعني أن الدورة الأولى ستكون من البداية إلى النهاية، ثم ستليها الدورة الثانية من النهاية إلى البداية، ثم الدورة الثالثة من البداية إلى النهاية، وهكذا.
</p>

<p>
	في SMIL للقيام بذلك، يجب عليك استخدام JavaScript لتغيير قيم الخاصيات <code>from</code> و<code>to</code> بشكل صريح. كتب جون مكبارتلاند من Big Bite Creative <a href="https://bigbite.net/insights/introduction-svg-animation/" rel="external nofollow">منشورًا</a> لفترة من الوقت يشرح فيه كيف فعل ذلك من أجل تحريك رمز القائمة الذي عمل عليه.
</p>

<p>
	حل آخر هو تحديد القيمة النهائية كقيمة متوسطة ومن ثم تكون القيمة النهائية هي نفسها القيمة الأولية. على سبيل المثال، يمكنك تعيين الحركة لتبدأ من <code>from</code> قيمة وتنتهي بنفس القيمة مع <code>to</code> وكذلك باستثناء أنك تحدد ما كنت قد حددته ليكون قيمة نهائية كقيمة وسيطة بين <code>from</code> و<code>to</code>.
</p>

<p>
	في CSS، سنفعل ذلك باستخدام شيء مثل هذا:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_3117_24" style="">
<span class="lit">@keyframes</span><span class="pln"> example </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">from</span><span class="pun">,</span><span class="pln"> to </span><span class="pun">{</span><span class="pln">
    left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="lit">50</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">300px</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	المكافئ في SMIL هو استخدام خاصية <code>values</code>، والتي سنشرحها قريبًا. ومع ذلك، فإن الحل المذكور أعلاه قد يعمل أو لا يعمل وفقًا لنوع الحركة التي تتبعها، وما إذا كنت تقوم بسلسلة الحركة أم لا، أو تكرارها، أو القيام برسوم متحركة إضافية.
</p>

<p>
	إليكم رسمًا جميلًا بسيطًا من قِبل Miles Elam يستخدم فيه بعض أوقات البدء المتأخرة:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="387" id="cp_embed_kprKm" name="cp_embed_4" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 387px;" title="CodePen Embed" src="https://codepen.io/mileselam/embed/kprKm?height=387&amp;theme-id=1&amp;slug-hash=kprKm&amp;default-tab=result&amp;user=mileselam&amp;name=cp_embed_4"></iframe>
</p>

<h3>
	تقييد وقت التكرار باستخدام <code>repeatDur</code>
</h3>

<p>
	قد تصبح حركة العنصر المستمرة مزعجة أو غير متآلفة مع الاستخدام في حالة استمرار الحركة لفترة طويلة. لذلك، قد يكون من الجيد ضبط وقت التكرار على فترة زمنية معينة، وإيقاف التكرار بعد مرور بعض الوقت بالنسبة لبداية المستند. هذا هو المعروف باسم وقت العرض.
</p>

<p>
	يشير وقت العرض التقديمي إلى أن الموضع في الخط الزمني بالنسبة للمستند يبدأ من جزء معين. يُحدد باستخدام خاصية <code>repeatDur</code>. يشبه بناء الجملة الخاص بقيمة الساعة، ولكن بدلاً من أن يكون متصلاً بحدث حركة آخر أو حدث تفاعلي، فهو يتعلق ببداية المستند.
</p>

<p>
	على سبيل المثال، ستؤدي الشيفرة التالية إلى إيقاف تكرار الحركة لمدة دقيقة و 30 ثانية بعد بدء المستند:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_26" style="">
<span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#orange-circle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"cx"</span><span class="pln">
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"450"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"2s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"0s"</span><span class="pln">
    </span><span class="atn">repeatCount</span><span class="pun">=</span><span class="atv">"indefinite"</span><span class="pln">
    </span><span class="atn">repeatDur</span><span class="pun">=</span><span class="atv">"01:30"</span><span class="pln"> 
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"circ-anim"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	وهنا تستطيع مشاهدة العرض الحي:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="550" id="cp_embed_366b9fba478e7ac1de2188f5a2594c3c" name="cp_embed_5" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/366b9fba478e7ac1de2188f5a2594c3c?height=550&amp;theme-id=1&amp;slug-hash=366b9fba478e7ac1de2188f5a2594c3c&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_5"></iframe>
</p>

<h3>
	مزامنة الحركة على أساس عدد التكرارات
</h3>

<p>
	الآن لنرجع خطوة إلى المزامنة بين موضوعين في التحريك. في الواقع، في SMIL يمكنك مزامنة الحركة بحيث تبدأ حركة إحداهما بناء على عدد تكرار حركة الأخرى. على سبيل المثال، يمكنك بدء رسم متحرك بعد تكرار رقم آخر، بإضافة أو طرح مقدار الوقت الذي قد ترغب في إضافته.
</p>

<p>
	المثال التالي يبدأ في تحريك للمستطيل في التكرار الثاني لحركة الدائرة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_28" style="">
<span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#blue-rectangle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"x"</span><span class="pln"> 
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"425"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"5s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"circ-anim.repeat(2)"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"rect-anim"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	يوضح العرض التالي بداية حركة المستطيل بعد ثانيتين من ثاني تكرار لحركة الدائرة:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="550" id="cp_embed_d8e38406a5a90f4392a4bb85f6aadd78" name="cp_embed_6" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/d8e38406a5a90f4392a4bb85f6aadd78?height=550&amp;theme-id=1&amp;slug-hash=d8e38406a5a90f4392a4bb85f6aadd78&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_6"></iframe>
</p>

<p>
	يمكنك الاطلاع على <a href="http://oreillymedia.github.io/svg-essentials-examples/ch12/sync_repetition.html" rel="external nofollow">نموذج</a> لأساسيات SVG بإصدارها الثاني من إعداد David Eisenberg.
</p>

<h3>
	التحكم في قيم الإطارات المفتاحية للحركة: <code>keyTimes</code> و<code>values</code>
</h3>

<p>
	في CSS يمكننا تحديد القيم التي نريد أن تأخذها حركة الرسوم الخاصة بنا في إطار معين أثناء التحريك. على سبيل المثال، إذا كنت تحرك العنصر بإزاحة لليساربدلًا من تنشيطه من 0 إلى 300 مثلاً، يمكنك تحريكه بحيث يأخذ قيمًا معينة مثل هذا:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_3117_30" style="">
<span class="lit">@keyframes</span><span class="pln"> example </span><span class="pun">{</span><span class="pln">
  </span><span class="lit">0</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="lit">50</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">320px</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="lit">80</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">270px</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="lit">100</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">300px</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الإطارات 0٪ و 20٪ و 80٪ و 100٪ هي إطارات الحركة، والقيم الموجودة في كل إطار تحدد قيمته. التأثير الموصوف أعلاه هو أحد العناصر التي ترتد عن الحائط، ثم تعود إلى الموضع النهائي.
</p>

<p>
	في SMIL، يمكنك التحكم في القيم لكل إطار بطريقة مماثلة، لكن بناء الشيفرة مختلف تمامًا.
</p>

<p>
	لتحديد إطارات مفتاحية، يمكنك استخدام خاصية <code>keyTimes</code> ثم لتحديد قيمة الخاصية المتحركة لكل إطار، يمكنك استخدام خاصية <code>values</code>. اصطلاحات التسمية في SMIL مريحة للغاية.
</p>

<p>
	إذا أردنا العودة إلى الدائرة المتحركة التي رافقتنا في الأمثلة السابقة، واستخدمنا قيمًا مماثلة لتلك الموجودة في إطارات CSS الأساسية أعلاه، فإن الشيفرة سيبدو كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_32" style="">
<span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#orange-circle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"cx"</span><span class="pln">
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"450"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"2s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"click"</span><span class="pln">
    </span><span class="atn">values</span><span class="pun">=</span><span class="atv">"50; 490; 350; 450"</span><span class="pln">
    </span><span class="atn">keyTimes</span><span class="pun">=</span><span class="atv">"0; 0.5; 0.8; 1"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"circ-anim"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	إذن ماذا فعلنا هناك؟ أول ما يجب ملاحظته هنا هو تحديد أوقات الإطار الرئيسي والقيم الوسيطة كقوائم. خاصية <code>keyTimes</code> هي قائمة مفصولة بفواصل منقوطة لقيم الوقت المستخدمة للتحكم في سرعة الحركة. في كل مرة في القائمة يتوافق مع قيمة في قائمة خاصية <code>values</code>، ويحدد متى تُستخدم القيمة في وظيفة التحريك. تُحدد كل قيمة زمنية في قائمة <code>keyTimes</code> كقيمة نقطة عائمة بين 0 و 1 (ضمنًا)، مما يمثل إزاحة متناسبة في المدة البسيطة لعنصر الحركة. لذا تشبه أوقات المفاتيح تلك الموجودة في CSS، إلا أنه بدلًا من تحديدها كنسب مئوية، فإنك تحددها ككسر.
</p>

<p>
	ما يلي هو العرض الحي للشيفرة أعلاه. انقر على الدائرة لبدء الحركة.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="550" id="cp_embed_ab87fd834cdf0af7ec27850e81b1c08a" name="cp_embed_7" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/ab87fd834cdf0af7ec27850e81b1c08a?height=550&amp;theme-id=1&amp;slug-hash=ab87fd834cdf0af7ec27850e81b1c08a&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_7"></iframe>
</p>

<p>
	لاحظ أنه إذا استخدمت قائمة<code>values</code>، فإن الحركة ستطبق القيم بالترتيب على مدار فترة الحركة. إذا حددت قائمة <code>values</code>، فسيتم تجاهل أي من الخاصيات <code>from</code> و<code>to</code> و<code>by</code>. في هذه المرحلة، تجدر الإشارة أيضًا إلى أنه يمكنك استخدام خاصية <code>values</code> بدون خاصية <code>keyTimes</code> - تنتشر القيم تلقائيًا بالتساوي خلال الوقت لكل قيمة <code>calcMode</code> بخلاف <code>paced</code> (راجع القسم التالي).
</p>

<h3>
	التحكم في سرعة الحركة باستخدام التخفيف المخصص: <code>calcMode</code> و <code>keySplines</code>
</h3>

<p>
	سنتطرق إلى موازنة CSS-SMIL مرة أخرى لأن بناء SMIL ومفاهيمه سيكون أسهل بكثير لفهم ما إذا كنت ستعتاد بالفعل على التحريك بواسطة CSS.
</p>

<p>
	في CSS، يمكنك اختيار تغيير سرعة الحركة الافتراضية الموحدة وتحديد وظيفة تخفيف مخصصة تتحكم في الحركة، باستخدام خاصية animation-timing-function. يمكن أن تكون وظيفة التوقيت واحدة من الكلمات المفتاحية المحددة مسبقًا، أو وظيفة مكعب <a href="https://en.wikipedia.org/wiki/B%C3%A9zier_curve" rel="external nofollow">cubic bezier</a>. يمكن إنشاء ذلك باستخدام أداة مثل <a href="https://cubic-bezier.com/#.17,.67,.85,.06" rel="external nofollow">هذه</a> المعدة بواسطة Lea Verou.
</p>

<p>
	في SMIL، تُحدد سرعة الحركة باستخدام خاصية <code>calcMode</code>. سرعة الحركة الافتراضية هي <code>linear</code> لجميع عناصر الحركة باستثناء <code>animateMotion</code> (سنصل إليها لاحقًا في المقالة). بالإضافة إلى قيمة <code>linear</code>، يمكنك تعيين القيمة إلى: discrete أو<code>paced</code> أو<code>spline</code>.
</p>

<ul>
<li>
		<code>discrete</code>: تحدد أن وظيفة الحركة ستقفز من قيمة إلى أخرى دون أي تقاطع. هذا مشابه للدالة <code>steps()‎</code> في CSS.
	</li>
	<li>
		<code>paced</code>: يشبه <code>linear</code>، إلا أنه سيتجاهل أي أوقات تقدم وسطية تحددها <code>keyTimes</code>. ويحسب المسافة بين القيم اللاحقة ويقسم الوقت وفقًا لذلك. إذا كانت قيمك كلها بترتيب خطي linear، فلن تلاحظ الفرق. ولكن إذا كانت ذهابًا وإيابًا، أو إذا كانت ألوانًا (والتي يعامل معها كقيم متجه ثلاثي الأبعاد)، فسترى بالتأكيد القيم الوسيطة. فيما يلي عرض حي من Amelia Bellamy-Royds، يُظهر الفرق بين قيم <code>calcMode</code> الثلاث المذكورة حتى الآن:
	</li>
</ul>
<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="266" id="cp_embed_EzAju" name="cp_embed_8" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/AmeliaBR/embed/EzAju?height=266&amp;theme-id=1&amp;slug-hash=EzAju&amp;default-tab=result&amp;user=AmeliaBR&amp;name=cp_embed_8"></iframe>
</p>

<ul>
<li>
		spline: وهي القيمة الرابعة المقبولة بواسطة <code>calcMode</code>. يتشابك من قيمة واحدة في قائمة <code>values</code> إلى القيمة التالية وفقًا لوظيفة الوقت المحددة بواسطة <code>cubic Bezier spline</code>. تعرف نقاط الشريحة في خاصية <code>keyTimes</code>، وتحددد نقاط التحكم لكل فاصل زمني في خاصية <code>keySplines</code>.
	</li>
</ul>
<p>
	ربما لاحظت الخاصية HTML الجديدة في الجملة الأخيرة: خاصية <code>keySplines</code>. لذا، ماذا تفعل خاصية <code>keySplines</code>؟
</p>

<p>
	مرة أخرى، إلى ما يعادلها في CSS.
</p>

<p>
	في CSS، يمكنك تحديد سرعة الحركة داخل كل إطار رئيسي، بدلاً من تحديد سرعة حركة واحدة للحركة بأكملها. يمنحك هذا تحكمًا أفضل في كيفية متابعة كل حركة للإطار الرئيسي. مثال باستخدام هذه الميزة هو إنشاء تأثير ارتداد الكرة. قد تبدو الإطارات المفتاحية لذلك كما يلي:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_3117_34" style="">
<span class="lit">@keyframes</span><span class="pln"> bounce </span><span class="pun">{</span><span class="pln">
    </span><span class="lit">0</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        animation</span><span class="pun">-</span><span class="pln">timing</span><span class="pun">-</span><span class="kwd">function</span><span class="pun">:</span><span class="pln"> ease</span><span class="pun">-</span><span class="kwd">in</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="lit">15</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">200px</span><span class="pun">;</span><span class="pln">
        animation</span><span class="pun">-</span><span class="pln">timing</span><span class="pun">-</span><span class="kwd">function</span><span class="pun">:</span><span class="pln"> ease</span><span class="pun">-</span><span class="kwd">out</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="lit">30</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">70px</span><span class="pun">;</span><span class="pln">
        animation</span><span class="pun">-</span><span class="pln">timing</span><span class="pun">-</span><span class="kwd">function</span><span class="pun">:</span><span class="pln"> ease</span><span class="pun">-</span><span class="kwd">in</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="lit">45</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">200px</span><span class="pun">;</span><span class="pln">
        animation</span><span class="pun">-</span><span class="pln">timing</span><span class="pun">-</span><span class="kwd">function</span><span class="pun">:</span><span class="pln"> ease</span><span class="pun">-</span><span class="kwd">out</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="lit">60</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">120px</span><span class="pun">;</span><span class="pln">
        animation</span><span class="pun">-</span><span class="pln">timing</span><span class="pun">-</span><span class="kwd">function</span><span class="pun">:</span><span class="pln"> ease</span><span class="pun">-</span><span class="kwd">in</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="lit">75</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">200px</span><span class="pun">;</span><span class="pln">
        animation</span><span class="pun">-</span><span class="pln">timing</span><span class="pun">-</span><span class="kwd">function</span><span class="pun">:</span><span class="pln"> ease</span><span class="pun">-</span><span class="kwd">out</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="lit">90</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">170px</span><span class="pun">;</span><span class="pln">
        animation</span><span class="pun">-</span><span class="pln">timing</span><span class="pun">-</span><span class="kwd">function</span><span class="pun">:</span><span class="pln"> ease</span><span class="pun">-</span><span class="kwd">in</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="lit">100</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">200px</span><span class="pun">;</span><span class="pln">
        animation</span><span class="pun">-</span><span class="pln">timing</span><span class="pun">-</span><span class="kwd">function</span><span class="pun">:</span><span class="pln"> ease</span><span class="pun">-</span><span class="kwd">out</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بدلاً من تسهيل الكلمات المفتاحية، كان بإمكاننا استخدام الدالة <code>()cubic-bezier</code> ذات الصلة:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_3117_36" style="">
<span class="pln">ease</span><span class="pun">-</span><span class="kwd">in</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> cubic</span><span class="pun">-</span><span class="pln">bezier</span><span class="pun">(</span><span class="lit">0.47</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.745</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.715</span><span class="pun">)</span><span class="pln">
ease</span><span class="pun">-</span><span class="kwd">out</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> cubic</span><span class="pun">-</span><span class="pln">bezier</span><span class="pun">(</span><span class="lit">0.39</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.575</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.565</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span></pre>

<p>
	لنبدأ بتحديد الأوقات الرئيسية وقائمة القيم للدائرة البرتقالية لتخضع لنفس تأثير الارتداد:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_38" style="">
<span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#orange-circle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"cy"</span><span class="pln">
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"250"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"3s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"click"</span><span class="pln">
    </span><span class="atn">values</span><span class="pun">=</span><span class="atv">"50; 250; 120;250; 170; 250; 210; 250"</span><span class="pln">
    </span><span class="atn">keyTimes</span><span class="pun">=</span><span class="atv">"0; 0.15; 0.3; 0.45; 0.6; 0.75; 0.9; 1"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"circ-anim"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	ستبدأ الحركة عند النقر، وستتوقف بمجرد وصولها إلى القيمة النهائية. بعد ذلك، من أجل تحديد وتيرة كل إطار رئيسي، سنضيف خاصية <code>keySplines</code>.
</p>

<p>
	تأخذ خاصية <code>keySplines</code> مجموعة من نقاط التحكم bezier المرتبطة بقائمة <code>keyTimes</code>، وتحديد وظيفة bezier المكعبة التي تتحكم في سرعة الفاصل الزمني. قيمة الخاصية HTML هي قائمة مفصولة بفواصل منقوطة لوصف نقطة التحكم. كل وصف لنقطة التحكم عبارة عن مجموعة من أربع قيم: y1 x1 x2 y2، تصف نقاط التحكم bezier لشريحة وقت واحدة. يجب أن تكون جميع القيم في النطاق من 0 إلى 1، وتستبعد الخاصية HTML ما لم تُعين <code>calcMode</code> على شكل <code>spline</code>.
</p>

<p>
	بدلاً من أخذ دوال cubic-bezier كقيم، تأخذ <code>keySplines</code> إحداثيات نقطتي التحكم المستخدمة لرسم المنحنى. يمكن رؤية نقاط التحكم في لقطة الشاشة التالية المأخوذة من أداة Lea. تعرض لقطة الشاشة أيضًا إحداثيات كل نقطة، كل لون بنفس لون النقطة نفسها. بالنسبة لخاصية <code>keySplines</code>، هذه هي القيم التي سنستخدمها لتحديد سرعة الحركة الموجودة في keyframe.
</p>

<p>
	يسمح SMIL بفصل هذه القيم إما بفواصل بمسافة بيضاء اختيارية أو بمسافة بيضاء فقط. قيم <code>keyTimes</code> التي تحدد الجزء المرتبط هي "نقاط الربط" bezier، وقيم <code>keySplines</code> هي نقاط التحكم. وبالتالي، يجب أن يكون هناك مجموعة واحدة أقل من نقاط التحكم من <code>keyTimes</code>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="36380" href="https://academy.hsoub.com/uploads/monthly_2020_04/01.png.9f538200efbb3a6f7c8e866e263be115.png" rel=""><img alt="01.png" class="ipsImage ipsImage_thumbnailed" data-fileid="36380" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_04/01.png.9f538200efbb3a6f7c8e866e263be115.png"></a>
</p>

<p>
	إذا عدنا إلى مثال الكرة المرتدة، تُعرض إحداثيات نقطة التحكم للدالتين <code>ease-in</code> و <code>ease-out</code> كما هو موضح في الصور التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="36381" href="https://academy.hsoub.com/uploads/monthly_2020_04/02.png.521532283c9bd77567289c022c0352d7.png" rel=""><img alt="02.png" class="ipsImage ipsImage_thumbnailed" data-fileid="36381" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_04/02.png.521532283c9bd77567289c022c0352d7.png"></a>
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="36382" href="https://academy.hsoub.com/uploads/monthly_2020_04/03.png.7eed2a31cb6ffc6989b30045aa2f7ba9.png" rel=""><img alt="03.png" class="ipsImage ipsImage_thumbnailed" data-fileid="36382" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_04/03.png.7eed2a31cb6ffc6989b30045aa2f7ba9.png"></a>
</p>

<p>
	لترجمة ذلك إلى عنصر متحرك في SVG، نحصل على الشيفرة التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_40" style="">
<span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#orange-circle"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"cy"</span><span class="pln">
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"250"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"3s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"click"</span><span class="pln">
    </span><span class="atn">values</span><span class="pun">=</span><span class="atv">"50; 250; 120;250; 170; 250; 210; 250"</span><span class="pln">
    </span><span class="atn">keyTimes</span><span class="pun">=</span><span class="atv">"0; 0.15; 0.3; 0.45; 0.6; 0.75; 0.9; 1"</span><span class="pln">
    </span><span class="atn">keySplines</span><span class="pun">=</span><span class="atv">".42 0 1 1;
                0 0 .59 1;
                .42 0 1 1;
                0 0 .59 1;
                .42 0 1 1;
                0 0 .59 1;
                .42 0 1 1;
                0 0 .59 1;"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
    </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"circ-anim"</span><span class="tag">/&gt;</span></pre>

<p>
	وهنا تتابع العرض الحي:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="550" id="cp_embed_ecd0f3197b5fc0d7950ed94cc8afb97f" name="cp_embed_9" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 290px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/ecd0f3197b5fc0d7950ed94cc8afb97f?height=550&amp;theme-id=1&amp;slug-hash=ecd0f3197b5fc0d7950ed94cc8afb97f&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_9"></iframe>
</p>

<p>
	إذا كنت ترغب فقط في تحديد دوال التسارع (easing function) بأكملها دون أي قيم وسيطة، فلا يزال يتعين عليك تحديد الإطارات المفتاحية باستخدام خاصية <code>keyTimes</code>، ولكن عليك فقط تحديد إطارات المفاتيح للبداية والنهاية، وهي<code>1 ؛ 0</code>، وليس القيم المتوسطة <code>values</code>.
</p>

<h3>
	الحركات المضافة والتراكمية: <code>addictive</code> و<code>accumulate</code>
</h3>

<p>
	في بعض الأحيان، من المفيد تحديد رسم متحرك يبدأ من حيث انتهت الحركة السابقة؛ أو آخر يستخدم المجموع التراكمي للحركات السابقة كقيمة للمتابعة. لذلك، يحتوي SVG على خاصيتين مناسبتين: <code>addictive</code> و<code>accumulate</code>.
</p>

<p>
	افترض أن لديك عنصرًا تريد أن "يزداد" عرضه، أو خطًا تريد زيادة طوله، أو عنصرًا تريد نقله خطوة بخطوة من موضع إلى آخر، عبر خطوات منفصلة. هذه الميزة مفيدة بشكل خاص للحركة المتكررة.
</p>

<p>
	تمامًا مثل أي حركة أخرى، ستحدد قيم <code>from</code> و<code>to</code>. ومع ذلك، عند تعيين <code>additive</code> إلى<code>sum</code>، ستكون قيمتهما متناسبة مع القيمة الأصلية للخاصية HTML المتحركة.
</p>

<p>
	لذا، بالعودة إلى دائرتنا، يكون الموضع الأولي لـ cx هو 50. عندما تقوم بتعيين <code>from = "0"‎</code> و<code>to = "100"‎</code>، فإن الصفر إذا كان في الواقع هو 50 الأصلي، و 100 هو في الواقع 50 + 100؛ بمعنى آخر، من الناحية العملية يشبه <code>from = "50" to = "150"‎</code>.
</p>

<p>
	من خلال القيام بذلك، نحصل على النتيجة التالية:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="290" id="cp_embed_77b1afdefe05eff8f1d538e0f3f8727e" name="cp_embed_10" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 290px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/77b1afdefe05eff8f1d538e0f3f8727e?height=290&amp;theme-id=1&amp;slug-hash=77b1afdefe05eff8f1d538e0f3f8727e&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_10"></iframe>
</p>

<p>
	هذا هو كل ما تفعله خاصية <code>additive</code>. إنه تحدد فقط ما إذا كان يجب أن تكون القيم <code>from</code> و<code>to</code> متناسبة مع القيمة الحالية أم لا. تأخذ الخاصية HTML واحدة من قيمتين فقط: <code>sum</code> و<code>replace</code>. الأخير هو القيمة الافتراضية، وهذا يعني بشكل أساسي أن القيم <code>from</code> و<code>to</code>سوف تحل محل القيم الحالية /الأصلية، والتي قد تؤدي في النهاية إلى قفزة غريبة قبل بدء الحركة. (حاول استبدال <code>sum</code> بـ<code>replace</code> في المثال أعلاه للحصول على مقارنة أفضل).
</p>

<p>
	ومع ذلك، ماذا لو أردنا إضافة القيم بحيث يبدأ التكرار الثاني من قيمة نهاية القيمة السابقة؟ هذا هو المكان الذي تأتي فيه خاصية <code>accumulate</code>.
</p>

<p>
	تتحكم خاصية <code>accumulate</code> فيما إذا كانت الحركة تراكمية أم لا. القيمة الافتراضية هي <code>none</code>، مما يعني أنه عند تكرار الحركة على سبيل المثال، ستبدأ من البداية. ومع ذلك، يمكنك تعيينها على<code>sum</code>، والتي تحدد أن كل إعادة للتكرار بعد الأول يبني على القيمة الأخيرة للتكرار السابق.
</p>

<p>
	لذلك، إذا أردنا العودة إلى الحركة السابقة وتحديد <code>accumulate = "sum"‎</code>، فسنحصل على النتيجة المفضلة التالية:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="290" id="cp_embed_e21b7dd0af3d0a6db2828362bee24d48" name="cp_embed_11" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 500px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/e21b7dd0af3d0a6db2828362bee24d48?height=290&amp;theme-id=1&amp;slug-hash=e21b7dd0af3d0a6db2828362bee24d48&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_11"></iframe>
</p>

<p>
	لاحظ أنه يتم تجاهل خاصية <code>accumulate</code> إذا كانت قيمة الخاصية HTML الهدف لا تدعم الإضافة، أو إذا كان العنصر المتحرك لا يتكرر. سيتم تجاهله أيضًا إذا عُينت وظيفة الحركة مع خاصية <code>to</code> فقط.
</p>

<h3>
	تحديد نهاية الحركة باستخدام <code>end</code>
</h3>

<p>
	كما أنه بإمكانك تحديد بداية حركة الرسوم فبإمكانك أيضًا تحديد نهايتها باستخدام خاصية <code>end</code>. على سبيل المثال، يمكنك تعيين حركة عنصر ما لتتكرر بشكل دائم ومن ثم إيقاف الحركة عند بداية حركة عنصر آخر. تأخذ خاصية <code>end</code> قيم شبيهة للقيم التي تأخذها <code>begin</code>. بإمكانك تحديد قيم مطلقة أو نسبية للوقت أو تطبيق إزاحة أو تكرار أو غيرها.
</p>

<p>
	فمثلًا في العرض الحي التالي تتحرك الدائرة ذات اللون البرتقالي ببطء في دورة تستمر 30 ثانية بالاتجاه الآخر لمسطح العمل. الدائرة ذات اللون الأخضر ستتحرك فقط عند النقر عليها. حركة الدائرة البرتقالية ستنتهي عند بدء حركة الدائرة الخضراء. انقر على الدائرة الخضراء وانظر كيف ستتوقف حركة الدائرة البرتقالية:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="500" id="cp_embed_1a67cdf89a865d044e2993a81a4f26be" name="cp_embed_12" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 280px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/1a67cdf89a865d044e2993a81a4f26be?height=500&amp;theme-id=1&amp;slug-hash=1a67cdf89a865d044e2993a81a4f26be&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_12"></iframe>
</p>

<p>
	يمكن تحقيق نفس التزامن للحركة عند تطبيق حركتين على نفس العنصر. على سبيل المثال، افترض تعيين حركة تغيير لون عنصر ما من قيمة لأخرى بشكل لانهائي. بعدها عند النقر على العنصر فإنه يتحرك للناحية الأخرى من مسطح العمل. والآن أوقف حركة تغيير اللون عند النقر على العنصر ومن بعدها تتوقف الحركة كليًا.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="280" id="cp_embed_71fa25f8bd43d55ca04fa2259cb7d5f5" name="cp_embed_13" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 266px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/71fa25f8bd43d55ca04fa2259cb7d5f5?height=280&amp;theme-id=1&amp;slug-hash=71fa25f8bd43d55ca04fa2259cb7d5f5&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_13"></iframe>
</p>

<h3>
	تعيين فترات الحركة باستخدام قيم كلًا من <code>begin</code> و<code>end</code>
</h3>

<p>
	في الواقع، تقبل كل من الخاصية <code>begin</code> و<code>end</code> قائمة القيم شبه المفصولة. ستتوافق كل قيمة في خاصية <code>begin</code> مع قيمة في خاصية <code>end</code>، وبالتالي تتشكل فواصل متحركة نشطة وغير نشطة.
</p>

<p>
	يمكنك أن تفكر في هذا على أنه يشبه سيارة متحركة، حيث تكون إطارات السيارة نشطة ومن ثم غير نشطة لفترات زمنية، اعتمادًا على ما إذا كانت السيارة تتحرك أم لا. يمكنك أيضًا إنشاء تأثير سيارة متحركة من خلال تطبيق الحركة على السيارة: أحدها يترجم السيارة أو يحركها على طول مسار يمثل أيضًا حركة مضافة وتراكمية، والأخرى تدور إطارات السيارة في فواصل يمكن مزامنتها مع عملية التحويل.
</p>

<p>
	مثال يوضح أوقات البدء والانتهاء المتعددة (أي الفواصل الزمنية) هو العرض الحي التالي، حيث يدور المستطيل استنادًا إلى الفواصل الزمنية المحددة، ويتغير من نشط إلى غير نشط وفقًا لذلك. (أعد تشغيل العرض الحي إذا فاتتك الحركة).
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="266" id="cp_embed_cb46822d292b7a542eba729c897ed046" name="cp_embed_14" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 257px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/cb46822d292b7a542eba729c897ed046?height=266&amp;theme-id=1&amp;slug-hash=cb46822d292b7a542eba729c897ed046&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_14"></iframe>
</p>

<p>
	لاحظ أنه في المثال أعلاه، استخدمت عنصر<code>&lt;animateTransform&gt;</code> لتدوير المستطيل حول مركزه. سنتحدث عن هذا العنصر بمزيد من التفصيل في القسم التالي أدناه.
</p>

<p>
	لاحظ أيضًا أنه، حتى إذا قمت بتعيين تكرار <code>repeatCount</code> بشكل غير نهائي <code>indefinite</code>، سيتجاوز من خلال قيم <code>end</code> ولن يتكرر بتلك الصورة النهائية.
</p>

<h3>
	تقييد المدة النشطة لعنصر باستخدام <code>min</code> و<code>max</code>
</h3>

<p>
	مثلما يمكنك تقييد وقت تكرار الحركة، يمكنك أيضًا تقييد المدة النشطة الخاصة بها. تحدد خاصيات <code>min</code> و<code>max</code> الحد الأدنى والحد الأقصى لقيمة المدة النشطة على التوالي. حيث أنها توفر لنا وسيلة للسيطرة على الحد السفلي والعلوي من فترة العنصر النشط. تأخذ كلا الخاصيتين قيمة الساعة كقيمة.
</p>

<p>
	بالنسبة لـ <code>min</code>، يحدد طول الحد الأدنى لقيمة المدة النشطة، ويقاس بالوقت الفعلي للعنصر. يجب أن تكون القيمة أكبر من أو تساوي 0، وهي القيمة الافتراضية ولا تقيد المدة النشطة على الإطلاق.
</p>

<p>
	بالنسبة إلى<code>max</code>، تحدد قيمة الساعة طول الحد الأقصى لقيمة المدة النشطة، وتُقاس في وقت العنصر النشط. يجب أن تكون القيمة أكبر من 0. القيمة الافتراضية لـ <code>max</code> هي <code>indefinite</code>. وهذا لا يقيد المدة النشطة على الإطلاق.
</p>

<p>
	إذا حددت كل من الخاصيتين <code>min</code> و<code>max</code>، فيجب أن تكون قيمة <code>max</code> أكبر من أو تساوي قيمة <code>min</code>. وإلا فسيتم تجاهل كلا الخاصيتين.
</p>

<p>
	ولكن ما الذي يحدد المدة النشطة لعنصر ما؟ ذكرنا مدة التكرار من قبل، بالإضافة إلى "المدة البسيطة"، وهي مدة الحركة دون أي تكرار (محدد باستخدام <code>dur</code>)، فكيف تعمل كل هذه الأشياء معًا؟ من الذي يتجاوز ماذا؟ ثم ماذا عن الخاصية <code>end</code> التي سيتم تجاوزها ومن ثم ببساطة تنتهي الحركة؟
</p>

<p>
	الطريقة التي يحدث بها ذلك هي أن المتصفح سيقوم أولاً بحساب المدة النشطة بناءً على قيم <code>dur</code> و <code>repeatCount</code> و<code>repeatDur</code> و<code>end</code>. بعد ذلك، تعمل المدة المحسوبة مقابل قيم <code>min</code> و<code>max</code> المحددة. إذا كانت النتيجة ضمن الحدود، تكون قيمة المدة المحسوبة الأولى صحيحة ولن تتغير. وإلا قد تحدث حالتان:
</p>

<ul>
<li>
		إذا كانت المدة الزمنية المحسوبة الأولى أكبر من قيمة <code>max</code>، تعرف المدة النشطة للعنصر بأنها تساوي قيمة <code>max</code>.
	</li>
	<li>
		إذا كانت المدة المحسوبة الأولى أقل من قيمة <code>min</code>، تصبح المدة النشطة للعنصر مساوية للقيمة <code>min</code> ويكون سلوك العنصر كما يلي:
		<ul>
<li>
				إذا كانت مدة التكرار (أو المدة البسيطة إذا لم يتكرر العنصر) للعنصر أكبر من <code>min</code>، يُشغل العنصر بشكل طبيعي لمدة نشطة (<code>min</code> مقيدة).
			</li>
			<li>
				بخلاف ذلك، يعمل العنصر بشكل طبيعي خلال مدة التكرار (أو المدة البسيطة إذا لم يتكرر العنصر) ثم يُجمد أو يختفي عتمادًا على قيمة خاصية <code>fill</code>.
			</li>
		</ul>
</li>
</ul>
<p>
	هذا يتركنا مع تساؤل عن طريقة قيام المتصفح بحساب المدة النشطة فعليًا. من أجل الإيجاز، لن نخوض في التفاصيل هنا. ولكن هناك جدول شامل للغاية في المواصفات التي تعرض التكوينات المختلفة لخصائص <code>dur</code>، و<code>repeatCount</code>، و<code>repeatDor</code> و<code>end</code>، ثم توضح المدة الفعلية التي ستستند إليها كل مجموعة. يمكنك التحقق من الجدول وقراءة المزيد حول هذا الموضوع في <a href="https://www.w3.org/TR/2001/REC-smil-animation-20010904/#ComputingActiveDur" rel="external nofollow">هذا القسم من المواصفات</a>
</p>

<p>
	أخيرًا، إذا حدد عنصر للبدء في الحركة قبل العنصر الآخر (على سبيل المثال مع قيمة إزاحة سالبة بسيطة)، يُقاس الحد الأدنى للمدة من وقت البدء المحسوب وليس بداية الملاحظة. هذا يعني أن قيمة <code>min</code> قد لا يكون لها أي تأثير ملحوظ.
</p>

<h3>
	أمثلة على <code>&lt;animate&gt;</code>: تحوير المسارات
</h3>

<p>
	إحدى الخاصيات التي يمكن تحريكها في SMIL (ولكن ليس في CSS)هي الخاصية <code>d</code> (اختصار لـ data) الخاصة بـ SVG <code>&lt;path&gt;</code>‎. تحتوي الخاصية <code>d</code> على البيانات التي تحدد الخطوط العريضة للشكل الذي ترسمه. تتكون بيانات المسار من مجموعة من الأوامر والإحداثيات التي تخبر المتصفح عن مكان وكيفية رسم النقاط والأقواس والخطوط التي تشكل المسار النهائي.
</p>

<p>
	يسمح لنا تنشيط هذه الخاصية HTML بتحويل مسارات SVG وإنشاء تأثيرات ربط الأشكال. ولكن لكي تتمكن من <a href="https://codepen.io/noahblon/post/an-intro-to-svg-animation-with-smil" rel="external nofollow">تحوير الأشكال</a>، يجب أن يكون لأشكال المسار البداية والنهاية وأي مسار وسطي نفس عدد الرؤوس /النقاط بالضبط، ويجب أن تظهر بنفس الترتيب. إذا لم يتطابق عدد النقاط، فلن تعمل الحركة. والسبب في ذلك هو أن تغيير الشكل يحدث فعليًا عن طريق تحريك الرؤوس، وتحريف مواقعها، لذلك إذا كانت نقطة واحدة مفقودة أو غير متطابقة، فلن تُقرب المسارات.
</p>

<p>
	لتحريك مسارSVG، يمكنك تحديد attributeName لتكون <code>d</code>، ثم اضبط قيم <code>from</code> و<code>to</code> التي تحدد أشكال البداية والنهاية، ويمكنك استخدام خاصية <code>values</code> لتحديد أي قيم وسيطة تريد أن يمر الشكل فيما بينها.
</p>

<p>
	من أجل الإيجاز، لن نخوض في تفاصيل كيفية القيام بذلك هنا. بدلًا من ذلك، يمكنك قراءة <a href="https://codepen.io/noahblon/post/an-intro-to-svg-animation-with-smil" rel="external nofollow">هذا المقال الممتاز من تأليف Noah Blon</a>، إذ يشرح كيف قام بتحوير الأشكال لإنشاء حركة التحميل باستخدام <code>&lt;animate&gt;</code>. بإمكانك الاطلاع على العرض الحي للمقال:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="257" id="cp_embed_IhLFK" name="cp_embed_15" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 338px;" title="CodePen Embed" src="https://codepen.io/noahblon/embed/IhLFK?height=257&amp;theme-id=1&amp;slug-hash=IhLFK&amp;default-tab=result&amp;user=noahblon&amp;name=cp_embed_15"></iframe>
</p>

<p>
	وهنا مثال آخر لتحوير الأشكال من إعداد Felix Hornoiu:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="338" id="cp_embed_dovub" name="cp_embed_16" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 271px;" title="CodePen Embed" src="https://codepen.io/felixhornoiu/embed/dovub?height=338&amp;theme-id=1&amp;slug-hash=dovub&amp;default-tab=result&amp;user=felixhornoiu&amp;name=cp_embed_16"></iframe>
</p>

<p>
	يمكنك حتى تحوير قيم المسار المستخدم كـ clipping mask مثال على ذلك من إعداد Heather Buchel:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="271" id="cp_embed_qLxAB" name="cp_embed_17" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/hbuchel/embed/qLxAB?height=271&amp;theme-id=1&amp;slug-hash=qLxAB&amp;default-tab=result&amp;user=hbuchel&amp;name=cp_embed_17"></iframe>
</p>

<h2>
	الحركة على طول المسارات الافتراضية: العنصر <code>&lt;animateMotion&gt;</code>
</h2>

<p>
	يعد عنصر<code>&lt;animateMotion&gt;</code> عنصر الحركة المفضل في SMIL. يمكنك استخدامه لنقل عنصر على طول المسار. عن طريق تحديد مسار الحركة باستخدام إحدى الطريقتين اللتين سنتطرق لهما بعد ذلك، ثم لإعداد العنصر بحيث يتحرك على طول هذا المسار.
</p>

<p>
	يقبل عنصر<code>&lt;animateMotion&gt;</code> نفس الخاصيات المذكورة سابقًا، بالإضافة إلى ثلاث خاصيات أخرى: <code>keyPoints</code>، و <code>rotate</code>، و<code>path</code>. أيضًا، هناك اختلاف واحد فيما يتعلق بخاصية <code>calcMode</code>، حيث تكون القيمة الافتراضية لـ <code>&lt;animateMotion&gt;</code> هي <code>paced</code>، وليست <code>linear</code>.
</p>

<h3>
	تحديد مسار الحركة باستخدام خاصية <code>path</code>
</h3>

<p>
	تستخدم خاصية <code>path</code> لتحديد مسار الحركة. حيث يُعبر عنها بنفس التنسيق وتُفسر بنفس طريقة الخاصية <code>d</code> في العنصر <code>path</code>. يتمثل تأثير الحركة لمسار الحركة في إضافة مصفوفة تحويل تكميلية إلى مصفوفة التحويل الحالية للكائن المشار إليه والتي تتسبب في ترجمة على طول المحورين x و y لنظام إحداثيات المستخدم الحالي بواسطة قيم X و Y المحسوبة على زمن. بمعنى آخر، يُحسب المسار المحدد بالنسبة إلى الموضع الحالي للعنصر، باستخدام بيانات المسار لتحويل العنصر إلى موضع المسار.
</p>

<p>
	بالعودة إلى دائرتنا، سنقوم بتحريكها على طريق يشبه ما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="36383" href="https://academy.hsoub.com/uploads/monthly_2020_04/04.png.f6422ab11143a857ac49e8d1da562cc2.png" rel=""><img alt="04.png" class="ipsImage ipsImage_thumbnailed" data-fileid="36383" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_04/04.png.f6422ab11143a857ac49e8d1da562cc2.png"></a>
</p>

<p>
	بإمكانك تطبيق تلك الحركة على الدائرة باستخدام الشيفرة التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_42" style="">
<span class="tag">&lt;animateMotion</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#circle"</span><span class="pln">
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"1s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"click"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln">
    </span><span class="atn">path</span><span class="pun">=</span><span class="atv">"M0,0c3.2-3.4,18.4-0.6,23.4-0.6c5.7,0.1,10.8,0.9,16.3,2.3    c13.5,3.5,26.1,9.6,38.5,16.2c12.3,6.5,21.3,16.8,31.9,25.4c10.8,8.7,21,18.3,31.7,26.9c9.3,7.4,20.9,11.5,31.4,16.7
    c13.7,6.8,26.8,9.7,41.8,9c21.4-1,40.8-3.7,61.3-10.4c10.9-3.5,18.9-11.3,28.5-17.8c5.4-3.7,10.4-6.7,14.8-11.5
    c1.9-2.1,3.7-5.5,6.5-6.5"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	هناك أمر واحد ركزنا عليه هنا: الإحداثيات في بيانات المسار. يبدأ المسار عن طريق تحريك (M) إلى النقطة مع الإحداثيات (0، 0)، قبل أن يبدأ في رسم منحنى (c) إلى نقطة أخرى. من المهم أن نلاحظ أن النقطة (0، 0) هي في الواقع موضع الدائرة، بغض النظر عن مكانها - ليست الزاوية العليا اليسرى من نظام الإحداثيات. كما ذكرنا أعلاه، فإن الإحداثيات في خاصية <code>path</code> تتعلق بالموضع الحالي للعنصر!
</p>

<p>
	نتيجة الشيفرة أعلاه هي:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="550" id="cp_embed_184082960ac3cc65d00b22f2551a330a" name="cp_embed_18" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/184082960ac3cc65d00b22f2551a330a?height=550&amp;theme-id=1&amp;slug-hash=184082960ac3cc65d00b22f2551a330a&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_18"></iframe>
</p>

<p>
	إذا كنت ترغب في تحديد المسار الذي يبدأ من نقطة أخرى غير (0، 0)، ستقفز الدائرة فجأة بالمقدار المحدد في نقطة البداية. على سبيل المثال، افترض أنك رسمت مسارًا في Illustrator ثم قمت بتصدير بيانات المسار لاستخدامها كمسار حركة (هذا ما فعلته في المرة الأولى التي قمت فيها بهذا)؛ قد يبدو المسار المُصدّر كالتالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_44" style="">
<span class="tag">&lt;path</span><span class="pln"> </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"none"</span><span class="pln"> </span><span class="atn">stroke</span><span class="pun">=</span><span class="atv">"#000000"</span><span class="pln"> </span><span class="atn">stroke-miterlimit</span><span class="pun">=</span><span class="atv">"10"</span><span class="pln"> </span><span class="atn">d</span><span class="pun">=</span><span class="atv">"M100.4,102.2c3.2-3.4,18.4-0.6,23.4-0.6c5.7,0.1,10.8,0.9,16.3,2.3
    c13.5,3.5,26.1,9.6,38.5,16.2c12.3,6.5,21.3,16.8,31.9,25.4c10.8,8.7,21,18.3,31.7,26.9c9.3,7.4,20.9,11.5,31.4,16.7
    c13.7,6.8,26.8,9.7,41.8,9c21.4-1,40.8-3.7,61.3-10.4c10.9-3.5,18.9-11.3,28.5-17.8c5.4-3.7,10.4-6.7,14.8-11.5
    c1.9-2.1,3.7-5.5,6.5-6.5"</span><span class="tag">/&gt;</span></pre>

<p>
	نقطة بداية المسار في هذه الحالة هي (100.4، 102.2). إذا أردنا استخدام هذه البيانات كمسار للحركة، ستقفز الدائرة بمقدار 100 وحدة تقريبًا إلى اليمين و102 وحدة تقريبًا لأسفل، ثم تبدأ الحركة على طول المسار بالنسبة للموضع الجديد. لذلك، تأكد من وضع ذلك في الاعتبار عند إعداد مسار الحركة للحركة الخاصة بك.
</p>

<p>
	في حالة استخدامها، تحدد الخاصيات <code>from</code> و<code>by</code> و<code>to</code> و<code>values</code> شكلًا على مساحة العمل الحالية التي تمثل مسار الحركة.
</p>

<h3>
	تحديد مسار الحركة باستخدام عنصر <code>&lt;mpath&gt;</code>
</h3>

<p>
	هناك أيضًا طريقة أخرى يمكنك من خلالها تحديد مسار الحركة. بدلًا من استخدام خاصية HTML المسار النسبي path، يمكنك الرجوع إلى مسار خارجي باستخدام عنصر <code>&lt;mpath&gt;</code> التابع لعنصر <code>&lt;animateMotion&gt;</code>، والذي يشير إلى المسار الخارجي باستخدام الخاصية <code>xlink: href</code>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_46" style="">
<span class="tag">&lt;animateMotion</span><span class="pln"> </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#circle"</span><span class="pln"> </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"1s"</span><span class="pln"> </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"click"</span><span class="pln"> </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;mpath</span><span class="pln"> </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#motionPath"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
</span><span class="tag">&lt;/animateMotion&gt;</span></pre>

<p>
	يمكن تحديد مسار الحركة <code>&lt;path&gt;</code> في أي مكان في المستند؛ يمكن تعريفه حرفيًا فقط داخل عنصر <code>&lt;defs&gt;</code> ولا يُعرض على سطح العمل على الإطلاق. في المثال التالي، المسار ظاهر وواضح لأنه في معظم الحالات قد ترغب في إظهار المسار الذي يتحرك فيه العنصر.
</p>

<p>
	لاحظ أنه، وفقا للمواصفات:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		توفر نقاط (x، y) المتنوعة من الشكل مصفوفة تحويل تكميلية على CTM للكائن المشار إليه مما يؤدي إلى ترجمة على طول محاور x و y لنظام إحداثيات المستخدم الحالي بواسطة قيم (x، y) الشكل محسوب مع مرور الوقت. وبالتالي، يُترجم الكائن المشار إليه بمرور الوقت عن طريق إزاحة مسار الحركة بالنسبة إلى أصل نظام إحداثيات المستخدم الحالي. يُطبق التحويل الإضافي على أعلى أي تحويلات بسبب خاصية <code>transform</code> أو أي حركة على هذه الخاصية HTML بسبب عنصر <code>animateTransform</code> في العنصر الهدف.
	</p>
</blockquote>

<p>
	مرة أخرى، "يتضاعف" موضع الدائرة أو "يتحول" بواسطة الإحداثيات في بيانات المسار.
</p>

<p>
	في المثال التالي، لدينا مسار في منتصف اللوحة. تُوضع الدائرة في بداية المسار. ومع ذلك، عند تطبيق مسار الحركة، لا تبدأ الدائرة حركتها من موضعها الحالي. تفقد العرض الحي للحصول على شرح أفضل. انقر على الدائرة لتحريكها.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="550" id="cp_embed_0642931398bf1cf3ed1ff9b3e6b52398" name="cp_embed_19" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/0642931398bf1cf3ed1ff9b3e6b52398?height=550&amp;theme-id=1&amp;slug-hash=0642931398bf1cf3ed1ff9b3e6b52398&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_19"></iframe>
</p>

<p>
	انظر كيف تتبع الدائرة نفس شكل المسار، ولكن على موضع مختلف؟ هذا يرجع إلى حقيقة أن موضع الدائرة يُحول بواسطة قيم بيانات المسار.
</p>

<p>
	تتمثل إحدى طرق الالتفاف حول ذلك في البدء بوضع الدائرة في (0، 0)، بحيث عند استخدام بيانات المسار لتحويلها، ستبدأ وتستمر كما هو متوقع.
</p>

<p>
	هناك طريقة أخرى تتمثل في تطبيق <a href="https://www.sarasoueidan.com/blog/svg-transformations/" rel="external nofollow">تحويل</a> "يعيد تعيين" إحداثيات الدائرة بحيث تُحسب على الصفر قبل تطبيق المسار.
</p>

<p>
	فيما يلي نسخة معدلة من العرض الحي أعلاه، وذلك باستخدام مسار مغلق وتكرار الحركة بشكل غير نهائي.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="550" id="cp_embed_ef9f0e1242263cf23067b09be894cfa9" name="cp_embed_20" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/ef9f0e1242263cf23067b09be894cfa9?height=550&amp;theme-id=1&amp;slug-hash=ef9f0e1242263cf23067b09be894cfa9&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_20"></iframe>
</p>

<h3>
	تجاوز القواعد لـ <code>&lt;animateMotion&gt;</code>
</h3>

<p>
	نظرًا لوجود أكثر من طريقة واحدة لفعل نفس الشيء مع <code>animateMotion</code>، فمن المنطقي أن يكون هناك قواعد تجاوز لتحديد القيم التي تتجاوز القيم الأخرى.
</p>

<p>
	قواعد التجاوز لـ <code>animateMotion</code> كالتالي:
</p>

<ul>
<li>
		فيما يتعلق بتعريف مسار الحركة، يتجاوز عنصر <code>mpath</code> خاصية <code>path</code>، التي تتجاوز <code>values</code>، والتي بدورها تتجاوز <code>from</code> و<code>by</code> و<code>to</code>.
	</li>
	<li>
		فيما يتعلق بتحديد النقاط التي تتوافق مع خاصيات <code>keyTimes</code>، فإن مسار<code>keyPoints</code> يتخطى <code>path</code>، والذي يتجاوز <code>values</code>، والذي بدوره يتخطى <code>from</code> و<code>by</code> و<code>to</code>.
	</li>
</ul>
<h3>
	تحديد اتجاه عنصر على طول مسار الحركة باستخدام <code>rotate</code>
</h3>

<p>
	في المثال السابق، حدث أن العنصر الذي كنا نتحرك فيه على طول المسار هو دائرة. ولكن ماذا لو كنا نحرك عنصرًا له اتجاه معين، على سبيل المثال، رمز سيارة؟ رمز السيارة في المثال التالي من <a href="https://codepen.io/AmeliaBR/pen/ewvrC" rel="external nofollow">إعداد Freepik</a>.
</p>

<p>
	في هذا المثال، استبدلت الدائرة بمعرف "السيارة"، الذي يحتوي على العنصر الذي يُكون المجموعة. بعد ذلك، من أجل تجنب مشكلة الحركة على طول المسار المذكور أعلاه، ثم تطبيق تحويل على السيارة بحيث يترجمها بمقدار معين، بحيث ينتهي الموضع الأولي عند (0، 0). القيم الموجودة داخل التحويلات هي في الواقع إحداثيات النقطة التي يبدأ فيها رسم المسار الأول للسيارة (مباشرة بعد أمر النقل M).
</p>

<p>
	ثم تبدأ السيارة تتحرك على طول مسار الحركة. لكن… هكذا تبدو الحركة:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="500" id="cp_embed_3a300b8c4c0f9db4ff345f5d44992b74" name="cp_embed_21" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/3a300b8c4c0f9db4ff345f5d44992b74?height=500&amp;theme-id=1&amp;slug-hash=3a300b8c4c0f9db4ff345f5d44992b74&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_21"></iframe>
</p>

<p>
	اتجاه السيارة ثابت، ولا يتغير لمطابقة مسار الحركة. لتغيير ذلك، سنستخدم خاصية <code>rotate</code>.
</p>

<p>
	تأخذ خاصية <code>rotate</code> إحدى القيم الثلاث:
</p>

<ul>
<li>
		<code>auto</code>: تشير إلى أن الكائن يدور بمرور الوقت بزاوية الاتجاه (أي متجه الظل الاتجاهي) لمسار الحركة.
	</li>
	<li>
		<code>auto-reverse</code>: تشير إلى أن الكائن يدور بمرور الوقت بزاوية الاتجاه (أي متجه الظل الاتجاهي) لمسار الحركة بإضافة 180 درجة.
	</li>
	<li>
		رقم: يشير إلى أن العنصر الهدف يحتوي على تحويل دوران ثابت مطبق عليه، حيث تكون زاوية الدوران هي العدد المحدد من الدرجات.
	</li>
</ul>
<p>
	لإصلاح اتجاه السيارة في المثال أعلاه، سنبدأ بتعيين قيمة الدوران على <code>auto</code>. سننتهي بالنتيجة التالية:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="500" id="cp_embed_74af0bd0bbc7ca46d4d568ca0d473b40" name="cp_embed_22" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/74af0bd0bbc7ca46d4d568ca0d473b40?height=500&amp;theme-id=1&amp;slug-hash=74af0bd0bbc7ca46d4d568ca0d473b40&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_22"></iframe>
</p>

<p>
	أما في حال أردت تدوير السيارة خارج المسار، قيمة <code>auto-revesre</code> ستتكفل بذلك.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="500" id="cp_embed_1027d099f0e9cca94f8f8865d169c49f" name="cp_embed_23" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/1027d099f0e9cca94f8f8865d169c49f?height=500&amp;theme-id=1&amp;slug-hash=1027d099f0e9cca94f8f8865d169c49f&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_23"></iframe>
</p>

<p>
	يبدو هذا أفضل، لكن لا تزال لدينا مشكلة واحدة وهي أن السيارة تبدو وكأنها تتحرك للخلف على طول المسار! لتغيير ذلك، نحتاج إلى قلب السيارة على طول محورها y. يمكن القيام بذلك عن طريق تحجيمه بعامل "-1" على طول هذا المحور. لذلك، إذا طبقنا التحويل على <code>g</code> باستخدام معرف السيارة <code>car</code>، فستتحرك السيارة للأمام كما هو متوقع. سيرتبط التحجيم مع الترجمة السابقة التي طبقناها سابقًا.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_48" style="">
<span class="tag">&lt;g</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"car"</span><span class="pln"> </span><span class="atn">transform</span><span class="pun">=</span><span class="atv">"scale (-1, 1) translate(-234.4, -182.8)"</span><span class="tag">&gt;</span></pre>

<p>
	وبالتالي، ستكون النتيجة كما هي موضحة في العرض:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="500" id="cp_embed_48caf2f5fa42a8c154fcb5dec0dbe4d5" name="cp_embed_24" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 266px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/48caf2f5fa42a8c154fcb5dec0dbe4d5?height=500&amp;theme-id=1&amp;slug-hash=48caf2f5fa42a8c154fcb5dec0dbe4d5&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_24"></iframe>
</p>

<h3>
	التحكم في مسافة الحركة على طول مسار الحركة باستخدام <code>keyPoints</code>
</h3>

<p>
	توفر خاصية <code>keyPoints</code> القدرة على تحديد التقدم على طول مسار الحركة لكل من قيم <code>keyTimes</code> المحددة. إذا حددت ذلك، فإن <code>keyPoints</code> تؤدي إلى تطبيق <code>keyTimes</code> على القيم الموجودة في <code>keyPoints</code> بدلاً من النقاط المحددة في خاصية <code>values</code> أو النقاط الموجودة في خاصية <code>path</code>.
</p>

<p>
	تأخذ <code>keyPoints</code> قائمة مفصولة بفواصل منقوطة لقيم الفاصلة العائمة بين 0 و 1 وتشير إلى مدى طول مسار الحركة التي يجب أن يتحرك فيها الكائن في الوقت المحدد بواسطة قيمة <code>keyTimes</code> المقابلة. تُحدد الحسابات عن بعد من خلال خوارزميات المتصفح. تقابل كل قيمة تقدم في القائمة قيمة في قائمة خاصية <code>keyTimes</code>. عند تحديد قائمة نقاط <code>KeyPoints</code>، يجب أن يكون هناك بالضبط العديد من القيم في قائمة <code>keyPoints</code> كما هو الحال في قائمة <code>keyTimes</code>.
</p>

<p>
	أحد الأشياء المهمة التي يجب ملاحظتها هنا هو ضبط قيمة <code>calcMode</code> على <code>linear</code> لكي تعمل <code>KeyPoints</code>. يبدو أيضًا أنه يجب أن يعمل بشكل منطقي مع الحركة، إذا كانت النقاط الرئيسية تتحرك ذهابًا وإيابًا، لكنها لا تعمل.
</p>

<p>
	فيما يلي مثال من إعداد Amelia Bellamy-Royds <a href="https://codepen.io/AmeliaBR/" rel="external nofollow">(تفقد صفحتها الشخصية)</a> توضح فيه استخدام <code>keyPoints</code> لتقليد السلوك فتبدأ الحركة على مسار من إزاحة محددة مسبقًا، لأننا لا نملك هذه القدرة حاليًا بشكل افتراضي في SMIL.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="266" id="cp_embed_ewvrC" name="cp_embed_25" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/AmeliaBR/embed/ewvrC?height=266&amp;theme-id=1&amp;slug-hash=ewvrC&amp;default-tab=result&amp;user=AmeliaBR&amp;name=cp_embed_25"></iframe>
</p>

<h2>
	تحريك النص على طول مسار افتراضي
</h2>

<p>
	يختلف نقل النص عبر مسار افتراضي عن نقل عناصر SVG الأخرى عبر المسارات. لتحريك النص، سيتعين عليك استخدام عنصر <code>&lt;animation&gt;</code>، وليس عنصر <code>&lt;animateMotion&gt;</code>.
</p>

<p>
	أولاً، لنبدأ بوضع النص على طول المسار. يمكن القيام بذلك عن طريق تداخل عنصر<code>&lt;textPath&gt;</code> داخل عنصر <code>&lt;text&gt;</code>. سيتحدد النص الذي سيوضع على طول مسار داخل عنصر<code>&lt;textPath&gt;</code>، وليس كتابع لعنصر<code>&lt;text&gt;</code>.
</p>

<p>
	ستقوم <code>textPath</code> بعد ذلك بالإشارة إلى المسار الفعلي المراد استخدامه، تمامًا كما فعلنا في الأمثلة السابقة. يمكن أيضًا تقديم المسار المشار إليه على مسطح العمل أو تعريفه داخل <code>&lt;defs&gt;</code>. تحقق من الشيفرة في العرض الحي التالي:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="500" id="cp_embed_ebfc92e45e24b29c266f50e6f617cdf5" name="cp_embed_26" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/ebfc92e45e24b29c266f50e6f617cdf5?height=500&amp;theme-id=1&amp;slug-hash=ebfc92e45e24b29c266f50e6f617cdf5&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_26"></iframe>
</p>

<p>
	لتحريك النص على طول هذا المسار، سنستخدم العنصر <code>&lt;animate&gt;</code> لتحريك خاصية <code>startOffset</code>.
</p>

<p>
	تمثل <code>startOffset</code> إزاحة النص على المسار. 0٪ هي بداية المسار؛ 100 ٪ تمثل نهايته. لذلك، على سبيل المثال، إذا ضبطت الإزاحة على 50٪، فسيبدأ النص في منتصف المسار. ومن هنا ستتضح الأمور للذهاب قدمًا.
</p>

<p>
	عن طريق تنشيط <code>startOffset</code>، سنقوم بإنشاء تأثير نقل النص على طول المسار. تحقق من الشيفرة في العرض الحي التالي.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="500" id="cp_embed_501308e154923359ed1cdbfa29eadcc0" name="cp_embed_27" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 200px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/501308e154923359ed1cdbfa29eadcc0?height=500&amp;theme-id=1&amp;slug-hash=501308e154923359ed1cdbfa29eadcc0&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_27"></iframe>
</p>

<h2>
	تحولات الحركة: عنصر <code>&lt;animateTransform&gt;</code>
</h2>

<p>
	ينقل عنصر <code>&lt;animateTransform&gt;</code> خاصية HTML تحويل على عنصر مستهدف، مما يسمح للحركة بالتحكم في التحوير والتحجيم و/أو التدوير و/أو الربط. يستغرق نفس الخصائص المذكورة للعنصر <code>&lt;animation&gt;</code>، بالإضافة إلى خاصية HTML إضافية: <code>type</code>.
</p>

<p>
	تستخدم خاصية <code>type</code> لتحديد نوع التحويل الذي تُطبق الحركة عليه. وتأخذ أحد القيم الخمسة: <code>translate</code> و<code>scale</code> و<code>rotate</code> و<code>skewX</code> و<code>skewY</code>.
</p>

<p>
	تأخذ الخاصيات <code>from</code> و<code>by</code> و<code>to</code> قيم يعبّرعنها باستخدام تركيب الجملة نفسه المتاح لنوع التحويل المحدد:
</p>

<ul>
<li>
		بالنسبة لـ<code>"type="translate</code>، يُعبر عن كل قيمة فردية كـ <code>[&lt;tx&gt; [,&lt;ty&gt;</code>
	</li>
	<li>
		بالنسبة لـ <code>"type="scale</code>، يُعبر عن كل قيمة فردية كـ <code>[&lt;sx&gt; [,&lt;sy&gt;</code>
	</li>
	<li>
		بالنسبة لـ <code>"type="rotate</code>، يُعبر عن كل قيمة فردية كـ<code>[&lt;rotate-angle&gt; [&lt;cx&gt; &lt;cy&gt;</code>
	</li>
	<li>
		بالنسبة لـ <code>"type="skewX</code> و<code>"type="skewY</code>، يُعبر عن كل قيمة فردية كـ <code>&lt;skew-angle&gt;</code>
	</li>
</ul>
<p>
	إذا لم تكن معتادًا على بناء جملة SVG لخاصية <code>transform</code>، ومن أجل إيجاز هذه المقالة، ولأن تفاصيل بناء الجملة وكيفية التعامل معها خارج نطاقها، بإمكانك قراءة مقال <a href="https://www.sarasoueidan.com/blog/svg-transformations/" rel="external nofollow">فهم أنظمة تنسيق SVG والتحولات (الجزء 2): خاصية HTML التحويل</a>، قبل الانتقال إلى هذا الدليل.
</p>

<p>
	بالعودة إلى العرض الحي السابق، حيث قمنا بتدوير المستطيل الوردي باستخدام عنصر <code>&lt;animateTransform&gt;</code>. تبدو شيفرة الدوران كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3117_50" style="">
<span class="tag">&lt;rect</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"deepPink-rectangle"</span><span class="pln"> </span><span class="atn">width</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">height</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">x</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">y</span><span class="pun">=</span><span class="atv">"50"</span><span class="pln"> </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"deepPink"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

  </span><span class="tag">&lt;animateTransform</span><span class="pln"> 
      </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#deepPink-rectangle"</span><span class="pln">
      </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"transform"</span><span class="pln"> 
      </span><span class="atn">attributeType</span><span class="pun">=</span><span class="atv">"XML"</span><span class="pln">
      </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"rotate"</span><span class="pln">
      </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"0 75 75"</span><span class="pln">
      </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"360 75 75"</span><span class="pln"> 
      </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"2s"</span><span class="pln">
      </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"0s"</span><span class="pln">
      </span><span class="atn">repeatCount</span><span class="pun">=</span><span class="atv">"indefinite"</span><span class="pln">
      </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
     </span><span class="tag">/&gt;</span></pre>

<p>
	تحدد خاصيات <code>from</code> و<code>to</code> زاوية الدوران (البداية والنهاية) ومركز الدوران. في كليهما، يبقى مركز الدوران كما هو بالطبع. إذا لم تُحدد المركز، فسيكون ذلك هو الركن العلوي الأيسر من سطح العمل SVG. العرض الحي للرمز أعلاه هو ما يلي:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="280" id="cp_embed_1bb859d4103d5e32b037f69e906319fb" name="cp_embed_28" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 350px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/1bb859d4103d5e32b037f69e906319fb?height=280&amp;theme-id=1&amp;slug-hash=1bb859d4103d5e32b037f69e906319fb&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_28"></iframe>
</p>

<p>
	هنا مثال آخر ممتع لـ <code>animateTransform</code> من إعداد Gabriel:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="350" id="cp_embed_obhzc" name="cp_embed_29" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/guerreiro/embed/obhzc?height=350&amp;theme-id=1&amp;slug-hash=obhzc&amp;default-tab=result&amp;user=guerreiro&amp;name=cp_embed_29"></iframe>
</p>

<p>
	إن تنشيط عملية تحويل واحدة أمر بسيط، ومع ذلك، يمكن أن تصبح الأمور فوضوية ومعقدة حقًا عند تضمين تحويلات متعددة، خاصة لأن أحد تحويلات الحركة <code>animateTransform</code> يمكنه تجاوز الآخر، لذلك بدلاً من إضافة التأثيرات وتسلسلها، قد ينتهي بك الأمر على العكس تمامًا. هذا بالإضافة إلى طريقة تنسيق SVG للأنظمة والتحولات في الواقع (راجع المقالة المذكورة سابقًا حول الموضوع). الأمثلة واسعة، وخارج نطاق هذه المقالة. لتحويل SVGs، يوصى باستخدام تحويلات CSS. تعمل التطبيقات على جعل هذا الأخير يعمل بشكل مثالي مع SVG، لذلك قد لا تضطر أبدًا إلى استخدام SMIL لتنشيط التحويلات في SVG على الإطلاق.
</p>

<h2>
	عنصر <code>&lt;set&gt;</code>
</h2>

<p>
	يوفر عنصر <code>set</code> وسيلة بسيطة لتعيين قيمة الخاصية HTML لمدة محددة. يدعم جميع أنواع الخاصيات، بما في ذلك الأنواع التي لا يمكن تحريفها بشكل معقول، مثل قيم السلسلة والقيمة المنطقية. عنصر <code>set</code> غير مضاف ولا يُسمح بالخاصيات المضافة والإجمالية، وسيتم تجاهلها عند تحديدها.
</p>

<p>
	نظرًا لاستخدام <code>&lt;set&gt;</code> لتعيين عنصر إلى قيمة محددة في وقت معين، فإنه لا يقبل جميع الخاصيات المذكورة لعناصر التحريك السابقة. على سبيل المثال، لا يحتوي على خاصية <code>from</code> أو <code>by</code>، لأن القيمة التي تتغير لا تتغير تدريجيًا خلال الفترة الزمنية.
</p>

<p>
	بالنسبة لـ <code>set</code>، يمكنك تحديد العنصر الذي تستهدفه، واسم الخاصية HTML ونوعها، وقيمة to، ويمكن التحكم في توقيت الحركة: <code>begin</code> و<code>dur</code> و<code>end</code> و<code>min</code> و<code>max</code> و<code>restart</code> و<code>repeatCount</code> و<code>repeatDur</code> و<code>fill</code>.
</p>

<p>
	فيما يلي مثال يضبط لون المستطيل الدوّار إلى اللون الأزرق عند النقر فوقه. يظل اللون أزرق لمدة 3 ثوانٍ، ثم يعود إلى اللون الأصلي. في كل مرة ينفر فوق المستطيل، تعمل حركة <code>set</code>، ويتغير اللون لمدة ثلاث ثوانٍ.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="500" id="cp_embed_af159baaf57bc38eb40288db722e1245" name="cp_embed_30" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 550px;" title="CodePen Embed" src="https://codepen.io/SaraSoueidan/embed/af159baaf57bc38eb40288db722e1245?height=500&amp;theme-id=1&amp;slug-hash=af159baaf57bc38eb40288db722e1245&amp;default-tab=result&amp;user=SaraSoueidan&amp;name=cp_embed_30"></iframe>
</p>

<h2>
	العناصر وخاصيات HTML وخاصيات الكائنات التي يمكن تحريكها
</h2>

<p>
	لا يمكن تحريك كل خاصيات SVG، ولا يمكن تحريك كل الخاصيات التي يمكن تحريكها باستخدام جميع عناصر التحريك. للحصول على قائمة كاملة بجميع الخاصيات المتحركة، وجدول يربط الخاصيات بالعناصر التي تحركها، يرجى الرجوع إلى <a href="https://www.w3.org/TR/SVG2/animate.html#AnimationAttributesAndProperties" rel="external nofollow">هذا القسم من مواصفات SVG Animation</a>.
</p>

<h2>
	أخيرًا
</h2>

<p>
	لدى SMIL الكثير من الإمكانيات، وبالكاد تعرض المقال لمعلومات سطحية جدًا ولم يتطرق إلا إلى الأساسيات والتقنيات الخاصة بكيفية عملها فيSVG. يمكن إنشاء الكثير من التأثيرات المؤثرة للغاية، خاصة تلك التي تنطوي على تحوير الأشكال وتحويلها. <strong>لتكن حدودك هي السماء؛ عليك أن تكمل أنت الآن فامض بشغف!</strong> ولا تنس مشاركة ما تصنعه مع الآخرين. شكرًا لقراءتك!
</p>

<p>
	ترجمة وبتصرف للمقال <a href="https://css-tricks.com/guide-svg-animations-smil/" rel="external nofollow">A Guide to SVG Animations (SMIL)</a>‎ لصاحبته Sara Soueidan
</p>
]]></description><guid isPermaLink="false">868</guid><pubDate>Fri, 10 Apr 2020 05:11:05 +0000</pubDate></item><item><title>&#x631;&#x633;&#x648;&#x645;&#x64A;&#x627;&#x62A; SMIL &#x627;&#x644;&#x645;&#x62A;&#x62D;&#x631;&#x643;&#x629; &#x642;&#x62F; &#x627;&#x646;&#x62F;&#x62B;&#x631;&#x62A;: &#x62F;&#x644;&#x64A;&#x644;&#x643; &#x625;&#x644;&#x649; &#x627;&#x644;&#x628;&#x62F;&#x627;&#x626;&#x644;</title><link>https://academy.hsoub.com/programming/html/%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A7%D8%AA-smil-%D8%A7%D9%84%D9%85%D8%AA%D8%AD%D8%B1%D9%83%D8%A9-%D9%82%D8%AF-%D8%A7%D9%86%D8%AF%D8%AB%D8%B1%D8%AA-%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D8%AF%D8%A7%D8%A6%D9%84-r863/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_04/3--SMIL-is-dead-the-alternatives-to-SMIL-features.jpg.4646c333527996c925af06b448a030f1.jpg" /></p>

<p>
	حظيت مواصفات لغة التكامل المتزامن للوسائط المتعدّدة (<a data-ss1618065353="1" href="http://www.w3.org/TR/REC-smil" rel="external nofollow">Synchronized Multimedia Integration Language</a>، أو SMIL اختصارا)، وهي معيار مختص بترميز رسوميات SVG ، بشهرة كبيرة لتوفيرها إمكانيات عديدة للتعامل مع رسوميات SVG المتحركة. للأسف دعم SMIL يتناقص بمرور الزمن على محركات WebKit القياسية ولم تكن مدعومة أساسًا على متصفحات Microsoft (وغالبًا لن تدعمها أبدًا في المستقبل). لكن لا تقلق، يمكن علاج ذلك. هنا سنكتشف بدائل للميزات الخاصة في SMIL، ونبيِّن طرقًا بديلة لأداء تلك المهام وجعلها تحظى بدعم لفترة أطول.
</p>

<h2>
	ميزة SMIL: التحريك وفقًا لمسار
</h2>

<p>
	أحد أهم مميزات SMIL المتعلقة بالحركة الواقعية هي القدرة على التحريك وفقًا لمسار محدد. القليل فقط من الأشياء تتحرك في خط مستقيم على أرض الواقع، لذلك القدرة على التحكم بالرسوميات على مسار محدد مسبقًا يساعد على محاكاة الحركة الواقعية.
</p>

<p>
	باستعمال الخاصية <code>animateMotion</code>، كان يمكنك تمرير مسار SVG وتحديد بيانات الحركة والاتجاه ثم تحديد العنصر المراد تحريكه بإسناد معرّفه للرابط <code>xlink:href="#thingtoanimate"‎</code> كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9301_6" style="">
<span class="tag">&lt;animateMotion</span><span class="pln"> 
</span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#lil-guy"</span><span class="pln"> 
</span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"3s"</span><span class="pln"> 
</span><span class="atn">repeatCount</span><span class="pun">=</span><span class="atv">"indefinite"</span><span class="pln"> 
</span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> 
</span><span class="atn">path</span><span class="pun">=</span><span class="atv">"M 25,50 C 37.5,25 37.5,25 50,0 75,50 75,50 100,100 50,100 50,100 0,100 12.5,75 12.5,75 25,50 Z"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<h3>
	البديل باستخدام CSS
</h3>

<p>
	لحسن الحظ، القدرة على التحريك وفقًا لمسار مدمجة في لغة CSS. رغم ذلك مجال الدعم المتوفر لها لا يزال محدودًا (<a data-ss1618065353="1" href="https://caniuse.com/#feat=css-motion-paths" rel="external nofollow">متصفحات كروم، وأوبرا، وفيرفكس على سطح المكتب، وبعض متصفح أندرويد</a>).
</p>

<p>
	بالنسبة لمتصفح سفاري، فالأمر تطلب <a data-ss1618065353="1" href="https://idmsa.apple.com/IDMSWebAuth/login.html?appIdKey=77e2a60d4bdfa6b7311c854a56505800be3c24e3a27a670098ff61b69fc5214b&amp;sslEnabled=true&amp;rv=3" rel="external nofollow">الإبلاغ</a> عن الأعطال لطلب ميزة التحريك وفقًا لمسار كخاصية CSS.
</p>

<p>
	يتطلب استخدام التحريك وفقًا لمسار على CSS تحديد مسار الحركة باستعمال نقاط مرور كالتالي:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_9301_8" style="">
<span class="pun">.</span><span class="pln">move</span><span class="pun">-</span><span class="pln">me </span><span class="pun">{</span><span class="pln">
offset</span><span class="pun">-</span><span class="pln">path</span><span class="pun">:</span><span class="pln"> path</span><span class="pun">(</span><span class="str">'M3.9,74.8c0,0,0-106.4,75.5-42.6S271.8,184,252.9,106.9s-47.4-130.9-58.2-92s59.8,111.2-32.9,126.1 S5.9,138.6,3.9,74.8z'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<a data-ss1618065353="1" href="https://codepen.io/sdras/embed/31f2e998cbbced8d46c768b8d0ff8c9a?height=268&amp;theme-id=1&amp;slug-hash=31f2e998cbbced8d46c768b8d0ff8c9a&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_1#result-box" rel="external nofollow">نتيجة المثال أعلاه</a> يمكن الحصول على بيانات المسار ونقاط المرور من نتائج مخرجات تصميم SVG على <a data-ss1618065353="1" href="https://academy.hsoub.com/design/illustration/adobe-illustrator/" rel="">Illustrator</a> ثم تحسينها عن طريق أداة<a data-ss1618065353="1" href="https://jakearchibald.github.io/svgomg/" rel="external nofollow">SVGOMG</a>.
</p>

<p>
	سنتأكد في هذا المثال أن العنصر سيتبع المسار من نقطة البداية وصولًا لنهايته ويمكنك ملاحظة أنه مسار مغلق، أي أن العنصر سينتهي به المطاف عائدًا لنقطة البداية مكررًا مساره. حدّدت هنا قيم <a data-ss1618065353="1" href="https://wiki.hsoub.com/CSS/@keyframes" rel="external">الإطارات المفتاحية</a> وخُصّصت القيمة 100% فقط لأن القيمة الافتراضية محددة عند 0:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_9301_10" style="">
<span class="lit">@keyframes</span><span class="pln"> motionpathguy </span><span class="pun">{</span><span class="pln">
  </span><span class="lit">100</span><span class="pun">%</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    motion</span><span class="pun">-</span><span class="pln">offset</span><span class="pun">:</span><span class="pln"> </span><span class="lit">100</span><span class="pun">%;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ثم نحدد خيارات تحريك العنصر:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_9301_13" style="">
<span class="pun">.</span><span class="pln">move</span><span class="pun">-</span><span class="pln">me </span><span class="pun">{</span><span class="pln">
  animation</span><span class="pun">:</span><span class="pln"> motionpathguy </span><span class="lit">10s</span><span class="pln"> linear infinite both</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	بديل: أسلوب GreenSock للتحريك
</h3>

<p>
	إذا كنت تسعى لخيارات الدعم الأوسع والأكثر مرونة في التطبيق، فعليك باستخدام مكتبة GreenSock المكتوبة بجافاسكريبت. يوفّر ملحق <a data-ss1618065353="1" href="https://greensock.com/bezierplugin-js" rel="external nofollow"> Bezier-Plugin</a> دعمًا يمتد حتى الإصدار السابع من متصفح مايكروسوفت بدون استعمال عناصر SVG، وحتى الإصدار التاسع في حال أردت استعمال عناصر SVG (وهو أشمل دعم متوفّر لتحريكات SVG).
</p>

<p>
	يجدر بنا ذكر أنك ستحتاج إلى إدراج مصفوفة لإحداثيات المسار:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_9301_16" style="">
<span class="pln">bezier</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  type</span><span class="pun">:</span><span class="pln"> </span><span class="str">"soft"</span><span class="pun">,</span><span class="pln">
  values</span><span class="pun">:[{</span><span class="pln">x</span><span class="pun">:</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">:</span><span class="lit">30</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="pln">x</span><span class="pun">:-</span><span class="lit">30</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">:</span><span class="lit">20</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="pln">x</span><span class="pun">:-</span><span class="lit">40</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">:</span><span class="lit">10</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="pln">x</span><span class="pun">:</span><span class="lit">30</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">:</span><span class="lit">20</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="pln">x</span><span class="pun">:</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">:</span><span class="lit">30</span><span class="pun">}],</span><span class="pln">
  autoRotate</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك استعمال خيار التدوير التلقائي على غرار SMIL. وإذا كنت تفتقد قدرات SMIL على التحكم بالانعكاس التلقائي أو تحديد موضع الدوران التلقائي وزاويته، تتيح لك المكتبة التحكم بالدوران حتى 90 درجة من الميلان أو أي درجة من التحكم قد تحتاجها.
</p>

<pre class="ipsCode">
autorotate: [
  قيمة الموضع الأول "x",
  قيمة الموضع الثاني "y",
  "rotationY" أو "rotation" قيمة الحركة الدائرية، عادةً ,
  قيمة رقمية تمثل زاوية بداية الدوران، مثلًا "10",
  false أو true قيمة منطقية  
  (radians/degree) لاختيار وحدة قياس الزاوية 
]
</pre>

<p>
	يمكنك التحكم بدوران العنصر على SMIL أثناء حركته بالتلاعب بالمسار أو المسار، أما في مكتبة GreenSock فيمكنك أداء ذلك بسهولة بإيقاف التدوير التلقائي وبرمجة الدوران بسلسلة تعليمات، أيضًا يمكنك التلاعب بخصائص عناصر SVG كما كنت تفعل على SMIL برغم أنه أقل أناقة وأصعب في التتبع أثناء تحضيره.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_20" style="">
<span class="typ">TweenMax</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="str">"#foo"</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   rotation</span><span class="pun">:</span><span class="pln"> </span><span class="lit">90</span><span class="pln"> </span><span class="com">// أو أي قيمة مناسبة</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يمكنك الاختيار بين القيم <code>thru</code>، أو <code>soft</code>، أو <code>quadratic</code>، أو <code>cubic</code> لتحديد نوع المسار. تعليمات الشرح لكل منها موجودة على <a data-ss1618065353="1" href="https://www.greensock.com/asdocs/com/greensock/plugins/BezierPlugin.html" rel="external nofollow">مكتبة GreenSock البرمجية</a>. نقطة قوة <code>thru</code> هي القدرة على التأثير على مدى انحناء عنصر. إذا عدَدْنا أن نقاط المرور هي إحداثيات للتنقل منها وإليها، مدى الانحناء سيحدد اتجاه المسار عند الانتقال بين تلك النقاط. مدى الانحناء 0 سيكون اتجاهًا مباشرًا، 1 سيكون مائلًا قليلًا، 2 سينتج مسارًا منحنيًا، 3 وأكثر سيجعل المسار ينغلق على نفسه.
</p>

<p>
	إليك <a data-ss1618065353="1" href="https://codepen.io/sdras/embed/PqEPqz?height=372&amp;theme-id=1&amp;slug-hash=PqEPqz&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_3#result-box" rel="external nofollow">مثال حي</a>.
</p>

<p>
	مؤخرًا، أثبت GreenSock قدرته على تمرير بيانات المسار مثل CSS و SMIL. جاء ذلك في صيغة تمديد (Extension) لملحق MorphSVG الخاص بها. يُضاف الملحق ويُستعمَل كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_22" style="">
<span class="typ">TweenMax</span><span class="pun">.</span><span class="pln">to</span><span class="pun">(</span><span class="str">"#lil-guy"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  bezier</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">MorphSVGPlugin</span><span class="pun">.</span><span class="pln">pathDataToBezier</span><span class="pun">(</span><span class="str">"#path"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">align</span><span class="pun">:</span><span class="pln"> </span><span class="str">"#lil-guy"</span><span class="pln"> </span><span class="pun">}),</span><span class="pln"> 
    type</span><span class="pun">:</span><span class="pln"> </span><span class="str">"cubic"</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">
  ease</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Linear</span><span class="pun">.</span><span class="pln">easeNone</span><span class="pun">,</span><span class="pln">
  repeat</span><span class="pun">:</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">path id</span><span class="pun">=</span><span class="str">"path"</span><span class="pln"> d</span><span class="pun">=</span><span class="str">"M 25,50 C 37.5,25 37.5,25 50,0 75,50 75,50 100,100 50,100 50,100 0,100 12.5,75 12.5,75 25,50 Z"</span><span class="pln"> fill</span><span class="pun">=</span><span class="str">"none"</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

<p>
	إليك <a data-ss1618065353="1" href="https://codepen.io/sdras/embed/e028b7597cadf29b6d7eefcbc48d999c?height=268&amp;theme-id=1&amp;slug-hash=e028b7597cadf29b6d7eefcbc48d999c&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_4#result-box" rel="external nofollow">النتيجة</a> حية.
</p>

<p>
	سيعيّن الوضع الافتراضي أعلى مجموعة العناصر المُراد تحريكها، أي العنصر المسمى <code>lil-guy#</code>، إلى المسار، أي أنّ الركن العلوي الأيسر هو ما سيمرّ على المسار. بصريًا ستبدو الحركة غير متناسقة لذا قمنا بجعل العنصر <code>lil-guy#</code> يستخدم نقطة مركزية باستعمال تعليمات TweenLite.set:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_24" style="">
<span class="typ">TweenLite</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="str">"#lil-guy"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">xPercent</span><span class="pun">:-</span><span class="lit">50</span><span class="pun">,</span><span class="pln"> yPercent</span><span class="pun">:-</span><span class="lit">50</span><span class="pun">});</span><span class="pln"> </span></pre>

<p>
	يمكنك موازنة تلك المسارات بتمرير كائن إلى الوسيط الثاني في التابع <code>TweenLite.set</code>، وتعيين قيم <code>offsetX</code> و <code>offsetY</code> في التابع <code>pathDataToBezier</code>. كن حذرًا هنا فقد تحتاج لتوسيع صندوق العرض (viewBox) في SVG حتى لاتتداخل العناصر قيد التحريك ببعضها، أو تفقد بعض أجزائها خارج الصندوق.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_26" style="">
<span class="com">// أزح إحداثيات المسار بمقدار 125 بكسلًا أفقيًا و 50 بكسلًا رأسيًا</span><span class="pln">
</span><span class="typ">TweenMax</span><span class="pun">.</span><span class="pln">to</span><span class="pun">(</span><span class="str">"#lil-guy"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  bezier</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      values</span><span class="pun">:</span><span class="pln"> </span><span class="typ">MorphSVGPlugin</span><span class="pun">.</span><span class="pln">pathDataToBezier</span><span class="pun">(</span><span class="str">"#path"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    offsetX</span><span class="pun">:</span><span class="pln"> </span><span class="lit">125</span><span class="pun">,</span><span class="pln"> 
    offsetY</span><span class="pun">:</span><span class="pln"> </span><span class="lit">50</span><span class="pun">,</span><span class="pln"> 
    align</span><span class="pun">:</span><span class="pln"> </span><span class="str">"#lil-guy"</span><span class="pln">
    </span><span class="pun">}),</span><span class="pln">
    type</span><span class="pun">:</span><span class="pln"> </span><span class="str">"cubic"</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">
  ease</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Linear</span><span class="pun">.</span><span class="pln">easeNone</span><span class="pun">,</span><span class="pln">
  repeat</span><span class="pun">:</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إليك <a data-ss1618065353="1" href="https://codepen.io/sdras/embed/f771c09d9636d578138a9ac2c16d425f?height=268&amp;theme-id=1&amp;slug-hash=f771c09d9636d578138a9ac2c16d425f&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_5#result-box" rel="external nofollow">النتيجة حية</a>.
</p>

<p>
	يمكنك حتى تعريف مصفوفة إحداثيات لهذا التموضع:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_30" style="">
<span class="com">// ضاعف إحداثيات المسار بمقدار 1.25 </span><span class="pln">
</span><span class="com">// أزحه بمقدار 120 بكسل على المحور الأفقي </span><span class="pln">
</span><span class="com">// ارفعه بمقدار 30 بكسل على المحور الرأسي</span><span class="pln">
</span><span class="typ">TweenMax</span><span class="pun">.</span><span class="pln">to</span><span class="pun">(</span><span class="str">"#lil-guy"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    bezier</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      values</span><span class="pun">:</span><span class="pln"> </span><span class="typ">MorphSVGPlugin</span><span class="pun">.</span><span class="pln">pathDataToBezier</span><span class="pun">(</span><span class="str">"#path"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          matrix</span><span class="pun">:[</span><span class="lit">1.5</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1.5</span><span class="pun">,</span><span class="lit">120</span><span class="pun">,-</span><span class="lit">30</span><span class="pun">],</span><span class="pln"> 
  align</span><span class="pun">:</span><span class="str">"lil-guy"</span><span class="pun">}),</span><span class="pln">
    type</span><span class="pun">:</span><span class="pln"> </span><span class="str">"cubic"</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">
  ease</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Linear</span><span class="pun">.</span><span class="pln">easeNone</span><span class="pun">,</span><span class="pln">
  repeat</span><span class="pun">:</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إليك <a data-ss1618065353="1" href="https://codepen.io/sdras/embed/187a68190805a8f3cc440a8b0cf50829?height=268&amp;theme-id=1&amp;slug-hash=187a68190805a8f3cc440a8b0cf50829&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_6#result-box" rel="external nofollow">النتيجة حية</a>.
</p>

<p>
	يوجد خيار آخر يتمثّل في تحديد قيمة المحاذاة إلى <code>relative</code>، وهو ما سيمنع العنصر من القفز خارج مساره بتثبيت الموضع لكل الإحداثيات المرتبطة إلى القيم <code>x:0, y:0</code>.
</p>

<p>
	في الأمثلة السابقة استعملنا المحاذاة بالتزامن مع مجموعة عناصر <code>lil-guy#</code>. لمعلومات محدثة عن هذه الميزة لملحق Bezier، تفقَّد التوثيق على <a data-ss1618065353="1" href="http://greensock.com/docs/#/HTML5/GSAP/Plugins/MorphSVGPlugin/pathDataToBezier/" rel="external nofollow">مكتبة GreenSockالبرمجية</a>.
</p>

<h2>
	ميزة SMIL: تحوير الشكل
</h2>

<p>
	سابقًا كان باستطاعتك تمرير بيانات المسار كقيم داخل خصائص الرسوميات بهدف <a data-ss1618065353="1" href="https://codepen.io/noahblon/embed/IhLFK?height=241&amp;theme-id=1&amp;slug-hash=IhLFK&amp;default-tab=result&amp;user=noahblon&amp;name=cp_embed_7#result-box" rel="external nofollow">تحوير الشكل</a>.
</p>

<h3>
	البديل: مكتبة Snap.svg أو SVG Morpheus
</h3>

<p>
	توفر بعض المكتبات البرمجية مثل <a data-ss1618065353="1" href="http://snapsvg.io" rel="external nofollow">Snap.svg</a> و <a data-ss1618065353="1" href="https://github.com/alexk111/SVG-Morpheus" rel="external nofollow"> SVG Morpheus</a> القدرة على تحوير الشكل أو المسار. لكن يجب مطابقة عدد نقاط الشكل الأساسي والمحوَّر وإلا تشوَّه الشكل الناتج. بسبب ذلك، عليك مراقبة الشكل الناتج من التحوير باستمرار أثناء التصميم أو نسِّق مع مصممك لتحصل على بيانات تلك النقاط مع تلافي إضافة نقاط غير ضرورية حتى لا تتسبب بإبطاء الرسوميات الناتجة.
</p>

<h3>
	بديل: ملحق MorphSVG من GreenSock
</h3>

<p>
	ينبغي التأكيد على بهذا الملحق، إذ يمكنه تحوير الأشكال والمسارات بسلاسة باستعمال مقادير مختلفة من النقاط، كما في <a data-ss1618065353="1" href="https://codepen.io/sdras/embed/BodKjP?height=477&amp;theme-id=1&amp;slug-hash=BodKjP&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_8#result-box" rel="external nofollow">هذا المثال</a>.
</p>

<p>
	لمَّا كان ملحق MorphSVG يُعدل على بيانات المسار، فستحتاج إلى استعمال خيار <code>convertToPath</code> إذا احتجت لتعديل الشكل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_32" style="">
<span class="typ">MorphSVGPlugin</span><span class="pun">.</span><span class="pln">convertToPath</span><span class="pun">(</span><span class="str">"ellipse"</span><span class="pun">);</span><span class="pln"> 
    </span><span class="com">// or circle, rect, etc</span></pre>

<p>
	هذا سيسمح لك بإجراء تعديلات معقدة على الأشكال وهي طفرة حقيقية على مستوى التحريك على الويب.
</p>

<p>
	يقدّم الملحق ميزات إضافية جديرة بالذكر. الأولى هي ميزة <code>findShapeIndex</code> متعددة الاستخدامات. لنقل إن الشكل الحالي المحَّر لا يعجبك (برغم أن إعادة الضبط التلقائي عادةً ما تفي بالغرض). ستُحمِّل الملحق الخاص (ليس عليك القلق بشأن زيادة حجم مشروعك، فلا داعي للملحق بعد مرحلة التطوير)، ثم تمرر قيمتين: معرَّف الشكل الأول، ومعرّف الشكل الثاني. ستظهر لديك واجهة رسومية يمكنك بها الانتقال بين القيم، وأيضًا ستستعمل التكرار على نحو افتراضي (<code>repeat: -1</code>) لتستمر إعادة الحركة بين الأشكال.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_34" style="">
<span class="pln">findShapeIndex</span><span class="pun">(</span><span class="str">"#hex"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"#star"</span><span class="pun">);</span><span class="pln">
</span><span class="com">// findShapeIndex() يمكنك تعليق السطر البرمجي أعلاه لإلغاء تفعيل واجهة</span></pre>

<p>
	إليك <a data-ss1618065353="1" href="https://codepen.io/sdras/embed/f4e735983d9972abd35d74062ea0e543?height=350&amp;theme-id=1&amp;slug-hash=f4e735983d9972abd35d74062ea0e543&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_9#result-box" rel="external nofollow">النتيجة حية</a>.
</p>

<p>
	بمجرد حصولك على تلك القيم الإضافية، يمكنك تحديد قيمة <code>shapeIndex</code> داخل مصفوفة <code>morphSVG</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_36" style="">
<span class="typ">TweenLite</span><span class="pun">.</span><span class="pln">to</span><span class="pun">(</span><span class="str">"#hex"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">morphSVG</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> shape</span><span class="pun">:</span><span class="pln"> </span><span class="str">"#star"</span><span class="pun">,</span><span class="pln"> shapeIndex</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">}});</span></pre>

<p>
	الميزة الثانية لهذا الملحق هي قدرته على تحليل المسارات، لا يوجد ملحق آخر يمكّنك من ذلك. أخيرًا يمكن إعادة استعمال قيمة المعرّف الخاصة ببداية الحركة بدون الحاجة لتخزينها. من الجدير بالذكر أنه عند الإطلاق الأول لهذا الملحق لم تكن هذه الميزات موجودة، لكن GreenSock ظلّت تدعمه بالميزات بلستمرار وبما أننا لم نعد ملزمين بعدد معين للنقاط يمكننا توسيع آفاقنا لمزيد من التأثيرات. <a data-ss1618065353="1" href="https://codepen.io/sdras/embed/EVRJqg?height=479&amp;theme-id=1&amp;slug-hash=EVRJqg&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_10#result-box" rel="external nofollow">هنا مثال</a> على دخان.
</p>

<h2>
	ميزة SMIL: أحداث التفاعل مع الصفحة
</h2>

<p>
	وفَّر SMIL تأثيرات مثل التحويم على العناصر والضغط عليها وعند الرغبة باستعمال أي منها يمكنك تحديد الحدث باستعلام مثل <code>begin="click"‎</code> أو <code>begin="hover"‎</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9301_38" style="">
<span class="tag">&lt;animate</span><span class="pln"> 
    </span><span class="atn">xlink:href</span><span class="pun">=</span><span class="atv">"#rectblue"</span><span class="pln">
    </span><span class="atn">attributeName</span><span class="pun">=</span><span class="atv">"x"</span><span class="pln">
    </span><span class="atn">from</span><span class="pun">=</span><span class="atv">"0"</span><span class="pln">
    </span><span class="atn">to</span><span class="pun">=</span><span class="atv">"300"</span><span class="pln"> 
    </span><span class="atn">dur</span><span class="pun">=</span><span class="atv">"1s"</span><span class="pln">
    </span><span class="atn">begin</span><span class="pun">=</span><span class="atv">"click"</span><span class="pln">
    </span><span class="atn">values</span><span class="pun">=</span><span class="atv">"20; 50"</span><span class="pln">
    </span><span class="atn">keyTimes</span><span class="pun">=</span><span class="atv">"0; 1"</span><span class="pln">
    </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"freeze"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<h3>
	بديل: لغة JavaScript
</h3>

<p>
	هنالك أحداث مدمجة ضمن اللغة مثل <code>onmouseenter</code> و <code>onmouseleave</code> لتأثيرات الحومان والضغط. يمكنك استعمالها لتفعيل رسوميات JavaScript.
</p>

<h3>
	البديل: التعاون بين JavaScript و CSS
</h3>

<p>
	يمكنك استعمال JavaScript لتغيير صنف عنصر ما أو تغيير تنسيقات CSS الخاصة به مباشرة. كمثال سنغير حالة الرسوميات لتتفعل بناءً على حدث ما:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_9301_40" style="">
<span class="pun">.</span><span class="pln">st0 </span><span class="pun">{</span><span class="pln">
  animation</span><span class="pun">:</span><span class="pln"> moveAcross </span><span class="lit">1s</span><span class="pln"> linear both</span><span class="pun">;</span><span class="pln">
  animation</span><span class="pun">-</span><span class="pln">play</span><span class="pun">-</span><span class="pln">state</span><span class="pun">:</span><span class="pln"> paused</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="lit">@keyframes</span><span class="pln"> moveAcross </span><span class="pun">{</span><span class="pln">
    to </span><span class="pun">{</span><span class="pln">
       transform</span><span class="pun">:</span><span class="pln"> translateX</span><span class="pun">(</span><span class="lit">100px</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_42" style="">
<span class="pln">document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">"rectblue"</span><span class="pun">).</span><span class="pln">addEventListener</span><span class="pun">(</span><span class="str">"click"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">style</span><span class="pun">.</span><span class="pln">animationPlayState </span><span class="pun">=</span><span class="pln"> </span><span class="str">"running"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إما إذا اعتدت على استعمال jQuery فالاستعلام كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_44" style="">
<span class="pln">$</span><span class="pun">(</span><span class="str">".st0"</span><span class="pun">).</span><span class="pln">on</span><span class="pun">(</span><span class="str">"click"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">).</span><span class="pln">css</span><span class="pun">(</span><span class="str">"animation-play-state"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"running"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إليك <a data-ss1618065353="1" href="https://codepen.io/sdras/embed/40d36071c08f694fc14c176a5f881e33?height=268&amp;theme-id=1&amp;slug-hash=40d36071c08f694fc14c176a5f881e33&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_12#result-box" rel="external nofollow">النتيجة حية</a>.
</p>

<p>
	تنفيذ هذا الاستعلام لن يعيد الرسوميات إلى نقطة البداية مباشرة كما فعل SMIL في المثال السابق. إذا أردت إنجاز ذلك فستحتاج إلى استعمال عدَّة خدع CSS مختصة بذلك.
</p>

<h3>
	البديل: Greensock
</h3>

<p>
	إعادة الحركة باستخدام مكتبة GreenSock أكثر بساطة. يمكننا إضافة الرسوميات إلى جدول زمني للتحكم بإيقاف واستئناف الرسوميات بالضغط على العنصر. طريقة التنفيذ هذه شبيهة بما اعتدته من SMIL حيث لا نحتاج للتعامل مع نسخ أو إعادة إدخال أي نقاط شجرية للصفحة أو تغيير خصائص العناصر:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_46" style="">
<span class="com">// TimelineLite إنشاء نسخة من</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> tl </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TimelineLite</span><span class="pun">();</span><span class="pln">

</span><span class="com">// إضافة رسوميات إلى جدول زمني</span><span class="pln">
tl</span><span class="pun">.</span><span class="pln">to</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.5</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">100</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

$</span><span class="pun">(</span><span class="str">".st0"</span><span class="pun">).</span><span class="pln">on</span><span class="pun">(</span><span class="str">"click"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    tl</span><span class="pun">.</span><span class="pln">restart</span><span class="pun">();</span><span class="pln">
</span><span class="pun">});</span></pre>

<h2>
	ميزة SMIL: تشغيل X بعد اكتمال Y
</h2>

<p>
	يستطيع SMIL إنشاء أحداث بتوقيت أكثر تعقيدًا مثل <code>begin="circ-anim.begin + 1s"‎</code> (بدء حركة عنصر بعد ثانية من بدء حركة عنصر آخر). وهذا مفيد بالأخص عند إنشاء رسوميات متسلسلة.
</p>

<h3>
	بديل: CSS
</h3>

<p>
	على CSS يمكنك إنشاء تسلسل للرسوميات بتحديد تأخير على الرسوميات اللاحقة:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_9301_48" style="">
<span class="pun">.</span><span class="pln">foo </span><span class="pun">{</span><span class="pln">
  animation</span><span class="pun">:</span><span class="pln"> foo</span><span class="pun">-</span><span class="pln">move </span><span class="lit">2s</span><span class="pln"> ease both</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">.</span><span class="pln">bar </span><span class="pun">{</span><span class="pln">
  animation</span><span class="pun">:</span><span class="pln"> bar</span><span class="pun">-</span><span class="pln">move </span><span class="lit">4s</span><span class="pln"> </span><span class="lit">2s</span><span class="pln"> ease both</span><span class="pun">;</span><span class="pln"> 
  </span><span class="com">/* تتطابق القيمة ‏2s‏ مع مدة التكرار في العنصر الأول أعلاه  */</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	طريقة العمل قد تصبح مسببة للإزعاج إذ عليك تذكر تغيير الفجوة الزمنية الأولى وكذلك التأخير لكل عنصر.
</p>

<h3>
	بديل آخر: برمجة CSS مسبقة (SASS)
</h3>

<p>
	إعداد وإدارة تلك الفجوات الزمنية يمكن تسهيله إذا استعملت متغيرات Sass مثلًا:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_9301_50" style="">
<span class="pln">$secs</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2s</span><span class="pun">;</span><span class="pln">
</span><span class="pun">.</span><span class="pln">foo </span><span class="pun">{</span><span class="pln">
    animation</span><span class="pun">:</span><span class="pln"> foo</span><span class="pun">-</span><span class="pln">move $secs ease both</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">.</span><span class="pln">bar </span><span class="pun">{</span><span class="pln">
    animation</span><span class="pun">:</span><span class="pln"> bar</span><span class="pun">-</span><span class="pln">move </span><span class="lit">4s</span><span class="pln"> $secs ease both</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	هكذا ستتأكد أن تحديث قيمة واحدة لن يؤثر على التزامن. لكن إذا أردت تتبع الرسوميات عند اكتمالها، فجافاسكريبتيقدم دعمًا وظيفيًا أصليًّا باستعمال <code>animationEnd</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_52" style="">
<span class="pln">$</span><span class="pun">(</span><span class="str">"#rectblue"</span><span class="pun">).</span><span class="pln">on</span><span class="pun">(</span><span class="str">"animationend"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">   
  $</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">).</span><span class="pln">closest</span><span class="pun">(</span><span class="str">"svg"</span><span class="pun">).</span><span class="pln">find</span><span class="pun">(</span><span class="str">"#rectblue2"</span><span class="pun">).</span><span class="pln">css</span><span class="pun">(</span><span class="str">"animation-play-state"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"running"</span><span class="pun">);</span><span class="pln">     
</span><span class="pun">});</span></pre>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_9301_54" style="">
<span class="com">#rectblue2 {</span><span class="pln">
    animation</span><span class="pun">:</span><span class="pln"> moveAcross </span><span class="lit">2s</span><span class="pln"> </span><span class="lit">1s</span><span class="pln"> ease both</span><span class="pun">;</span><span class="pln">
    animation</span><span class="pun">-</span><span class="pln">play</span><span class="pun">-</span><span class="pln">state</span><span class="pun">:</span><span class="pln"> paused</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إليك <a data-ss1618065353="1" href="https://codepen.io/sdras/embed/bdec2d2428ea3927247148167f187b8e?height=268&amp;theme-id=1&amp;slug-hash=bdec2d2428ea3927247148167f187b8e&amp;default-tab=result&amp;user=sdras&amp;name=cp_embed_13#result-box" rel="external nofollow">النتيجة حية</a> (قد تحتاج للنقرعلى زر إعادة التشغيل لرؤية الحركة).
</p>

<p>
	لتنفيذ التأخير يمكننا جدولة توقيت ظهور العناصر عبر خاصيات تأخير رسوميات CSS للعناصر أو باستعمال <code>setTimeout</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_56" style="">
<span class="pln">setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> timeoutHandler</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// أدرج الرسوميات هنا، بغض النظر عن لغة البرمجة المستخدمة</span><span class="pln">
</span><span class="pun">},</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">);</span><span class="pln"> </span><span class="com">//  انتظر لثانية واحدة</span></pre>

<h3>
	بديل آخر: Greensock
</h3>

<p>
	هذا هو الخيار المفضل لديّ للحصول على تحكم دقيق بالمسار الزمني الخاص بالرسوميات، إذ يمكنك أداء ذلك بعدة طرق مختلفة.
</p>

<ul>
<li>
		خط زمني بسيط:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_58" style="">
<span class="com">// TimelineLite أنشئ    </span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> tl </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TimelineLite</span><span class="pun">();</span><span class="pln">

</span><span class="com">// أضف الرسوميات لبداية الخط الزمني</span><span class="pln">
tl</span><span class="pun">.</span><span class="pln">to</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.5</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">100</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

</span><span class="com">// استعمل قيمة الموضع (+=1) لبدء الرسوميات التالية بعد ثانية واحدة من انتهاء الحالية</span><span class="pln">
tl</span><span class="pun">.</span><span class="pln">to</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.5</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">200</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="str">"+=1"</span><span class="pun">);</span></pre>

<ul>
<li>
		خط زمني بوصف نسبي:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9301_60" style="">
<span class="com">// أضف علامة متأخرة 0.5 ثانية لتحديد موضع الإطار التالي</span><span class="pln">
tl</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="str">"العلامة"</span><span class="pun">)</span><span class="pln">
</span><span class="com">// استخدم العلامة لتحديد ظهور الرسوميات بعد الثانية التالية </span><span class="pln">
tl</span><span class="pun">.</span><span class="pln">to</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.5</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> scale</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="str">"العلامة+=1"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// أو استعمل العلامة لإنشاء واجهة للتفاعل </span><span class="pln">
tl</span><span class="pun">.</span><span class="pln">play</span><span class="pun">(</span><span class="str">"العلامة"</span><span class="pun">);</span></pre>

<p>
	من الأفضل استعمال الوصف النسبي حيث تختار نقطة زمنية ما لتقوم بتفعيل العديد من الثأثيرات أو تأخيرها. حتى لو كانت خاضعة لتعديل زمني، وليس عليك القيام بأي إعادة لحسابات CSS.
</p>

<p>
	الفائدة من استعمال المسار الزمني هي القدرة على التحكم الدقيق بعدة عناصر من مكان واحد كما يمكنك استعمال خاصيّات مثل تأخير التكرارات.
</p>

<p>
	يقدم SMIL أيضًا خاصية <code>repeatDur</code> التي تمكنك من تحديد مدة التكرار المحدد، إذا لم ترغب بالقيمة الافتراضية <code>"repeatDur="01:30</code> يمكنك التحكم بالسرعة بمساعدة GreenSock وبالتالي تعدي مدة التكرار باستعمال timeScale (n) أو <code>repeat: -1</code>. خلاف ذلك، يمكنك تحديد التكرار بالخاصية <code>"repeatDur="indefinite</code>.
</p>

<h2>
	جدول بياني للبدائل
</h2>

<p>
	بعدما انتهينا من استكشاف أفضل مميزات SMIL يجدر بنا الإشارة إلى مزيد من البدائل لخصائص SMIL والتي ربما استعملتها مسبقا. في ما يلي جدول للرجوع إليه للحصول بسرعة على بدائل الوظائف الأكثر سهولة.
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<table>
<thead><tr>
<th>
				SMIL
			</th>
			<th style="text-align:center">
				الشفرة البديلة
			</th>
			<th style="text-align:right">
				التقنية البديلة
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				keyTimes
			</td>
			<td style="text-align:center">
				‎@keyframes
			</td>
			<td style="text-align:right">
				CSS
			</td>
		</tr>
<tr>
<td>
				keySplines
			</td>
			<td style="text-align:center">
				cubic-bezier
			</td>
			<td style="text-align:right">
				CSS
			</td>
		</tr>
<tr>
<td>
				restart
			</td>
			<td style="text-align:center">
				restart()‎
			</td>
			<td style="text-align:right">
				GSAP
			</td>
		</tr>
<tr>
<td>
				calcMode="discrete"‎
			</td>
			<td style="text-align:center">
				steps()‎
			</td>
			<td style="text-align:right">
				CSS
			</td>
		</tr>
<tr>
<td>
				remove
			</td>
			<td style="text-align:center">
				kill(); clear(); clearProps: "all"‎
			</td>
			<td style="text-align:right">
				GSAP
			</td>
		</tr>
<tr>
<td>
				freeze
			</td>
			<td style="text-align:center">
				animation-play-state: paused
			</td>
			<td style="text-align:right">
				CSS
			</td>
		</tr>
<tr>
<td>
				freeze
			</td>
			<td style="text-align:center">
				pause()‎
			</td>
			<td style="text-align:right">
				GSAP
			</td>
		</tr>
<tr>
<td>
				fill
			</td>
			<td style="text-align:center">
				animation-fill-mode
			</td>
			<td style="text-align:right">
				CSS
			</td>
		</tr>
<tr>
<td>
				repeatCount="indefinite"‎
			</td>
			<td style="text-align:center">
				animation-iteration-count: infinite;‎
			</td>
			<td style="text-align:right">
				CSS
			</td>
		</tr>
<tr>
<td>
				repeatCount="indefinite"‎
			</td>
			<td style="text-align:center">
				repeat: -1
			</td>
			<td style="text-align:right">
				GSAP
			</td>
		</tr>
<tr>
<td>
				whenNotActive
			</td>
			<td style="text-align:center">
				detect animation-play-state in JS
			</td>
			<td style="text-align:right">
				CSS, vanilla JavaScript or jQuery
			</td>
		</tr>
<tr>
<td>
				animateMotion path
			</td>
			<td style="text-align:center">
				motion-path
			</td>
			<td style="text-align:right">
				CSS
			</td>
		</tr>
<tr>
<td>
				animateMotion path
			</td>
			<td style="text-align:center">
				bezier
			</td>
			<td style="text-align:right">
				GSAP
			</td>
		</tr>
<tr>
<td>
				animate values (path morphing)
			</td>
			<td style="text-align:center">
				MorphSVG
			</td>
			<td style="text-align:right">
				GSAP
			</td>
		</tr>
<tr>
<td>
				begin="hover"‎
			</td>
			<td style="text-align:center">
				mouseover, mouseenter, mouseout, mouseleave
			</td>
			<td style="text-align:right">
				jQuery, vanilla JS
			</td>
		</tr>
<tr>
<td>
				begin="circ-anim.begin + 1s"‎
			</td>
			<td style="text-align:center">
				animation-delay: $vars;‎
			</td>
			<td style="text-align:right">
				SASS
			</td>
		</tr>
<tr>
<td>
				begin="circ-anim.begin + 1s"‎
			</td>
			<td style="text-align:center">
				timeline, position parameter ex "+=1"‎
			</td>
			<td style="text-align:right">
				GSAP
			</td>
		</tr>
</tbody>
</table>
<p>
	ترجمة - وبتصرف - للمقال <a data-ss1618065353="1" href="https://css-tricks.com/smil-is-dead-long-live-smil-a-guide-to-alternatives-to-smil-features/" rel="external nofollow">SMIL is dead! Long live SMIL! A Guide to Alternatives to SMIL Features</a> لصاحبته Sarah Drasner.
</p>
]]></description><guid isPermaLink="false">863</guid><pubDate>Sun, 26 Apr 2020 18:07:00 +0000</pubDate></item><item><title>&#x632;&#x64A;&#x627;&#x62F;&#x629; &#x633;&#x631;&#x639;&#x629; &#x623;&#x62F;&#x627;&#x621; &#x627;&#x644;&#x645;&#x648;&#x627;&#x642;&#x639; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x62A;&#x642;&#x646;&#x64A;&#x629; pre-fetching</title><link>https://academy.hsoub.com/programming/html/%D8%B2%D9%8A%D8%A7%D8%AF%D8%A9-%D8%B3%D8%B1%D8%B9%D8%A9-%D8%A3%D8%AF%D8%A7%D8%A1-%D8%A7%D9%84%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%AA%D9%82%D9%86%D9%8A%D8%A9-pre-fetching-r790/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/5e1da4f582d9d_------pre-fetching.jpg.a48f5b4a7829f70714ad2489a99e1c6a.jpg" /></p>

<p>
	يشهد عالم البرمجة في عصرنا تطورًا هائلاً لا حدود له، إذ يُركز المطورين والمبرمجين على تحسين أداء الأعمال البرمجية من أنظمة، وبرامج، ومواقع وغيرها، وراحة المستخدم في التعامل معها، ومن أهم وأبرز عناصر وأركان هذا التطور <strong>سرعة استجابتها وأدائها</strong>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33352" href="https://academy.hsoub.com/uploads/monthly_2020_01/intro.gif.0f2053d67bcdeba3073311156f864f40.gif" rel=""><img alt="intro.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="33352" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/intro.gif.0f2053d67bcdeba3073311156f864f40.gif"></a>
</p>

<p>
	لاحظ الفرق في الصورة السابقة بين الحالتين، إذ تجد إحداها أسرع في العرض عند طلبها من الأخرى، والسبب في ذلك تطبيق تقنية prefetching فيها.
</p>

<p>
	تكمن تقنية prefetching (الجلب أو الاحضار المسبق) في تجهيز وتحميل الملف أو مجموعة الملفات قبل البدء بفتحها واستخدامها، وهي معروفة في كثير من مجالات البرمجة، حيث تستخدم في المعالجات لتسريع جلب البيانات والتعليمات قبل الحاجة لها، وفي ذاكرة DDR SDRAM، وفي أنظمة تشغيل الحاسوب، وفي المواقع الإلكترونية وهي من أبرز تطبيقاتها. <strong>سيكون الحديث هنا مقيدًا في مجال المواقع</strong>.
</p>

<p>
	المقصود من prefetching في مجال المواقع: تنقل أسرع بين صفحات الموقع من خلال تحميل الصفحات أو جزء منها قبل الشروع باستخدامها، <strong>أي بكل بساطة نخبر المتصفح بجلب الموارد قبل فتحها</strong>، وعند طلب المستخدم فتح الصفحة فإنها تُعرض مباشرةً كونها جاهزة للعرض كما ظهر في الصورة السابقة.
</p>

<h2>
	كيفية إضافة هذه تقنية والاستفادة منها
</h2>

<p>
	يستفاد من هذه تقنية في تسريع عرض صفحات الموقع أو جزءٍ منها كملفات JavaScript أو ملفات CSS (من أبرزها الخطوط حيث يتم عرض الخطوط من دون انتظار تحميل DOM و CSSOM)، أو الوسائط (صور ومقاطع مرئية وصوتية)، أو المستندات.
</p>

<p>
	يمكن إضافتها بعدة طرق، الأكثر شيوعًا باستخدام الوسم link في لغة HTML، وذلك بإدراجه في الصفحة السابقة للمراد تطبيق تقنية فيها، وفيه rel من نوع prefetching كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7839_6" style="">
<span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"prefetch"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"URL"</span><span class="tag">&gt;</span></pre>

<p>
	يوضع مكان <code>URL</code> رابط الملف المراد تحميله سابقًا وتجهيزه للعرض مباشرةً عند طلب المستخدم فتحه.
</p>

<h2>
	نظرة أعمق لآلية عمل prefetching
</h2>

<p>
	عند اكتمال تحميل الصفحة التي تحوي الوسم link من النوع prefetching (للمراد تطبيق تقنية الجلب المسبق فيها)، يرسل طلب تحميل الملف (المطبق عليه تقنية) بواسطة ترويسة HTTP التالية:
</p>

<pre class="ipsCode">
Link: &lt;/js/chat-widget.js&gt;; rel=prefetch
</pre>

<p>
	بعدئذٍ يتم تحميل الملف وتخزينه في ذاكرة المتصفح المؤقتة، ومن المهم معرفته أنها تأخذ أقل أولوية بالتحميل (priority:lowest)، ويتم حفظها مدة لا تتجاوز الخمسة دقائق، خلال هذه المدة تكون جاهزة للعرض وما إن يقوم المستخدم بطلب فتح الصفحة تظهر مباشرةً، وتنتقل إلى إعدادات وقواعد cache-control الافتراضية لأي صفحة عادية، وإن لم يفعل وانتهت المدة يتم حذفها وتفقد هذه تقنية.
</p>

<h2>
	تحديد الصفحة الأنسب والأولى بالتحميل المسبق
</h2>

<p>
	تضاف هذه التقنية إلى الصفحات التي تملك الاحتمال الأكبر من انتقال المستخدم إليها، على سبيل المثال عند فتح موقع في صفحته الرئيسية يمكن للمستخدم أن ينتقل إلى 20 صفحة ثانوية، ولكن إحدى هذه الصفحات هي الأهم وأغلب المستخدمين ينتقلون إليها مباشرة عند فتح الموقع. ويتم إضافة تقنية إلى الصفحة التي من المؤكد انتقال المستخدم إليها كخطوة تالية، على سبيل المثال عند دخول إلى موقع تظهر في البداية صفحة إدخال بيانات شخصية وعند إتمام ذلك يتم الانتقال إلى الصفحة الرئيسية.
</p>

<p>
	وهذا يتطلب معرفة جيدة لوظيفة الموقع وطريقة استخدامه من قبل الزائرين، ومعرفة الصفحات الأكثر زيارة، ومما يساعد على ذلك الأداة <a href="https://predictjs.firebaseapp.com/" rel="external nofollow">Next Page Predictor</a> فهي أداة تقترح الصفحة التالية التي تناسب تطبيق التقنية عليها.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33353" href="https://academy.hsoub.com/uploads/monthly_2020_01/NextPagePredictor.jpg.c705a20c345c744d23da31ea95f17ce2.jpg" rel=""><img alt="NextPagePredictor.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="33353" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/NextPagePredictor.thumb.jpg.cc24ebeb20fe9cd15732061436a92199.jpg"></a>
</p>

<p>
	ولكن عند التعمق والتشعب أكثر في الموقع تصبح عملية اختيار الصفحة المناسبة لذلك أكثر صعوبة، ولكن من الممكن باستخدام بيانات إضافية التنبؤ بالصفحة الأنسب لإضافة التقنية، فعند فتح أي رابط URL من الموقع تحديد الصفحة التالية الأنسب لذلك وإضافة لها الوسم <code>&lt;link rel="prefetch" href="URL"‎&gt;</code>، مما يضفي لمسة تقنية أفضل أداءً للموقع كامل، ويمكن التعديل على الاختيارات يدويًا، وهذا ما تقدمه مكتبة <a href="https://guess-js.github.io/" rel="external nofollow">Guess</a> المعدة من قبل فريق تابع لجوجل، والتي تستند في نتائجها على استخدام الموقع (عدد الدخولات على الصفحات، وتحليلات جوجل) وعلى التعلم الآلي (Machine Learning) والتنبؤ بالصفحات التالية ذات الصلة بالحالية، وتقوم أيضًا بتجميع مصادر JavaScript المتوفرة بالصفحة الحالية والتي تلزم ببناء الصفحة التالية.
</p>

<h2>
	توخي الحذر عند استخدام prefetching
</h2>

<p>
	قد لا يتم الاستفادة من البيانات المحملة مسبقًا، بسبب عدم استخدامها وفتحها أو لانتهاء مدة تخزينها المؤقت أو غيرها من الأسباب، مما يتسبب بسحب وتبديد لبيانات الإنترنت من دون فائدة، وهذا قد يؤثر تأثير كبير على بعض المستخدمين الذين يملكون بيانات محدودة وشحيحة متاحة للسحب من الانترنت.
</p>

<p>
	يمكن التخفيف من هذه المشكلة بمعرفة نوع الشبكة بواسطة لغة JavaScript مع <code>navigator.connection.effectiveType</code>، حيث يقوم بإعطاء نوع الشبكة، فمثلا إن كانت الشبكة 4G على الأقل يتم تطبيق التقنية.
</p>

<p>
	ومن المشاكل التي قد ترتبط بهذه التقنية، طلب المستخدم فتح الصفحة قبل اكتمال الجلب المسبق لها، فذلك يؤدي إلى حذفها وإعادة تحميلها من جديد، لذا يفضل أن يحرص المبرمج على عرض جزء منها للمستخدم قبل حذفها.
</p>

<p>
	وعلى المبرمج أن يتنبه إلى أن التخزين المؤقت للملفات المالكة لهذه التقنية محدود، لذا يفضل عدم إدراج التقنية إلى ملفات كبيرة الحجم، بل إنه قد يعطي الخطأ:
</p>

<pre class="ipsCode">
Failed to load resource: net::ERR_CACHE_WRITE_FAILURE
</pre>

<p>
	وذلك لأن حجم الملف المطلوب جلبه مسبقًا كبير بشكل لا يمكن تخزينه في ذاكرة المتصفح المؤقتة.
</p>

<h2>
	أمثلة عملية
</h2>

<ul>
<li>
		الموقع الياباني <a href="https://www.nikkei.com/" rel="external nofollow">Nikkei</a>: عندما وثقوا بانتقال المستخدمين إلى صفحات معينة، لم يتركوا المستخدم ينتظر تحميل الصفحة عند طلبها، بل قاموا بإدراج تقنية prefetching إلى تلك الصفحات مما أدى إلى تخفيض الوقت الكلي لعملية الانتقال إلى الصفحات من 880 ملي ثانية إلى 37، أي تخفيضها بنسبة 96% وهو فرق شاسع.
	</li>
	<li>
		شركة <a href="https://medium.com/dev-channel/a-netflix-web-performance-case-study-c0bcde26a9d9" rel="external nofollow">Netflix</a> إذ قامت باستثمار هذه التقنية بتسهيل التنقلات إلى الصفحات.
	</li>
	<li>
		موقع <a href="https://london.craigslist.org/" rel="external nofollow">Craigslist</a> استفاد من هذه التقنية في تسهيل الوصول إلى صفحات نتائج البحث.
	</li>
	<li>
		موقع <a href="https://www.indiegogo.com/" rel="external nofollow">IndieGogo</a> استفاد من هذه التقنية في تسهيل التعامل مع صفحات بطاقات الائتمان قبل الدخول إليها.
	</li>
</ul>
<h2>
	المتصفحات التي تدعم هذه التقنية
</h2>

<p>
	في ما يلي شكلٌ توضيحي من <a href="https://caniuse.com/#search=prefetch" rel="external nofollow">CanIUse</a> للإصدارات التي تتيح تطبيق تقنية prefetching (الإصدار المظلل باللون الأخضر يدعم تقنية prefetching، والإصدار المظلل باللون الأحمر لا يدعمها):
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33351" href="https://academy.hsoub.com/uploads/monthly_2020_01/browsers.PNG.b545a36d1d1bed13c6751090e12ccd83.PNG" rel=""><img alt="browsers.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="33351" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/browsers.thumb.PNG.7244387ec03e6134e2c6fe84f3be70b3.PNG"></a>
</p>

<h2>
	مراجع
</h2>

<ul>
<li>
		<a href="https://addyosmani.com/blog/prefetching/" rel="external nofollow">Speed up next-page navigations with prefetching</a>
	</li>
	<li>
		<a href="https://en.wikipedia.org/wiki/Prefetching" rel="external nofollow">Prefetching wikipedia</a>
	</li>
	<li>
		<a href="https://medium.com/@soorajchandran/speeding-up-your-website-using-prefetching-techniques-8077058b7418" rel="external nofollow">Speeding up your website using Prefetching techniques</a>
	</li>
	<li>
		<a href="https://blog.bitsrc.io/faster-page-loads-by-prefetching-links-during-idle-time-5abe42dacf9" rel="external nofollow">Faster Page-Loads by Prefetching Links During Idle Time</a>
	</li>
	<li>
		<a href="https://css-tricks.com/prefetching-preloading-prebrowsing/" rel="external nofollow">Prefetching, preloading, prebrowsing</a>
	</li>
	<li>
		<a href="https://w3c.github.io/resource-hints/#prefetch" rel="external nofollow">Prefetch W3C</a>
	</li>
	<li>
		‎<a href="https://medium.com/webpack/link-rel-prefetch-preload-in-webpack-51a52358f84c" rel="external nofollow">&lt;link rel="prefetch/preload"&gt; in webpack</a>
	</li>
	<li>
		<a href="https://caniuse.com/#search=prefetch" rel="external nofollow">Can I use prefetch</a>‎<a href="https://caniuse.com/#search=prefetch" rel="external nofollow">?</a>‎
	</li>
	<li>
		<a href="https://developers.google.com/web/showcase/2018/nikkei" rel="external nofollow">Nikkei achieves a new level of quality and performance with their multi-page PWA</a>
	</li>
	<li>
		<a href="https://guess-js.github.io/" rel="external nofollow">Guess.js announcement</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">790</guid><pubDate>Mon, 20 Jan 2020 08:49:38 +0000</pubDate></item><item><title>&#x646;&#x642;&#x644;&#x629; &#x646;&#x648;&#x639;&#x64A;&#x629; &#x641;&#x64A; &#x623;&#x62F;&#x627;&#x621; &#x627;&#x644;&#x645;&#x648;&#x627;&#x642;&#x639; &#x645;&#x639; &#x62E;&#x627;&#x635;&#x64A;&#x629; loading</title><link>https://academy.hsoub.com/programming/html/%D9%86%D9%82%D9%84%D8%A9-%D9%86%D9%88%D8%B9%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A3%D8%AF%D8%A7%D8%A1-%D8%A7%D9%84%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D9%85%D8%B9-%D8%AE%D8%A7%D8%B5%D9%8A%D8%A9-loading-r792/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/5e1dad7b179fa_-------loading.jpg.4da2bc72c26144f265aa5e8bf98bce76.jpg" /></p>

<p>
	يشهد عالم مواقع الويب تطورًا هائلًا في الفترة الأخيرة، ومن جوانب ذلك التطور التحكم في تحميل العناصر الموجودة في الصفحة الواحدة، إذ جرت العادة تحميل كامل الصفحة مرة واحدة عند فتحها، وهذا يؤثر سلبًا على السحب من البيانات المتاحة، وفي ثقل الصفحة، بالإضافة إلى انخفاض سرعة تحميل الصفحة وغيرها من آثارٍ ليست محمودة تتعارض مع فلسفة ذلك التطور.
</p>

<p>
	ولو افترضنا وجود صفحة مقال يحوي 30 صورة بدقة عالية يصل حجم كل صورة منها 4MB، ويحتاج أحد المستخدمين الإطلاع على معلومة موجودة في مطلع المقال فقط، يدخل المستخدم مطلعًا على تلك المعلومة ويخرج من الصفحة دون الحاجة لغير ذلك، لكن سيتم تحميل كامل الصفحة بمحتوياتها التي قد يصل حجمها 100MB (إن مَكَث في الصفحة فترة كافية لتحميل كامل الصفحة)، وهذا غير مقبول أبدًا.
</p>

<h2>
	آلية تحميل المتصفحات للصفحات
</h2>

<p>
	قد يظن البعض بأن المتصفحات تحمِّل العناصر الموجودة في الصفحات بشكل عشوائي الترتيب، أو تبدأ بتحميل كل عنصر في نفس الوقت وينتهي تحميل كل عنصر حسب حجمه مثلاً، لكن الصحيح أن المتصفحات تملك طرقها المنظمة في تحميل الصفحات، إذ تعطي ترتيبًا وأولويةً في تحميل العناصر تعتمد على مكانها في الصفحة ونوعها وغير ذلك، وفي بعض الأحيان يأجل تحميل عناصر معينة، ويسعى دائمًا مطوري المتصفحات إلى تحسين طرق تحميل الصفحات بما يصب في راحة المستخدم وتحسين التجربة.
</p>

<p>
	لكن مع ذلك يتم تحميل جميع العناصر بأسرع وقت ممكن، لذا جاءت الحاجة للتحكم بتحميل العناصر أكثر بواسطة خاصية loading. ومن ذلك عدم تحميل العنصر كليًا إذا لم يمرر المستخدم شاشة العرض إليه.
</p>

<h2>
	ما هي الخاصية loading؟
</h2>

<p>
	في إصدارات chrome الأخيرة (الإصدار 76، 30/7/2019) تم دعم التعرف على خاصية تسمى loading، إذ أصبحت جزءًا أصليًا من لغة HTML يتم إضافتها مع <strong>الوسم <code>&lt;img&gt;</code> و الوسم <code>&lt;iframe&gt;</code> فقط</strong>، وتمكننا من التحكم في تحميل هذه العناصر التي قد تشكل عبئًا على الصفحة، والصحيح أن فكرة الخاصية loading ليست جديدةً البتة، إذ دَرج تطبيقها عند كثير من المبرمجين بواسطة مكتبات معدة بلغة JavaScript أو بشيفرات يصنعوها (سنتطرق بالتفصيل حول هذه النقطة في نهاية المقال). ويندرج تحت هذه الخاصية عدة أنواع تتيح لنا تحكمًا أفضل في تحميل عناصر الصفحة.
</p>

<h2>
	أنواع خاصية loading
</h2>

<p>
	وفي محاولة للحصول على فهمٍ عميق لهذه الخاصية، نطرح أنواعها الثلاثة:
</p>

<h3>
	النوع eager
</h3>

<p>
	عند إضافة الخاصية <code>loading: eager</code> إلى وسم (<code>img</code> أو <code>iframe</code>) فإن ذلك إشارة إلى المتصفح أن هذا العنصر يجب البدء بتحميله أولًا والمسارعة لذلك وأن لا يتم تأخير أو تأجيل تحميله أبدًا، أي حمله فورًا. وهذا يكون للعناصر المهمة التي يجب تحميلها وتجهيزها قبل أي عنصر آخر.
</p>

<h3>
	النوع lazy
</h3>

<p>
	عند إضافة هذا النوع إلى عنصر فإن ذلك إشارة إلى المتصفح بعدم تحميل هذا العنصر عند فتح الصفحة، <strong>وإنما تأجيل تحميله إلى أن يمرِّر المستخدم شاشة العرض بالقرب من هذا العنصر.</strong> وهذا يعني عدم تحميل العنصر كليًا إذا لم يحتاج المستخدم عرض هذا العنصر ولم يقم بتمرير الشاشة إليه.
</p>

<p>
	يمكنك النظر في هذا <a href="https://scalable-loading-contribs.firebaseapp.com/test.html" rel="external nofollow">المثال</a> الذي يحوي 100 صورة، ويتم تحميل القليل من الصور (التي تظهر في شاشة العرض والقريبة منها) عند فتح الصفحة كما تُظهر الصورة في الأسفل.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33355" href="https://academy.hsoub.com/uploads/monthly_2020_01/example.png.82619f2012a4cbbc915c51f63d91122d.png" rel=""><img alt="example.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33355" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/example.thumb.png.4c472a4927dced7cb8ffabe4786ae524.png"></a>
</p>

<h3>
	النوع auto
</h3>

<p>
	إذا لم يتم إضافة الخاصية loading إلى العناصر ما الذي سيحدث؟ الإجابة كما ورد سابقًا في (آلية تحميل المتصفحات للصفحات)، وهو الوضع الافتراضي لتحميل العناصر، وهذا بالضبط مفهوم النوع auto، أي عند إضافة هذا النوع أو عدم إضافة الخاصية كليًا إلى عنصر إشارة للمتصفح بعدم أهمية ترتيب تحميل هذا العنصر، وأن يجتهد المتصفح بنظام تحميله الافتراضي للعناصر في تحميل هذا العنصر.
</p>

<h2>
	الأهمية والفوائد
</h2>

<ul>
<li>
		عدم تحميل كامل الصفحة إذا لم يحتاج المستخدم لذلك.
	</li>
	<li>
		سرعة أفضل، فإذا احتاج المستخدم لتحميل الصفحة كاملة، فلن تُحمل الصفحة دفعةً واحدة، وهذا يؤدي لتسريع كل جزء يُعرض أكبر قدر مستطاع. فلو تخيلنا صفحة ما نصفين، عند دخول المستخدم إلى الصفحة فسيحمل المتصفح النصف العلوي فقط أي تحميل ملفات أقل وحجم أخف، وعند تمرير المستخدم الشاشة للنصف الآخر سيتم تحميله وحده، وهذا يعطي سرعة أعلى في تحميل الصفحات.
	</li>
	<li>
		توفير البيانات، فإن تحميل جميع الصور مرة واحدة يؤثر في البيانات المتاحة، ومن الممكن أن تحتوي صفحة على عدد كبير من الصور، لكن مع هذه الخاصية يحتمل أن يدخل المستخدم لهذه الصفحة ويخرج منها ولم يتم تحميل سوى عدد قليل من الصور، مما يحدث فرق شاسعًا في السحب من البيانات.
	</li>
	<li>
		تقليل استخدام الذاكرة، وصفحات أقل ثقلًا على المتصفح.
	</li>
</ul>
<h2>
	كيفية استخدامها وآلية عملها
</h2>

<p>
	يتم إضافتها بواسطة لغة HTML إلى الوسم <code>&lt;img&gt;</code> و الوسم <code>&lt;iframe&gt;</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4309_6" style="">
<span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"picture.jpg"</span><span class="pln"> </span><span class="atn">loading</span><span class="pun">=</span><span class="atv">"النوع"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"..."</span><span class="pln"> </span><span class="atn">width</span><span class="pun">=</span><span class="atv">”العرض”</span><span class="pln"> </span><span class="atn">height</span><span class="pun">=</span><span class="atv">”الارتفاع”</span><span class="tag">/&gt;</span><span class="pln">
</span><span class="tag">&lt;iframe</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"video-player.html"</span><span class="pln"> </span><span class="atn">loading</span><span class="pun">=</span><span class="atv">"النوع"</span><span class="pln"> </span><span class="atn">width</span><span class="pun">=</span><span class="atv">”العرض”</span><span class="pln"> </span><span class="atn">height</span><span class="pun">=</span><span class="atv">”الارتفاع”</span><span class="tag">&gt;&lt;/iframe&gt;</span></pre>

<p>
	ومن الجدير بالذكر بأن تأجيل تحميل عناصر معينة لا يؤثر البتة على تحميل عناصر أخرى لم يتم تأجيل تحميلها، إلا إن كانت تتبع لها(child).
</p>

<p>
	ويفضل إضافة طول وعرض للعناصر مؤجلة التحميل تجنبًا لإعادة اتخاذ العناصر المحيطة مكانها. فعند فتح الصفحة لا يتم تحميل تلك العناصر المؤجلة بل يتم تحميل بيانات مبدئية (2KB تقريبًا) من أبعاد العنصر وبعض المعلومات المتعلقة به وغيرها من البيانات الصغيرة، ويتم حجز المساحة المناسبة له من الصفحة، وهذا يكون طلب التحميل الأولي (للعنصر المؤجل) عند فتح الصفحة، ثم يليه الطلب الثاني والكامل عند الاقتراب من العنصر.
</p>

<h2>
	متى يبدأ تحميل العنصر المؤجل؟
</h2>

<p>
	قد ذكرنا مسبقًا بأن العناصر التي تملك خاصية <code>loading</code> من النوع <code>lazy</code> يتم بدأ تحميلها عند الاقتراب منها، لكن السؤال الذي يطرح نفسه، هل هذه الخاصية تُلزِم المتصفح ببدأ تحميل العنصر على بعد مسافة ثابتة محددة، 50 أو 70 بكسل مثلًا؟
</p>

<p>
	والصحيح بأن مسافة بدأ التحميل التي تبعد عن العنصر غير ثابتة بل يتم احتسابها بكل مرة يتم فتح الصفحة فيها، ويعتمد احتسابها على عدة عوامل منها:
</p>

<ul>
<li>
		نوع العنصر (img أو iframe).
	</li>
	<li>
		تفعيل وضع <a href="https://blog.chromium.org/2019/04/data-saver-is-now-lite-mode.html" rel="external nofollow">Lite Mode</a>.
	</li>
	<li>
		نوع اتصال الشبكة، كما تبين الصورة أدناه.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33354" href="https://academy.hsoub.com/uploads/monthly_2020_01/connection.png.b35d1f3e738bedc2a92a54b897eb7a77.png" rel=""><img alt="connection.png" class="ipsImage ipsImage_thumbnailed" data-fileid="33354" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/connection.png.b35d1f3e738bedc2a92a54b897eb7a77.png"></a>
</p>

<p>
	والمفروض من المسافة المحتسبة بين العنصر المؤجل وشاشة عرض المستخدم، أن تكون كفيلة بتحميل العنصر وتجهيزه قبل وصول شاشة عرض المستخدم إليه. ويجري العمل على تحسين وقت بدأ تحميل العنصر المؤجل من قبل جوجل.
</p>

<h2>
	أثر استخدام loading من النوع lazy على واردات الموقع
</h2>

<p>
	يؤثر على دخل الموقع المادي (إن كان موقع تجاري، أو يعرض إعلانات) عوامل عدة من أبرزها وأكبرها أثرًا <strong>السرعة</strong>، إذ أن زيادة السرعة في تشغيل الصفحات والتنقل بينها تؤثر إيجابيًا على عائدات الإعلانات أو المبيعات، ولا يخفى أن استخدام loading من النوع lazy يزيد من سرعة تشغيل الصفحات والتنقل بينها.
</p>

<p>
	ومن اللطيف طرحه ما ذكرته جوجل في <a href="https://www.thinkwithgoogle.com/intl/en-gb/advertising-channels/mobile/mobile-site-speed-playbook//" rel="external nofollow">Mobile Speed Playbook</a> : <strong>أن تأخير ثانية واحدة يؤدي إلى انخفاض الواردات المادية للمواقع على الاجهزة المحمولة بما يصل الى 20%</strong>، وتعد نسبة كبيرة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="33356" href="https://academy.hsoub.com/uploads/monthly_2020_01/mobileSpeed.jpg.2380fd53f6bb4aae4623ec84a87c082b.jpg" rel=""><img alt="mobileSpeed.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="33356" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_01/mobileSpeed.jpg.2380fd53f6bb4aae4623ec84a87c082b.jpg"></a>
</p>

<p>
	وعلى جانب آخر، سيؤثر سلبيًا على دخل الموقع إذا بدأ المعلنون باستخدامها في إعلاناتهم، فلن يتم دفع رسوم الإعلانات إلا عند وصول المستخدم بالقرب من الإعلان وتحميله. وجرت العادة بدفع رسوم جميع الإعلانات في الصفحة بمجرد فتحِها بغض النظر إن رآها المستخدم أم لم يفعل.
</p>

<p>
	ومن باب الإنصاف من حق المعلنين ألا يدفعوا رسوم الإعلان إلا عند عرضه للمستخدم. ويسد ذلك في المواقع التي تعتمد على الإعلانات في دخلها ما تعطيه الخاصية من ميزات ترفع دخل الموقع كما ذكرنا.
</p>

<h2>
	دعم الخاصية من قبل المتصفحات
</h2>

<p>
	جرت العادة عند استخدام هذه الخاصية إدراج مكتبات مصنوعة بلغة JavaScript (مثل LazySizes و lozad.js) أو بشيفرات يدرجها المبرمج. حديثًا، أصبحت الخاصية مدعومة من قبل المتصفح Chrome والمتصفحات التي تستند إلى Chromium، ووجود الخاصية بشكل أصلي في المتصفح يدعمه دون الحاجة لهذه المكتبات يعطي أداءً أفضل وسهولة في التعامل معها.
</p>

<p>
	صحيح أن دعم Chrome للخاصية خبر رائع، لكن يجب أن ننتظر دعمها من قبل جميع المتصفحات، وإلى أن يتحقق ذلك يُفضَّل عند استخدام الخاصية قبل التأكد من وجود دعم في المتصفح للخاصية بواسطة لغة JavaScript باستخدام <code>loading in HTMLImageElement.prototype</code> فإن كان متصفح المستخدم يدعم الخاصية اترك له تنفيذ الخاصية بمجرد إدراجها، وإن لم يكون كذلك قم بطلب مكتبة JavaScript لتؤدي وظيفة الخاصية عند إدراجها، وتبين الشيفرة أدناه تفاصيل ذلك. لاحظ بهذه الحالة أنَّه يجب استبدال اسم الخاصية <code>src</code> بالاسم <code>data-src</code>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4309_8" style="">
<span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">data-src</span><span class="pun">=</span><span class="atv">"picture.png"</span><span class="pln"> </span><span class="atn">loading</span><span class="pun">=</span><span class="atv">"lazy"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">".."</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"lazyload"</span><span class="tag">/&gt;</span><span class="pln">

</span><span class="tag">&lt;script&gt;</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="str">'loading'</span><span class="pln"> in </span><span class="typ">HTMLImageElement</span><span class="pun">.</span><span class="pln">prototype</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">const</span><span class="pln"> images </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">querySelectorAll</span><span class="pun">(</span><span class="str">"img.lazyload"</span><span class="pun">);</span><span class="pln">
      images</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">(</span><span class="pln">img </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        img</span><span class="pun">.</span><span class="pln">src </span><span class="pun">=</span><span class="pln"> img</span><span class="pun">.</span><span class="pln">dataset</span><span class="pun">.</span><span class="pln">src</span><span class="pun">;</span><span class="pln">
      </span><span class="pun">});</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="com">// تلقائيًا LazySizes استيراد المكتبة</span><span class="pln">
    let script </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">"script"</span><span class="pun">);</span><span class="pln">
    script</span><span class="pun">.</span><span class="pln">async </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    script</span><span class="pun">.</span><span class="pln">src </span><span class="pun">=</span><span class="pln"> </span><span class="str">"https://cdnjs.cloudflare.com/ajax/libs/lazysizes/4.1.8/lazysizes.min.js"</span><span class="pun">;</span><span class="pln">
    document</span><span class="pun">.</span><span class="pln">body</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">script</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="tag">&lt;/script&gt;</span><span class="pln"> </span></pre>

<h2>
	المراجع
</h2>

<ul>
<li>
		<p>
			<a href="https://addyosmani.com/blog/lazy-loading/" rel="external nofollow">Native image lazy-loading for the web! </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://chromestatus.com/feature/5645767347798016" rel="external nofollow">Lazily load iframes and images via ‘loading’ attribute </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://www.smashingmagazine.com/2019/05/hybrid-lazy-loading-progressive-migration-native/" rel="external nofollow">Hybrid Lazy Loading: A Progressive Migration To Native Lazy Loading </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://web.dev/native-lazy-loading" rel="external nofollow">Native lazy-loading for the web </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://www.searchenginejournal.com/lazy-loading-attribute/302155/" rel="external nofollow">New Chrome Lazy Loading Feature Coming Soon </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://github.com/scott-little/lazyload" rel="external nofollow">LazyLoad Explainer </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/frame/settings.json5?l=971-1003&amp;rcl=e8f3cf0bbe085fee0d1b468e84395aad3ebb2cad" rel="external nofollow">Lazy image loading distance-from-viewport thresholds for different effective connection types.</a>
		</p>
	</li>
</ul>
]]></description><guid isPermaLink="false">792</guid><pubDate>Fri, 17 Jan 2020 18:06:00 +0000</pubDate></item><item><title>&#x646;&#x635;&#x627;&#x626;&#x62D; &#x644;&#x625;&#x646;&#x634;&#x627;&#x621; &#x648;&#x62A;&#x635;&#x62F;&#x64A;&#x631; &#x631;&#x633;&#x648;&#x645;&#x627;&#x62A; SVG &#x644;&#x644;&#x648;&#x64A;&#x628;</title><link>https://academy.hsoub.com/programming/html/%D9%86%D8%B5%D8%A7%D8%A6%D8%AD-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%AA%D8%B5%D8%AF%D9%8A%D8%B1-%D8%B1%D8%B3%D9%88%D9%85%D8%A7%D8%AA-svg-%D9%84%D9%84%D9%88%D9%8A%D8%A8-r766/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_11/5ddd24627b151_----SVG-.jpg.3c7c2c2abb3885172eebce374d230354.jpg" /></p>

<p>
	يتضمن العمل مع أشكال SVG (الرسوميات المتجهية متغيرة الحجم) في سير عمل تصميم الويب المتجاوب مرحلة تصميم ومرحلة تطوير. يتعامل المصممون عادةً مع مرحلة التصميم وقد يعرفون أو لايعرفون كيفية كتابة الشيفرة. ونظرًا لطبيعة SVG كتنسيق صورة وتنسيق مستند معًا، فإنّ كل خطوة تتم في محرر الرسومات أثناء عملية إنشاء SVG تؤثر بشكلٍ مباشر على الشيفرة الناتجة وبالتالي على عمل المطور المسؤول عن تضمين SVG أو كتابته كنص برمجي أو تحريكه. عادةً، خلال عملي اليومي أنا المطور الذي يسلّم المصممون له أصول التصميم، وصور SVG هي جزء من هذه الأصول.
</p>

<p>
	احتاجت معظم الأصول التي تم تسليمها في مشاريعي السابقة إلى المزيد من العمل و/أو جولة ثانية من التحرير في محرر الرسومات قبل أن أتمكن من كتابتها كنصوص برمجية، لأنّ شيفرة SVG الناتجة لم تُحسَّن بما فيه الكفاية لنوع العمل - خاصةً الرسوم المتحركة - التي تم استئجاري للقيام بها. سبب ذلك هو أنّ العديد من المصممين الذين عملت معهم يعرفون القليل جدًا - إن كانوا يعرفون - عن شيفرة SVG. ينشؤون رسوميات متجهة وأصول واجهة المستخدم كل الوقت، لكن بالنسبة لهم فإنّ SVG ليس سوى تنسيق صورة ولا يعرفون الكثير عن الشيفرة المتولّدة عند تصدير أصولهم كمستندات SVG.
</p>

<p>
	هناك بعض الخطوات التي يمكن للمصممين اتخاذها أو تجنبها - مجموعة من "افعل ولا تفعل" - يمكن أن تساعد في جعل الشيفرة المتولدة أنظف. أودّ أن أشارك بعضها في هذه المقالة، إذا كنت تعرف أي شيء آخر يرجى مشاركته في التعليقات الموجودة في نهاية المقال.
</p>

<p>
	النصائح التي سنتحدث عنها قابلة للتطبيق في Adobe Illustrator -محرر الرسومات المفضل لي- وكذلك محررات الرسومات الأخرى. لكن بما أنني شخصيًا أستخدم AI فهذا ما سأركّز عليه خلال هذه المقالة.
</p>

<p>
	سنتحدث أيضًا عن خيارات تصدير SVG الحالية المتوفرة في AI وأيّ منها تختار ولماذا. لكن لاحظ أنّ هذه الخيارات ستتغير في المستقبل، وبعدها سيتم تحديث هذه المقالة لتعكس هذه التغييرات.
</p>

<p>
	تعتمد هذه المقالة على حديثي "SVG لمصممي ومطوري الويب" - حديث قمت به في CSSDevConf 2015 الشهر الماضي.
</p>

<p>
	لذا، لنبدأ.
</p>

<p>
	إذا كنت تستخدم برنامج Sketch لإنشاء SVG، هناك أيضًا بعض الأشياء التي يمكن أن تقوم بها لتصدير شيفرة أنظف. شارك Sean Kesterson بعض النصائح في <a href="https://medium.com/sketch-app-sources/exploring-ways-to-export-clean-svg-icons-with-sketch-the-correct-way-752e73ec4694#.gbtebz7ex" rel="external nofollow">هذه المقالة</a>.
</p>

<h2>
	1- أنشئ الأشكال البسيطة باستخدام عناصر شكل بسيطة وليس عناصر <code>&lt;path&gt;</code>
</h2>

<p>
	هناك سبب لوجود أشكال أساسية مختلفة في SVG لإنشاء أشكال أساسية بشكلٍ جيد. يمكن للشخص إنشاء أي شكل عمليًّا باستخدام عنصر <code>&lt;path&gt;</code>، أليس كذلك؟
</p>

<p>
	عناصر الشكل البسيطة (<code>&lt;line&gt;</code>، <code>&lt;circle&gt;</code>، <code>&lt;rect&gt;</code>، <code>&lt;ellipse&gt;</code>، <code>&lt;polygon&gt;</code> و<code>&lt;polyline&gt;</code>) موجودة لعدة أسباب، وأحد هذه الأسباب هو أنّها سهلة القراءة وسهلة الصيانة وقابلية للتحرير باليد من بدائلها <code>&lt;path&gt;</code>.
</p>

<p>
	تأتي الأشكال الأساسية مع مجموعة من الخاصيات التي تسمح لك بالتحكم في ميزات الشكل، مثل الموضع (<code>x</code>، <code>y</code>، <code>cx</code>، <code>cy</code>) والأبعاد (<code>width</code> و<code>height</code>)، بينما لا يكون لعناصر <code>&lt;path&gt;</code> مثل هذه الخاصيات.
</p>

<p>
	مثلًا، يعرض المقتطف التالي الاختلاف بين دائرة تم إنشاؤها وتصديرها كشكلٍ بسيط، مقابل دائرة تم إنشاؤها وتصديرها كمسار:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4516_6" style="">
<span class="tag">&lt;circle</span><span class="pln"> </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"#FFFFFF"</span><span class="pln">
        </span><span class="atn">stroke</span><span class="pun">=</span><span class="atv">"#000"</span><span class="pln">
        </span><span class="atn">cx</span><span class="pun">=</span><span class="atv">"28.1"</span><span class="pln">
        </span><span class="atn">cy</span><span class="pun">=</span><span class="atv">"28.1"</span><span class="pln">
        </span><span class="atn">r</span><span class="pun">=</span><span class="atv">"27.6"</span><span class="tag">/&gt;</span><span class="pln">

</span><span class="com">&lt;!-- مقابل --&gt;</span><span class="pln">
</span><span class="tag">&lt;path</span><span class="pln"> </span><span class="atn">fill</span><span class="pun">=</span><span class="atv">"#FFFFFF"</span><span class="pln">
      </span><span class="atn">stroke</span><span class="pun">=</span><span class="atv">"#000"</span><span class="pln">
      </span><span class="atn">d</span><span class="pun">=</span><span class="atv">"M55.7,28.1
         c0,15.2-12.4,27.6-27.6,27.6
         S0.5,43.3,0.5,28.1
         S12.9,0.5,28.1,0.5
         S55.7,12.9,55.7,28.1z"</span><span class="tag">/&gt;</span></pre>

<p>
	إذا أردت تحريك شكلك عن طريق تحريك موضع الدائرة أو تكبيرها، يمكنك القيام بذلك عن طريق تحريك موضع المركز عبر الإحداثيات x و y أي (<code>cx</code> و<code>cy</code>) ونصف قطر الدائرة (<code>r</code>). بينما إذا كنت تعمل مع دائرة متولدة كمسار، يجب عليك استخدام تحويلات CSS/SVG (التحريك وإعادة التحجيم) للقيام بذلك. ثمّ بفرض أردت تحريك ذلك المسار وتتطلب منك الحركة تطبيق المزيد من التحويلات، يمكن أن يصبح لديك ببساطة فوضى تحويلات.
</p>

<p>
	ميزة أخرى لاستخدام الأشكال البسيطة هي أنّه في معظم الحالات، الشيفرة المطلوبة لإنشاء شكل باستخدام عناصر شكل بسيطة هي أقلّ من المطلوبة لإنشاء نفس الشكل باستخدام عنصر <code>&lt;path&gt;</code> (شاهد المقتطف اعلاه للمقارنة)، لذا فإنّ استخدام أشكال بسيطة سيؤدي أيضًا إلى حجم ملف أصغر، وهذا أفضل دائمًا.
</p>

<h2>
	2 - حوّل النص إلى حدود خارجية..أو لا تحوّله
</h2>

<p>
	لتحويل النص إلى حدود خارجية:
</p>

<ol>
<li>
		اختر النص الذي تريد تحويله
	</li>
	<li>
		اختر النوع (Type) -&gt; إنشاء حدود خارجية (Create Outlines)
	</li>
</ol>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic01.png.b483b8b05f712480ae0f03efb97e8659.png" data-fileid="32862" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32862" data-unique="qrs2tysaa" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic01.thumb.png.9fab5571fca29459da02b5c026d563d6.png" alt="pic01.png"></a>
</p>

<h3>
	الإيجابيات
</h3>

<ul>
<li>
		النص المحوّل إلى حدود خارجية سيحافظ على نوع الخط المستخدم، بدون الحاجة إلى استخدام خط ويب لعرضه. هذا يعني أنك تحفظ القليل من طلبات HTTP الإضافية ولا تخاطر بعرض نصك بالخط الاحتياطي الذي لا يبدو جيدًا بشكلٍ كافٍ لاستبدال الخط الجميل الذي اخترته. يعدّ تحويل النص إلى حدود خارجية والحفاظ على نوع الخط المستخدم جيّدًا للحفاظ على هوية العلامة التجارية عندما تُعرّف بنوع خط مستخدم، مثلًا في شعار، أقوم دائمًا بتحويل نص الشعار إلى حدود خارجية وهذا جيد للحفاظ على الخط لنصوص برمجية معينة عندما تستخدم العناوين.
	</li>
</ul>
<h3>
	السلبيات
</h3>

<ul>
<li>
		النص المحوّل إلى خطوط خارجية ليس نصًا حقيقيًا: إنّه مجموعة من المسارات التي تشكل الحدود الخارجية (الشكل) للنص. وبالتالي يصبح النص غير واقعي ولا يمكن الوصول إليه، وغير قابل للبحث وغير قابل للتحديد. إذا تمّ تحويل النص إلى حدود خارجية في عنوان نص برمجي أو حتى شعار، فإنّ استخدام نص <code>alt</code> (إذا تم تضمين الشعار كصورة) أو عناصر سهلة الوصول لـ SVG مثل (<code>&lt;title&gt;</code> و<code>&amp;&gt;</code>) هو فكرة جيدة لتوفير نص بديل لقارئات الشاشة.
	</li>
</ul>
<p>
	أوصي بشدّة بقراءة كل شيء عن جعل SVG سهل الوصول في هاتين المقالتين لـLéonie Watson: - <a href="https://www.sitepoint.com/tips-accessible-svg/" rel="external nofollow">نصائح لإنشاء SVG سهلة الوصول</a> - <a href="https://developer.paciellogroup.com/blog/2013/12/using-aria-enhance-svg-accessibility/" rel="external nofollow">استخدام ARIA لتحسين سهولة الوصول لـSVG</a>
</p>

<ul>
<li>
		يمكن أن يسبب تحويل النص إلى حدود خارجية زيادةً كبيرةً في حجم ملف SVG، حسب تعقيد الخط المستخدم. تُظهر الصورة أدناه الاختلاف في حجم (وسهولة القراءة) لـSVG مع النص المحوّل إلى حدود خارجية (يسار) والنص الذي يتم تصديره كـ SVG <code>&lt;text&gt;‎</code> (يمين).
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic02.jpg.c3d57f52e0bf17a993979caa4181fb67.jpg" data-fileid="32863" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32863" data-unique="31w9ua6pq" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic02.thumb.jpg.8c08e3fd51b4d0431f6eb742df53dc0b.jpg" alt="pic02.jpg"></a>
</p>

<ul>
<li>
		لا يمكن التحكم بالمسارات أو تحريكها بسهولة مثلما يتم ذلك في عناصر <code>&lt;text&gt;</code> (المتضمنة عناصر <code>&lt;tspan&gt;</code>). إذ تحتوي الأخيرة على مجموعة من الخاصيات التي تمنحك المزيد من التحكم في رسومك المتحركة، بينما تبقى بيانات المسار محدودة بهذا الشأن.
	</li>
</ul>
<h2>
	3- تبسيط المسارات
</h2>

<p>
	يعرَّف المسار بمجموعة من النقاط والتي بدورها يتم تحديد كلّ منها بزوج من الإحداثيات.
</p>

<p>
	كلّما قلّ عدد النقاط، قلّت بيانات المسار (خاصية <code>d</code>)، وبالتالي انخفض حجم ملف SVG الكلي. هذه الخطوة الجيدة يجب اتخاذها دائمًا لأنّ حجم الملف الأصغر أفضل للأداء.
</p>

<p>
	لتبسيط مسار:
</p>

<ol>
<li>
		اختر المسار
	</li>
	<li>
		اذهب إلى كائن (Object) -&gt; مسار (Path) -&gt; تبسيط (Simplify)
	</li>
	<li>
		عدّل عدد النقاط. تأكّد من أن أنّك فحصت المعاينة حتى تتمكن من معرفة كيف يتغير المسار أثناء تغيّر عدد النقاط. عدّل العدد حتى تحصل على أقل عدد من النقاط أثناء المحافظة (أو التضحية) على أفضل مظهر مرئي للمسار الذي تحتاجه.
	</li>
</ol>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic03.png.b4df31740f57c581fac237ccfe553aa8.png" data-fileid="32864" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32864" data-unique="akdwzwwae" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic03.thumb.png.799edf4d657953cf0852434aa88f54d3.png" alt="pic03.png"></a>
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic04.png.583c14b3fb89018873892a1ff5af901f.png" data-fileid="32865" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32865" data-unique="ob50lsiqm" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic04.thumb.png.8dc6250e6a3e672237df17e5dc11fd1d.png" alt="pic04.png"></a>
</p>

<p>
	يوجد فيديو تعليمي لشركة Adobe يشرح العملية، لذا إذا كنت أكثر انسجامًا مع مقاطع الفيديو، يمكنك الاطلاع عليه <a href="http://tv.adobe.com/watch/companion-videos-for-inspire/svg-for-the-web-using-the-simplify-panel-in-illustrator-cc/" rel="external nofollow">هنا</a>.
</p>

<p>
	يمكنك أيضًا تبسيط المسارات باستخدام أداة Warp Tool. أنا لست مصممة ولكن أستخدم عادةً خوارزمية تبسيط Ai لتبسيط مساراتي، لذا إذا كنت مصممًا متمرّسًا، من المحتمل أنّك تعرف أكثر بكثير عن أداة Warp tool مني. يوجد <a href="https://www.smashingmagazine.com/2011/07/examples-and-tips-for-using-illustrator-s-warp-tools/" rel="external nofollow">مقال في مجلة Smashing</a> حول هذه الأداة، يمكنك الاطلاع عليها إن أردت.
</p>

<h2>
	4- تجنب دمج المسارات إذا لم تكن بحاجة للتحكم في المسارات الفردية
</h2>

<p>
	يميل العديد من المصممين إلى جمع المسارات أو دمجها كلما أمكن ذلك. لدمج المسارات:
</p>

<ol>
<li>
		اختر الطرق التي تريد دمجها
	</li>
	<li>
		اذهب إلى نافذة (Pathfinder &lt;- (Window
	</li>
	<li>
		اختر خيار الدمج (Merge) من بين قائمة الخيارات أسفل اللوحة (الأيقونة الثالثة من اليسار، المبينة في لقطة الشاشة أدناه).
	</li>
</ol>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic05.png.f9d9e8e1de21a02513640b751c0d5d24.png" data-fileid="32866" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32866" data-unique="xxfe0gu1h" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic05.thumb.png.9c3fdfa65814c9554dd5829fc452b5e8.png" alt="pic05.png"></a>
</p>

<p>
	قد يكون هناك فوائدٌ لجمع المسارات، لكن تجنبها عندما تحتاج أنت أو المطور للتحكم و/أو تحريك المسارات بشكلٍ منفصل. تم تصميم بعض الرسوم المتحركة بحيث يتم تحريك عناصر متعددة بشكلٍ منفصلٍ، أو في بعض الأحيان قد تريد فقط تصميم المسارات باستخدام ألوان تعبئة مختلفة. إذا قمت بجمع المسارات، فلن يكون ذلك ممكنًا بعد الآن.
</p>

<p>
	تحتاج إلى التأكّد من معرفتك لما يحتاجه المطور (أو أنت إذا كنت ستتعامل مع مرحلة التطوير أيضًا) ولما يريد القيام به مع الأشكال التي تعمل عليها، واتخاذ قرار الدمج أو عدم الدمج وفقًا لذلك. هذا سيوفر لكما الكثير من الوقت والخلاف.
</p>

<h2>
	5- إنشاء مرشّحات باستخدم مرشّحات SVG، وليس تأثيرات Photoshop
</h2>

<p>
	إذا كنت تستخدم المرشّحات في قسم تأثيرات Photoshop ضمن خيار تأثير، فسيقوم Illustrator بتصدير التأثيرات التي تنشؤها كصور نقطية. مثلًا، إذا قمت بإنشاء ظل إسقاط باستخدام تأثير الضبابية Blur في فوتوشوب، فإن الظلّ المسقط المتولّد سيكون صورة نقطية مضمنة داخل SVG إما مضمنة داخليًا أو خارجيًا، باستخدام عنصر <code>&lt;image&gt;</code>. أنت بالتأكيد لا تريد ذلك عند العمل مع SVG.
</p>

<p>
	تحتاج لتوليد مؤثراتك كشيفرة SVG إلى استخدام مرشّحات SVG المتاحة:
</p>

<ol>
<li>
		اذهب إلى تأثير (Effect) -&gt; مرشّحات (SVG Filters (SVG
	</li>
	<li>
		اختر واستخدم أحد المرشّحات المتاحة في اللائحة.
	</li>
</ol>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic06.png.2f1d55deab3b1a41952d3ce65c46f6e9.png" data-fileid="32867" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32867" data-unique="sklk1skla" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic06.thumb.png.6c37c15c6fb6ec1843fdcdee3a1df637.png" alt="pic06.png"></a>
</p>

<h2>
	6- اجعل لوح الرسم (Artboard) مناسبًا لرسمتك
</h2>

<p>
	هل قمت يومًا بتضمين SVG في صفحة، وإعطائه ارتفاعًا وعرضًا محددين ثمّ وجدت أنه كان معروضًا بحجم أصغر من الحجم الذي حددته؟
</p>

<p>
	في معظم الحالات، يكون السبب في ذلك هو وجود مساحة بيضاء داخل منفذ العرض (viewport) الخاص بـ SVG. يتم عرض منفذ العرض بالحجم الذي تحدده في صفحة الأنماط (style sheet) الخاصة بك، لكن المساحة الإضافية داخلها - حول الرسم - تتسبب في "تقليص" صورتك، لأنّ هذه المساحة البيضاء تأخذ مساحةً داخل منفذ العرض.
</p>

<p>
	لتجنّب ذلك، تحتاج إلى التأكّد من أنَّ لوح الرسم الخاص بك كبير بما فيه الكفاية ليناسب الرسمة بداخله، ولكن ليس أكبر منها.
</p>

<p>
	أبعاد لوح الرسم هي أبعاد منفذ عرض SVG المصدَّر، وأي مساحة بيضاء في لوح الرسم سيتم إنشاؤها كمساحة بيضاء داخل منفذ العرض.
</p>

<p>
	ليتناسب لوح الرسم مع رسمتك:
</p>

<ol>
<li>
		حدد كامل الرسمة (أنا أستخدم الاختصار cmd/ctrl + A)
	</li>
	<li>
		اذهب إلى كائن (Object) -&gt; ألواح الرسم (Artboards) واختر الخيار تناسب مع حدود العمل الفني (Fit to Artwork Bounds option).
	</li>
</ol>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic07.png.121d48dd87b0e7914f35d5cd7ff37b75.png" data-fileid="32868" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32868" data-unique="eatc704ax" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic07.thumb.png.e78fc842f775bacd0df653cee976fe8b.png" alt="pic07.png"></a>
</p>

<h2>
	7- استخدم اصطلاحات تسمية، وتجميع وطبقات جيّدة
</h2>

<p>
	أعلم أنّ هذا يبدو كأنّه غير عقلاني، لكن يجب التأكيد عليه لعدة أسباب:
</p>

<ul>
<li>
		ستتم ترجمة معرّفات وأسماء الفئات التي تستخدمها في محرر الرسومات إلى معرّفات وأسماء الفئات في الشيفرة المتولّدة. كلّما كانت هذه الأسماء أكثر منطقيةً وأكثر وضوحًا في تصنيف العناصر الخاصة بكل منها، سيكون هناك تعارضًا أقل عندما يعمل المطوّر مع الشيفرة.
	</li>
</ul>
<p>
	أنا لا أقول الآن أنّه يجب عليك التفكير في الأسماء المثالية - أنا متأكّدة أنّه لكلّ منّا طرق مختلفة لتسمية الأشياء ويمكن أن تكون التسمية واحدة من أصعب المهام، لكن تسمية المجموعات بشكلٍ مناسب تقطع شوطًا طويلًا. مثلًا، إذا كنت ترسم سيارة، فإنّه من المناسب استخدام معرّف العجلة لتسمية الطبقة أو مجموعة تغليف الأشكال المكوّنة للعجلة. إذا كنت تقوم بتجميع كل العجلات في مجموعة واحدة، فقد تعطيها معرّف العجلات. تؤثّر الأسماء البسيطة في التعبير عن العناصر والمجموعات وتحفظ الكثير من الوقت، خاصةً إذا كان المطوّر سيحرر الشيفرة ويعالجها يدويًا.
</p>

<p>
	لا يقوم Illustrator بعمل أفضل في تسمية الأشياء، لذا فإنّ تحديد الأسماء يساعد في تقليل كمية المخلّفات التي ينتجها. وبالتأكيد، سيكون هناك بعض التحرير الإضافي المطلوب للتخلّص من الخطوط السفلية المزعجة التي يصرّ Ai على توليدها، لكن استخدام الأسماء الصحيحة يساعد في جعل هذه العملية أسهل قليلًا.
</p>

<p>
	كما ذُكر سابقًا، ستُظهر النسخة التالية من Illustrator تحسّنًا كبيرًا في طريقة توليد SVG، متضمنةً المعرّفات المتولّدة.
</p>

<ul>
<li>
		<p>
			استخدم الطبقات لتجميع العناصر ذات الصلة. تُترجم الطبقات إلى مجموعات في الشيفرة، لذا يجب تسميتها بشكلٍ جيّد أيضًا. أنشئ طبقات/مجموعات لتجميع العناصر ذات الصلة معًا، خاصةً تلك التي قد تكون متحركة بالكامل. إذا لم يتم ذلك بالفعل في مرحلة التصميم فمن الممكن قضاء الكثير من الوقت في إعادة ترتيب وتجميع العناصر يدويًا من قِبل المطوّر. تأكّد من التجميع بشكلٍ مناسب لتوفير الوقت. يُعدّ التحدّث مع المطور في مرحلة التصميم وتصميم كيفية ستُنفّذ الرسوم المتحركة معًا هما أكبر موفران للوقت.
		</p>
	</li>
	<li>
		<p>
			إذا كانت الصور التي تقوم بإنشائها ستُستخدم لإنشاء SVG sprite، فإنّ الأسماء التي تستخدمها يمكن أن تُستخدم وستُستخدم من قِبل معظم أدوات الأتمتة لتوليد ملفات جديدة. لذا فإنّ استخدام أسماء واضحة ومناسبة سيؤدي إلى أسماء ملفات أنظف.
		</p>
	</li>
</ul>
<h2>
	8- اختر أفضل خيارات تصدير مناسبة للويب
</h2>

<p>
	بدءًا من Illustrator CC 2015.2 الذي تمّ إصداره في تشرين الأول 2015، يوجد تدفق عمل جديد لتصدير SVG (ملف&gt; تصدير&gt; SVG) لتصدير ملفات SVG مُحسّنة للويب لتدفقات عمل تصميم الشاشة والويب لديك. يمكنك أيضًا أن تختار تصدير الأغراض الفردية أو كامل لوح الرسم. راجع <a href="https://helpx.adobe.com/illustrator/how-to/export-svg.html" rel="external nofollow">هذه المقالة</a> لمزيدٍ من التفاصيل.
</p>

<p>
	في وقت كتابة هذا المقال، يأتي Illustrator مع مجموعة من خيارات التصدير التي تسمح لك بتوليد شيفرة SVG أفضل بشكلٍ عام.
</p>

<p>
	لتصدير الـ SVG الخاص بك:
</p>

<ol>
<li>
		اختر ملف (File) -&gt; حفظ كـ (Save As)
	</li>
</ol>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic08.png.0e44f88e7345d184a0ecf097e92d5a9e.png" data-fileid="32869" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32869" data-unique="tji9nmm9y" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic08.thumb.png.1de2ca8370d85c3887e614fdd26c78c9.png" alt="pic08.png"></a>
</p>

<ol start="2">
<li>
		اختر SVG من القائمة المنسدلة
	</li>
</ol>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic09.png.de41f0180f1badb40cb3f8b36f491e98.png" data-fileid="32870" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32870" data-unique="6nmn6wv9p" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic09.thumb.png.1426e2cae57ac7956201e2b9dddb56fd.png" alt="pic09.png"></a>
</p>

<ol start="3">
<li>
		اضغط حفظ (Save)
	</li>
</ol>
<p>
	بمجرد النقر على حفظ، سيظهر مربع حوار يحتوي على مجموعة من الخيارات التي يمكنك تخصيصها، والتي ستؤثّر على شيفرة SVG المتولّدة:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic10.png.111c69f7763975e0aa0cd476d997aba5.png" data-fileid="32871" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32871" data-unique="j3qnsaatt" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic10.thumb.png.ab192e9085072999b18309be7560bbba.png" alt="pic10.png"></a>
</p>

<p>
	الخيارات الموضّحة في الصورة أعلاه هي الخيارات المستحسنة لتوليد SVG للويب.
</p>

<p>
	يمكنك بالطبع اختيار تحويل النص إلى حدود خارجية إذا لم تكن ترغب باستخدام خط ويب، وكما ترى يوفر لك Illustrator خيارًا أيضًا للقيام بذلك عند التصدير.
</p>

<p>
	يحدد خيار موقع الصورة (Image Location) فيما إذا سيتم تضمين أي صور نقطية داخليًا في الـ SVG الخاص بك أو خارجيًا مع رابط يدلّ عليه في الـ SVG. ومجددًا، هذا يعتمد على ما تحتاجه. يمكن أن تزيد الصور المضمنة داخليًا في الـ SVG حجم الملف بشكلٍ كبيرٍ. آخر مرة أرسل مصممٌ لي SVG مع صورة مضمنة فيه، كان حجم الملف أكثر من 1 ميغابايت! بعد حذف تلك الصورة (وبسبب تأثيرات Photoshop المستخدمة المذكورة سابقًا)، انخفض حجم الملف إلى أكثر من 100 كيلو بايت! لذا، اختر بحكمة.
</p>

<p>
	يمنحك خيار خصائص CSS الحرية لاختيار كيف تريد إنشاء الأنماط داخل الـ SVG: استخدام خاصيات التقديم، الأنماط المضمنة داخليًا، أو داخل وسم <code>&lt;style&gt;</code>. هذا أيضًا مسألة تفضيل وتعتمد على الطريقة التي تنوي بها التعامل مع SVG بمجرد تضمينها. إذا لم تكن الشخص الذي سيفعل ذلك، فتأكد من التشاور مع المطور لتحديد الخيار الذي يناسب احتياجاته على أفضل وجه.
</p>

<p>
	كلّما قلّ عدد المنازل العشرية، قلّ حجم ملف SVG. يجب أن تكون منزلة عشرية واحدة كافية بشكلٍ عام، لذا سأتّبع ذلك.
</p>

<p>
	لاحظ أنّه إذا اخترت 3 أو 4 منازل عشرية، مثلًا، ثمّ استخدمت أداة تحسين لتحسين SVG وخفض هذا الرقم إلى 1، فقد ينتهي بك الأمر إلى SVG معطوب، لذا من الأفضل اختيار هذا الخيار في وقت مبكر.
</p>

<p>
	هناك المزيد في لائحة الخيارات التي قمت بتغطيتها. كتب Michaël Chaize من Adobe مقالةً ممتازةً حول لائحة التصدير توضّح ما يفعله كل خيار تمامًا. أوصي بشدّة بمراجعة مقالته:
</p>

<p>
	<a href="http://www1.creativedroplets.com/?subid4=1570624033.0049298286&amp;kw=Web+Design+Services&amp;KW1=Web%20Design%20Services&amp;KW2=Web%20Hosting&amp;KW3=Help%20Desk%20Ticket%20System&amp;searchbox=0&amp;domainname=0&amp;backfill=0" rel="external nofollow">تصدير SVG للويب مع Illustrator CC</a>
</p>

<p>
	الآن، في وقت كتابة هذا المقال، سيبقى Illustrator يولّد شيفرةً غير ضرورية مثل البيانات الوصفية للمحرر، والمجموعات الفارغة، من أمورٍ أخرى، لذا ستحتاج إلى تحسين الـ SVG بشكلٍ أكبر بعد تصديره، سواء كان ذلك باليد، أو باستخدام أداة تحسين SVG مستقلة.
</p>

<p>
	لكن قبل أن ننتقل إلى جزء التحسين، أريد أن أشير إلى أنّك قد ترغب أو لا ترغب في التحقق من خيارٍ إضافي أثناء حفظ SVG: خيار "استخدم ألواح الرسم" ، في لائحة الحفظ:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic11.png.4da20a3dea579a5e3583f0e010db6828.png" data-fileid="32872" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32872" data-unique="2yzmqko0x" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic11.thumb.png.19786391e728b70d9169e3f295fdcd50.png" alt="pic11.png"></a>
</p>

<p>
	يعدّ هذا الخيار مفيدًا عندما تعمل مع صور SVG متعددة (مثل الأيقونات) وتستخدم لوح رسم لكلّ أيقونة.
</p>

<p>
	سيؤدي تصدير ألواح رسم متعددة إلى توليد ملفات svg. متعددة، ملف لكل لوح رسم (واحد لكل أيقونة).
</p>

<p>
	سيتم تعطيل هذا الخيار بشكلٍ افتراضي إذا كنت تعمل مع لوح رسم واحد.
</p>

<p>
	يعتمد اختيار تصدير ملف SVG واحد أو عدة ملفات SVG على كيفية تضمين SVG.
</p>

<p>
	مثلًا، إذا كنت تريد إنشاء SVG sprite لنظام أيقونات SVG، فهناك عدة طرق يمكنك من خلالها إنشاء واستخدام الـ sprite، وكلّ منها تتطلب منهجًا مختلفًا: تتطلّب إحدى التقنيات فصل الأيقونات في البداية، بينما تتطلّب الأخرى أن تكون الأيقونات جزءًا من صورة واحدة.
</p>

<p>
	سأكتب منشورًا مفصّلًا حول SVG sprite وخيارات لوح الرسم، لكن حتى ذلك الحين، يمكنك أن تأخذ نظرة عامة حول التقنيات المختلفة لـ SVG sprite في المقالة التالية التي كتبتها لـ24Ways.org:
</p>

<p>
	<a href="https://24ways.org/2014/an-overview-of-svg-sprite-creation-techniques/" rel="external nofollow">نظرة عامة حول تقنيات إنشاء SVG sprite</a>
</p>

<h2>
	للتحسين أو لعدم التحسين
</h2>

<p>
	يوصى عادةً بتحسين SVG بعد تصديره من محرر رسومات باستخدام أداة تحسين مستقلة. أداة التحسين الحالية الأكثر شيوعًا هي الأداة المعتمدة على NodeJS والتي تسمى SVGO. لكن قد لا يكون من الأفضل دائمًا تحسين SVG، خاصة إذا كنت تنوي تحريكه.
</p>

<p>
	إذا كنت تنوي كتابة SVG كنص برمجي و/أو تحريكه، فمن المحتمل أن تقوم بإعداد بنية وثيقة معينة - غلاف المجموعات، وأسماء المعرفات التي لا تستخدمها/تشير إليها داخل الـ SVG لكنك تنوي استخدامها في جافاسكربت أو غيرها. ستتغير البنية إذا قمت بتحسين الـ SVG باستخدام SVGO (أو أي أداة تحسين أخرى).
</p>

<p>
	عادةً ما تزيل أدوات التحسين أي مجموعات ومعرّفات غير مستخدمة، بالإضافة إلى أنّها تطبّق العديد من التغييرات على الـ SVG للتأكد من تحسينه بشكلٍ جيد.
</p>

<p>
	لقد قمت بتحسين ملف SVG مرةً بعد تطبيق رسم متحرك عليه باستخدام <code>&lt;animate&gt;</code>. كان ملف الـ SVG معطوبًا والحركة بداخله، لأنّه تم تغيير البنية بالكامل. وهذا شيء يجب تذكره قبل تحسين SVG.
</p>

<p>
	تجنّب التحسين مستخدمًا أداة تحسين، إذا قمت بتحرير و/أو توليد SVG يدويًا ببنية معينة تحتاجها، وحسّن يدويًا قدر الإمكان. يمكن إزالة بعض مخلفات التحرير في بداية ونهاية الـ SVG يدويًا بسهولة، والمخلفات الأخرى مثل البيانات الوصفية والفئات المتولّدة من قِبل برامج التحرير التي لا تحتوي على خيارات تحسين SVG - مثل Sketch - قد يكون من الصعب تحسينها يدويًا.
</p>

<p>
	عمومًا، أنا لا أستخدم Sketch لتوليد SVG معقدة. أستخدم Illustrator أو Inkscape؛ إذ يأتي الأخير مع لائحة تصدير افتراضية تعطيك الكثير من الخيارات لتحسين الـ SVG قبل تصديره (انظر الصورة أدناه). يولّد Inkscape أنظف شيفرة SVG في وقت كتابة هذا المقال. أي إذا اخترت خيار تحسين SVG، لكن ضبابية واجهة المستخدم على شاشة شبكة العين وكذلك اعتمادها على X11 على OS X يجعل من الصعب استخدامه، لذلك أنا متمسكة حاليًا بـ Illustrator.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic12.png.0a3b2288d6bcaf9b5e0b24c745705c7e.png" data-fileid="32873" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32873" data-unique="dx9nwnyye" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic12.thumb.png.8c10d0077a78826bfa356537d002158e.png" alt="pic12.png"></a>
</p>

<p>
	إذا كنت تحتاج/تريد تحسين الـ SVG الخاص بك فإنني أنصحك بأداة SVGO، إذ يأتي SVGO مع مجموعة من الإضافات التي يمكن دمجها مع أي نوع من تدفقات العمل تقريبًا.
</p>

<h2>
	9- تواصل. تواصل مبكرًا
</h2>

<p>
	ربما كان أهم نصيحة يمكنني تقديمها هو التواصل والقيام بذلك مبكرًا في عملية التصميم.
</p>

<p>
	أفترض أنّك الآن - المصمم الذي ينشئ SVG - لست الشخص نفسه المسؤول عن تطوير SVG (كتابة نص برمجي، التحريك، التضمين، …إلخ).
</p>

<p>
	تتطلّب كل واحدة من النصائح السابقة تقريبًا معرفة مرحلة التطوير وما ينوي المطور القيام به مع الـ SVG - كيف ينوون تضمينه، وكتابته كنص برمجي، وتصميمه، وتحريكه. لذا إذا لم تكن أنت نفس الشخص الذي يصنع القرارات لكلا المرحلتين، وما لم تكن تريد تضييع الكثير من الوقت في تكرار وتحرير الـ SVG، تحتاج إلى التأكّد من معرفتك لما يحتاج لمطور أن يفعله مع الـ SVG وما المنهجية (أو المنهجيات) التي سيتبعها. إذا كنت تعمل في مشروع له موعد نهائي ضيق، فمن المحتمل أنك لا تستطيع أن تضيع وقتًا كبيرًا في إجراء تغييرات ومراجعات على أصول الصور، عندما يمكنك تجنب ذلك عن طريق التواصل مبكرًا.
</p>

<p>
	يمكن أن يكون المصممون والمطورون أفضل أصدقاء لبعضهم بعضًا. تتطلّب طبيعة SVG أن تكون مراحل التصميم والتطوير مفتوحة على بعضها بعضًا، وهذا بدوره يتطلب من المصمم (المصممين) والمطور (المطورين) التحدّث قبل بدء عملية التصميم وطوال العملية أيضًا .
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.sarasoueidan.com/blog/svg-tips-for-designers/" rel="external nofollow">Tips for Creating and Exporting Better SVGs for the Web</a> لصاحبته Sara Soueidan
</p>
]]></description><guid isPermaLink="false">766</guid><pubDate>Tue, 26 Nov 2019 13:14:41 +0000</pubDate></item><item><title>&#x62A;&#x635;&#x645;&#x64A;&#x645; &#x645;&#x641;&#x627;&#x62A;&#x64A;&#x62D; &#x62A;&#x628;&#x62F;&#x64A;&#x644; (Toggle Switches) &#x648;&#x625;&#x646;&#x634;&#x627;&#x624;&#x647;&#x627;</title><link>https://academy.hsoub.com/programming/html/%D8%AA%D8%B5%D9%85%D9%8A%D9%85-%D9%85%D9%81%D8%A7%D8%AA%D9%8A%D8%AD-%D8%AA%D8%A8%D8%AF%D9%8A%D9%84-toggle-switches-%D9%88%D8%A5%D9%86%D8%B4%D8%A7%D8%A4%D9%87%D8%A7-r765/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_11/5ddd2279917df_---(Toggle-Switches)-.jpg.af71dbdbc61976319a795072e404b64e.jpg" /></p>

<p>
	كنت أعمل البارحة على إنشاء الشرائح والعروض التجريبية المرافقة لحديثي القادم عن الشيفرة في موقع <a href="https://www.webdirections.org/" rel="external nofollow">web directions</a> الأسبوع المقبل. أحد العروض التجريبية التي أنشئها هو دليل أساسي لمفهوم المفتاح البسيط الذي يُستخدم لتبديل مظهر واجهة المستخدم من مضيء إلى مظلم وبالعكس، أحببته واستلهمته من مبدّل المظهر في تطبيق Medium المبين أدناه.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32859" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic01.jpg.5804ff3f3dc18619110205197244fe2e.jpg" rel=""><img alt="pic01.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32859" data-unique="o4oj8cxtn" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic01.jpg.5804ff3f3dc18619110205197244fe2e.jpg"></a>
</p>

<p>
	مُخصِّص مظهر تطبيق Medium هو لوحة منبثقة بسيطة تتضمن مفتاح بسيط للتبديل من وضع مضيء إلى مظلم وبالعكس.
</p>

<p>
	الاختلاف الوحيد الذي أريده هو أن يشير مفتاحي إلى حالة المظهر الفعالة حاليًا بشكلٍ واضح. لذا بدلًا من تفعيل وتعطيل المظهر المظلم فقط مثل مفتاح Medium، أريد أن يبدّل المستخدم بين خيارَي مضيء ومظلم بوضوح. لا يوجد سبب محدد لذلك سوى أنّه تفضيل شخصي. هناك <a href="https://inclusive-components.design/a-theme-switcher/" rel="external nofollow">طرق أخرى</a> للقيام بذلك أيضًا، يبقى أمر كيفية تصميمه تفضيلًا شخصيًا، طالما أنّه يعمل وقابلًا للفهم بسهولة من قِبل المستخدمين.
</p>

<p>
	بدأت أفكر كالعادة في كيفية تمييز هذا العنصر البسيط، مع التأكّد من سهولة الوصول إليه مباشرةً من البداية. لذا بدأت القيام بواجبي وقراءة وتعلّم كل ما بوسعي بشأن هذا الموضوع.
</p>

<p>
	كان من المهم بالنسبة إليّ التأكد أنّ هذا العرض التجريبي سهل الوصول حتى لو كان مجرد دليل سريع للمفهوم لحديث. أولًا وقبل كل شيء، بما أنّ شيفرة العرض التجريبي ستكون متاحة للعامة، كان لدي مسؤولية أكبر للتأكّد من أنّها سهلة الوصول، لأنني لا أريد نشر أي شيفرة لا يمكن الوصول إليها، خاصةً إذا كان هناك فرصة ليستخدمها الناس في مكان آخر.
</p>

<p>
	وأردت أن تكون الشيفرة جيدةً لسببٍ آخر هو أنّني ربما أرغب في إعادة استخدامها لمكونات أخرى في ورشة عمل قادمة لي حول تطوير الواجهة الأمامية.
</p>

<h2>
	البدء بالشيفرة
</h2>

<p>
	كما ذكرت أعلاه، بدأت أفكر في كيفية ترميز هذا العنصر لضمان سهولة وصوله إلى قارئات الشاشة. عندها أدركت (وأحسست بالغباء نوعًا ما) أنّ الوظيفة والترميز يعتمدان على الطريقة التي أريد أن يكون سلوك التبديل بها وكيف أريده أن يظهر.
</p>

<p>
	كان الأمر واضحًا جدًا بالنسبة لي: سيسمح المفتاح للمستخدم بالاختيار بين المظهر المضيء والمظهر المظلم، وسيكون المظهر المضيء هو الافتراضي. وفي هذه اللحظة تبادر إلى ذهني أزرار الانتقاء (radio buttons): خياران يمكن تفعيل أحدهما فقط في وقت واحد، هذا يمكن أن يصنع حالة استخدام ممتازة لأزرار الانتقاء القديمة الجيدة.
</p>

<p>
	كنت أعلم أنّه يجب عليّ اختيار شيء ما مختلف في حال أردت أن تبدو واجهة المستخدم وتتصرف بشكلٍ مختلف. مثلًا، إذا أردت لواجهة المستخدم أن تعرض "تفعيل/تعطيل النمط المظلم"، عندها لن أحتاج إلى استخدام أزرار الانتقاء لأنّ لدي خيارًا واحدًا فقط للتعامل معه وهو التشغيل أو إيقاف التشغيل، سيكون ذلك حالة استخدام رائعة <a href="https://wiki.hsoub.com/HTML/input/checkbox" rel="external">لمربع تأشير</a> (checkbox) أو عنصر زر <a href="https://wiki.hsoub.com/HTML/button" rel="external"><code>&lt;button&gt;</code></a> تبديل قديم جيد.
</p>

<h3>
	تحليلات
</h3>

<ul>
<li>
		التصميم والوظيفة مترابطان، مما يساعد على التفكير في هذين الأمرين في وقت واحد عند التصميم لسهولة الوصول (وفي الحقيقة تصميم أي شيء بشكلٍ عام).
	</li>
	<li>
		ابدأ دائمًا وأبدًا بالتفكير حول الترميز وسهولة الوصول عند إنشاء المكونات بغض النظر عن مدى صغرها وبساطتها.
	</li>
</ul>
<h2>
	دراسة
</h2>

<p>
	كنت بحاجة -كما هو الحال دائمًا- إلى دعم نظريتي وتطبيقي العملي بالبحث الجيد، لذا بدأت بالقراءة، مراجعي الأولى التي ألجأ إليها هي <a href="https://inclusive-components.design/" rel="external nofollow">المكونات الشاملة</a> و<a href="https://a11yproject.com/" rel="external nofollow">مشروع A11y</a> لـ Heydon Pickering. كما اتّضح، لدى Heydon <a href="https://inclusive-components.design/toggle-button/" rel="external nofollow">مقالة رائعة حول أزرار التبديل</a> تعلّمت منها الكثير، ولدى صديقي <a href="https://www.scottohara.me/" rel="external nofollow">Scott O’Hara</a> زر تبديل ARIA مضمّن في <a href="https://a11yproject.com/patterns" rel="external nofollow">قسم الأنماط</a> من مشروع A11y. لذلك، بطبيعة الحال، فحصتُ شيفرة الزر وقرأتُ مقالة Heydon للتأكّد فيما إذا كنت على الطريق الصحيح.
</p>

<p>
	تجدر الإشارة قبل المتابعة إلى أنّ هذه ليست مقالة حول كيفية إنشاء مفاتيح تبديل سهلة الوصول. مقالة Heydon تقوم بعمل رائع يغطي ذلك.
</p>

<p>
	النقاط الرئيسية التي استخلصتها شخصيّا من البحث أعلاه هي:
</p>

<ul>
<li>
		هناك أنواع مختلفة من المفاتيح التي تبدو وكأنّها تقوم بأشياء مماثلة ولكنها تختلف اختلافًا جوهريًا عندما يتعلق الأمر بالترميز وسهولة الوصول. ليس بالضرورة أن تكون متشابهة، لمجرد أنّها مصممة لتظهر بنفس الشكل.
	</li>
	<li>
		أحتاج إلى التفكير بالسلوك الذي ستسلكه واجهة المستخدم، الشكل والصوت عند التبديل. أولًا التصميم وتجربة المستخدم، ثمّ الشيفرة.
	</li>
	<li>
		يمكن استخدام مفتاح التبديل للتبديل بين خيارين منفصلين، أو يمكن استخدامه لتشغيل خيار واحد أو إيقاف تشغيله (أو مثل تفعيل/تعطيل خيار). هنا تبدأ اختلافات التطبيق بالظهور.
	</li>
	<li>
		إذا كنت تبدّل بين خيارين منفصلين، فإنّ استخدام أزرار الانتقاء القياسية يبدو منطقيًا. يتم استخدام أزرار الانتقاء عندما تريد من المستخدمين اختيار خيار واحد فقط من خيارين أو أكثر، لذا فإنّ هذه حالة استخدام مثالية لهم. لديهم أيضّا إمكانية وصول أساسية وسيتم وضع إشارة إلى جانب الخيار الذي تم تفعيله. تأكّد فقط أنّك لا تحدّ من إمكانية الوصول لأيٍّ منهما في HTML أو باستخدام CSS.
	</li>
	<li>
		إذا كان الهدف من التبديل هو تفعيل/تعطيل ميزة (أو تشغيلها/إيقافها)، هناك طرق أخرى لذلك:
		<ul>
<li>
				استخدام صندوق تأشير لتأشير/إلغاء تأشير (تفعيل/تعطيل) هذا الخيار.
			</li>
			<li>
				استخدام زر <code>&lt;button&gt;</code> يكون له حالتان: مضغوط وغير مضغوط. تتطلب هذه الطريقة استخدام ARIA والذي بدوره سيتطلب جافاسكربت لتعمل التقنيات المساعدة بشكل صحيح (يتم تحديث قيم خاصية ARIA عند الضغط باستخدام جافاسكربت). اقرأ مقال Heydon للمزيد من التفاصيل عن هذه الطريقة.
			</li>
			<li>
				تعني هذه الطريقة أن لديك خيارًا واحدًا فقط، وهذا يعني بدوره أنّ زر التبديل له تسمية واحدة مرتبطة فقط، وربما لن يبدو زر "التبديل المزدوج" بعد الآن، إلا إذا:
				<ul>
<li>
						حالات زر التبديل المزدوج (التي تشير إلى تشغيل/إيقاف) سيكون لها نصّا واضحًا يصف الحالة الحالية الفعالة، لذا ستبدو مثل هذا المثال من العرض التجريبي لـScott في مشروع A11y:
					</li>
				</ul>
</li>
		</ul>
</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32860" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic02.png.5b51d65c6c6e6beb42f6623df565019f.png" rel=""><img alt="pic02.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32860" data-unique="xdkb5hfrr" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic02.png.5b51d65c6c6e6beb42f6623df565019f.png"></a>
</p>

<p>
	بالنسبة لاستخدامي لمحوّل المظهر، فهو خيارٌ واضحٌ: بما أنّ المستخدم لديه خيارات (مظلم ومضيء)، أردت استخدام أزرار الانتقاء. لم أكن أريد أن أقول "تشغيل/إيقاف تشغيل الوضع المظلم" إنّما أردت أن أقول "تفعيل الوضع المضيء أو تفعيل الوضع المظلم". سيكون الحل هو HTML وCSS فقط، ولا يتطلب جافاسكربت، وستتم إتاحة إمكانية الوصول بشكلٍ افتراضي.
</p>

<h3>
	تحليل
</h3>

<ul>
<li>
		دَع لديك فكرة واضحة حول كيفية تصميم المكون وماذا يُفترض أن يفعل أو لا يفعل، واجعل الترميز والتصميم يعتمدان على هذه الفكرة.
	</li>
</ul>
<h2>
	فحص الشيفرة
</h2>

<p>
	الآن، وبعد قراءة وفحص المصادر السابقة، قررت أن أرى كيف يقوم الناس بالتبديل. بعد كل ذلك، كنت أعلم أنني سأجد الكثير من الأمثلة لمفاتيح التبديل التي تبدو وتتصرف مثل هذا المثال الحي على <a href="https://codepen.io/" rel="external nofollow">codepen</a>، من الرائع دومًا أن أرى كيف يفعل الآخرون ذلك - ربما أفتقد بعض التقنيات الرائعة التي يمكن أن أتعلمها للتصميم، أو ربما أفتقد بعض المعلومات المهمة عندما يتعلق الأمر بالترميز وقابلية الوصول.
</p>

<p>
	نظرًا لأنني كنت أعمل في codepen على نسختي الخاصة من هذا المفتاح (شاركت العرض التجريبي أدناه)، أظنُّ أنني فحصت مفتاح التبديل الخاص بـcodepen: المفتاح الذي تستعمله لاختيار فيما إذا إذا كنت تريد لتصميمك أن يكون عامًا أو خاصًا.
</p>

<h3>
	تحليل سريع
</h3>

<ul>
<li>
		من المفيد والممتع أن تتعلم من عمل الآخرين بفحص شيفرتهم (سواء ذلك عن طريق أدوات المطور [devtools] أو على codepen).
	</li>
</ul>
<h2>
	مفتاح الخصوصية في Codepen
</h2>

<p>
	يعرض مفتاح التبديل في codepen بعض السلوكيات الغريبة التي لاحظتها سابقًا ولكن لم أشعر أبدًا بالفضول لأقوم بال"تنقيح". يُظهر الفيديو التالي هذا السلوك:
</p>

<p>
	<video controls="" height="240" style="width: 100%;" width="320"><source src="https://d33wubrfki0l68.cloudfront.net/8deb8af8bcf5e1b34bab77660b80ac80305121a2/235ad/videos/codepen-switch-bug.mp4" type="video/mp4"> Your browser does not support the video tag.
	</source></video></p>

<p>
	تجدر الإشارة أولًا إلى أنّني كنت محتارة بشأن هذا المفتاح. دائمًا ما يعطي اللون الأحمر مقابل الأخضر حلقة ردود فعل غريبة. إذا جعلت التصميم خاصًا، سيتحول اللون للأخضر، وجعله عامًا سيجعل اللون أحمر. بالنسبة لي فإنَّ الأخضر يعني أكثر من ذلك "التصميم قابل للوصول من قِبل الأشخاص، إنّه متاح" واللون الأحمر أكثر من ذلك "هذا التصميم مغلق، لا يُسمح للأشخاص بالوصول". ولكن بالنسبة لـcodepen فإن هذه الألوان ترمز إلى أشياء أخرى. وبشكل أكثر تحديدًا يرمز الأحمر إلى "المنطقة العامة = المنطقة الخطرة" أو "احذر هذا التصميم متاح للعامة وهذا غير جيّد". (آسفة لأنّي درامية جدًا، ولكن هذا هادفًا).
</p>

<p>
	ثمّ هناك سلوك الأخطاء المبيّن في الفيديو أعلاه (إذ أنّ النقر على نفس التسمية يغيّر قيمة المفتاح إلى قيمة التسمية الأخرى). كنت فضولية مجددًا لمعرفة سبب ذلك، شغّلتُ أدوات المطور وفحصت الشيفرة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32861" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic03.png.19867041acaa0bd3cb053fd3de0b63f6.png" rel=""><img alt="pic03.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32861" data-unique="fza1qtoz0" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic03.thumb.png.ac59fe48587186ada78fa9d2d441323e.png"></a>
</p>

<p>
	وجدت أنَّ مفتاح codepen هو صندوق تأشير واحد يبدو أنّه يحتوي تسميتين. لذلك عند الضغط على "عام" و"خاص" معًا عدة مرات يؤدي إلى تشغيل وإيقاف تشغيل المفتاح عدة مرات. بكلماتٍ أخرى، هذا هو السبب في أنَّ رد الفعل/ السلوك المرئي للمفتاح لا يُطابق هدف المفتاح أو ما يبدو أنّه يعمل.
</p>

<p>
	كتبت <a href="https://twitter.com/SaraSoueidan/status/1021068702110887937" rel="external nofollow">تغريدةً حول هذا الخطأ</a>، و<a href="https://twitter.com/SaraSoueidan/status/1021068905652121600" rel="external nofollow">سببه المحتمل</a> و<a href="https://twitter.com/SaraSoueidan/status/1021069590628044800" rel="external nofollow">اقترحتُ حلًا بديلًا</a> يُصلح الأمر.
</p>

<p>
	بدأت في الحصول على ردود وآراء من مطورين آخرين، مما أدّى إلى نقاش جيد ومفيد للغاية استمتعت به تمامًا (أحد الجوانب الإيجابية القليلة في تويتر).
</p>

<p>
	بالطبع، كان الإجماع العام هو أنّ المفتاح يحتاج إلى إصلاح. لكن كيفية إصلاحه تعتمد بشكلٍ كبير على ما يريد فريق codepen القيام به:
</p>

<p>
	إذا كان من المفترض أن يكون مفتاح التبديل هو زر تفعيل/تعطيل للخيار "خاص" عندها:
</p>

<ul>
<li>
		هذا يعني أنّ نمط التبديل تشغيل/إيقاف المذكور في القسم السابق أعلاه سيكون الحل المثالي.
	</li>
	<li>
		هذا يعني أنّه سيتم تجاهل التسمية "عام" والاحتفاظ بالتسمية "خاص" فقط، مع إشارة واضحة إلى أنّ المفتاح المجاور لها يعمل على إيقاف الخيار أو تشغيله، وهذا يقودني إلى نقطة أخرى:
		<ul>
<li>
				يجب إمّا أن يتغير التمثيل البصري للمفتاح بالكامل أو يتم تعديله:
			</li>
			<li>
				إذا كان يجب أن يبقى زر المفتاح كما هو بصريًا (أي الحفاظ على سلوك المفتاح المزدوج "نقل هذا التبديل يسارًا ويمينًا")، أقترح إضافة تسميات "تشغيل/إيقاف" له بشكلٍ شبيه لما فعله Scott في عرضه التجريبي مشروع A11y، لأنّه وفقًا لإرشادات الوصول لمحتوى الويب (WCAG)، يجب ألا تستخدم اللون فقط لنقل المعلومات. تحتاج الألوان أيضًا أن يكون لديها تباين كافٍ إذا كنت تستخدمها. ومرةً أخرى، كنت أعيد النظر في ألوان الأحمر والأخضر لأنّها قد تربك شخصًا ما مثلما أربكتني لفترةٍ من الوقت. (اقترح عليّ أحدهم الرمادي والأخضر، لأنّ "إضافة اللون يمكن أن تدلّ بشكلٍ كبيرٍ على الحالة الفعّالة (بدون لون مقابل لون يواجه لونين منفصلين)").
			</li>
		</ul>
</li>
	<li>
		يمكن أن تكون البنية الأساسية والترميز لهذه الحالة (تسمية واحدة فقط):
		<ul>
<li>
				صندوق تأشير، يمكن أن يكون مفعّلًا أو غير مفعّل. أودّ اقتراح استخدام تصاميم صندوق تأشير بسيطة (ربما رائعة) لهذا السلوك والتخلّي عن أسلوب التبديل المزدوج بالكامل.
			</li>
			<li>
				زر &lt;button&gt; مع خاصية <code>aria-pressed</code> (و <code>aria-checked</code> إذا احتجت)، إذ تشير حالة الضغط إلى أنّ التصميم خاص، وحالة عدم الضغط إلى أنّ التصميم غير خاص، أي أنّه عام. سيتغير تصميم الزر في هذه الحالة أيضًا، وقد يتطلّب سلوكه استخدام جافاسكربت لتعديل قيمة خواص ARIA عند الضغط.
			</li>
		</ul>
</li>
</ul>
<p>
	إذا كان من المفترض أن يعرض مفتاح التبديل خيارين بشكلٍ واضح ويمكّنهما: عام وخاص
</p>

<p>
	برأيي، عندها سيكون استخدام زوج من أزرار الانتقاء له معنىً كبير. يعلن زري الانتقاء، كلّ منهما بتسمية خاصة به، عن تقنيات جذابة كخيارين منفصلين يجب على المستخدم اختيار أحدهما، وسهلة الوصول تمامًا عبر لوحة المفاتيح، ولا تتطلب ARIA أو جافاسكربت لتعمل، واستخدم قليلًا من الـCSS لها لتخلق تصميم زر "التبديل المزدوج" إذا أردت (حقيقةً لا أعرف ماذا أسميه بشكلٍ آخر) وستكون قمت بكل العمل. قد يختلف قليلًا الترميز والتصميم لمثل هذا الحل بين المطورين، ولكن جوهر الشيفرة سيكون نفسه.
</p>

<p>
	وهذا سيقودني إلى التجربة الحية…
</p>

<h2>
	مثال حيّ
</h2>

<p>
	هذا تنفيذي لمفتاح تبديل بين خيارين. لقد قمت بإنشاءه ليس كحلّ لمفتاح codepen، لكن ببساطة كمفتاح لتبديل المظهر مضيء/مظلم الذي أستخدمه في حديثي:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="result-iframe " data-src="https://cdpn.io/SaraSoueidan/fullembedgrid/jpBbrq?type=embed&amp;animations=stop-after-5" frameborder="0" id="result-iframe" name="CodePen Preview for Accessible Option(/Toggle) Switch" sandbox="allow-forms allow-modals allow-pointer-lock allow-popups allow-presentation allow-same-origin allow-scripts" scrolling="yes" tabindex="-1" title="CodePen Preview for Accessible Option(/Toggle) Switch" style="height: 450px;" src="https://cdpn.io/SaraSoueidan/fullembedgrid/jpBbrq?type=embed&amp;animations=stop-after-5"></iframe>
</p>

<p>
	سيكون مفتاح التبديل في سياق مجموعة أكبر من عناصر النموذج، لهذا السبب ليس لدي أيّ مجموعة حقول (fieldset) أو وسيلة إيضاح (legend) في العرض التجريبي. وأعلم جيّدًا أنّك قد تعدّل الشيفرة لعدم الحاجة إلى عناصر <code>span</code> إضافية في الترميز وتستخدم عناصر زائفة بدلًا منها، ولكنني على أيّة حال قد اخترت هذه الطريقة، فقط لأنني أريدها. جرّب أن تلعب بالشيفرة وتزيل تعليقات بعض التصاميم (حاول إزالة عناصر <code>span</code> بشكلٍ خاص لتشاهد كيف يبدو مفتاحي بدونها) لتحلل الشيفرة وتمتلك فكرة أفضل عن خياراتي وما الذي كنت أحاول تحقيقه.
</p>

<p>
	أضفت أيضًا تصميمًا للتأكّد من أنّ مستخدمي لوحة المفاتيح يمكنهم رؤية مكان التركيز، إذ أنني غطيت أزرار الانتقاء الافتراضية بعناصر <code>span</code>، ولم يتم تسليط الضوء على التسميات بشكلٍ افتراضي. استخدمت <code>:focus-visible</code> فقط في البداية (مع polyfill) لكنه لم يعمل كما هو متوقع في متصفحي فايرفوكس وسفاري، لذا انتهيت بإضافة <code>:focus</code> مجددًا واستخدمته بدلًا من <code>:focus-visible</code>. وأعلم أيضًا أنّ تصميم التركيز ليس جميلًا جدًا، لكن هذا العرض التجريبي هو مجرد دليل للمفهوم لذا لا يحتاج أن يكون جميلًا بشكلٍ ملفت للنظر.
</p>

<p>
	إذا كنت ترغب في مشاهدة عرض تجريبي آخر يستخدم أيضًا أزرار انتقاء لكن ينفذّها بطريقةٍ مختلفةٍ، بدون عناصر <code>span</code>واستخدام عناصر زائفة، راجع هذا التصميم على codepen لصديقي Scott O’hara:
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="result-iframe " data-src="https://cdpn.io/scottohara/fullembedgrid/zLZwNv?type=embed&amp;animations=stop-after-5" frameborder="0" id="result-iframe" name="CodePen Preview for Radio Toggle Switch" sandbox="allow-forms allow-modals allow-pointer-lock allow-popups allow-presentation allow-same-origin allow-scripts" scrolling="yes" tabindex="-1" title="CodePen Preview for Radio Toggle Switch" style="height: 200px;" src="https://cdpn.io/scottohara/fullembedgrid/zLZwNv?type=embed&amp;animations=stop-after-5"></iframe>
</p>

<h2>
	كلمات أخيرة
</h2>

<p>
	دعني أبدأ بالقول أنني قد أكون مخطئة. أعلم أنّ مستخدمي codepen قد يريدون شيئًا آخر مختلف تمامًا، أو يفكرون في شيء ما مختلف تمامًا. لذلك لا تهدف هذه المقالة إلى إعادة تصميم زر التبديل في codepen، إنّما تقدم توثيقًا لبحثي وتدريبي على التفكير أثناء العمل على إنشاء زر التبديل الخاص بي لحديثي. سأحتاج أن أقوم بالمزيد من الأبحاث عندما يحين الوقت لمتابعة عملي على ورشة العمل الجديدة الخاصة بي، وقد تتغير الأمور، وأعلم أنني سأتعلّم وأعرف المزيد عندما أنشئ مفتاحي التالي. لكن، حتى ذلك الحين، أعلم أنني حصلت على منشور المدونة هذا للإشارة إلى بعض الأفكار والآراء التي دارت في ذهني عندما اتخذت الخطوة الأولى لذلك.
</p>

<p>
	أتمنى أن تجد شيئًا مفيدًا بقراءتك لهذا المقال. إذا حصل ذلك بالفعل، فشكرًا لقراءتك.
</p>

<p>
	شكرًا.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.sarasoueidan.com/blog/toggle-switch-design/" rel="external nofollow">On Designing and Building Toggle Switches</a> لصاحبته Sara Soueidan
</p>
]]></description><guid isPermaLink="false">765</guid><pubDate>Tue, 26 Nov 2019 13:07:10 +0000</pubDate></item><item><title>&#x625;&#x639;&#x62F;&#x627;&#x62F; &#x635;&#x648;&#x631; &#x645;&#x62A;&#x62C;&#x627;&#x648;&#x628;&#x629;</title><link>https://academy.hsoub.com/programming/html/%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%B5%D9%88%D8%B1-%D9%85%D8%AA%D8%AC%D8%A7%D9%88%D8%A8%D8%A9-r687/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_06/5cfcfe8849884_.png.a2037d5cd4f80291ad1b0a67dabd1774.png" /></p>

<p>
	المرة الأولى التي صنعت فيها صورة متجاوبة (responsive)، كانت بسيطة مثل ترميز هذه الأسطر الأربعة.
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8405_6" style="">
<span class="pln">img </span><span class="pun">{</span><span class="pln">
  max</span><span class="pun">-</span><span class="pln">width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">100</span><span class="pun">%;</span><span class="pln">
  height </span><span class="kwd">auto</span><span class="pun">;</span><span class="pln"> </span><span class="com">/* default */</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	رغم أن ذلك كان مناسبًا لي كمطور، إلا أنه لم يكن الأفضل للمستخدمين. ماذا يحدث إذا كانت الصورة في الخاصية <code>src</code> ثقيلة؟ على الأجهزة المتطورة (مثل الجهاز الذي يحتوي على ذاكرة وصول عشوائي بسعة 16 جيجابايت)، قد تحدث مشكلة بسيطة في الأداء أو لا تحدث، ولكن ماذا عن الأجهزة متدنية الأداء؟ إنها قضية أخرى.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="29977" href="https://academy.hsoub.com/uploads/monthly_2019_06/01.png.3a28cc302c85f101dedecbdf2e43443e.png" rel=""><img alt="01.png" class="ipsImage ipsImage_thumbnailed" data-fileid="29977" data-unique="xf4271hvl" src="https://academy.hsoub.com/uploads/monthly_2019_06/01.thumb.png.28c81bbe09440dde15094d3940458784.png"></a>
</p>

<p>
	الرسم التوضيحي أعلاه غير مفصل بما فيه الكفاية. أنا من نيجيريا، وإذا كان منتجك يعمل في إفريقيا فعليك ألا تنظر إلى ذلك الرسم، انظر إلى هذا الرسم البياني بدلًا من ذلك.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="29978" href="https://academy.hsoub.com/uploads/monthly_2019_06/02.png.bb69c745f2de056d7dbba317c486c741.png" rel=""><img alt="02.png" class="ipsImage ipsImage_thumbnailed" data-fileid="29978" data-unique="od86bsgam" src="https://academy.hsoub.com/uploads/monthly_2019_06/02.thumb.png.f975961d2f70976bfd7209a135d0c93b.png"></a>
</p>

<p>
	في الوقت الحاضر، iPhone الأقل سعرًا يُباع في المتوسط بسعر 300 دولار أمريكي، ولا يستطيع المواطن الأفريقي العادي تحمل تكاليفه على الرغم من أن iPhone يمثل عتبة لقياس الأجهزة السريعة.
</p>

<p>
	هذا هو كل تحليل الأعمال الذي تحتاجه لفهم أن نطاق CSS لا يقلل من الصور المتجاوبة. على حال، هل تعرف حقًا ما هي الصور؟
</p>

<h2 id="-">
	الفروق الدقيقة في الصور
</h2>

<p>
	تُعدُّ الصور جاذبة للمستخدمين ولكنها تمثل تحديًا صعبًا للمطورين حيث يجب عليهم مراعاة النقاط التالية:
</p>

<ul>
<li>
		الشكل
	</li>
	<li>
		حجم القرص
	</li>
	<li>
		تجسيد البعد (عرض المخطط والارتفاع في المتصفح)
	</li>
	<li>
		الأبعاد الأصلية (العرض والارتفاع الأصلي)
	</li>
	<li>
		نسبة العرض إلى الارتفاع
	</li>
</ul>
<p>
	لذا، كيف نختار المعاملات الصحيحة ونطبقها بمهارة لتقديم تجربة مثالية لجمهور المستخدمين؟ تعتمد الإجابة بدورها، على إجابات هذه الأسئلة:
</p>

<ul>
<li>
		هل الصور التي تم إنشاؤها ديناميكيًا بواسطة المستخدم أم بشكل ثابت بواسطة فريق تصميم؟
	</li>
	<li>
		إذا تم تغيير عرض الصورة وارتفاعها بشكل غير متناسب، فهل سيؤثر ذلك على جودة الصورة؟
	</li>
	<li>
		هل يتم عرض جميع الصور عند تقديمها بنفس العرض والارتفاع؟ هل يجب أن يكون لديهم نسبة عرض إلى ارتفاع محددة أو نسبة مختلفة تمامًا؟ ما الذي يجب مراعاته عند تقديم الصور بطُرق عرض مختلفة؟
	</li>
</ul>
<p>
	دون إجاباتك على هذه الأسئلة فهي لن تساعدك فقط في فهم صورك ومصادرها ومتطلباتها الفنية وما إلى ذلك، ولكن ستمكنك أيضًا من اتخاذ الخيارات الصحيحة في توفيرها وعرضها على المستخدم النهائي.
</p>

<h2 id="-">
	الاستراتيجيات المشروطة لتوصيل الصور وعرضها على المستخدم
</h2>

<p>
	تطور تسليم الصور من إضافة بسيطة لعناوين URL إلى خاصية src الخاصة بالصور إلى سيناريوهات معقدة. قبل الخوض فيها، دعنا نتحدث عن الخيارات المتعددة لتقديم الصور بحيث يمكنك ابتكار إستراتيجية حول كيفية تسليم الصور خاصتك وتصييرها وعرضها على المستخدم النهائي.
</p>

<p>
	أولاً، حدِّد مصادر الصور، إذ يمكن بهذه الطريقة تقليل عدد حالات الغموض واللبس ويمكنك معالجة الصور بأكبر قدر ممكن من الكفاءة.
</p>

<p>
	بشكل عام، الصور إما أن تكون:
</p>

<ul>
<li>
		ديناميكية: يتم تحميل الصور الديناميكية من قبل المستخدمين، بعد أن تم إنشاؤها بواسطة أحداث أخرى في النظام.
	</li>
	<li>
		ثابتة: يتم إنشاء هذه الصور من قبل مصور، أو مصمم، أو أنت (المطور) لموقع الويب.
	</li>
</ul>
<p>
	دعنا نتعرف إلى إستراتيجية كلًا هذين النوعين من الصور.
</p>

<h3 id="-">
	استراتيجية الصور الديناميكية
</h3>

<p>
	الصور الثابتة سهلة الاستخدام إلى حد ما؛ من ناحية أخرى، الصور الديناميكية معقدة وعرضةً للمشاكل. ما الذي يمكن فعله للتخفيف من حدة طبيعتها الديناميكية وجعلها أكثر قابلية للتنبؤ بها مثل الصور الثابتة؟ هناك شيئان هما: التحقق من الصحة (validation) والاقتصاص الذكي للصور (intelligent cropping).
</p>

<h4 id="-">
	التحقق من الصحة
</h4>

<p>
	ضع بعض القواعد للمستخدمين حول ما هو مقبول وما هو غير مقبول. في الوقت الحاضر يمكننا التحقق من صحة جميع خصائص الصورة، هذه الخصائص تتلخص بالنقاط التالية:
</p>

<ul>
<li>
		الصيغة
	</li>
	<li>
		حجم القرص
	</li>
	<li>
		الأبعاد
	</li>
	<li>
		نسبة العرض إلى الارتفاع
	</li>
</ul>
<p>
	ملاحظة: يتم تحديد حجم الصورة أثناء التصيير (rendering)، وبالتالي لا يتم التحقق من صحة الصور من جانبنا.
</p>

<p>
	بعد التحقق من الصحة، ستظهر مجموعة يمكن التنبؤ بها من الصور التي يسهل استخدامها.
</p>

<h4 id="-">
	الاقتصاص الذكي للصور
</h4>

<p>
	تتمثل الاستراتيجية الأخرى للتعامل مع الصور الديناميكية في اقتصاصها بذكاء لتجنب حذف محتوى مهم وإعادة التركيز على المحتوى الأساسي. هذا صعب ومع ذلك يمكنك الاستفادة من الذكاء الاصطناعي الذي توفره أدوات مفتوحة المصدر أو شركات SaaS التي تتخصص في إدارة الصور.
</p>

<p>
	بمجرد أن يتم الانتهاء من تنفيذ هذه الإستراتيجية للصور الديناميكية، أنشئ جدول قواعد به جميع خيارات التخطيط للصور. أدناه مثال يجدر بك النظر في تحليلاته لتحديد أهم الأجهزة وأحجام الإطار المعروض (viewport).
</p>

<p>
	<img alt="03.png" class="ipsImage ipsImage_thumbnailed" data-fileid="29971" data-unique="8l8qjn9gy" src="https://academy.hsoub.com/uploads/monthly_2019_06/03.png.3275ae550439f6ab3077e72b1f70841b.png"></p>

<h2 id="-">
	الحد الأدنى (شبه الأمثل)
</h2>

<p>
	الآن، ضع جانبًا تعقيدات الاستجابة وانظر للمثال التالي - شيفرة HTML بسيطة مع CSS ذا أقصى عرض. تعرض الشيفرة التالية بعض الصور:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8405_8" style="">
<span class="tag">&lt;main&gt;</span><span class="pln">
  </span><span class="tag">&lt;figure&gt;</span><span class="pln">
    </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://res.cloudinary.com/...w700/ps4-slim.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"PS4 Slim"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;/figure&gt;</span><span class="pln">

  </span><span class="tag">&lt;figure&gt;</span><span class="pln">
    </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://res.cloudinary.com/...w700/x-box-one-s.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"X Box One S"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;/figure&gt;</span><span class="pln">

  </span><span class="com">&lt;!-- More images --&gt;</span><span class="pln">

  </span><span class="tag">&lt;figure&gt;</span><span class="pln">
    </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://res.cloudinary.com/...w700/tv.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Tv"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;/figure&gt;</span><span class="pln">
</span><span class="tag">&lt;/main&gt;</span></pre>

<p>
	<strong>ملاحظة</strong>: علامة الحذف (…) التي تمثل استراتيجية الاقتصاص في عنوان URL الخاص بالصورة أو المجلد. يوجد الكثير من التفاصيل التي يجب تضمينها، لكن الاقتصاص للتركيز هو ما يهم الآن. للحصول على الإصدار الكامل، انظر مثال CodePen أدناه.
</p>

<p>
	هذه هي أقصر شيفرة CSS موجودة على الإنترنت تجعل الصور سريعة الاستجابة:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8405_12" style="">
<span class="com">/* الحاوية الأب */</span><span class="pln">
main </span><span class="pun">{</span><span class="pln">
  display</span><span class="pun">:</span><span class="pln"> grid</span><span class="pun">;</span><span class="pln">
  grid</span><span class="pun">-</span><span class="kwd">template</span><span class="pun">-</span><span class="pln">columns</span><span class="pun">:</span><span class="pln"> repeat</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">-</span><span class="pln">fill</span><span class="pun">,</span><span class="pln"> minmax</span><span class="pun">(</span><span class="lit">300px</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1fr</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
 
img </span><span class="pun">{</span><span class="pln">
  max</span><span class="pun">-</span><span class="pln">width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">100</span><span class="pun">%;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا لم يكن للصور عرض وارتفاع متساويان، بدلِّ <code>object-fit</code> مكان <code>max-width</code> واضبط القيمة إلى <code>cover</code>.
</p>

<p>
	<img alt="s_FC2DE27452E05E045139FF003894009220F807" src="https://academy.hsoub.com/uploads/imageproxy/s_FC2DE27452E05E045139FF003894009220F80784C1D613CC87FFB9D39C36AD83_1548841978428_Jan-30-201913-52-23.gif.7c4f17cc6d6ed59485290c70904d8d55.gif"></p>

<p>
	يشرح منشور مدونة Jo Franchetti عن <a href="https://medium.com/samsung-internet-dev/common-responsive-layouts-with-css-grid-and-some-without-245a862f48df" rel="external nofollow">التنسيقات الشائعة المتجاوبة مع تخطيط CSS</a> كيف أن قيمة <code>grid-template-columns</code> تجعل التخطيط بأكمله متجاوبًا.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="465" id="cp_embed_vbXWEM" name="cp_embed_1" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 100%; min-height: 350px;" title="Grid Gallery" src="https://codepen.io/codebeast/embed/vbXWEM?height=465&amp;theme-id=1&amp;default-tab=html%2Cresult&amp;user=codebeast&amp;slug-hash=vbXWEM&amp;pen-title=Grid%20Gallery&amp;name=cp_embed_1"></iframe>
</p>

<p>
	ما سبق ليس ما نبحث عنه، لأن:
</p>

<ul>
<li>
		حجم الصورة ووزنها متماثلان في كل من الأجهزة المتطورة وغير المتطورة.
	</li>
	<li>
		قد نرغب في أن نكون أكثر صرامة مع عرض الصورة بدلًا من تعيينها على 250 ويتغير حجمها فيما بعد.
	</li>
</ul>
<p>
	حسنًا، يغطي هذا القسم «الحد الأدنى»، لذلك هذا كل شيء.
</p>

<h2 id="-">
	اختلافات التخطيط
</h2>

<p>
	أسوأ شيء يمكن أن يحدث لتخطيط الصور هو سوء تدبير وإدارة التوقعات. نظرًا لأن الصور قد يكون لها أبعاد مختلفة (العرض والارتفاع)، يجب أن نحدِّد كيفية تقديم وعرض هذه الصور.
</p>

<p>
	هل يجب علينا اقتصاص جميع الصور بذكاء لتصبح ذات أبعاد منتظمة؟ هل يجب أن نحتفظ بنسبة العرض إلى الارتفاع لجهة العرض ونغير النسبة لشيء آخر؟ الخيار لنا.
</p>

<p>
	في حالة وجود صور في شبكة، مثل تلك الموجودة في المثال أعلاه مع نسب أبعاد مختلفة، يمكننا تطبيق تقنية الاتجاه الفني (art direction) لتصيير وعرض الصور، إذ يمكن أن يساعد في تحقيق شيء مثل هذا:
</p>

<p>
	<img alt="planning-rwd-images.gif" src="https://academy.hsoub.com/uploads/imageproxy/planning-rwd-images.gif.58685114e2d1d87a9e4d3bbce4dc3772.gif"></p>

<p>
	انظر المثال أدناه:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8405_14" style="">
<span class="tag">&lt;main&gt;</span><span class="pln">
  </span><span class="tag">&lt;figure&gt;</span><span class="pln">
    </span><span class="tag">&lt;picture&gt;</span><span class="pln">
      </span><span class="tag">&lt;source</span><span class="pln"> </span><span class="atn">media</span><span class="pun">=</span><span class="atv">"(min-width: 900px)"</span><span class="pln"> </span><span class="atn">srcset</span><span class="pun">=</span><span class="atv">"https://res.cloudinary.com/.../c_fill,g_auto,h_1400,w_700/camera-lens.jpg"</span><span class="tag">&gt;</span><span class="pln">      
      </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://res.cloudinary.com/.../c_fill,g_auto,h_700,w_700/camera-lens.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"Camera lens"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;/picture&gt;</span><span class="pln">
  </span><span class="tag">&lt;/figure&gt;</span><span class="pln">

  </span><span class="tag">&lt;figure&gt;</span><span class="pln">
    </span><span class="tag">&lt;picture&gt;</span><span class="pln">
      </span><span class="tag">&lt;source</span><span class="pln"> </span><span class="atn">media</span><span class="pun">=</span><span class="atv">"(min-width: 700px)"</span><span class="pln"> </span><span class="atn">srcset</span><span class="pun">=</span><span class="atv">"https://res.cloudinary.com/.../c_fill,g_auto,h_1000,w_1000/ps4-pro.jpg"</span><span class="tag">&gt;&lt;/source&gt;</span><span class="pln">
    </span><span class="tag">&lt;/picture&gt;</span><span class="pln">
    </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://res.cloudinary.com/.../c_fill,g_auto,h_700,w_700/ps4-pro.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"PS4 Pro"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;/figure&gt;</span><span class="pln">
</span><span class="tag">&lt;/main&gt;</span></pre>

<p>
	بدلاً من تقديم صورة واحدة بعرض 700 بكسل، نعرضها بشكل 700 بكسل × 700 بكسل فقط في حال إذا تجاوز عرض منفذ العرض 700 بكسل. إذا كان حجم العرض أكبر، فسيحدث التالي:
</p>

<ul>
<li>
		يتم تصيير صور عدسة الكاميرا كصورة عرضية تبلغ 700 بكسل وعرضها 1000 بكسل في الارتفاع (700 بكسل × 1000 بكسل).
	</li>
	<li>
		يتم عرض صور PS4 Pro بدقة 1000 بكسل × 1000 بكسل.
	</li>
</ul>
<h2 id="-art-direction-">
	الاتجاه الفني (Art direction)
</h2>

<p>
	قد نحذف المحتوى الأساسي عن غير قصد عن طريق اقتصاص الصور لجعلها أكثر استجابة. كما ذُكر سابقًا، يمكن أن تساعد أدوات الذكاء الصنعي AI مفتوحة المصدر على الاقتصاص بذكاء وإعادة التركيز على الكائنات الأساسية للصور، بالإضافة إلى ذلك يعد منشور Nadav Soferman عن الاقتصاص الذكي بمثابة دليل إرشادي مفيد.
</p>

<h3 id="-strict-grid-and-spanning-">
	شبكة دقيقة وممتدة (Strict grid and spanning)
</h3>

<p>
	المثال الأول على الصور سريعة الاستجابة في هذا المقال هو مثال رائع. عند عرض 300 بكسل كحد أدنى، تتدفق عناصر الشبكة تلقائيًا إلى مكانها وفقًا لعرض الإطار المعروض من النافذة (viewport).
</p>

<p>
	من ناحية أخرى، قد نرغب في تطبيق قاعدة أكثر صرامة على عناصر الشبكة بناءً على مواصفات التصميم. تكون استعلامات الوسائط في هذه الحالة مفيدة.
</p>

<p>
	بدلاً من ذلك، يمكننا الاستفادة من قدرة الشبكة الممتدة <code>grid-span</code> لإنشاء عناصر شبكية ذات طول وعرض مختلف.
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8405_16" style="">
<span class="lit">@media</span><span class="pun">(</span><span class="pln">min</span><span class="pun">-</span><span class="pln">width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">700px</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  main </span><span class="pun">{</span><span class="pln">
    display</span><span class="pun">:</span><span class="pln"> grid</span><span class="pun">;</span><span class="pln">
    grid</span><span class="pun">-</span><span class="kwd">template</span><span class="pun">-</span><span class="pln">columns</span><span class="pun">:</span><span class="pln"> repeat</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1fr</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="lit">@media</span><span class="pun">(</span><span class="pln">min</span><span class="pun">-</span><span class="pln">width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">900px</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  main </span><span class="pun">{</span><span class="pln">
    display</span><span class="pun">:</span><span class="pln"> grid</span><span class="pun">;</span><span class="pln">
    grid</span><span class="pun">-</span><span class="kwd">template</span><span class="pun">-</span><span class="pln">columns</span><span class="pun">:</span><span class="pln"> repeat</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1fr</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  figure</span><span class="pun">:</span><span class="pln">nth</span><span class="pun">-</span><span class="pln">child</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    grid</span><span class="pun">-</span><span class="pln">row</span><span class="pun">:</span><span class="pln"> span </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  figure</span><span class="pun">:</span><span class="pln">nth</span><span class="pun">-</span><span class="pln">child</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    grid</span><span class="pun">-</span><span class="pln">column</span><span class="pun">:</span><span class="pln"> span </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    grid</span><span class="pun">-</span><span class="pln">row</span><span class="pun">:</span><span class="pln"> span </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بالنسبة لصورة تبلغ مساحتها 1000 بكسل × 1000 بكسل على منفذ عرض واسع، يمكننا توسيعها لالتقاط خليتين من الشبكات في كل من الصف والعمود. يمكن أن تأخذ الصورة التي تتغير إلى اتجاه عمودي (700 بكسل × 1000 بكسل) على حجم أوسع من الإطار المعروض خليتين على التوالي.
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="465" id="cp_embed_exdMjj" name="cp_embed_2" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 100%; min-height: 350px;" title="Grid Gallery [Art Direction]" src="https://codepen.io/codebeast/embed/exdMjj?height=465&amp;theme-id=1&amp;default-tab=html%2Cresult&amp;user=codebeast&amp;slug-hash=exdMjj&amp;pen-title=Grid%20Gallery%20%5BArt%20Direction%5D&amp;name=cp_embed_2"></iframe>
</p>

<h2>
	التحسين التصاعدي (Progressive optimization)
</h2>

<p>
	التحسين غير المدروس ليس ذو فائدة كما لو أنه لم يحصل أي تحسين. لا تركز على التحسين دون تحديد القياسات المناسبة، ولا تقوم به إذا لم يتم دعمه بالبيانات اللازمة.
</p>

<p>
	ومع ذلك، يوجد مجال واسع للتحسين في الأمثلة المذكورة أعلاه. لقد بدأنا بالحد الأدنى، وأظهرنا لك بعض الحيل الرائعة، السؤال التالي الذي يجب طرحه هو: «إذا كانت الصفحة تحتوي على 20-100 صورة، فما مدى جودة تجربة المستخدم؟»
</p>

<p>
	فيما يلي الإجابة، يجب أن نضمن أنه في حالة وجود العديد من الصور للعرض أن يكون حجمها يناسب الجهاز الذي يعرضها. لتحقيق ذلك، نحتاج إلى تحديد عناوين URL لعدة صور بدلًا من صورة واحدة. سيختار المتصفح الصورة الأنسب لعرض الجهاز منها (الصورة ذات العرض الأمثل) وفقًا للمعايير. وتسمى هذه التقنية تبديل الدقة (resolution switching) في الصور سريعة الاستجابة. انظر مثال هذه الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8405_18" style="">
<span class="tag">&lt;img</span><span class="pln"> 
  </span><span class="atn">srcset</span><span class="pun">=</span><span class="atv">"https://res.cloudinary.com/.../h_300,w_300/v1548054527/ps4.jpg 300w,
          https://res.cloudinary.com/.../h_700,w_700/v1548054527/ps4.jpg 700w,
          https://res.cloudinary.com/.../h_1000,w_1000/v1548054527/ps4.jpg 1000w"</span><span class="pln">
             
  </span><span class="atn">sizes</span><span class="pun">=</span><span class="atv">"(max-width: 700px) 100vw, (max-width: 900px) 50vw, 33vw"</span><span class="pln">
  </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://res.cloudinary.com/.../h_700,w_700/v1548054527/ps4.jpg 700w"</span><span class="pln">
  </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"PS4 Slim"</span><span class="tag">&gt;</span></pre>

<p>
	تشرح تغريدة هاري روبرتس بشكل حدسي ما يحدث:
</p>

<p>
	<img alt="06.png" class="ipsImage ipsImage_thumbnailed" data-fileid="29974" data-unique="s9ghcyf1u" src="https://academy.hsoub.com/uploads/monthly_2019_06/06.png.6e62b89d2bd7aaeb324bb61b10eeffb6.png"></p>

<p>
	عندما جربت تقنية تبديل الدقة لأول مرة، شعرت بالارتباك وغردت ب:
</p>

<p>
	<img alt="07.png" class="ipsImage ipsImage_thumbnailed" data-fileid="29975" data-unique="gdm1jdbwz" src="https://academy.hsoub.com/uploads/monthly_2019_06/07.png.3636eab45cdabe4303eebc35bffc6aa0.png"></p>

<p>
	رفعت القبعة إلى جيسون جريجسبي للتوضيح الذي أدلى به.
</p>

<p>
	بفضل تقنية تبديل الدقة، إذا تم تغيير عرض نافذة المتصفح، فإنه يقوم بتنزيل الصورة الصحيحة المناسبة لحجم الإطار المعروض آنذاك من النافذة؛ وبالتالي، تُستخدَم الصور الصغيرة للهواتف الصغيرة (مناسبة لوحدة المعالجة المركزية وذاكرة الوصول العشوائي) والصور الأكبر لعرض نافذة أكبر.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="29979" href="https://academy.hsoub.com/uploads/monthly_2019_06/08.png.6778a0f3b0e5a5de4cdb087554a76a28.png" rel=""><img alt="08.png" class="ipsImage ipsImage_thumbnailed" data-fileid="29979" data-unique="lzy4rwhni" src="https://academy.hsoub.com/uploads/monthly_2019_06/08.thumb.png.79155110a9d561d37c24371bb8f52588.png"></a>
</p>

<p>
	يوضح الجدول أعلاه أن المتصفح يقوم بتنزيل نفس الصورة (المستطيل الأزرق) بأحجام مختلفة للقرص (المستطيل الأحمر).
</p>

<p>
	<iframe allowfullscreen="true" allowpaymentrequest="true" allowtransparency="true" class="cp_embed_iframe " frameborder="0" height="465" id="cp_embed_wNodJR" name="cp_embed_3" scrolling="no" style="width: 100%; overflow: hidden; display: block; height: 100%; min-height: 350px;" title="Grid Gallery [Optimized]" src="https://codepen.io/codebeast/embed/wNodJR?height=465&amp;theme-id=1&amp;default-tab=html%2Cresult&amp;user=codebeast&amp;slug-hash=wNodJR&amp;pen-title=Grid%20Gallery%20%5BOptimized%5D&amp;name=cp_embed_3"></iframe>
</p>

<p>
	يعد تطبيق <a href="https://www.responsivebreakpoints.com/" rel="external nofollow">Respp Image Breakpoints Generator</a> من Cloudinary المجاني والمفتوح المصدر مفيدًا للغاية في تكييف صور موقع الويب مع أحجام شاشات متعددة. ومع ذلك في كثير من الحالات، سيكون إعدادات <code>srcset</code> و <code>sizes</code> وحدها كافية.
</p>

<h2 id="-">
	الخلاصة
</h2>

<p>
	تهدف هذه المقالة إلى توفير إرشادات بسيطة وفعالة لإعداد صور وتخطيطات سريعة الاستجابة في ضوء العديد من الخيارات المتاحة وأحيانًا المربكة. تعرّف على CSS Grid والاتجاه الفني (Art Direction) وتبديل الدقة (Resolution Switching) وستكون مبدعًا في وقت قصير في مجال الصور المتجاوب. استمر بالتعلم!
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://css-tricks.com/planning-for-responsive-images/" rel="external nofollow">Planning for Responsive Images</a> لصاحبه Chris Nwamba
</p>
]]></description><guid isPermaLink="false">687</guid><pubDate>Sun, 09 Jun 2019 14:27:36 +0000</pubDate></item><item><title>&#x627;&#x644;&#x635;&#x648;&#x631; &#x627;&#x644;&#x645;&#x64F;&#x62A;&#x62C;&#x627;&#x648;&#x628;&#x629; Responsive Images</title><link>https://academy.hsoub.com/programming/html/%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D8%A7%D9%84%D9%85%D9%8F%D8%AA%D8%AC%D8%A7%D9%88%D8%A8%D8%A9-responsive-images-r652/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_01/responsive-img.png.9fcce57d55177f7c8925c998ca9f59f4.png" /></p>

<p>
	استُخدم وسم img لتزويد صفحات الويب بالصور، التي تضفي للموقع المزيد من التألق. وقد كان هذا الوسم مفيدًا وغير معقد الاستخدام، إذ يقوم وعبر الرابط المُمرَّر في الصفة src الملحقة بالـ img بطلب ملف الصورة، كما أُضيفت بعض التقنيات المساعدة للحالات البديلة التي لاتظهر فيها الصورة بالشكل الافتراضي، وبالتالي نستنتج أن وسم img يمتاز بالسرعة، الفعالية والسلاسة.
</p>

<p>
	لذلك أودّ التنبيه بأن هذه المقالة لم تأت للتقليل من أهمية وسم img ، وإنّما لإبراز الطرق الجديدة في استخدامها مع تصميم الويب المتجاوب Responsive Web Design (اختصارًا هو RWD).
</p>

<p>
	شهد تصميم صفحات الويب الكثير من المنافسة في السنوات السابقة، حيث كانت متصفحات الويب تعمل على تحسين أداء عرض الصور، من خلال تحسين التعامل مع الوسم الخاص بالصور img، والتي تمتاز بالوثوقية ولكن أيضًا قابليتها الضعيفة للتغيير.
</p>

<p>
	يمتاز تصميم الويب المُتجاوب RWD بأنه يعمل على بناء صفحات ويب مُتجاوبة مع أي طريقة عرض، وهي ميزة جميلة جدًا، ولكن الميزة الأكبر هي سعيه لإجياد تقنيات يمكنها التكيُّف مع أجهزة العرض المجهولة التي تظهر أمامها، ومحاولة إيجاد طريقة عرض جذابة تشابها، وسنختصر ذلك بالقول أن RWD يمتاز بالمرونة وأنه غير قابل للتنبؤ.
</p>

<p>
	من المهم هنا وقبل أن أبدأ بالتفصيل في موضوع الصور المُتجاوبة أن ألفت انتباهكم إلى أن صفحات الويب التي نفتحها عبر متصفحات الويب الموجودة في الأجهزة الخلوية، أي تلك الروابط التي تحوي على الحرف m متبوعًا بنقطة (ونسميها اختصارًا مواقع m-dot)، تطبّق الكثير من أفكار التصميم المتجاوب RWD، ولكنها لاتندرج تحت اسمه، إذ أنها تستخدم طرق أخرى تكيّف من خلالها البيانات الأساسية (الأصول) المتوافرة في صفحة الويب لتناسب الجهاز الذي تُعرض عليه وهذا مانسميه tailored assets.
</p>

<h2>
	تكييف الأصول Tailored Assets
</h2>

<p>
	بمجرد إضافة الإعداد max-width: 100%  ضمن ملف CSS، ستظهر الصور بالشكل المناسب لشاشة العرض viewport، فمثلًا إذا كان لدينا صورة بعرض 300 بكسل ونريد عرضها على شاشة بعرض 200 بكسل فستُكبّر الصورة لتتناسب معها، والعكس أيضًا صحيح ففي حال كان العرض على شاشة بحجم صغير فستُصغّر الصورة للحجم المناسب، وهذا يعني هدر كبير في كلفة نقل الصورة، وذلك لأنه ستُنقل الصورة من مصدرها بحجمها الأصلي ثم ستُصَغّر عند العرض.
</p>

<p>
	أي أن عرض الصور عالية الدقة high resolution على شاشات منخفضة الدقة low resolution، يتسبب دومًا في كلفة عالية في عرض النطاق bandwidth cost بدون فائدة تعود على المستخدم من نقل هذه الحزم الكبيرة، بالإضافة إلى وقت أطول لمعالجة هذه البيانات ثم إظهارها.
</p>

<p>
	وقد كانت عملية النقل تتم بهذه الطريقة حتى في الأيام الأولى لاستخدام تصميم الويب المتجاوب RWD، لذلك كان من الشائع عرض أو إخفاء كتلة كاملة من المحتوى بالاعتماد على حجم وطريقة العرض viewport، ولكن هذه الطريقة أصبحت أقل شيوعًا.
</p>

<p>
	لكن للوسم img اعتبارات خاصة في عملية الإظهار بسبب خصوصية المحتوى الذي يحمله، وذلك لأن طريقة العمل في الويب هي تحليل وترجمة HTML كاملًا ثم تحليل CSS. وبما أن وسم img هو تابع للغة HTML ،ستُحمّل دومًا الصورة بحجمها الأصلي دون أي إمكانية لمعرفة حجم العرض المطلوب حتى لو استخدمنا السطر display:none في تعريف الوسم img أو القالب container الذي يحوي هذا الوسم، أي غالبًا سيكون هناك ضياع في عرض النطاق bandwidth  من دون أي فائدة تعود على المستخدم.
</p>

<h2>
	المحاولات الأولى
</h2>

<p>
	كان انتشار مواقع m-dot في عام 2011 واسعًا على اعتباره أفضل حل عملي لعرض مواقع الويب على الأجهزة الخلوية، ولكن ظهر تصُّور في تلك المرحلة بأن استخدام التصميم المتجاوب قد يكون أيضًا حلًا عمليًا لبناء المناسبة لعرض الموقع على جميع أحجام الشاشات، وقد كانت مجرد فكرة صعبة التنفيذ إلى أن استُخدمت في إعادة تصميم موقع Globe، فانتشرت طريقة استخدام تصميم الويب المتجاوب RWD في المواقع الإخبارية الضخمة.
</p>

<p>
	كما كانت هناك محاولات لتطوير نقل صورة كبيرة للشاشات الكبيرة، وذلك من خلال الفكرة التي طُرحت بإمكانية أن تكون الصورة بحجم شاشة الموبايل مع الاحتفاظ بالصيغة الأساسية format للصورة الأصلية ثم نكبرها في حال كانت شاشة المستخدم أكبر، وبهذه الطريقة لن يكون عرض الصورة بنفس الجودة ولكننا حافظنا على فكرة عرض الصور المتجاوبة.
</p>

<p>
	أما الطريقة التقنية لتنفيذ هذه الفكرة فهي من خلال الحصول على عرض الشاشة باستخدام الجافا سكربت في قسم head الموجود في المستند، ثم نقل المعلومات إلى الخادم في الوقت المناسب وونؤجّل طلب الحصول على الصور إلى أسفل الصفحة، ثم وفي الوقت الذي تقوم به الجافا سكربت بتنفيذ الطلبات الموجودة في قسم body نكون قد أعددنا ملف تعريف الارتباط وحفظنا حجم شاشة العرض لدى المستخدم فيه وبهذا يمكن استخدام هذه المعلومات في نفس طلب تحميل الصورة من خلال الوسم img حيث تتم قراءة التعليمات المرفقة بملف تعريف الارتباط وتحديد ماهية البيانات التي يجب إرسالها في الرد.
</p>

<p>
	وقد كانت تعمل هذه الطريقة بشكل جيد ولكن سرعان ما استولى عليها المخترقون hackers وقاموا بتحليل السلوك بين الطلب والرد وفهموا محتواه جيدًا رغم أنه لم يكن معرَّفًا صراحة في أي من المواصفات المذكورة، وبالتالي لم يعد هناك جدوى من استخدام هذه الطريقة.
</p>

<p>
	تمّ بعد ذلك تطوير فكرة الجلب المسبق prefetching كما سميت أيضًا speculative preparsing، وقد كانت فكرة ضخمة جعلت المتصفحات تعمل بشكل أسرع وذلك لأن الفكرة في أساسيها هي أن يبدأ المتصفح بطلب البيانات الأساسية حتى قبل أن يبدأ عرض الصفحة، وبالتالي ستكون البيانات أقرب إلى الجاهزة عندما يحين وقت ظهور الصفحة.
</p>

<p>
	وقد قامت المتصفحات الرئيسية بعدة تغييرات رئيسية للتعامل مع الجلب المُسبَق، حيث كانت الفكرة "بما أنه طُلبت الصورة من مصدرها قبل فترة بالتالي سيكون لدينا فرصة لتنفيذ أي منطق مخصص نريده".
</p>

<p>
	وقد كانت المتصفحات تتنافس فيما بينها للوصول إلى أداء أفضل، وقد ساعدها في تنفيذ ذلك الجلب المسبق (كما هو موضح في المقالة <a href="https://andydavies.me/blog/2013/10/22/how-the-browser-pre-loader-makes-pages-load-faster/" rel="external nofollow">improving load time by as much as 20 percent</a>).
</p>

<p>
	منطقيًا إن أسرع تنفيذ طلب هو الطلب الذي لا يُنشأ أو يُعدّل عليه، وبالتالي فإن طلب صورة من خلال رابطها الموجود في src المُرفق بالوسم img هو أسرع طلب، ولكن غالبًا سيكون محتوى هذه الطلبات غير فعال منذ البداية بغض النظر عن السرعة التي ينجح المتصفح في طلبها وتحليلها وعرضها وذلك بسبب كبر البيانات الأساسية التي نحتاج إليها في أي وقت، لذلك وُجدت تقنية جديدة هي عبارة عن دمج الوسم noscript ديناميكيًا مع الوسم base ضمن document.write و eval، وبتحليل وعرض كل القسم المكتوب بـ HTML في صفحتنا ضمن عنصر head نكون قد تغلبنا على المشكلة السابقة.
</p>

<p>
	ولكن تعتبر هذه الطريقة صعبة التعامل معها دومًا لأنها تعتمد على طريقة عمل المتصفح وذلك أمر غير مُوثَّق وبالتالي غير موثوق به.
</p>

<p>
	نلاحظ أن الحلول التي طُرحت كانت دومًا حلولًا وسطية مع تنازلات كبيرة، فمرة لا تُعرض الصورة ويكون هناك هدر في طلبات الصور، ومرة تكون الصور المعروضة باهتة، وبالتالي لم يكن الحل المُنفَّذ باستخدام الجافا سكربت ذكيًا بما فيه الكفاية وذلك لأن التحسينات جميعها كانت تتم على مستوى المتصفح بدلًا من الاستفادة من تلك البيانات القادمة.
</p>

<p>
	وقد وُجد الحل الجذري لهذه المشكلة في HTML5 بما فيها من إمكانات.
</p>

<h2>
	الحل الجذري
</h2>

<p>
	يعد W3C المجتمع الأهم لمطوري الويب الذي يشاركون فيه اقتراحاتهم وأفكارهم لتطوير الويب. وفي نقاش كبير حول الصور المُتجاوبة والذي كان بعنوان "Responsive Images Community Groups" قدم Bruce Lawson اقتراحًا لتحديث طريقة تقديم الصور لتصبح ملائمة مع عناصر الوسائط المتعددة media التي أصبحت متنوعة وغنية في HTML5 وقد اقترح صيغة تشبه كثيرًا صيغة الوسم video حتى أنه استعار الصفة media منه، حيث كان الوسم الجديد المقترح لتوصيف الصور هو picture، والمميز في هذا الاقتراح هو أنه أبقى على الوسم img المعروف أساسًا بوثوقيته وعمل الوسم الجديد picture على تأطير –تغليف- الوسم السابق بالصيغة التالية:
</p>

<pre class="ipsCode">
  &lt;picture&gt;
  &lt;source …&gt;
  &lt;img src="source.jpg" alt="…"&gt;
  &lt;/picture&gt;
</pre>

<p>
	إنّ وجود وسم img داخل وسم img يؤمن لنا دعمًا احتياطيًّا قويًّا، فالوسم الجديد ليس أحد الوسوم المعيارية التي تحتم علينا أن ننتظر حتى يُدعم من قبل المتصفحات ثم نستطيع بعدها الاستفادة منه، وإنما يمكننا استخدامه مباشرة وستقوم المتصفحات التي لاتدعمه وبالتالي لاتفهم الموجود في عنصر picture و source بتجاهلهما وتنفيذ الوسم الداخلي img، أما المتصفحات اللواتي تدعم picture فستستخدم المعايير المرفقة في العنصر source لتحدد للوسم الداخلي img ماهو الملف الموجود في المصدر والذي نريد الحصول عليه.
</p>

<p>
	وبالتالي فنحن لانحتاج إلى بناء جميع الميزات الخاصة بالـ img ومن ثم إرفاقها بالعنصر الجديد picture، وذلك لأنها لم تقدم أي شيء جديد في حد ذاتها وإنما طوّرت أداء وإمكانية الوصول إلى الوسم img، ولكن مع المزيد من الأبحاث سنجد أن picture لا تقدم لنا جميع الخصائص التي تحتاجها الصورة في ظل التطور المستمر للويب المتجاوب وللطرق المتقدمة الجديدة المستخدمة في عرض الصور، ومع ذلك حصلنا على العديد من التحسينات لعنصر img منها خيارات جديدة للتعامل مع الشاشات عالية الدقة من خلال تغيير حجم الصورة ليناسب المكان المخصص، وتأمين صيغ بديلة للصورة لم نكن قادرين على الحصول عليها من قبل.
</p>

<p>
	ترجمة -بتصرّف- للمقال <a href="https://alistapart.com/article/responsive-images" rel="external nofollow">Responsive Images</a> لصاحبه Mat Marquis
</p>
]]></description><guid isPermaLink="false">652</guid><pubDate>Thu, 03 Jan 2019 23:07:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x648;&#x635;&#x64A;&#x641; &#x627;&#x644;&#x623;&#x62D;&#x62F;&#x627;&#x62B; &#x648;&#x627;&#x644;&#x645;&#x631;&#x627;&#x62C;&#x639;&#x627;&#x62A; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; microdata &#x639;&#x644;&#x649; HTML5</title><link>https://academy.hsoub.com/programming/html/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D8%A3%D8%AD%D8%AF%D8%A7%D8%AB-%D9%88%D8%A7%D9%84%D9%85%D8%B1%D8%A7%D8%AC%D8%B9%D8%A7%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-microdata-%D8%B9%D9%84%D9%89-html5-r473/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_04/main.png.4b312a424877336c4587a8f8d1b0a7cb.png" /></p>

<p>
	تعلمنا في الدرسين السابقين كيف نوصِّف الأشخاص والمنظمات، وسنتناول في هذا الدرس الأحداث والمراجعات
</p>

<p style="text-align: center;">
	<img alt="main.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22794" data-unique="o1rjxyumn" src="https://academy.hsoub.com/uploads/monthly_2017_04/main.png.224a884fdd62a88d7124df97d7f7cf63.png"></p>

<h3>
	توصيف الأحداث
</h3>

<p>
	تحدث بعض المناسبات في أوقاتٍ معيّنة، ألن يكون من الجميل أن تستطيع إخبار محركات البحث متى ستقع تلك المناسبات تحديدًا؟ هنالك طريقةٌ لفعل هذا في HTML5.<br>
	لنبدأ بإلقاء نظرة على الجدول الزمني الخاص بالمحاضرات والكلمات التي سألقيها.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<span class="tag">&lt;article&gt;</span><span class="pln">
  </span><span class="tag">&lt;h1&gt;</span><span class="pln">Google Developer Day 2009</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
  </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">width</span><span class="pun">=</span><span class="atv">"300"</span><span class="pln"> </span><span class="atn">height</span><span class="pun">=</span><span class="atv">"200"</span><span class="pln">
       </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"http://diveintohtml5.org/examples/gdd-2009-prague-pilgrim.jpg"</span><span class="pln">
       </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"[Mark Pilgrim at podium]"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;p&gt;</span><span class="pln">
    Google Developer Days are a chance to learn about Google
    developer products from the engineers who built them. This
    one-day conference includes seminars and “office hours”
    on web technologies like Google Maps, OpenSocial, Android,
    AJAX APIs, Chrome, and Google Web Toolkit.
  </span><span class="tag">&lt;/p&gt;</span><span class="pln">
  </span><span class="tag">&lt;p&gt;</span><span class="pln">
    </span><span class="tag">&lt;time</span><span class="pln"> </span><span class="atn">datetime</span><span class="pun">=</span><span class="atv">"2009-11-06T08:30+01:00"</span><span class="tag">&gt;</span><span class="pln">2009 November 6, 8:30</span><span class="tag">&lt;/time&gt;</span><span class="pln">
      –
    </span><span class="tag">&lt;time</span><span class="pln"> </span><span class="atn">datetime</span><span class="pun">=</span><span class="atv">"2009-11-06T20:30+01:00"</span><span class="tag">&gt;</span><span class="pln">20:30</span><span class="tag">&lt;/time&gt;</span><span class="pln">
  </span><span class="tag">&lt;/p&gt;</span><span class="pln">
  </span><span class="tag">&lt;p&gt;</span><span class="pln">
    Congress Center</span><span class="tag">&lt;br&gt;</span><span class="pln">
    5th května 65</span><span class="tag">&lt;br&gt;</span><span class="pln">
    140 21 Praha 4</span><span class="tag">&lt;br&gt;</span><span class="pln">
    Czech Republic
  </span><span class="tag">&lt;/p&gt;</span><span class="pln">
  </span><span class="tag">&lt;p&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://code.google.com/intl/cs/events/developerday/2009/home.html"</span><span class="tag">&gt;</span><span class="pln">GDD/Prague home page</span><span class="tag">&lt;/a&gt;&lt;/p&gt;</span><span class="pln">
</span><span class="tag">&lt;/article&gt;</span></pre>

<p>
	جميع المعلومات التي تخص الحدث موجودةٌ في عنصر <code>&lt;article&gt;</code>، وهو المكان الذي نريد وضع خاصيتي itemtype و itemscope فيه.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">article</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/Event"</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	رابط URL لنوع الاصطلاحات Event هو <a href="http://schema.org/Event" rel="external nofollow">http://schema.org/Event</a>، الذي يحتوي أيضًا على جدولٍ يصف خاصيات هذه النوع من الاصطلاحات؛ التي ذكرتُ بعضها في هذا الجدول.
</p>

<center>
	<table border="1"><tbody>
<tr>
<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					<strong>الخاصية</strong>
				</td>
				<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					<strong>الشرح</strong>
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					name
				</td>
				<td style=" padding: 5px 10px;">
					اسم الحدث
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					url
				</td>
				<td style=" padding: 5px 10px;">
					رابط لصفحة تفاصيل الحدث
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					location
				</td>
				<td style=" padding: 5px 10px;">
					الموقع الذي سيُجرى فيه الحدث الذي يمكن أن يُمثَّل بنوع الاصطلاحات PostalAddress أو Place
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					description
				</td>
				<td style=" padding: 5px 10px;">
					وصفٌ قصيرٌ للحدث
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					startDate
				</td>
				<td style=" padding: 5px 10px;">
					تاريخ بدء فعاليات الحدث بصيغة ISO
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					endDate
				</td>
				<td style=" padding: 5px 10px;">
					تاريخ انتهاء فعاليات الحدث بصيغة ISO
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					duration
				</td>
				<td style=" padding: 5px 10px;">
					المدة الزمنية لفعاليات الحدث بصيغة ISO
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					image
				</td>
				<td style=" padding: 5px 10px;">
					صورة تعبيرية متعلقة بالحدث
				</td>
			</tr>
</tbody></table>
</center>

<p>
	اسم الحدث موجودٌ في عنصر <code>&lt;h1&gt;</code>، ووفقًا للنموذج الهيكلي للبيانات الوصفية في HTML5، عنصر <code>&lt;h1&gt;</code> ليس له معالجةٌ خاصةٌ، وستكون قيمة خاصية البيانات الوصفية هي المحتوى النصي للعنصر <code>&lt;h1&gt;</code>، لذا كل ما نحتاج له هو إضافة الخاصية itemprop لكي نُصرِّح أنَّ هذا العنصر يحتوي على اسم الحدث.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">  </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">h1</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"name"</span></span><span class="tag">&gt;</span></span><span class="pln">Google Developer Day 2009</span><span class="hljs-tag"><span class="pln">&lt;/</span><span class="hljs-title"><span class="pln">h1</span></span></span></code></pre>

<p>
	نقول بالعربية: «اسم هذا الحدث هو Google Developer Day 2009».<br>
	يحتوي الحدث على صورة، التي يمكن توصيفها باستخدام الخاصية image، وكما تتوقع، تُعرَض الصورةُ عبر عنصر <code>&lt;img&gt;</code>، وكما في خاصية image في نوع الاصطلاحات Person، الصورة في نوع الاصطلاحات Event هي رابط URL، ولأن النموذج الهيكلي للبيانات الوصفية يقول أنَّ قيمة الخاصية الموجودة في العنصر <code>&lt;img&gt;</code> هي قيمة خاصية src، فكل ما علينا فعله هو إضافة الخاصية itemprop إلى العنصر <code>&lt;img&gt;</code>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">  </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">img</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"image"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">width</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"300"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">height</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"200"</span></span><span class="pln">
       </span><span class="hljs-attribute"><span class="atn">src</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://diveintohtml5.org/examples/gdd-2009-prague-pilgrim.jpg"</span></span><span class="pln">
       </span><span class="hljs-attribute"><span class="atn">alt</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"[Mark Pilgrim at podium]"</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	نقول بالعربية: «إحدى الصور المتعلقة بهذا الحدث موجودٌ في رابط
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs avrasm"><span class="hljs-label"><span class="pln">http</span><span class="pun">:</span></span><span class="com">//diveintohtml5</span><span class="hljs-preprocessor"><span class="com">.org</span></span><span class="com">/examples/gdd-</span><span class="hljs-number"><span class="com">2009</span></span><span class="com">-prague-pilgrim</span><span class="hljs-preprocessor"><span class="com">.jpg</span></span><span class="com">»</span></code></pre>

<p>
	يأتي بعد الصورة وصفٌ مختصرٌ للحدث، وهو فقرةٌ نصيةٌ من الكلام العادي.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs livecodeserver"><span class="pln">  </span><span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="hljs-string"><span class="atv">"description"</span></span><span class="tag">&gt;</span><span class="pln">Google Developer Days are </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> chance </span><span class="hljs-built_in"><span class="pln">to</span></span><span class="pln">
learn about Google developer products </span><span class="hljs-built_in"><span class="pln">from</span></span><span class="pln"> </span><span class="hljs-operator"><span class="pln">the</span></span><span class="pln"> engineers who built
them. This </span><span class="hljs-constant"><span class="pln">one</span></span><span class="pln">-day conference includes seminars </span><span class="hljs-operator"><span class="pln">and</span></span><span class="pln"> “office
hours” </span><span class="hljs-command"><span class="hljs-keyword"><span class="pln">on</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">web</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">technologies</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">like</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">Google</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">Maps</span></span><span class="pln">, </span><span class="hljs-title"><span class="pln">OpenSocial</span></span><span class="pln">,</span></span><span class="pln">
Android, AJAX APIs, Chrome, </span><span class="hljs-operator"><span class="pln">and</span></span><span class="pln"> Google Web Toolkit.</span><span class="tag">&lt;/p&gt;</span></code></pre>

<p>
	المعلومة التي تلي الوصف جديدةٌ علينا. تقع الأحداث عمومًا في تواريخ مُحدَّدة وتبدأ وتنتهي في أوقاتٍ معيّنة. يجب أن نضع الأوقات والتواريخ في HTML5 في عنصر <code>&lt;time&gt;</code>، وهذا ما فعلناه. لذا سيُصبِح السؤال الآن: كيف سنتمكن من إضافة خاصيات البيانات الوصفية إلى عناصر <code>&lt;time&gt;</code> السابقة؟ بالنظر مرةً أخرى إلى النموذج الهيكلي للبيانات الوصفية في HTML، سنلاحظ أنَّ هنالك معالجةٌ خاصةٌ للعنصر <code>&lt;time&gt;</code>. فقيمة خاصية البيانات الوصفية هي قيمة خاصية datetime في العنصر <code>&lt;time&gt;</code>. لكن مهلًا، أليست الصيغة المعيارية لخاصيات البيانات الوصفية startDate و endDate هي ISO، مَثَلُهَا كمَثَلِ خاصية datetime في العنصر <code>&lt;time&gt;</code>. وأكرر مرةً أخرى كيف تتوافق ةتتناغم البُنى الهيكلية من أساس HTML مع البُنى الهيكلية التي نُضيفها من نوع الاصطلاحات الخاص بالبيانات الوصفية. عملية توصيف تواريخ بداية ونهاية الحدث عبر البيانات الوصفية سهلةٌ وتتم كالآتي:
</p>

<ol>
<li>
		استخدام HTML استخدامًا صحيحًا في المقام الأول (باستخدام عناصر <code>&lt;time&gt;</code> للوقت والتاريخ)، ومن ثم
	</li>
	<li>
		إضافة خاصية itemprop
	</li>
</ol>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">  </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span><span class="pln">
    </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">time</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"startDate"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">datetime</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"2009-11-06T08:30+01:00"</span></span><span class="tag">&gt;</span></span><span class="pln">2009 November 6, 8:30</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">time</span></span><span class="tag">&gt;</span></span><span class="pln">
      &amp;ndash;
    </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">time</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"endDate"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">datetime</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"2009-11-06T20:30+01:00"</span></span><span class="tag">&gt;</span></span><span class="pln">20:30</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">time</span></span><span class="tag">&gt;</span></span><span class="pln">
  </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	بالعربية: «هذا الحديث يبدأ في November 6, 2009 الساعة 8:30 صباحًا، ويستمر إلى November 6, 2009 الساعة 20:30 (بتوقيت مدينة براغ المحلي، GMT+1)».<br>
	ثم ستأتي خاصية location، التي تقول عنها صفحة تعريف نوع الاصطلاحات Event أنها قد تكون من نوع PostalAddress أو Place. وفي حالتنا، سيُقام الحدث في مكانٍ متخصصٍ بالمؤتمرات، وهو Congress Center في مدينة براغ. وإمكانية توصيفه على أنَّه «مكان» (Place) ستسمح لنا بتضمين اسمه بالإضافة إلى عنوانه.<br>
	لنبدأ بالتصريح أنَّ العنصر <code>&lt;p&gt;</code> الذي يحتوي على العنوان هو خاصية location لنوع الاصطلاحات Event، وهذا العنصر يحتوي على خاصياتٍ تابعةٍ لنوع الاصطلاحات <a href="http://schema.org/Place" rel="external nofollow">http://schema.org/Place</a>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">  </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">p</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"location"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln">
           </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/Place"</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	ثم سنُعرِّف اسم المكان بوضعه في عنصر <span> وإضافة الخاصية itemprop إليه. </span>
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">    </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"name"</span></span><span class="tag">&gt;</span></span><span class="pln">Congress Center</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">br</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	وبسبب قواعد المجالات (scoping rules) في البيانات الوصفية، خاصية itemprop=”name”‎ السابقة تُعرِّف اسم المكان في نوع الاصطلاحات Place وليس في نوع الاصطلاحات Event. وذلك لأنَّ العنصر <code>&lt;p&gt;</code> السابق قد صرَّح عن بداية خاصيات المكان (Place)، ولمّا يُغلَق عنصر <code>&lt;p&gt;</code> بعدُ عبر وسم <code>&lt;‎/p&gt;</code>. أيّة خاصيات نُعرِّفها والتي تَتبَع للبياناتِ الوصفيةِ تكونُ من خصائصِ آخرِ نوعِ اصطلاحاتٍ دخلَ المجالَ. يمكن أن تتداخل أنواع الاصطلاحات مثل <a href="http://en.wikipedia.org/wiki/Stack_(data_structure)" rel="external nofollow">المكدس</a> (stack). لم نحذف إلى الآن آخر عنصر من المكدس، وهذا يعني أننا ما زلنا ضمن مجال نوع الاصطلاحات Place.<br>
	في الحقيقة، سيلزمنا إضافة نوع اصطلاحات ثالث إلى المكدس: عنوانٌ (Address) للمكان (Place) الذي سيُقام به الحدث (Event).
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"address"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln">
          </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/PostalAddress"</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	مرةً أخرى، علينا أن نضع كل جزء من العنوان كخاصية بيانات وصفية مستقلة، لذلك علينا أن نُضيف عددًا من عناصر <code>&lt;span&gt;</code> لكي نضع خاصيات itemprop فيها (إذا رأيتني أشرح الأمور بسرعة هنا، فأنصحك بالعودة إلى الأقسام السابقة وقراءة كيفية توصيف العنوان للأفراد وكيفية توصيف العنوان للمنظمات).
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">      </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"address"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln">
           </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/PostalAddress"</span></span><span class="tag">&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"streetAddress"</span></span><span class="tag">&gt;</span></span><span class="pln">5th května 65</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">br</span></span><span class="tag">&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"postalCode"</span></span><span class="tag">&gt;</span></span><span class="pln">140 21</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"addressLocality"</span></span><span class="tag">&gt;</span></span><span class="pln">Praha 4</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">br</span></span><span class="tag">&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"addressCountry"</span></span><span class="tag">&gt;</span></span><span class="pln">Czech Republic</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln">
      </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	لا توجد خاصيات إضافية للعنوان، لذا لنغلق عنصر <code>&lt;span&gt;</code> الذي بدأ المجال الخاص بنوع الاصطلاحات Address.<br><code>&lt;/span&gt;</code><br>
	علينا الآن إضافة الخاصية geo لتمثيل الموقع الفيزيائي للحدث. سنستخدم نفس نوع الاصطلاحات (GeoCoordinates) الذي استعملناه في القسم السابق لتحديد موقع المنظمة. سنحتاج إلى عنصر <code>&lt;span&gt;</code> لكي يعمل كحاوية، والذي يملك الخاصتين itemtype و itemscope. وضمن العنصر <code>&lt;span&gt;</code> سنضع عنصرَي <code>&lt;meta&gt;</code>، واحدٌ لتحديد إحداثيات العرض (الخاصية latitude) والآخر لتحديد إحداثيات الطول (الخاصية longitude).
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">       </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"geo"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/GeoCoordinates"</span></span><span class="tag">&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">meta</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"latitude"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">content</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"50.047893"</span></span><span class="pln"> </span><span class="tag">/&gt;</span></span><span class="pln">
        </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">meta</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"longitude"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">content</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"14.4491"</span></span><span class="pln"> </span><span class="tag">/&gt;</span></span><span class="pln">
      </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	بعد إغلاقنا لعنصر <code>&lt;span&gt;</code> الذي يحوي خاصيات الموقع الجغرافي، سنعود إلى مجال Place، لكن لم تعد هنالك أيّة خاصيات لإضافتها إلى Place، لذا سنُغلِق العنصر <code>&lt;p&gt;</code> الذي بدأ مجال نوع الاصطلاحات Place، وبهذا سنعود إلى تعريف الخاصيات التابعة لنوع الاصطلاحات Event.<br><code>&lt;/p&gt;</code><br>
	وأخيرًا وليس آخرًا، بقيت الخاصية url، التي يجب أن تكون مألوفةً لك. تُضاف روابط URL المتعلقة بالأحداث بنفس طريقة إضافة الروابط للأشخاص وطريقة إضافة روابط للمنظمات. إذا كنتَ تستعمل HTML استعمالًا صحيحًا (أي وضع الروابط في عنصر <code>&lt;a href&gt;</code>)، فآلية التصريح أنَّ الروابطَ تُمثِّلُ خاصيةَ url في البيانات الوصفية بسيطةٌ جدًا وذلك بإضافة خاصية itemprop إلى تلك العناصر فقط.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">  </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span><span class="pln">
    </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">a</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"url"</span></span><span class="pln">
       </span><span class="hljs-attribute"><span class="atn">href</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://code.google.com/intl/cs/events/developerday/2009/home.html"</span></span><span class="tag">&gt;</span></span><span class="pln">
      GDD/Prague home page
    </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">a</span></span><span class="tag">&gt;</span></span><span class="pln">
  </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span><span class="pln">
</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">article</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	يجدر بالذكر أنَّك تستطيع توصيف أكثر من حدث في نفس الصفحة.
</p>

<h3>
	المقتطفات المنسقة من جديد!
</h3>

<p>
	وفقًا <a href="https://developers.google.com/structured-data/testing-tool/" rel="external nofollow">لأداة اختبار البيانات المنظمة من Google</a>، المعلومات التي تحصل عليها عناكب محرك البحث من صفحة الحدث السابقة هي:
</p>

<p style="text-align: center;">
	<img alt="111.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22790" data-unique="m910talgq" src="https://academy.hsoub.com/uploads/monthly_2017_04/111.png.d2f1bfd55a502e259f2700240cc78e5a.png"></p>

<p>
	كما لاحظتَ، جميع البيانات التي وصَّفناها موجودةٌ هنا. لاحظ كيف تُظهِر أداة اختبار البيانات الهيكلية تشعّب أنواع الاصطلاحات؛ هذا التمثيل الرسومي سيساعدك كثيرًا على تخيّل الوضع.<br>
	هذا رسمٌ توضيحيٌ للطريقة المتوقعة لتمثيل الصفحة في نتائج بحث Google (أكرر مرةً أخرى أنَّ هذا مجرد مثال، فقد يُغيّر Google طريقة تنسيق نتائج البحث في أيّ وقت، ولا توجد هنالك ضمانة أنَّ Google ستُفسِّر البيانات الوصفية في صفحتك من الأساس!).
</p>

<p style="text-align: center;">
	<img alt="112.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22791" data-unique="6aewzmuk1" src="https://academy.hsoub.com/uploads/monthly_2017_04/112.png.b84cfe804f496c77e2ece4c93cd568a5.png"></p>

<p>
	<br>
	بعد عنوان الصفحة والمُقتطف المولَّد تلقائيًا، سيبدأ محرك Google باستعمال البيانات الوصفية التي أضفناها إلى الصفحة لعرض جدول المحتويات. لاحظ طريقة تنسيق التاريخ «Fri, Nov 6». لم ترد هذه السلسلة النصية في أيّ مكانٍ في عناصر HTML أو خاصيات البيانات الوصفية. لكننا استخدمنا سلسلتين نصيتين هما التاريخ بصيغةٍ معياريةٍ (‎2009-11-06T08:30+01:00 و ‎2009-11-06T20:30+01:00). أخذ Google هاذين التاريخين وعَرِفَ أنَّهما في نفس اليوم، وقرر عرض تاريخٍ وحيدٍ بصيغةٍ قراءتها أسهل.
</p>

<p>
	<br>
	انظر الآن إلى العنوان الفيزيائي. اختار Google أن يعرض اسم المكان + البلدة (locality) + الدولة، لكنه لم يعرض عنوان الشارع المُفصَّل. أصبح هذا ممكنًا لأننا قسّمنا العنوان إلى خمسِ خاصياتٍ مستقلةً –streetAddress وaddressLocality و addressRegion و postalCode و addressCountry– استفاد Google من هذا لعرض عنوانٍ مختصرٍ للمكان. قد يختار مستهلكونَ آخرونَ للمعلوماتِ التي توفرُها عبر البيانات الوصفية استخدامها بطرائقَ مختلفةٍ، إذ سيقررون ما الذي سيَعرضوه وما الذي لن يعرضوه. لا يوجد خيارٌ صائب وخيارٌ خاطئ هنا. عليكَ أن توفرَ أكبرَ قدرٍ من البيانات الهيكلية، وبأكبر دقةٍ ممكنةٍ، واترك الباقي على الآخرين ليفسروه كيفما يشاؤون.
</p>

<h3>
	<br>
	توصيف المراجعات
</h3>

<p>
	<br>
	هذا مثالٌ آخر عن كيفية جعل الويب (وربما نتائج البحث) أفضل عبر استخدام البيانات الوصفية: مراجعات (reviews) الشركات والمنتجات.<br>
	هذه مراجعةٌ قصيرةٌ كتبتُها لأحد مطاعم البيتزا المُفضَّلة لدي (بالمناسبة، هذا المطعم حقيقي). لننظر أولًا إلى الشيفرة الأصلية قبل إضافة البيانات الوصفية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs livecodeserver"><span class="tag">&lt;article&gt;</span><span class="pln">
  </span><span class="tag">&lt;h1&gt;</span><span class="pln">Anna’s Pizzeria</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
  </span><span class="tag">&lt;p&gt;</span><span class="pln">★★★★☆ (</span><span class="hljs-number"><span class="pln">4</span></span><span class="pln"> stars out </span><span class="hljs-operator"><span class="pln">of</span></span><span class="pln"> </span><span class="hljs-number"><span class="pln">5</span></span><span class="pln">)</span><span class="tag">&lt;/p&gt;</span><span class="pln">
  </span><span class="tag">&lt;p&gt;</span><span class="pln">New York-style pizza </span><span class="hljs-constant"><span class="pln">right</span></span><span class="pln"> </span><span class="hljs-operator"><span class="pln">in</span></span><span class="pln"> historic downtown Apex</span><span class="tag">&lt;/p&gt;</span><span class="pln">
  </span><span class="tag">&lt;p&gt;</span><span class="pln">
    Food is top-notch. Atmosphere is just </span><span class="hljs-constant"><span class="pln">right</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">for</span></span><span class="pln"> </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> “neighborhood
    pizza joint.” The restaurant itself is </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> bit cramped; </span><span class="hljs-keyword"><span class="pln">if</span></span><span class="pln"> you’re
    overweight, you may have difficulty getting </span><span class="hljs-operator"><span class="pln">in</span></span><span class="pln"> </span><span class="hljs-operator"><span class="pln">and</span></span><span class="pln"> out </span><span class="hljs-operator"><span class="pln">of</span></span><span class="pln"> your
    seat </span><span class="hljs-operator"><span class="pln">and</span></span><span class="pln"> navigating between other tables. Used </span><span class="hljs-built_in"><span class="pln">to</span></span><span class="pln"> give free
    garlic knots when you sat down; now they give you plain bread
    </span><span class="hljs-operator"><span class="pln">and</span></span><span class="pln"> you have </span><span class="hljs-built_in"><span class="pln">to</span></span><span class="pln"> pay </span><span class="hljs-keyword"><span class="pln">for</span></span><span class="pln"> </span><span class="hljs-operator"><span class="pln">the</span></span><span class="pln"> good stuff. Overall, </span><span class="hljs-keyword"><span class="pln">it</span></span><span class="pln">’s </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> winner.
  </span><span class="tag">&lt;/p&gt;</span><span class="pln">
  </span><span class="tag">&lt;p&gt;</span><span class="pln">
    </span><span class="hljs-number"><span class="pln">100</span></span><span class="pln"> North Salem Street</span><span class="tag">&lt;br&gt;</span><span class="pln">
    Apex, NC </span><span class="hljs-number"><span class="pln">27502</span></span><span class="tag">&lt;br&gt;</span><span class="pln">
    USA
  </span><span class="tag">&lt;/p&gt;</span><span class="pln">
  </span><span class="tag">&lt;p&gt;</span><span class="pln">— reviewed </span><span class="hljs-keyword"><span class="pln">by</span></span><span class="pln"> Mark Pilgrim, </span><span class="hljs-keyword"><span class="pln">last</span></span><span class="pln"> updated March </span><span class="hljs-number"><span class="pln">31</span></span><span class="pln">, </span><span class="hljs-number"><span class="pln">2010</span></span><span class="tag">&lt;/p&gt;</span><span class="pln">
</span><span class="tag">&lt;/article&gt;</span></code></pre>

<p>
	هذه المراجعة موجودةٌ ضمن عنصر &lt;article&gt;، الذي علينا وضع خاصيتي itemtype و itemscope فيه. رابط URL لمجال أسماء نوع الاصطلاحات الذي سنستعمل هو <a href="http://schema.org/Review." ipsnoembed="true" rel="external nofollow" style="background-color: rgb(255, 255, 255);">http://schema.org/Review.</a>
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">article</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/Review"</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	ما هي الخاصيات الموجودة في نوع الاصطلاحات Review؟ أنا ممتنٌ لسؤالك.
</p>

<center>
	<table border="1"><tbody>
<tr>
<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					<strong>الخاصية</strong>
				</td>
				<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					<strong>الشرح</strong>
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					itemReviewed
				</td>
				<td style=" padding: 5px 10px;">
					اسم العنصر الذي ستتم مراجعته. يمكن أن يكون منتجًا أو خدمةً أو شركةً… إلخ.
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					reviewRating
				</td>
				<td style=" padding: 5px 10px;">
					التقييم الذي أعطاه المُراجِع للعنصر. يُمثَّل بنوع الاصطلاحات Rating ‏(<a href="http://schema.org/Rating" rel="external nofollow">http://schema.org/Rating</a>)
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					author
				</td>
				<td style=" padding: 5px 10px;">
					اسم الشخص الذي كتب المراجعة
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					datePublished
				</td>
				<td style=" padding: 5px 10px;">
					تاريخ نشر المراجعة<a href="http://en.wikipedia.org/wiki/ISO_8601" rel="external nofollow"> بصيغة ISO</a>
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					name
				</td>
				<td style=" padding: 5px 10px;">
					عنوان مختصر للمراجعة
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					reviewBody
				</td>
				<td style=" padding: 5px 10px;">
					الوصف الذي كتبه المُراجِع للعنصر
				</td>
			</tr>
</tbody></table>
</center>

<p>
	<br>
	أولُ خاصيةٍ بسيطةٌ: itemReviewed هي نصٌ عاديٌ، وقيمتها موجودةٌ في عنصر <code>&lt;h1&gt;</code>، لذا سنضع تلك الخاصية في ذاك العنصر.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">  </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">h1</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"itemReviewed"</span></span><span class="tag">&gt;</span></span><span class="pln">Anna’s Pizzeria</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">h1</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	سأتجاوز حاليًا قسم التقييم وسأعود إليه لاحقًا في النهاية.<br>
	الخاصيتان التاليتان سهلتان وبسيطتان. خاصية name هي عنوانٌ مختصرٌ للمراجعة، وخاصية reviewBody هي النص الذي كتبه المراجع لوصف العنصر المُراجَع.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs livecodeserver"><span class="pln">  </span><span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="hljs-string"><span class="atv">"name"</span></span><span class="tag">&gt;</span><span class="pln">New York-style pizza </span><span class="hljs-constant"><span class="pln">right</span></span><span class="pln"> </span><span class="hljs-operator"><span class="pln">in</span></span><span class="pln"> historic downtown Apex</span><span class="tag">&lt;/p&gt;</span><span class="pln">
  </span><span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="hljs-string"><span class="atv">"reviewBody"</span></span><span class="tag">&gt;</span><span class="pln">
    Food is top-notch. Atmosphere is just </span><span class="hljs-constant"><span class="pln">right</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">for</span></span><span class="pln"> </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> “neighborhood
    pizza joint.” The restaurant itself is </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> bit cramped; </span><span class="hljs-keyword"><span class="pln">if</span></span><span class="pln"> you’re
    overweight, you may have difficulty getting </span><span class="hljs-operator"><span class="pln">in</span></span><span class="pln"> </span><span class="hljs-operator"><span class="pln">and</span></span><span class="pln"> out </span><span class="hljs-operator"><span class="pln">of</span></span><span class="pln"> your
    seat </span><span class="hljs-operator"><span class="pln">and</span></span><span class="pln"> navigating between other tables. Used </span><span class="hljs-built_in"><span class="pln">to</span></span><span class="pln"> give free
    garlic knots when you sat down; now they give you plain bread
    </span><span class="hljs-operator"><span class="pln">and</span></span><span class="pln"> you have </span><span class="hljs-built_in"><span class="pln">to</span></span><span class="pln"> pay </span><span class="hljs-keyword"><span class="pln">for</span></span><span class="pln"> </span><span class="hljs-operator"><span class="pln">the</span></span><span class="pln"> good stuff. Overall, </span><span class="hljs-keyword"><span class="pln">it</span></span><span class="pln">’s </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> winner.
  </span><span class="tag">&lt;/p&gt;</span></code></pre>

<p>
	يجب أن يكون توصيف العنوان وإحداثيات الموقع الجغرافي مألوفًا لديك الآن (إذا لم تكن تتابع معنا منذ بداية هذه الدروس، فراجع آلية توصيف عنوان شخص، وآلية توصيف عنوان منظمة، وآلية توصيف إحداثيات الموقع الجغرافي من الدروس السابقة).
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">  </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">p</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"contentLocation"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln">
           </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/Place"</span></span><span class="tag">&gt;</span></span><span class="pln">
    </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"address"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln">
           </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/PostalAddress"</span></span><span class="tag">&gt;</span></span><span class="pln">
      </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"streetAddress"</span></span><span class="tag">&gt;</span></span><span class="pln">100 North Salem Street</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">br</span></span><span class="tag">&gt;</span></span><span class="pln">
      </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"addressLocality"</span></span><span class="tag">&gt;</span></span><span class="pln">Apex</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln">,
      </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"addressRegion"</span></span><span class="tag">&gt;</span></span><span class="pln">NC</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln">
      </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"postalCode"</span></span><span class="tag">&gt;</span></span><span class="pln">27502</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">br</span></span><span class="tag">&gt;</span></span><span class="pln">
      </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"addressCountry"</span></span><span class="tag">&gt;</span></span><span class="pln">USA</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln">
    </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln">
    </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"geo"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln">
      </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/GeoCoordinates"</span></span><span class="tag">&gt;</span></span><span class="pln">
      </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">meta</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"latitude"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">content</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"50.047893"</span></span><span class="pln"> </span><span class="tag">/&gt;</span></span><span class="pln">
      </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">meta</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"longitude"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">content</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"14.4491"</span></span><span class="pln"> </span><span class="tag">/&gt;</span></span><span class="pln">
    </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln">
  </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	في آخر سطرٍ مشكلةٌ شائعة: يحتوي على معلومتين في عنصرٍ وحيدٍ. اسم الشخص الذي كتب المراجعة هو Mark Pilgrim، وتاريخ المراجعة هو March 31, 2010. كيف نستطيع توصيف هاتين الخاصيتين المستقلتين؟ ضعهما في عنصرَين منفصلين وضع خاصية itemprop في كلٍ عنصرٍ. يجدر بنا في هذا المثال أن نضع التاريخ في عنصر <code>&lt;time&gt;</code>، لكي يوفر لنا طريقةً سليمةً لوضع خاصية itemprop المناسبة. لكن اسم المُراجِع يمكن أن يُحتوى في عنصرٍ ليس له قيمةٌ دلاليةٌ مثل <code>&lt;span&gt;</code>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">  </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span><span class="pln">— </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"author"</span></span><span class="tag">&gt;</span></span><span class="pln">Mark Pilgrim</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln">, last updated
     </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">time</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"datePublished"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">datetime</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"2010-03-31"</span></span><span class="tag">&gt;</span></span><span class="pln">
       March 31, 2010
     </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">time</span></span><span class="tag">&gt;</span></span><span class="pln">
  </span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span><span class="pln">
</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">article</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	حسنًا، لنتحدث عن التقييمات. أصعب جزء في توصيف المراجعة هو التقييم. افتراضيًا، التقييمات في نوع الاصطلاحات Rating تكون على مقياس من 1 إلى 5، حيث 1 هو «سيء جدًا» و5 هو «رائع». لكنك ما تزال قادرًا على توصيف التقييم إذا كنت تستخدم مقياسًا مختلفًا، لكن دعنا نناقش المقياس الافتراضي أولًا.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="pln">  </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span><span class="pln">★★★★☆ (</span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"reviewRating"</span></span><span class="tag">&gt;</span></span><span class="pln">4</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln"> stars out of 5)</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	إذا كنتَ تستعمل مقياسًا افتراضيًا من 1 إلى 5، فالخاصية الوحيدة التي عليك توصيفها هي التقييم نفسه (4 في مثالنا). لكن ماذا لو كنتَ تستعمل مقياسًا مختلفًا؟ كل ما عليك فعله هو التصريح عن حدود المقياس الذي تستعمل. على سبيل المثال، إذا أردت أن تستعمل مقياسًا من 0 إلى 10، فما يزال عليك التصريح عن خاصية itemprop=”rating”‎ لكن بدلًا من إعطاء قيمة التقييم مباشرةً، سيتوجب عليك استخدام نوع <a href="http://schema.org/Rating" rel="external nofollow">http://schema.org/Rating</a> لتعيين أقل قيمة وأعلى قيمة في مقياسك المُخصَّص بالإضافة إلى تحديد قيمةٍ للتقييم الفعلي ضمن ذاك المقياس.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6087_7">
<code class="hljs xml"><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">p</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"reviewRating"</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemscope</span></span><span class="pln">
   </span><span class="hljs-attribute"><span class="atn">itemtype</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"http://schema.org/Rating"</span></span><span class="tag">&gt;</span></span><span class="pln">
  ★★★★★★★★★☆
  (</span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"ratingValue"</span></span><span class="tag">&gt;</span></span><span class="pln">9</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln"> on a scale of
   </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"worstRating"</span></span><span class="tag">&gt;</span></span><span class="pln">0</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln"> to
   </span><span class="hljs-tag"><span class="tag">&lt;</span><span class="hljs-title"><span class="tag">span</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="atn">itemprop</span></span><span class="pun">=</span><span class="hljs-value"><span class="atv">"bestRating"</span></span><span class="tag">&gt;</span></span><span class="pln">10</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">span</span></span><span class="tag">&gt;</span></span><span class="pln">)
</span><span class="hljs-tag"><span class="tag">&lt;/</span><span class="hljs-title"><span class="tag">p</span></span><span class="tag">&gt;</span></span></code></pre>

<p>
	بالعربية: «هذا المنتج الذي أكتب مراجعةً عنه يملك تقييمًا قيمته 9 في مقياسٍ من 0 إلى 10».<br>
	هل ذكرتُ لك أنَّ البيانات الوصفية المُضافة للمراجعات قد تؤثر على نتائج البحث؟ هذه هي البيانات التي تستيطع <a href="https://developers.google.com/structured-data/testing-tool/" rel="external nofollow">أداة اختبار البيانات المنظّمة</a> استخلاصها من مراجعتنا:
</p>

<p style="text-align: center;">
	<img alt="113.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22792" data-unique="igw9jsf7e" src="https://academy.hsoub.com/uploads/monthly_2017_04/113.png.e5a5057d9d861e21f055697deeeffe6a.png"></p>

<p>
	<br>
	وهذه صورةٌ توضيحيةٌ لكيف يمكن أن تبدو المراجعة عند عرضها في نتائج البحث:
</p>

<p style="text-align: center;">
	<img alt="114.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22793" data-unique="a423teks7" src="https://academy.hsoub.com/uploads/monthly_2017_04/114.png.3815419916bf64a738521071ddfed85c.png"></p>

<p>
	<br>
	أليس هذا مُبهرًا؟
</p>

<h3>
	<br>
	مصادر إضافية 
</h3>

<p>
	<br>
	مصادر عن البيانات الوصفية (Microdata):
</p>

<ul>
<li>
		<a href="https://www.w3.org/TR/microdata/" rel="external nofollow">مواصفة Microdata في HTML5</a>
	</li>
	<li>
		<a href="https://en.wikipedia.org/wiki/Microdata_(HTML)" rel="external nofollow">صفحة Microdata في ويكيبيديا</a>
	</li>
</ul>
<p>
	مصادر عن المقتطفات المنسقة:
</p>

<ul>
<li>
		<a href="https://developers.google.com/structured-data/rich-snippets/" rel="external nofollow">صفحة Rich Snippets</a>
	</li>
	<li>
		<a href="https://developers.google.com/structured-data/testing-tool/" rel="external nofollow">أداة اختبار البيانات المنظمة</a>
	</li>
	<li>
		موقع <a href="https://schema.org/" rel="external nofollow">schema.org</a> الذي يحتوي معلوماتٍ عن أنواع الاصطلاحات المختلفة التي ذكرناها في هذا دروس هذه السلسلة.
	</li>
</ul>
<p>
	<br>
	ترجمة -وبتصرّف- لفصل «<a href="http://diveinto.html5doctor.com/extensibility.html" rel="external nofollow">Microdata</a>» من كتاب Dive Into HTML5 لمؤلفه Mark Pilgrim.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/html/html5/%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D9%85%D9%86%D8%B8%D9%85%D8%A7%D8%AA%D8%A7%D9%84%D8%B4%D8%B1%D9%83%D8%A7%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-microdata-%D9%81%D9%8A-html5-r472/" rel="">توصيف المنظمات/الشركات باستخدام microdata في HTML5</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">نحو فهم أعمق لتقنيات HTML5 </a>
	</li>
</ul>
]]></description><guid isPermaLink="false">473</guid><pubDate>Wed, 12 Oct 2016 21:00:00 +0000</pubDate></item><item><title>&#x62A;&#x648;&#x635;&#x64A;&#x641; &#x627;&#x644;&#x645;&#x646;&#x638;&#x645;&#x627;&#x62A;/&#x627;&#x644;&#x634;&#x631;&#x643;&#x627;&#x62A; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; microdata &#x641;&#x64A; HTML5</title><link>https://academy.hsoub.com/programming/html/%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D9%85%D9%86%D8%B8%D9%85%D8%A7%D8%AA%D8%A7%D9%84%D8%B4%D8%B1%D9%83%D8%A7%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-microdata-%D9%81%D9%8A-html5-r472/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_04/main.png.abcb16164e84c6775cc1ac2bd212ab52.png" /></p>

<p>
	البيانات الوصفية ليست محدودةً لنوع اصطلاحاتٍ وحيد. صفحة «About» التي أنشأناها في <a href="https://academy.hsoub.com/programming/html5/%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D8%A3%D8%B4%D8%AE%D8%A7%D8%B5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-metadata-%D9%81%D9%8A-html5-r377/" rel="">الدرس السابق</a> جيدة، لكن من المرجح أنَّ لديك صفحةً واحدةً اسمها «About»، ولكنك متعطشٌ للمزيد؟ لنتعلم كيف نوصِّف المنظمات والشركات.
</p>

<p style="text-align: center;">
	<img alt="main.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22760" data-unique="uc1dhlm4p" src="https://academy.hsoub.com/uploads/monthly_2017_04/main.png.8a874388a846840843d8cf90c19504c1.png"></p>

<p>
	هذه نموذجٌ لصفحة شركةٍ ما، لنلقِ نظرةً على شيفرة HTML دون البيانات الوصفية.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_28">
<span class="tag">&lt;article&gt;</span><span class="pln">

</span><span class="tag">&lt;h1&gt;</span><span class="pln">Google, Inc.</span><span class="tag">&lt;/h1&gt;</span><span class="pln">

</span><span class="tag">&lt;p&gt;</span><span class="pln">

1600 Amphitheatre Parkway</span><span class="tag">&lt;br&gt;</span><span class="pln">

Mountain View, CA 94043</span><span class="tag">&lt;br&gt;</span><span class="pln">

USA

</span><span class="tag">&lt;/p&gt;</span><span class="pln">

</span><span class="tag">&lt;p&gt;</span><span class="pln">650-253-0000</span><span class="tag">&lt;/p&gt;</span><span class="pln">

</span><span class="tag">&lt;p&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://www.google.com/"</span><span class="tag">&gt;</span><span class="pln">Google.com</span><span class="tag">&lt;/a&gt;&lt;/p&gt;</span><span class="pln">

</span><span class="tag">&lt;/article&gt;</span></pre>

<p>
	وصفٌ قصيرٌ ومنظَّم، فجميع المعلومات حول هذه المنظمة موجودةٌ ضمن عنصر &lt;article&gt;، فلنبدأ هناك.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_26">
<span class="tag">&lt;article</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln"> </span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/Organization"</span><span class="tag">&gt;</span></pre>

<p>
	وكما فعلنا عند توصيف الأشخاص في<a href="https://academy.hsoub.com/programming/html5/%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D8%A3%D8%B4%D8%AE%D8%A7%D8%B5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-metadata-%D9%81%D9%8A-html5-r377/" rel=""> الدرس السابق</a>، سنحتاج إلى ضبط الخاصيتين itemscope و itemtype في العنصر الحاوي لبقية العناصر، وهو في حالتنا العنصر &lt;article&gt;. خاصية itemtype تُصرِّح ما هو نوع الاصطلاحات التي تستعملها (في هذه الحالة <a href="http://schema.org/Organization)%D8%8C" ipsnoembed="true" rel="external nofollow">http://schema.org/Organization)،</a> وخاصية itemscope تُصرِّح أنَّ كل الخاصيات التي تضبطها للعناصر الأبناء للعنصر الحالي ترتبط بنوع الاصطلاحات هذا.
</p>

<p>
	إذًا، ماذا يوجد في نوع الاصطلاحات Organization؟ بضع خاصياتٍ بسيطة، التي يكون بعضها مألوفًا لديك.
</p>

<center>
	<table border="1"><tbody>
<tr>
<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					<strong>الخاصية</strong>
				</td>
				<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					<strong>الشرح</strong>
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					name
				</td>
				<td style=" padding: 5px 10px;">
					اسم المنظمة (على سبيل المثال: «Initech»)
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					url
				</td>
				<td style=" padding: 5px 10px;">
					رابط URL لصفحة ويب، مثل الصفحة الرئيسية للمنظمة
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					address
				</td>
				<td style=" padding: 5px 10px;">
					العنوان الفيزيائي للمنظمة، يمكن أن يحتوي على خاصيات أخرى مثل streetAddress وaddressLocality و addressRegion و postalCode و addressCountry
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					telephone
				</td>
				<td style=" padding: 5px 10px;">
					رقم هاتف المنظمة
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					geo
				</td>
				<td style=" padding: 5px 10px;">
					تحديد الإحداثيات الجغرافية لموقع المنظمة، ويملك خاصيتين دائمًا: latitude و longitude
				</td>
			</tr>
</tbody></table>
</center>

<p>
	أول قطعة من الشيفرات في عنصر &lt;article&gt; هي &lt;h1&gt;. يحتوي عنصر &lt;h1&gt; على اسم الشركة، ولهذا سأضيف خاصية itemprop="name"‎ إليه مباشرةً.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_24">
<span class="tag">&lt;h1</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"name"</span><span class="tag">&gt;</span><span class="pln">Google, Inc.</span><span class="tag">&lt;/h1&gt;</span></pre>

<p>
	ووفقًا للنموذج الهيكلي للبيانات الوصفية في HTML5، عناصر &lt;h1&gt; ليس لها معالجة خاصة، وستكون قيمة خاصية البيانات الوصفية هي المحتوى النصي للعنصر. أي أننا قلنا بالعربية: «اسم المنظمة هو "Google, inc.‎"».
</p>

<p>
	المعلومة التالية التي نريد توصيفها هي العنوان. توصيف عنوان المنظمة مماثل تمامًا لتوصيف عنوان شخصٍ ما. أضف أولًا خاصية itemprop="address"‎ إلى العنصر الذي يحتوي على العنوان (العنصر &lt;p&gt; في هذه الحالة). وهذا يُصرِّح أنَّ هذه هي خاصية address للمنظمة، لكن ماذا عن خاصيات العنوان نفسه؟ سنحتاج إلى الخاصيتين itemtype و itemscope لكي نقول أنَّ عنصر العنوان هذا له خاصياتٌ تابعة له.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_22">
<span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"address"</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln">

</span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/PostalAddress"</span><span class="tag">&gt;</span></pre>

<p>
	في النهاية، علينا وضع كل قطعة من المعلومات في عنصر &lt;span&gt; لكي نتمكن من وضع الخاصية الملائمة (streetAddress وaddressLocality و addressRegion و postalCode و addressCountry) في كل عنصر من تلك العناصر.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_20">
<span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"address"</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln">

</span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/PostalAddress"</span><span class="tag">&gt;</span><span class="pln">

</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"streetAddress"</span><span class="tag">&gt;</span><span class="pln">1600 Amphitheatre Parkway</span><span class="tag">&lt;/span&gt;&lt;br&gt;</span><span class="pln">

</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"addressLocality"</span><span class="tag">&gt;</span><span class="pln">Mountain View</span><span class="tag">&lt;/span&gt;</span><span class="pln">,

</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"addressRegion"</span><span class="tag">&gt;</span><span class="pln">CA</span><span class="tag">&lt;/span&gt;</span><span class="pln">

</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"postalCode"</span><span class="tag">&gt;</span><span class="pln">94043</span><span class="tag">&lt;/span&gt;&lt;br&gt;</span><span class="pln">

</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"addressCountry"</span><span class="tag">&gt;</span><span class="pln">USA</span><span class="tag">&lt;/span&gt;</span><span class="pln">

</span><span class="tag">&lt;/p&gt;</span></pre>

<p>
	بالعربية: «هذه المنظمة تملك عنوانًا بريديًا. اسم الشارع لذاك العنوان البريدي هو "1600 Amphitheatre Parkway"، أما البلدة (locality) فهي "Mountain View"، والإقليم (region) هو "CA"، والرمز البريدي (postal code) هو "94043"، واسم الدولة هو "USA"».
</p>

<p>
	الخطوة التالية هي توصيف رقم الهاتف للمنظمة، بُنيةُ أرقامِ الهواتفِ معقدةٌ بعض الشيء، والصيغة المُحدَّدة لها خاصةٌ بكل دولة (والأمر أسوأ إذا أردت الاتصال بدولةٍ أخرى). لدينا في مثالنا رقمٌ هاتفيٌ من الولايات المتحدة، وهو مكتوبٌ بصيغةٍ ملائمةٍ للاتصال من أي مكان داخل الولايات المتحدة.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_18">
<span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"telephone"</span><span class="tag">&gt;</span><span class="pln">650-253-0000</span><span class="tag">&lt;/p&gt;</span></pre>

<p>
	(في حال لم تنتبه، لقد خرج نوع الاصطلاحات Address من المجال [scope] عندما أُغلِق العنصر &lt;p&gt;. لقد عدنا الآن إلى تعريف الخاصيات لنوع الاصطلاحات Organization.)
</p>

<p>
	إذا كنت تريد وضع أكثر من رقم هاتف –ربما واحد للزبائن في الولايات المتحدة وآخر للزبائن من بقية دول العالم– فيمكنك فعل ذلك. إذ يمكن تكرار أي خاصية من خاصيات البيانات الوصفية أكثر من مرة. كل ما عليك فعله هو التأكد أنَّ لكل رقمٍ عنصرُ HTML خاصٌ به مفصولٌ عن أيّة لافتة وضعتَها له.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_16">
<span class="tag">&lt;p&gt;</span><span class="pln">

US customers: </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"telephone"</span><span class="tag">&gt;</span><span class="pln">650-253-0000</span><span class="tag">&lt;/span&gt;&lt;br&gt;</span><span class="pln">

UK customers: </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"telephone"</span><span class="tag">&gt;</span><span class="pln">00 + 1* + 6502530000</span><span class="tag">&lt;/span&gt;</span><span class="pln">

</span><span class="tag">&lt;/p&gt;</span></pre>

<p>
	ووفقًا للنموذج الهيكلي للبيانات الوصفية في HTML5، عناصر &lt;p&gt; أو عناصر &lt;span&gt; ليس لها معالجةٌ خاصةٌ، وستكون قيمة خاصية telephone هي المحتوى النصي للعنصر. لا يحاول نوع الاصطلاحات Organization أن يُقسِّم ويُصنِّف مختلف أجزاء رقم الهاتف، فخاصية telephone هي نصٌ عاديٌ. حيث تستطيع وضع رمز المنطقة بين قوسين، أو أن تستعمل الفراغات بدلًا من الشرطات للفصل بين الأرقام. وإذا حاول العميل الذي يُفسِّر البيانات الوصفية أن يُفسِّر رقم الهاتف، فآلية ذلك عائدةٌ تمامًا إليه.
</p>

<p>
	لدينا بعد ذلك خاصيةٌ نألفها: url. ومثل روابط URL المتعلقة بشخصٍ ما، يمكن لروابط URL أن تتعلق بمنظمة. وقد تكون هذه الروابط هي الصفحة الرئيسية للشركة، أو صفحة التواصل، أو صفحة المنتجات، أو أيّة صفحة أخرى. بعبارةٍ أخرى، إذا كان لديك رابط URL عن أو من أو يتعلق بالمنظمة، فوصِّفه بخاصية itemprop="url"‎.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_14">
<span class="tag">&lt;p&gt;&lt;a</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"url"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://www.google.com/"</span><span class="tag">&gt;</span><span class="pln">Google.com</span><span class="tag">&lt;/a&gt;&lt;/p&gt;</span></pre>

<p>
	ووفقًا للنموذج الهيكلي للبيانات الوصفية في HTML5، عنصر &lt;a&gt; له معالجةٌ خاصةٌ، فقيمة خاصية البيانات الوصفية هي قيمة الخاصية href، وليس المحتوى النصي للرابط. بالعربية: «لدى هذه المنظمة رابط URL الآتي <a href="http://www.google.com/%E2%80%8E%C2%BB." ipsnoembed="true" rel="external nofollow">http://www.google.com/‎».</a> لكن الخاصية لا تُحدِّد مزيدًا من المعلومات عن هذا الارتباط، ولا تُضمِّن السلسلة النصية للرابط Google.com».
</p>

<p>
	في النهاية، أريد الحديث عن الموقع الجغرافي. لا أقصد هنا الواجهة البرمجية لتحديد الموقع الجغرافي؛ وإنما أقصد كيفية توصيف الموقع الجغرافي للمنظمات باستخدام البيانات الوصفية.
</p>

<p>
	لحد هذه اللحظة، كل الأمثلة التي رأيناها ركَّزَت على توصيف البيانات المرئية. بعبارةٍ أخرى، لديك عنصر &lt;h1&gt; فيه اسم الشركة، لذا ستُضيف خاصية itemprop إلى عنصر &lt;h1&gt; لتُصرِّح أنَّ النص (المرئي) الموجود في تلك الترويسة هو اسم المنظمة. أو ربما لديك عنصر &lt;img&gt; الذي يُشير إلى صورةٍ ما، وتستطيع إضافة الخاصية itemprop لعنصر &lt;img&gt; لكي تُصرِّح أنَّ تلك الصورة (المرئية) هي صورةٌ لشخصٍ ما.
</p>

<p>
	أما في هذا المثال، لن تكون معلومات الموقع الجغرافي على هذا النحو؛ فلا يوجد نصٌ مرئيٌ يُعطي إحداثيات الطول والعرض (بدقة أربعة أرقام عشرية!) لموقع المنظمة. وفي الواقع، الصفحة التي نعمل عليها لا تحتوي على معلومات عن الموقع الجغرافي إطلاقًا. وحتى لو وُجِدَ رابطٌ إلى خرائط Google، لكنه لا يحتوي على إحداثيات الطول والعرض (يحتوي على معلومات مشابهة في صيغةٍ خاصةٍ بخرائط Google). لكن حتى لو افترضنا وجود رابط URL لإحدى خدمات الخرائط التي تضع إحداثيات خطوط الطول والعرض كوسائط في رابط URL، فلا توجد طريقة في البيانات الوصفية لفصل أجزاء URL عن بعضها؛ فلا تستطيع أن تقول أنَّ «أول وسيطٍ في طلبية URL هو إحداثيات الطول والوسيط الثاني هو إحداثيات العرض وبقية وسائط الطلبية غير مهمة بالنسبة إلينا».
</p>

<p>
	توفِّر HTML5 طريقةً لتوصيف البيانات غير المرئية للتعامل مع الحالات الخاصة مثل هذه الحالة. لا تَستعمل هذه التقنية إلا كملاذٍ أخيرٍ لك. فلو كانت هنالك طريقةٌ لعرض البيانات التي تريد توصيفها، فافعل ذلك. أرى أنَّ البيانات المخفية التي تستطيع «الآلات» قراءتها فقط «ستتعفن» بسرعة. وهذا يعني أنَّ أحدهم سيأتي عاجلًا أم آجلًا وسيُحدِّث النص المرئي الموجود في الصفحة لكنه سينسى تحديث البيانات غير المرئية. هذا يحدث بوتيرة كبيرة أكثر مما تتوقع، وأنا واثقٌ أنَّه سيحدث لك أيضًا.
</p>

<p>
	لكن مع هذا، هنالك وضع معلومات للموقع الجغرافي لكنه لا يريد أن تعم الفوضى في الواجهة بوجود زوجين من الأرقام غير المفهومة ذات ست خانات. الخيار الوحيد الذي أمامك هنا هو البيانات المخفية. كل ما تستطيع فعله هنا هو وضع البيانات المخفية بعد النص المرئي الذي يصفها مباشرةً، لعل ذلك يُذكِّر الشخص الذي أتى ليحدث النص المرئي لكي يُحدِّث البيانات المخفية بعده مباشرةً.
</p>

<p>
	في هذا المثال، أنشأنا عنصر &lt;span&gt; ضمن عنصر &lt;article&gt; الذي يحوي بقية خاصيات المنظمة، ثم وضعنا بيانات الموقع الجغرافي المخفية داخل عنصر &lt;span&gt; (هذه هي الطريقة التنظيمية لنوع الاصطلاحات Organization، راجع صفحة <a href="http://schema.org/Organization" rel="external nofollow">http://schema.org/Organization</a> لمزيدٍ من المعلومات).
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_12">
<span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"areaServed"</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln"> </span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/Place"</span><span class="tag">&gt;</span><span class="pln">

</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"geo"</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln">

</span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/GeoCoordinates"</span><span class="tag">&gt;</span><span class="pln">

</span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"latitude"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"37.4149"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

</span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"longitude"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"-122.078"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

</span><span class="tag">&lt;/span&gt;</span><span class="pln">

</span><span class="tag">&lt;/span&gt;</span><span class="pln">

</span><span class="tag">&lt;/article&gt;</span></pre>

<p>
	معلومات الموقع الجغرافي مُعرَّفةٌ في نوع الاصطلاحات الخاص بها، مثل «عنوان» (Address) الشخص أو المنظمة، وبالتالي، سيحتاج عنصر &lt;span&gt; إلى ثلاث خاصيات:
</p>

<p>
	itemprop="geo"‎ يقول أنَّ هذا العنصر يُمثِّل خاصية geo للمنظمة التي يتبع لها
</p>

<p>
	itemtype="http://schema.org/GeoCoordinates"‎ يُحدِّد أيُّ نوعِ اصطلاحاتٍ ستخضع له خاصيات هذا العنصر
</p>

<p>
	itemscope يقول أنَّ هذا العنصر هو عنصرٌ حاوٍ يملك نوع اصطلاحات خاص به (مُحدَّدٌ في خاصية itemtype). جميع الخاصيات الموجودة ضمن هذا العنصر هي خاصياتٌ لنوع الاصطلاحات <a href="http://schema.org/GeoCoordinates%D8%8C" ipsnoembed="true" rel="external nofollow">http://schema.org/GeoCoordinates،</a> وليس لنوع الاصطلاحات للعنصر الرئيسي <a href="http://schema.org/Organization" ipsnoembed="true" rel="external nofollow">http://schema.org/Organization</a>
</p>

<p>
	السؤال المهم في هذا المثال هو: «كيف تستطيع توصيف البيانات غير المرئية؟» يمكنك استخدام العنصر &lt;meta&gt;. لم تكن في السابق تستطيع استخدام العنصر &lt;meta&gt; إلا داخل ترويسة صفحتك؛ أما في HTML5، فتستطيع استخدام العنصر &lt;meta&gt; في أيِّ مكانٍ، وهذا ما سنفعله تمامًا.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8267_7">
<span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"latitude"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"37.4149"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	ووفقًا للنموذج الهيكلي للبيانات الوصفية في HTML5، عنصر &lt;meta&gt; له معالجةٌ خاصة، فقيمة خاصية البيانات الوصفية هي قيمة الخاصية content؛ ولأن هذه الخاصية لا تُعرَض أبدًا، فهي مثاليةٌ لضبط عددٍ غيرِ محدودٍ من البيانات المخفية. لكن ستزداد المسؤولية الملقاة على عاتقك هنا، حيث عليك التأكد أنَّ المعلومات المخفية ستبقى متوافقةً مع ما حولها من النص المرئي.
</p>

<p>
	لا يوجد دعمٌ مباشرٌ لنوع الاصطلاحات Organization في المُقتطفات المنسقة في Google، لذا لا أملك نتيجةَ بحثٍ جميلة لعرضها لك. لكن لها تأثيرٌ على الأحداث (events) والمراجعات (reviews)، اللتان تدعمهما المقتطفات المنسقة في Google (تقبل بعض خاصياتهما أن يكون نوع الخاصية Organization).
</p>

<p style="text-align: center;">
	<img alt="Untitled.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22759" data-unique="re7brbx4h" src="https://academy.hsoub.com/uploads/monthly_2017_04/Untitled.png.527dd2490d38e6109ee79d85616fa977.png"></p>

<p style="text-align: center;">
	الشكل 1: معلومات البيانات الوصفية كما تُظهِرها <a href="https://developers.google.com/structured-data/testing-tool/" rel="external nofollow">أداة اختبار البيانات المنظّمة</a>
</p>

<p>
	<br>
	ترجمة -وبتصرّف- لجزء من فصل «<a href="http://diveinto.html5doctor.com/extensibility.html" rel="external nofollow">Microdata</a>» من كتاب Dive Into HTML5 لمؤلفه Mark Pilgrim.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/html/html5/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D8%A3%D8%AD%D8%AF%D8%A7%D8%AB-%D9%88%D8%A7%D9%84%D9%85%D8%B1%D8%A7%D8%AC%D8%B9%D8%A7%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-microdata-%D8%B9%D9%84%D9%89-html5-r473/" rel="">كيفية توصيف الأحداث والمراجعات باستخدام microdata على HTML5</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/html/html5/%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D8%A3%D8%B4%D8%AE%D8%A7%D8%B5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-metadata-%D9%81%D9%8A-html5-r377/" rel="">توصيف الأشخاص باستخدام metadata في HTML5</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">نحو فهم أعمق لتقنيات HTML5</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">472</guid><pubDate>Mon, 10 Oct 2016 21:00:00 +0000</pubDate></item><item><title>&#x62A;&#x648;&#x635;&#x64A;&#x641; &#x627;&#x644;&#x623;&#x634;&#x62E;&#x627;&#x635; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; metadata &#x641;&#x64A; HTML5</title><link>https://academy.hsoub.com/programming/html/%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D8%A3%D8%B4%D8%AE%D8%A7%D8%B5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-metadata-%D9%81%D9%8A-html5-r377/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_10/html5-metadata.png.cf26223a51dd31c955d2880d2c701899.png" /></p>

<p>
	إن كنت قد قرأت المقال السّابق الذي يشرح <a href="https://academy.hsoub.com/programming/html5/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D8%B5%D9%81%D9%8A%D8%A9-microdata-%D9%81%D9%8A-html5-r375/" rel="">ماهية metadata وكيفية استخدامها</a> فأود أن أنوّه إلى أنني لم أخترع الأمثلة في الدرس السابق من عندي تمامًا، فهنالك اصطلاحات للبيانات الوصفية لتوصيف المعلومات الخاصة بالأشخاص، ومن السهل فعل ذلك. لنلقي نظرةً أقرب.
</p>

<p style="text-align: center;">
	<img alt="html5-metadata.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19254" data-unique="aabt5bj9c" src="https://academy.hsoub.com/uploads/monthly_2016_10/html5-metadata.png.90d727e64a3a9b06580487b0152d7493.png"></p>

<p>
	أسهل طريقة لدمج البيانات الوصفية في موقعك الشخصي تكون في صفحة About، من المرجح وجود صفحة About لديك، أليس كذلك؟ إن لم تكن لديك صفحة، فيمكنك المتابعة معي في توسعة صفحة About الآتية ببعض البنى الهيكلية.
</p>

<p>
	لننظر أولًا إلى الشيفرة المصدرية، قبل إضافة أيّة خاصيات لها علاقة بالبيانات الوصفية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_10">
<span class="tag">&lt;section&gt;</span><span class="pln">
  </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">width</span><span class="pun">=</span><span class="atv">"204"</span><span class="pln"> </span><span class="atn">height</span><span class="pun">=</span><span class="atv">"250"</span><span class="pln">
       </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"http://diveintohtml5.org/examples/2000_05_mark.jpg"</span><span class="pln">
       </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"[Mark Pilgrim, circa 2000]"</span><span class="tag">&gt;</span><span class="pln">

  </span><span class="tag">&lt;h1&gt;</span><span class="pln">Contact Information</span><span class="tag">&lt;/h1&gt;</span><span class="pln">

  </span><span class="tag">&lt;dl&gt;</span><span class="pln">
    </span><span class="tag">&lt;dt&gt;</span><span class="pln">Name</span><span class="tag">&lt;/dt&gt;</span><span class="pln">
    </span><span class="tag">&lt;dd&gt;</span><span class="pln">Mark Pilgrim</span><span class="tag">&lt;/dd&gt;</span><span class="pln">

    </span><span class="tag">&lt;dt&gt;</span><span class="pln">Position</span><span class="tag">&lt;/dt&gt;</span><span class="pln">
    </span><span class="tag">&lt;dd&gt;</span><span class="pln">Developer advocate for Google, Inc.</span><span class="tag">&lt;/dd&gt;</span><span class="pln">

    </span><span class="tag">&lt;dt&gt;</span><span class="pln">Mailing address</span><span class="tag">&lt;/dt&gt;</span><span class="pln">
    </span><span class="tag">&lt;dd&gt;</span><span class="pln">
      100 Main Street</span><span class="tag">&lt;br&gt;</span><span class="pln">
      Anytown, PA 19999</span><span class="tag">&lt;br&gt;</span><span class="pln">
      USA
    </span><span class="tag">&lt;/dd&gt;</span><span class="pln">
  </span><span class="tag">&lt;/dl&gt;</span><span class="pln">

  </span><span class="tag">&lt;h1&gt;</span><span class="pln">My Digital Footprints</span><span class="tag">&lt;/h1&gt;</span><span class="pln">

  </span><span class="tag">&lt;ul&gt;</span><span class="pln">
    </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://diveintomark.org/"</span><span class="tag">&gt;</span><span class="pln">weblog</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
    </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://www.google.com/profiles/pilgrim"</span><span class="tag">&gt;</span><span class="pln">Google profile</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
    </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://www.reddit.com/user/MarkPilgrim"</span><span class="tag">&gt;</span><span class="pln">Reddit.com profile</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
    </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://www.twitter.com/diveintomark"</span><span class="tag">&gt;</span><span class="pln">Twitter</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
  </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
</span><span class="tag">&lt;/section&gt;</span></pre>

<p>
	أول شيء عليك فعله دائمًا هو التصريح عن نوع الاصطلاحات الذي ستستعمله، ومجال (scope) الخاصيات التي تريد إضافتها. يمكنك القيام بذلك عبر إضافة خاصيتَي <span style="font-family:courier new,courier,monospace;">itemtype</span> و <span style="font-family:courier new,courier,monospace;">itemscope</span> إلى العنصر الأب الذي يحتوي على بقية العناصر التي تريد توصيف البيانات فيها، وهو في حالتنا العنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_12">
<span class="tag">&lt;section</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln"> </span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/Person"</span><span class="tag">&gt;</span></pre>

<p>
	يمكنك الآن البدء بتعريف خاصيات البيانات الوصفية من نوع الاصطلاحات <a href="http://schema.org/Person%D8%8C" ipsnoembed="true" rel="external nofollow">http://schema.org/Person،</a> لكن ما هي هذه الخاصيات؟ كما هو واضح، تستطيع رؤية كامل قائمة الخاصيات بزيارة الصفحة <a href="http://schema.org/Person" ipsnoembed="true" rel="external nofollow">http://schema.org/Person</a> في متصفحك. لا تتطلب مواصفة البيانات الوصفية أن توضع قائمة الخاصيات هناك، لكنني أرى أنَّ ذلك مستحسنٌ. فلو أردت مثلًا أن تجعل المطورين يستعملون نوع اصطلاحات البيانات الوصفية الذي أنشأته، فستحتاج إلى توثيقه. ولا يوجد مكانٌ أفضل لوضع التوثيق فيه من رابط نوع الاصطلاحات نفسه، أليس كذلك؟
</p>

<center>
	<table border="1"><tbody>
<tr>
<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					<strong>الخاصية</strong>
				</td>
				<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					<strong>الشرح</strong>
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					name
				</td>
				<td style=" padding: 5px 10px;">
					الاسم
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					additionalName
				</td>
				<td style=" padding: 5px 10px;">
					الاسم الإضافي، قد يكون الاسم الأوسط أو اللقب
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					image
				</td>
				<td style=" padding: 5px 10px;">
					رابطٌ لصورةٍ له
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					jobTitle
				</td>
				<td style=" padding: 5px 10px;">
					المُسمَّى الوظيفي (مثلًا، مدير مالي [Financial Manager])
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					url
				</td>
				<td style=" padding: 5px 10px;">
					رابط URL لصفحة ويب، مثل الصفحة الرئيسية لمدونة ذاك الشخص
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					affiliation
				</td>
				<td style=" padding: 5px 10px;">
					المنظمة التي يرتبط بها هذا الشخص (أن يكون -على سبيل المثال- موظفًا أو طالبًا فيها)
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					address
				</td>
				<td style=" padding: 5px 10px;">
					<p>
						العنوان الفيزيائي للشخص. يمكن أن يحتوي على خاصيات أخرى مثل
					</p>

					<p>
						streetAddress وaddressLocality و addressRegion و postalCode و addressCountry
					</p>
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px;">
					knows
				</td>
				<td style=" padding: 5px 10px;">
					علاقة اجتماعية بين الشخص الموصوف وشخصٍ آخر
				</td>
			</tr>
</tbody></table>
</center>

<p>
	أول شيء نصادفه في صفحة About السابقة هي صورةٌ موضوعةٌ ضمن عنصر <span style="font-family:courier new,courier,monospace;">&lt;img&gt;</span>، ولكي نُصرِّح أنَّ الصورة الموجودة هي صورة الشخص الموصوف، فكل ما نحتاج له هو إضافة <span style="font-family:courier new,courier,monospace;">itemprop="image"‎ </span>إلى عنصر<span style="font-family:courier new,courier,monospace;"> &lt;img&gt;</span>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_14">
<span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"image"</span><span class="pln"> </span><span class="atn">width</span><span class="pun">=</span><span class="atv">"204"</span><span class="pln"> </span><span class="atn">height</span><span class="pun">=</span><span class="atv">"250"</span><span class="pln">
	</span><span class="atn">src</span><span class="pun">=</span><span class="atv">"http://diveinto.html5doctor.com/examples/2000_05_mark.jpg"</span><span class="pln">
	</span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"[Mark Pilgrim, circa 2000]"</span><span class="tag">&gt;</span></pre>

<p>
	أين هي قيمة خاصية البيانات الوصفية؟ إنها موجودةٌ في خاصية <span style="font-family:courier new,courier,monospace;">src</span>، وإذا كنتَ تتذكر من النموذج الهيكلي للبيانات الوصفية في HTML5، "قيمة" خاصية البيانات الوصفية في عنصر <span style="font-family:courier new,courier,monospace;">&lt;img&gt;</span> هي محتوى الخاصية <span style="font-family:courier new,courier,monospace;">src</span>. ولكل عنصر <span style="font-family:courier new,courier,monospace;">&lt;img&gt;</span> خاصية <span style="font-family:courier new,courier,monospace;">src</span> -وإلا فلن تُعرَض الصورة- وخاصية <span style="font-family:courier new,courier,monospace;">src</span> تحتوي على رابط URL دائمًا، أترى؟ إذا كنت تكتب HTML بشكلٍ صحيح، فاستعمال البيانات الوصفية سهلٌ جدًا.
</p>

<p>
	علاوةً على ذلك، العنصر <span style="font-family:courier new,courier,monospace;">&lt;img&gt;</span> ليس موجودًا لوحده في الصفحة، فهو عنصر ابن للعنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span>، الذي عرَّفناه مع الخاصية <span style="font-family:courier new,courier,monospace;">itemscope</span>. تُعيد البيانات الوصفية استعمال علاقة "الأب-الابن" بين العناصر في الصفحة لتعريف مجال (scope) خاصيات البيانات الوصفية. أي أننا نقول بالعربية: "العنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span> يُمثِّل شخصًا، وأيّة خاصيات للبيانات الوصفية التي تجدها في العناصر التي تكون ابنًا للعنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span> هي خاصياتٌ تابعةٌ لذاك الشخص". يمكنك تخيل الأمر على أنَّ العنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span> هو الفاعل في الجملة، والخاصية <span style="font-family:courier new,courier,monospace;">itemprop</span> تمثِّل الفعل (وهو يُشبِه: "مُصوَّرٌ في")، وقيمة خاصية البيانات الوصفية هي المفعول به في الجملة.
</p>

<p>
	يجب تعريف "الفاعل" مرةً واحدةً فقط، وذلك بوضع الخاصيتين <span style="font-family:courier new,courier,monospace;">itemscope</span> و <span style="font-family:courier new,courier,monospace;">itemtype</span> في عنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span> الأب. أما "الفعل" فيُعرَّف بوضع الخاصية<span style="font-family:courier new,courier,monospace;"> itemprop="image"‎</span> في عنصر <span style="font-family:courier new,courier,monospace;">&lt;img&gt;</span>. أما "المفعول به" فلا يحتاج إلى أيّة شيفرات خاصة، لأنَّ النموذج الهيكلي للبيانات الوصفية في HTML5 يقول أنَّ قيمة خاصية البيانات الوصفية في عنصر <span style="font-family:courier new,courier,monospace;">&lt;img&gt;</span> هي في خاصية <span style="font-family:courier new,courier,monospace;">src</span>.
</p>

<p>
	سننتقل الآن إلى القسم التالي من الشيفرة، سنشاهد ترويسة <span style="font-family:courier new,courier,monospace;">&lt;h1&gt;</span> وبداية قائمة <span style="font-family:courier new,courier,monospace;">&lt;dl&gt;</span>. ليس من الضروري إضافة خاصيات البيانات الوصفية إلى عنصرَي <span style="font-family:courier new,courier,monospace;">&lt;h1&gt;</span> و <span style="font-family:courier new,courier,monospace;">&lt;dl&gt;</span>، فلا حاجة إلى وضع خاصية من خاصيات البيانات الوصفية في كل عنصر من عناصر HTML. الغرض من البيانات الوصفية هو "توصيف" البيانات وليس الشيفرات أو الترويسات التي تحيط بها. ترويسة <span style="font-family:courier new,courier,monospace;">&lt;h1&gt;</span> لا تحتوي على قيمة، فهي مجرد ترويسة. وكذلك الأمر لعنصر <span style="font-family:courier new,courier,monospace;">&lt;dt&gt; </span>الذي يحتوي على السلسلة النصية "Name» التي لا تمثل خاصية، وإنما لافتة (label) فقط.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_24">
<span class="tag">&lt;h1&gt;</span><span class="pln">Contact Information</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;dl&gt;</span><span class="pln">
  </span><span class="tag">&lt;dt&gt;</span><span class="pln">Name</span><span class="tag">&lt;/dt&gt;</span><span class="pln">
  </span><span class="tag">&lt;dd&gt;</span><span class="pln">Mark Pilgrim</span><span class="tag">&lt;/dd&gt;</span></pre>

<p>
	أين توجد المعلومات الحقيقية؟ في عنصر <span style="font-family:courier new,courier,monospace;">&lt;dd&gt;</span>، وهنالك سنحتاج إلى وضع خاصية <span style="font-family:courier new,courier,monospace;">itemprop</span>، لكن أيّ خاصية منها؟ إنها خاصية <span style="font-family:courier new,courier,monospace;">name</span>، وأين قيمة الخاصية؟ هي النص الموجود ضمن العنصر <span style="font-family:courier new,courier,monospace;">&lt;dd&gt;</span>، لكن ألا نحتاج إلى وضع القيمة في شيفرة خاصة؟ النموذج الهيكلي للبيانات الوصفية في HTML5 يقول لا، فلا يوجد معنى خاص لعناصر <span style="font-family:courier new,courier,monospace;">&lt;dd&gt;</span>، وستكون قيمة الخاصية هي النص الموجود ضمن العنصر.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_26">
<span class="tag">&lt;dd</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"name"</span><span class="tag">&gt;</span><span class="pln">Mark Pilgrim</span><span class="tag">&lt;/dd&gt;</span></pre>

<p>
	كيف نستطيع التعبير عما سبق بالعربية؟ "اسم هذا الشخص هو Mark Pilgrim". حسنًا، لنتابع.
</p>

<p>
	إضافة الخاصيتين التاليتين صعبٌ قليلًا، هذه هي الشيفرة قبل إضافة البيانات الوصفية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_28">
<span class="tag">&lt;dt&gt;</span><span class="pln">Position</span><span class="tag">&lt;/dt&gt;</span><span class="pln">
</span><span class="tag">&lt;dd&gt;</span><span class="pln">Developer advocate for Google, Inc.</span><span class="tag">&lt;/dd&gt;</span></pre>

<p>
	إذا نظرتَ إلى نوع اصطلاحات <span style="font-family:courier new,courier,monospace;">Person</span>، فستجد أنَّ النص "Developer advocate for Google, Inc.‎" يحتوي على خاصيتين: <span style="font-family:courier new,courier,monospace;">jobTitle</span> ‏(قيمتها "Developer advocate") و <span style="font-family:courier new,courier,monospace;">affiliation‏</span> ( قيمتها "Google, Inc.‎")، لكن كيف تستطيع أن تُعبِّر عن ذلك عبر البيانات الوصفية؟ الجواب المختصر: لا يمكنك فعل ذلك. لا توجد طريقة في البيانات الوصفية تمكِّنك من تقسيم سلسلة نصية إلى عدِّة خاصيات. لا يمكنك القول "أول 18 محرفًا من هذه السلسلة النصية هي خاصيةُ بياناتٍ وصفية، وآخر 12 محرفًا هي خاصيةٌ أخرى".
</p>

<p>
	لكن هذا لا يعني أنَّ الأمر مستحيلٌ. تخيل أنك تريد أن تُنسِّق النص "Developer advocate" بنوع خطٍ مختلف عن النص "Google, Inc.‎". حسنًا، CSS لا تستطيع فعل ذلك أيضًا، لكن ماذا كنتَ ستفعل؟ ستحتاج أولًا إلى وضع كل قسم من السلسلة النصية في حاويات مختلفة، مثل <span style="font-family:courier new,courier,monospace;">&lt;span&gt;</span>، ثم تُطبِّق أنماط CSS على كل عنصر <span style="font-family:courier new,courier,monospace;">&lt;span&gt;</span> على حدة.
</p>

<p>
	يمكنك تطبيق هذه التقنية أيضًا على البيانات الوصفية، فهنالك معلومتان منفصلتان هنا: <span style="font-family:courier new,courier,monospace;">jobTitle</span> و <span style="font-family:courier new,courier,monospace;">affiliation</span>. إذا وضعت كل معلومة في عنصر <span style="font-family:courier new,courier,monospace;">&lt;span&gt;</span>، فستستطيع أن تقول أنَّ كل عنصر <span style="font-family:courier new,courier,monospace;">&lt;span&gt;</span> هو خاصيةٌ مستقلةٌ من خاصيات البيانات الوصفية.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_30">
<span class="tag">&lt;dt&gt;</span><span class="pln">Position</span><span class="tag">&lt;/dt&gt;</span><span class="pln">

</span><span class="tag">&lt;dd&gt;&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"jobTitle"</span><span class="tag">&gt;</span><span class="pln">Developer advocate</span><span class="tag">&lt;/span&gt;</span><span class="pln"> for

</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"affiliation"</span><span class="tag">&gt;</span><span class="pln">Google, Inc.</span><span class="tag">&lt;span&gt;&lt;/dd&gt;</span></pre>

<p>
	هذا يعني: "وظيفة هذا الشخص هي "Developer advocate". هذا الشخص يعمل لدى "Google, Inc.‎"". تلك جملتان، وخاصيتا بياناتٍ وصفية. صحيحٌ أننا وضعنا مزيدًا من الشيفرات، لكننا استفدنا منها خيرَ استفادة.
</p>

<p>
	سنستفيد أيضًا من نفس التقنية لتوصيف معلومات العنوان، يُعرِّف نوع الاصطلاحات <span style="font-family:courier new,courier,monospace;">Person</span> الخاصية <span style="font-family:courier new,courier,monospace;">address</span>، التي هي بدورها عنصرٌ من عناصر البيانات الوصفية، وهذا يعني أنَّ للعنوان نوعُ اصطلاحاتٍ خاصٌ به (<a href="http://schema.org/PostalAddress" rel="external nofollow">http://schema.org/PostalAddress</a>)، وله خاصياتٌ متعلقةٌ به. يُعرِّف نوع الاصطلاحات <span style="font-family:courier new,courier,monospace;">PostalAddress</span> خمسَ خاصياتٍ: <span style="font-family:courier new,courier,monospace;">streetAddress</span> و <span style="font-family:courier new,courier,monospace;">addressLocality</span> و <span style="font-family:courier new,courier,monospace;">addressRegion</span> و <span style="font-family:courier new,courier,monospace;">postalCode</span> و <span style="font-family:courier new,courier,monospace;">addressCountry</span>.
</p>

<p>
	إذا كنتَ مبرمجًا، فمن المرجح أنَّك تعرف كيف تفصل النقطة بين الكائنات وخاصياتها، تخيل أنَّ العلاقة كالآتي:
</p>

<ul>
<li>
		Person
	</li>
	<li>
		Person.PostalAddress
	</li>
	<li>
		Person.PostalAddress.streetAddress
	</li>
	<li>
		Person.PostalAddress.addressLocality
	</li>
	<li>
		Person.PostalAddress.addressRegion
	</li>
	<li>
		Person.PostalAddress.postalCode
	</li>
	<li>
		Person.PostalAddress.addressCountry
	</li>
</ul>
<p>
	لنعد إلى مثالنا. العنوان بأكمله موجودٌ في عنصر <span style="font-family:courier new,courier,monospace;">&lt;dd&gt;</span> وحيد (أكرِّر مرةً أخرى أنَّ العنصر <span style="font-family:courier new,courier,monospace;">&lt;dt&gt;</span> هو لافتة، ولا يلعب دورًا في إضافة معلومات إلى البيانات الوصفية). من السهل الإشارة إلى خاصية <span style="font-family:courier new,courier,monospace;">address</span>، كل ما عليك فعله هو إضافة الخاصية <span style="font-family:courier new,courier,monospace;">itemprop</span> في عنصر <span style="font-family:courier new,courier,monospace;">&lt;dd&gt;</span>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_20">
<span class="tag">&lt;dt&gt;</span><span class="pln">Mailing address</span><span class="tag">&lt;/dt&gt;</span><span class="pln">

</span><span class="tag">&lt;dd</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"address"</span><span class="tag">&gt;</span></pre>

<p>
	لكن تذكَّر أنَّ خاصية <span style="font-family:courier new,courier,monospace;">address</span> هي بدورها عنصرٌ من عناصر البيانات الوصفية، هذا يعني أننا نحتاج إلى وضع الخاصيتين <span style="font-family:courier new,courier,monospace;">itemscope</span> و <span style="font-family:courier new,courier,monospace;">itemtype</span> أيضًا.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_33">
<span class="tag">&lt;dt&gt;</span><span class="pln">Mailing address</span><span class="tag">&lt;/dt&gt;</span><span class="pln">

</span><span class="tag">&lt;dd</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"address"</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln"> </span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/PostalAddress"</span><span class="tag">&gt;</span></pre>

<p>
	لقد رأينا هذا من قبل، لكن للعناصر من المستوى الأول (top-level). عنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span> يحتوي على <span style="font-family:courier new,courier,monospace;">itemtype</span> و <span style="font-family:courier new,courier,monospace;">itemscope</span>، وجميع العناصر الموجودة ضمن العنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span> التي لديها خاصيات للبيانات الوصفية هي ضمن "مجال" (scope) نوع اصطلاحات البيانات الوصفية. لكن هذه هي أول مرة نرى فيها "تشعّب" المجالات، أي تعريف <span style="font-family:courier new,courier,monospace;">itemtype</span> و <span style="font-family:courier new,courier,monospace;">itemscope</span> (في عنصر <span style="font-family:courier new,courier,monospace;">&lt;dd&gt;</span>) داخل مجال موجود مسبقًا (في عنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span>). المجالات المتشعبة تعمل تمامًا كما تعمل شجرة DOM في HTML. العنصر <span style="font-family:courier new,courier,monospace;">&lt;dd&gt;</span> يحتوي على عددٍ معيّنٍ من العناصر الأبناء، ويكون مجالها هو نوع الاصطلاحات المُعرَّف في العنصر <span style="font-family:courier new,courier,monospace;">&lt;dd&gt;</span>، وبعد أن ينتهي العنصر <span style="font-family:courier new,courier,monospace;">&lt;dd&gt;</span> عبر وسم الإغلاق <span style="font-family:courier new,courier,monospace;">&lt;‎/dd&gt;</span> فسيرجع المجال إلى نوع الاصطلاحات المُعرَّف في العنصر الأب (الذي هو <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span> في حالتنا).
</p>

<p>
	تُعاني خاصيات العنوان من نفس المشكلة التي واجهناها عند تعريف الخاصيتين <span style="font-family:courier new,courier,monospace;">jobTitle</span> و <span style="font-family:courier new,courier,monospace;">affiliation</span>، لكن السلسلة النصية للعنوان أطول قليلًا، وعلينا تقسيمها إلى خمس خاصيات للبيانات الوصفية. وسنستعمل نفس الآلية التي اتبعناها سابقًا: وضع كل قطعة من المعلومات في عنصر <span style="font-family:courier new,courier,monospace;">&lt;span&gt;</span>، ثم توصيف تلك المعلومات عبر خاصيات البيانات الوصفية.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_35">
<span class="tag">&lt;dd</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"address"</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln"> </span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/PostalAddress"</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"streetAddress"</span><span class="tag">&gt;</span><span class="pln">100 Main Street</span><span class="tag">&lt;/span&gt;&lt;br&gt;</span><span class="pln">
	</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"addressLocality"</span><span class="tag">&gt;</span><span class="pln">Anytown</span><span class="tag">&lt;/span&gt;</span><span class="pln">,
	</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"addressRegion"</span><span class="tag">&gt;</span><span class="pln">PA</span><span class="tag">&lt;/span&gt;</span><span class="pln">
	</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"postalCode"</span><span class="tag">&gt;</span><span class="pln">19999</span><span class="tag">&lt;/span&gt;</span><span class="pln">
	</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"addressCountry"</span><span class="tag">&gt;</span><span class="pln">USA</span><span class="tag">&lt;/span&gt;</span><span class="pln">
</span><span class="tag">&lt;/dd&gt;</span></pre>

<p>
	بالعربية: "هذا الشخص يملك عنوانًا بريديًا. اسم الشارع لذاك العنوان البريدي هو "100 Main Street"، أما البلدة (locality) فهي "Anytown"، والإقليم (region) هو "PA"، والرمز البريدي (postal code) هو "19999"، واسم الدولة هو "USA"".
</p>

<ul>
<li>
		<strong>س</strong>: هل صيغة العنوان البريدي خاصةٌ بالولايات المتحدة؟
	</li>
	<li>
		<strong>ج</strong>: لا. خاصيات نوع الاصطلاحات <span style="font-family:courier new,courier,monospace;">PostalAddress</span> عامةٌ لتتمكن من وصف أي عنوان بريدي في العالم. لكن لن يكون لجميع العناوين قيمٌ لكل خاصية من الخاصيات، لكن لا بأس بهذا. وقد تتطلب بعض العناوين وضع أكثر من "سطر" واحد في خاصية معيّنة، ولا بأس بهذا أيضًا. فمثلًا، لو كان يحتوي العنوان البريدي على عنوان الشارع ورقم البناء، فسيمثِّل كلاهما الخاصية <span style="font-family:courier new,courier,monospace;">streetAddress</span>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_37">
<span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"address"</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln"> </span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/PostalAddress"</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"streetAddress"</span><span class="tag">&gt;</span><span class="pln">
	100 Main Street
	Suite 415
	</span><span class="tag">&lt;/span&gt;</span><span class="pln">
	...	
</span><span class="tag">&lt;/p&gt;</span></pre>

<p>
	بقي شيءٌ أخيرٌ في صفحة About: قائمةٌ بروابط URL. لدى نوع الاصطلاحات <span style="font-family:courier new,courier,monospace;">Person</span> خاصيةٌ لهذا الغرض اسمها <span style="font-family:courier new,courier,monospace;">url</span>، التي يمكن أن تحتوي على أيّ نوعٍ من أنواع الروابط (المهم أن يكون "رابطًا"). ما أقصده هو أنَّ تعريف الخاصية <span style="font-family:courier new,courier,monospace;">url</span> غير مُحدَّد، ويمكن أن تحتوي على أيّة روابط متعلقة بالشخص: مدونة، أو معرض صور، أو حساب شخصي على موقعٍ آخر مثل فيسبوك أو تويتر.
</p>

<p>
	من المهم أن تلاحظ أنَّ الشخص الواحد قد يمتلك أكثر من خاصية <span style="font-family:courier new,courier,monospace;">url</span>. تقنيًا، يمكن لأي خاصية أن تتكرر، لكن إلى الآن لم نستفد من هذا. على سبيل المثال، قد يكون لديك أكثر من خاصية <span style="font-family:courier new,courier,monospace;">image</span> تُشير إلى روابط URL لصورتين مختلفتين. أريد هنا أن أذكر أربعة روابط URL مختلفة: المدونة، وحساب Google، وحساب Reddit، وحساب تويتر. هنالك قائمة في HTML فيها أربعة روابط موجودة في أربعة عناصر <span style="font-family:courier new,courier,monospace;">&lt;a&gt;</span>، كلُ واحدٍ منها موجودٌ في عنصر <span style="font-family:courier new,courier,monospace;">&lt;li&gt; </span>خاص به. سنُضيف الخاصية<span style="font-family:courier new,courier,monospace;"> itemprop="url"‎</span> إلى كل عنصر من عناصر<span style="font-family:courier new,courier,monospace;"> &lt;a&gt;</span>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5502_18">
<span class="tag">&lt;h1&gt;</span><span class="pln">My Digital Footprints</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
</span><span class="tag">&lt;ul&gt;</span><span class="pln">
  </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://diveintomark.org/"</span><span class="pln">
         </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"url"</span><span class="tag">&gt;</span><span class="pln">weblog</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
  </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://www.google.com/profiles/pilgrim"</span><span class="pln">
         </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"url"</span><span class="tag">&gt;</span><span class="pln">Google profile</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
  </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://www.reddit.com/user/MarkPilgrim"</span><span class="pln">
         </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"url"</span><span class="tag">&gt;</span><span class="pln">Reddit.com profile</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
  </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://www.twitter.com/diveintomark"</span><span class="pln">
         </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"url"</span><span class="tag">&gt;</span><span class="pln">Twitter</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
</span><span class="tag">&lt;/ul&gt;</span></pre>

<p>
	وفقًا للنموذج الهيكلي للبيانات الوصفية في HTML5، سيُعامَل العنصر <span style="font-family:courier new,courier,monospace;">&lt;a&gt;</span> معاملةً خاصةً، فقيمة خاصية البيانات الوصفية تؤخذ من الخاصية <span style="font-family:courier new,courier,monospace;">href</span>، وليس من المحتوى النصي للعنصر. وسيتم تجاهل المحتوى النصي لكل رابط من قِبَل مُفسِّر البيانات الوصفية. وهذا يعني -بالعربية-: "هذا الشخص لديه رابط URL في <a href="http://diveintomark.org/%E2%80%8E" ipsnoembed="true" rel="external nofollow">http://diveintomark.org/‎</a> وهذا الشخص لديه رابط URL آخر في <a href="http://www.google.com/profiles/pilgrim" ipsnoembed="true" rel="external nofollow">http://www.google.com/profiles/pilgrim</a> وهذا الشخص لديه رابط URL آخر في <a href="http://www.reddit.com/user/MarkPilgrim" ipsnoembed="true" rel="external nofollow">http://www.reddit.com/user/MarkPilgrim</a> وهذا الشخص لديه رابط URL آخر في <a href="http://www.twitter.com/diveintomark%C2%BB." ipsnoembed="true" rel="external nofollow">http://www.twitter.com/diveintomark</a>"
</p>

<h2>
	المقتطفات المنسقة Rich Snippets
</h2>

<p>
	ربما تتساءل : "لماذا نفعل هذا؟" هل نُضيف البنى الهيكلية عبثًا؟ لماذا نأبه للبيانات الوصفية ونستعملها؟
</p>

<p>
	هنالك نوعان رئيسيان من التطبيقات التي تستخدم HTML، وبطريقها تستخدم البيانات الوصفية أيضًا:
</p>

<ul>
<li>
		متصفحات الويب
	</li>
	<li>
		محركات البحث
	</li>
</ul>
<p>
	أما للمتصفحات، فهنالك واجهةٌ برمجيةٌ في DOM لاستخلاص عناصر البيانات الوصفية وخاصياتها وقيم تلك الخاصيات من صفحة الويب، لكن للأسف هذه الواجهة البرمجية غير مدعومة إلا من الإصدارات الحديثة لبعض المتصفحات، لهذا اعتبر أنَّ هذا الطريق مسدودٌ إلى أن تدعم جميع المتصفحات هذه الواجهة البرمجية.
</p>

<p>
	مستهلكٌ آخر لشيفرات HTML هو محركات البحث. ماذا يمكن لمحركات البحث فعله مع خاصيات البيانات الوصفية التي تتحدث عن شخصٍ ما؟ تخيل هذا: بدلًا من عرض عنوان الصفحة ومُلخَّص عن محتواها، فسيعرض محرِّك البحث بعض المعلومات الهيكلية الموجودة فيها، مثل الاسم الكامل، والمُسمى الوظيفي، والشركة التي يعمل بها، والعنوان، وربما سيعرض أيضًا صورةً مُصغَّرةً له. هل جذب ذلك انتباهك؟
</p>

<p>
	يدعم محرك البحث Google البيانات الوصفية كجزءٍ من برنامج "المقتطفات المنسقة" (Rich Snippets)، فعندما يُفسِّر عنكبوت البحث في Google صفحتك ويجد خاصيات للبيانات الوصفية التي تتطابق مع نوع الاصطلاحات <a href="http://schema.org/Preson%D8%8C" ipsnoembed="true" rel="external nofollow">http://schema.org/Preson،</a> فسيحاول تفسير تلك الخاصيات ويُخزِّن قيمها بجانب بقية بيانات الصفحة. لدى Google أداةٌ رائعةٌ لكي ترى كيف "يرى" Google خاصيات البيانات الوصفية في صفحتك، واختبارها على صفحة About التي نعمل عليها سيُعطي النتيجة:
</p>

<p style="text-align: center;">
	<img alt="img1 (1).png" class="ipsImage ipsImage_thumbnailed" data-fileid="19252" data-unique="umsu513uc" src="https://academy.hsoub.com/uploads/monthly_2016_10/57f754d240c46_img1(1).png.968b0befb976648ff724175b1832e19f.png"></p>

<p style="text-align: center;">
	<strong>الشكل 1: معلومات البيانات الوصفية كما تُظهِرها أداة اختبار البيانات المنظّمة</strong>
</p>

<p>
	كل البيانات الوصفية موجودٌ هنا: خاصية <span style="font-family:courier new,courier,monospace;">image</span> من <span style="font-family:courier new,courier,monospace;">&lt;img src&gt;</span>، جميع روابط URL من قائمة عناصر <span style="font-family:courier new,courier,monospace;">&lt;a href&gt;</span>، وحتى كائن العنوان (مذكورٌ في "<span style="font-family:courier new,courier,monospace;">address</span>") والخاصيات الخمس المتعلقة به.
</p>

<p>
	الآن، كيف يستعمل Google كل هذه المعلومات؟ الأمر نسبيٌ، فلا توجد قواعد مُلزِمَة لكيفية عرض خاصيات البيانات الوصفية، ولا أيُّها سيُعرَض، وحتى لا توجد قواعد تحكم إذا كانت ستُعرَض هذه الخاصيات أم لا. إذا بحث أحدهم عن "Mark Pilgrim" ورأى Google أنَّ صفحة "About" تستحق الظهور في نتائج البحث، وقرر Google أنَّ خاصيات البيانات الوصفية الموجودة في تلك الصفحة تستحق أن تُعرَض، فعندها ستبدو نتيجة البحث مشابهةً لما يلي:
</p>

<p style="text-align: center;">
	<img alt="img2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19253" data-unique="kdpdlax24" src="https://academy.hsoub.com/uploads/monthly_2016_10/img2.png.bf8ced1b0d1718c5ee8d83521bf4ff60.png"></p>

<p style="text-align: center;">
	<strong>الشكل 2: مثالٌ عن نتيجة البحث عن صفحة فيها بياناتٌ وصفيةٌ</strong>
</p>

<p>
	أول سطر "About Mark Pilgrim" هو عنوان الصفحة الموجود في عنصر <span style="font-family:courier new,courier,monospace;">&lt;title&gt;</span>، ولكن هذا ليس أمرًا مثيرًا للاهتمام؛ لأن محرك Google يفعل هذا لكل صفحة، لكن السطر الثاني مليءٌ بالمعلومات المأخوذة مباشرةً من البيانات الوصفية التي أضفناها إلى الصفحة. "Anytown PA" هو جزءٌ من العنوان البريدي، الموصوف عبر نوع الاصطلاحات <a href="http://schema.org/PostalAddress%D8%8C" ipsnoembed="true" rel="external nofollow">http://schema.org/PostalAddress،</a> أما "Developer advocate" و "Google, Inc.‎" هما الخاصيتان من نوع الاصطلاحات <a href="http://schema.org/Person" ipsnoembed="true" rel="external nofollow">http://schema.org/Person</a> (الخاصية <span style="font-family:courier new,courier,monospace;">jobTitle</span> و <span style="font-family:courier new,courier,monospace;">affiliation</span> على التوالي وبالترتيب).
</p>

<p>
	هذا رائع! لا تحتاج إلى أن تكون شركةً كبيرةً تُبرِمُ اتفاقياتٍ خاصةً مع شركات محركات البحث لتخصيص طريقة عرض نتيجة البحث. كل ما تحتاج له هو عشر دقائق وبعض خاصيات HTML لكي توصِّف فيها بياناتك التي ستنشرها في صفحتك.
</p>

<ul>
<li>
		<strong>س</strong>: فعلتُ كل ما قلتَه لي، لكن لم تتغير طريقة عرض نتائج البحث عن صفحتي في Google، ما الخطب؟
	</li>
	<li>
		<strong>ج</strong>: "لا تضمن Google أنَّ الشيفرة الموجودة في أيّة صفحة أو موقع ستُستخدَم في نتائج البحث"، لكن بغض النظر أنَّ محرك Google قرر ألّا يستعمل البيانات الوصفية في صفحتك، فقد يستعملها محركُ بحثٍ آخر. فمعيار البيانات الوصفية (Microdata) هو معيارٌ مفتوحٌ يستطيع أيُّ شخصٍ توظيفه -كما هي بقية HTML5-. من واجبك توفير أكبر قدر من البيانات تستطيع تقديمه. ثم اترك الأمر للآخرين لكي يُقرِّروا ماذا يفعلون معها. ربما يفاجئوك!
	</li>
</ul>
<p>
	ترجمة -وبتصرّف- لجزء من فصل "<a href="http://diveinto.html5doctor.com/extensibility.html" rel="external nofollow">Microdata</a>" من كتاب <a href="http://diveinto.html5doctor.com/index.html" rel="external nofollow">Dive Into HTML5</a> لمؤلفه Mark Pilgrim.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/html/html5/%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D9%85%D9%86%D8%B8%D9%85%D8%A7%D8%AA%D8%A7%D9%84%D8%B4%D9%91%D8%B1%D9%83%D8%A7%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-microdata-%D9%81%D9%8A-html5-r472/" rel="">توصيف المنظمات/الشركات باستخدام microdata في HTML5</a>
	</li>
	<li>
		المقال السابق:<a href="http://%D9%85%D8%AF%D8%AE%D9%84%20%D8%A5%D9%84%D9%89%20%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA%20%D8%A7%D9%84%D9%88%D8%B5%D9%81%D9%8A%D8%A9%20(microdata)%20%D9%81%D9%8A%20HTML5" rel="external nofollow"> مدخل إلى البيانات الوصفية (microdata) في HTML5</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">نحو فهم أعمق لتقنيات HTML5 </a>
	</li>
</ul>
]]></description><guid isPermaLink="false">377</guid><pubDate>Sat, 08 Oct 2016 07:33:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x627;&#x644;&#x648;&#x635;&#x641;&#x64A;&#x629; (microdata) &#x641;&#x64A; HTML5</title><link>https://academy.hsoub.com/programming/html/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D8%B5%D9%81%D9%8A%D8%A9-microdata-%D9%81%D9%8A-html5-r375/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_09/html5-microdata.png.da48b86ba62c07a2597908e5305c6e9b.png" /></p>

<p style="text-align: center;">
	<img alt="html5-microdata.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19015" data-unique="suq2edouk" src="https://academy.hsoub.com/uploads/monthly_2016_09/html5-microdata.png.b99804dfb45c5615e9f5c179a6524cb7.png"></p>

<p>
	هنالك <a href="https://simon.html5.org/html-elements" rel="external nofollow">أكثر من 100 عنصر في HTML5</a>، بعضها هيكليٌ تمامًا وبعضها مجردُ حاويةٍ لواجهةٍ برمجيةٍ. وعبر تاريخ HTML، تجادل كاتبو المعايير حول العناصر التي يجب تضمينها في اللغة، فهل يجب أن تحتوي HTML على عنصر <span style="font-family:courier new,courier,monospace;">&lt;figure&gt;</span>؟ أو عنصر <span style="font-family:courier new,courier,monospace;">&lt;person&gt;</span>؟ ماذا عن عنصر <span style="font-family:courier new,courier,monospace;">&lt;rant&gt;</span>؟ اُتخِذَت القرارات، وكُتِبَت المعايير، وطوَّر المطورون تطبيقاتهم، وأضاف صانعو المتصفحات الميزات لمتصفحاتهم، ودُفِعَت عجلة تطوير الويب إلى الأمام.
</p>

<p>
	من المؤكَّد أنَّ HTML لن تستطيع إرضاء الجميع، إذ لا يستطيع أيُّ معيارٍ فعل هذا. لم تصل بعض الأفكار المقترحة إلى المستوى المطلوب، فمثلًا، لا يوجد عنصر <span style="font-family:courier new,courier,monospace;">&lt;person&gt;</span> في HTML5 (وكذلك الأمر لعنصر <span style="font-family:courier new,courier,monospace;">&lt;rant&gt;</span>)؛ لا يوجد شيءٌ يمنعك من إضافة عنصر <span style="font-family:courier new,courier,monospace;">&lt;person&gt;</span> إلى صفحات الويب التي تكتبها، لكنها لن تكون سليمةً بنيويًا، ولن تعمل بشكلٍ متماثل في جميع المتصفحات، وقد تتعارض مع معايير HTML المستقبلية إن أضافتها لاحقًا.
</p>

<p>
	حسنًا، إن لم يكن الحل كامنًا في إنشاء عناصر جديدة، فماذا على مطوِّر الويب الذي يحب اتباع القواعد الهيكلية أن يفعل؟ كانت هنالك محاولاتٌ لتوسعة الإصدارات القديمة من HTML. أشهر طريقة هي microformats، التي تستعمل الخاصيتين <span style="font-family:courier new,courier,monospace;">class</span> و <span style="font-family:courier new,courier,monospace;">rel</span> في HTML. خيارٌ آخر هو RDFa، التي صُمِّمَت لتعمل في XHTML لكنها صُدِّرَت لاحقًا إلى HTML أيضًا.
</p>

<p>
	لدى Microformats و RDFa نقاطُ قوةٍ وضعف. إذ تأخذان طريقًا مختلفًا تمامًا لتحقيق نفس الهدف: توسعة صفحات الويب بإضافة بُنى هيكلية جديدة لا تُمثِّل جزءًا من أساس لغة HTML. لا أنوي أن أقلب هذا الدرس إلى حربٍ بين الصيغ؛ وإنما أريد أن أُركِّز على خيارٍ ثالثٍ طوِّرَ بعد تعلم الدروس من microformats و RDFa، وصُمِّمَ ليندمج جيدًا مع HTML5: إنه "البيانات الوصفية" (microdata).
</p>

<h2>
	ما هي البيانات الوصفية؟
</h2>

<p>
	كل كلمة في الجملة الآتية مهمة، لذا انتبه جيدًا إليها:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix">
		<p>
			توصِّف البيانات الوصفية شجرة DOM بثنائياتٍ على شكل "الاسم/القيمة" آتيةٌ من أنواع اصطلاحاتٍ مُخصَّصة.
		</p>
	</div>
</blockquote>

<p>
	حسنًا، ماذا تعني الجملة السابقة العجيبة؟ لنبدأ من نهايتها إلى بدايتها. تتمحور البيانات الوصفية (microdata) حول "أنواع الاصطلاحات المخصصة" (custom vocabularies). تخيّل أنَّ جميع عناصر HTML5 هي نوعٌ وحيدٌ من الاصطلاحات. وهذا النوع يستطيع تمثيل "قسم" (section) أو "مقالة" (article)، لكنه لا يستطيع تضمين عناصر لتمثيل "شخص" أو "حدث". فإذا أردت تمثيل "شخص" في صفحة الويب، فعليك تعريف نوع اصطلاحاتٍ خاص بك. تسمح لك البيانات الوصفية (microdata) بذلك، حيث يستطيع أيُّ شخصٍ أن يُعرِّف اصطلاحات microdata خاصة به ويبدأ بتضمين خاصياته (properties) في صفحات الويب التي يطورها.
</p>

<p>
	النقطة الثانية التي عليك أن تعرفها عن البيانات الوصفية أنَّه تعمل وفق ثنائيات "الاسم/القيمة". فكل نوع اصطلاحات يُعرِّف مجموعةً من الخاصيات التي لها أسماءٌ معيّنة. على سبيل المثال، قد يتضمن نوع الاصطلاحات "person" خاصياتٍ مثل name و image. ولتضمين خاصية من خاصيات البيانات الوصفية (microdata) في صفحة الويب، عليك وضع اسم الخاصية في مكانٍ معيّن. واعتمادًا على العنصر الذي تضع فيه خاصيتك، هنالك قواعد حول كيفية استخلاص قيمة الخاصية (سنأتي على ذكرها في القسم التالي).
</p>

<p>
	بالإضافة إلى الخاصيات التي لها أسماء، تعتمد البيانات الوصفية كثيرًا على مفهوم "المجال" (scope). أبسط طريقة تستطيع تخيّل المجالات في البيانات الوصفية هي أن تتخيل علاقة "الأب-الابن" بين عناصر DOM. العنصر <span style="font-family:courier new,courier,monospace;">&lt;html&gt; </span>يحتوي عادةً على عنصرين: <span style="font-family:courier new,courier,monospace;">&lt;head&gt;</span> و <span style="font-family:courier new,courier,monospace;">&lt;body&gt;</span>. العنصر <span style="font-family:courier new,courier,monospace;">&lt;body&gt;</span> يحتوي عادةً على عدِّة أبناء وقد يحتوي كلٌ منها على أبناء خاصة به. على سبيل المثال، قد تحتوي صفحة الويب على عنصر <span style="font-family:courier new,courier,monospace;">&lt;h1&gt;</span> موجودٌ ضمن عنصر <span style="font-family:courier new,courier,monospace;">&lt;hgroup&gt;</span> موجودٌ داخل عنصر <span style="font-family:courier new,courier,monospace;">&lt;header&gt;</span> الموجود داخل عنصر <span style="font-family:courier new,courier,monospace;">&lt;body&gt;</span>. وقد يحتوي جدولٌ ما على خلية <span style="font-family:courier new,courier,monospace;">&lt;td&gt;</span> موجودة ضمن<span style="font-family:courier new,courier,monospace;"> &lt;tr&gt;</span> الموجود ضمن <span style="font-family:courier new,courier,monospace;">&lt;table&gt; </span>(الذي يتفرّع من <span style="font-family:courier new,courier,monospace;">&lt;body&gt;</span>). تُعيد البيانات الوصفية استخدام هذه البنية الهيكلية لشجرة DOM لتوفير طريقة لقول "جميع الخاصيات ضمن هذا العنصر مأخوذةٌ من نوع الاصطلاحات المُحدَّد". وهذا يسمح لك باستخدام أكثر من نوع من أنواع الاصطلاحات في البيانات الوصفية في نفس الصفحة. تستطيع أيضًا أن تضع نوعًا من أنواع اصطلاحات البيانات الوصفية ضمن نوعٍ آخر، وذلك عبر إعادة استخدام البنية الهيكلية لشجرة DOM (سأريك عدِّة أمثلة عن تداخل أنواع الاصطلاحات في دروسٍ قادمة).
</p>

<p>
	تحدثتُ سابقًا عن موضوع DOM، لكن دعني أستفيض قليلًا فيه. مهمة البيانات الوصفية هي إضافةُ مزيدٍ من الهيكلية إلى البيانات الظاهرة في صفحة الويب. ليس الغرض من البيانات الوصفية أن تكون صيغةُ بياناتٍ تعملُ بمفردها، وإنما هي مكمِّلةٌ للغة HTML وتعتمد عليها. وكما سترى في القسم التالي، تعمل البيانات الوصفية بأفضل صورة ممكنة عندما تستعمل HTML استعمالًا سليمًا، لكن اصطلاحات HTML غير كافية للتعبير عن كل ما نريده، لذلك أتت البيانات الوصفية (microdata) للتحكم الدقيق في البُنى الهيكلية للبيانات الموجودة في شجرة DOM. إذا كانت البيانات التي تحاول توصيفها غير موجودةٍ في شجرة DOM، فربما عليك أن تتراجع وتعيد التفكير فيما إذا كانت البيانات الوصفية هي الحل الصحيح لمشكلتك.
</p>

<p>
	هل أصبحت هذه الجملة واضحةً الآن؟ "توصِّف البيانات الوصفية شجرة DOM بثنائياتٍ على شكل "الاسم/القيمة" آتيةٌ من أنواع اصطلاحاتٍ مُخصَّصة". أرجو ذلك، ولنرى تطبيقاتٍ عمليةً عليها في بقية هذا السلسلة.
</p>

<h2>
	النموذج الهيكلي للبيانات الوصفية
</h2>

<p>
	تعريف نوع اصطلاحات البيانات الوصفية الخاص بك سهلٌ. تحتاج أولًا إلى مجال أسماء (namespace) الذي هو URL. رابط URL لمجال الأسماء يمكن أن يُشير إلى صفحة ويب موجودة، لكن هذا ليس ضروريًا. لنقل أنَّك تريد إنشاء نوع اصطلاحات لوصف "شخص ما". إذا كنتُ أملك النطاق <span style="font-family:courier new,courier,monospace;">schema.org </span>فسأستعمل رابط URL الآتي<span style="font-family:courier new,courier,monospace;"> <a href="http://schema.org/Person" ipsnoembed="true" rel="external nofollow">http://schema.org/Person</a></span> كمجال أسماءٍ لنوع اصطلاحات البيانات الوصفية. هذه طريقة سهلة لإنشاء مُعرِّف فريد عالمي: اختر رابط URL في نطاقٍ تملكه.
</p>

<p>
	سأحتاج إلى تعريف بعض الخاصيات في نوع الاصطلاحات، لنبدأ بثلاث خاصيات أساسية:
</p>

<ul>
<li>
		<strong>name</strong> (اسمك الكامل)
	</li>
	<li>
		<strong>image</strong> (رابطٌ لصورةٍ لك)
	</li>
	<li>
		<strong>url</strong> (رابطٌ لموقعٍ يتعلق بك، مثل مدونتك أو حسابك على Google)
	</li>
</ul>
<p>
	بعض الخاصيات السابقة هي روابط URL، وبعضها الآخر مجرد نص بسيط. وتربُط كلُ واحدةٍ منها نفسها بنوعٍ معيّن من الشيفرات، وحتى قبل أن تبدأ بالتفكير عن البيانات الوصفية أو الاصطلاحات أو إلى ما هنالك… تخيّل أنَّ لديك صفحة لحساب المستخدم أو صفحة "About"، من المحتمل أنَّك ستضع اسمك كترويسة (ربما في عنصر <span style="font-family:courier new,courier,monospace;">&lt;h1&gt;</span>)، أما صورتك ففي عنصر <span style="font-family:courier new,courier,monospace;">&lt;img&gt;</span> ذلك لأنَّك تريد أن يراها زوار صفحتك، وستضع أيّة روابط URL مرتبطة بك في عناصر <span style="font-family:courier new,courier,monospace;">&lt;a&gt;</span> ذلك لأنَّك تريد أن يتمكن زوار صفحتك من النقر عليها. ولنقل أيضًا أنَّ كامل معلوماتك الشخصية موجودةٌ في عنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span> لفصلها عن بقية محتويات الصفحة. إذًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9517_9">
<span class="tag">&lt;section&gt;</span><span class="pln">
	</span><span class="tag">&lt;h1&gt;</span><span class="pln">Mark Pilgrim</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
	</span><span class="tag">&lt;p&gt;&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"http://www.example.com/photo.jpg"</span><span class="pln"> </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"[me smiling]"</span><span class="tag">&gt;&lt;/p&gt;</span><span class="pln">
	</span><span class="tag">&lt;p&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://diveintomark.org/"</span><span class="tag">&gt;</span><span class="pln">weblog</span><span class="tag">&lt;/a&gt;&lt;/p&gt;</span><span class="pln">
</span><span class="tag">&lt;/section&gt;</span></pre>

<p>
	النموذج الهيكلي للبيانات الوصفية هو ثنائيات على شكل "الاسم/القيمة". يُعرَّف اسم الخاصية التي تتبع لبيانات الوصفية (مثل <span style="font-family:courier new,courier,monospace;">name</span> أو <span style="font-family:courier new,courier,monospace;">image</span> أو <span style="font-family:courier new,courier,monospace;">url</span> في مثالنا) دومًا ضمن عنصر HTML. ثم تؤخذ قيمة تلك الخاصية من شجرة DOM للعنصر. ولأغلبية عناصر HTML، تكون قيمة الخاصية هي المحتوى النصي للعنصر، لكن هنالك عددٌ لا بأس به من الاستثناءات.
</p>

<center>
	<table border="1"><tbody>
<tr>
<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					<strong>العنصر</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					<strong>القيمة</strong>
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;meta&gt;
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					الخاصية content
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;audio&gt;
				</td>
				<td rowspan="6" style="padding: 5px 10px; text-align: center;">
					الخاصية src
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;embed&gt;
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;iframe&gt;
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;img&gt;
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;source&gt;
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;video&gt;
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;a&gt;
				</td>
				<td rowspan="3" style="padding: 5px 10px; text-align: center;">
					الخاصية href
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;area&gt;
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;link&gt;
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;object&gt;
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					الخاصية data
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					&lt;time&gt;
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					الخاصية datetime
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					جميع العناصر الأخرى
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					المحتوى النصي
				</td>
			</tr>
</tbody></table>
</center>

<p>
	"إضافة البيانات الوصفية" إلى صفحتك هي مسألة إضافة بعض الخاصية إلى عناصر HTML التي لديك. أول شيء عليك فعله هو التصريح عن نوع الاصطلاحات الذي ستستخدمه، وذلك عبر الخاصية <span style="font-family:courier new,courier,monospace;">itemtype</span>، أما الشيء الثاني الذي عليك دائمًا فعله هو التصريح عن مجال (scope) نوع الاصطلاحات، وذلك عبر الخاصية <span style="font-family:courier new,courier,monospace;">itemscope</span>. جميع البيانات التي نريد هيكلتها في المثال الآتي موجودةٌ في عنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span>، لذا سنُعرِّف الخاصيتين <span style="font-family:courier new,courier,monospace;">itemtype</span> و <span style="font-family:courier new,courier,monospace;">itemscope</span> في العنصر <span style="font-family:courier new,courier,monospace;">&lt;section&gt;</span>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9517_11">
<span class="tag">&lt;section</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln"> </span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/Person"</span><span class="tag">&gt;</span></pre>

<p>
	اسمك هو أول المعلومات الموجودة ضمن عنصر &lt;section&gt;، وهو موجودٌ ضمن عنصر <span style="font-family:courier new,courier,monospace;">&lt;h1&gt;</span>، وعنصر <span style="font-family:courier new,courier,monospace;">&lt;h1&gt;</span> لا يملك أيّ معنى خاص في النموذج الهيكلي للبيانات الوصفية في HTML5، لذلك سيُصنَّف تحت بند "جميع العناصر الأخرى" حيث تكون قيمة الخاصية هي المحتوى النصي الموجود ضمن العنصر (سيعمل ما سبق بشكلٍ مماثل إن كان اسمك موجودًا ضمن عنصر <span style="font-family:courier new,courier,monospace;">&lt;p&gt;</span> أو <span style="font-family:courier new,courier,monospace;">&lt;div&gt; </span>أو <span style="font-family:courier new,courier,monospace;">&lt;span&gt;</span>).
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9517_13">
<span class="tag">&lt;h1</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"name"</span><span class="tag">&gt;</span><span class="pln">Mark Pilgrim</span><span class="tag">&lt;/h1&gt;</span></pre>

<p>
	السطر السابق يقول بالعربية: "هذه هي خاصية <span style="font-family:courier new,courier,monospace;">name</span> لنوع الاصطلاحات <a href="http://schema.org/Person%D8%8C" ipsnoembed="true" rel="external nofollow">http://schema.org/Person،</a> وقيمة تلك الخاصية هي Mark Pilgrim".
</p>

<p>
	الخاصية التالية هي خاصية <span style="font-family:courier new,courier,monospace;">image</span>، التي من المفترض أن تكون رابط URL، ووفقًا للنموذج الهيكلي للبيانات الوصفية في HTML5، "قيمة" خاصية البيانات الوصفية الموجودة في العنصر <span style="font-family:courier new,courier,monospace;">&lt;img&gt; </span>هي قيمة الخاصية <span style="font-family:courier new,courier,monospace;">src</span>، لكن لاحظ أنَّ رابط URL لصورتك الشخصية موجودٌ في خاصية <span style="font-family:courier new,courier,monospace;">&lt;img src&gt;</span>، فكل ما علينا فعله هو التصريح أنَّ العنصر <span style="font-family:courier new,courier,monospace;">&lt;img&gt;</span> يُمثِّل خاصية <span style="font-family:courier new,courier,monospace;">image</span>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4367_10">
<span class="tag">&lt;p&gt;</span><span class="pln">
  </span><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"image"</span><span class="pln">
       </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"http://www.example.com/photo.jpg"</span><span class="pln">
       </span><span class="atn">alt</span><span class="pun">=</span><span class="atv">"[me smiling]"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/p&gt;</span></pre>

<p>
	السطر السابق يقول بالعربية: "هذه هي قيمة خاصية <span style="font-family:courier new,courier,monospace;">image</span> لنوع الاصطلاحات <a href="http://schema.org/Person%D8%8C" ipsnoembed="true" rel="external nofollow">http://schema.org/Person،</a> وقيمة الخاصية هي <a href="http://www.example.com/photo.jpg%C2%BB." ipsnoembed="true" rel="external nofollow">http://www.example.com/photo.jpg</a>".
</p>

<p>
	في النهاية، الخاصية <span style="font-family:courier new,courier,monospace;">url</span> هي رابط URL أيضًا، ووفقًا للنموذج الهيكلي للبيانات الوصفية في HTML5، "قيمة" خاصية البيانات الوصفية الموجودة في العنصر <span style="font-family:courier new,courier,monospace;">&lt;a&gt;</span> هي قيمة الخاصية <span style="font-family:courier new,courier,monospace;">href</span>، وهذا يتوافق توافقًا مثاليًا مع الشيفرة الموجودة عندك؛ فكل ما تحتاج له هو أن تقول أنَّ عنصر <span style="font-family:courier new,courier,monospace;">&lt;a&gt;</span> الموجود مسبقًا يُمثِّل الخاصية <span style="font-family:courier new,courier,monospace;">url</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4367_12">
<span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"url"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"http://diveintomark.org/"</span><span class="tag">&gt;</span><span class="pln">dive into mark</span><span class="tag">&lt;/a&gt;</span></pre>

<p>
	السطر السابق يقول بالعربية: "هذه هي قيمة خاصية <span style="font-family:courier new,courier,monospace;">url</span> لنوع الاصطلاحات <a href="http://schema.org/Person%D8%8C" ipsnoembed="true" rel="external nofollow">http://schema.org/Person،</a> وقيمة الخاصية هي <a href="http://diveintomark.org/%E2%80%8E%C2%BB." ipsnoembed="true" rel="external nofollow">http://diveintomark.org/‎</a>".
</p>

<p>
	إذا كانت شيفراتك مختلفةً قليلًا فلن تُشكِّل لك مشكلةً بكل تأكيد. يمكنك إضافة خاصيات البيانات الوصفية وقيمتها إلى أيّ شيفرة من شيفرات HTML، حتى الشيفرات من القرن العشرين التي كانت تستعمل الجداول لإنشاء تخطيط الصفحة. وبغض النظر عن أنني لا أنصحك بتاتًا بكتابة مثل هذه الشيفرات، لكنها للأسف ما تزال شائعةً، وما يزال بإمكاننا إضافة خاصيات البيانات الوصفية إليها.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4367_20">
<span class="tag">&lt;table&gt;</span><span class="pln">
  </span><span class="tag">&lt;tr&gt;&lt;td&gt;</span><span class="pln">Name</span><span class="tag">&lt;td&gt;</span><span class="pln">Mark Pilgrim
  </span><span class="tag">&lt;tr&gt;&lt;td&gt;</span><span class="pln">Link</span><span class="tag">&lt;td&gt;</span><span class="pln">
    </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">#</span><span class="pln"> </span><span class="atn">onclick</span><span class="pun">=</span><span class="pln">goExternalLink</span><span class="pun">()</span><span class="tag">&gt;</span><span class="pln">http://diveintomark.org/</span><span class="tag">&lt;/a&gt;</span><span class="pln">
</span><span class="tag">&lt;/table&gt;</span></pre>

<p>
	أضف خاصية <span style="font-family:courier new,courier,monospace;">itemprop</span> في خلية الجدول التي تحتوي على الاسم لإنشاء الخاصية <span style="font-family:courier new,courier,monospace;">name</span>. خلايا الجدول لا تملك أيّ معنى خاص في النموذج الهيكلي للبيانات الوصفية في HTML5، لذلك ستكون قيمة الخاصية هي المحتوى النصي الموجود ضمن الخلية.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4367_18">
<span class="tag">&lt;tr&gt;</span><span class="pln">
  </span><span class="tag">&lt;td&gt;</span><span class="pln">Name</span><span class="tag">&lt;td</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"name"</span><span class="tag">&gt;</span><span class="pln">Mark Pilgrim</span></pre>

<p>
	إضافة الخاصية <span style="font-family:courier new,courier,monospace;">url</span> أصعب بقليل، حيث لا تستعمل الشيفرة السابقة العنصر <span style="font-family:courier new,courier,monospace;">&lt;a&gt;</span> استعمالًا سليمًا، فبدلًا من وضع رابط للصفحة الهدف في خاصية <span style="font-family:courier new,courier,monospace;">href</span>، فستستعمل JavaScript والخاصية <span style="font-family:courier new,courier,monospace;">onclick</span> لاستدعاء دالة (غير معروضة هنا) التي تستخلص رابط URL ثم تنتقل إليه. ولكي تُصاب بالغثيان، لنقل أنَّ تلك الدالة ستفتح الرابط في نافذة منبثقة صغيرة دون شريط تمرير. ألم يكن الويب مسليًا في القرن الماضي؟
</p>

<p>
	على أيّة حال، ما يزال متوجبًا عليك إضافة خاصية البيانات الوصفية، لكن عليك أن تكون مبدعًا قليلًا. لا يمكنك استخدام عنصر <span style="font-family:courier new,courier,monospace;">&lt;a&gt;</span> إذ أنَّ الرابط الهدف ليس موجودًا في خاصية <span style="font-family:courier new,courier,monospace;">href</span>، ولا توجد طريقةٌ تستطيع فيها تجاوز القاعدة التي تقول "في العنصر <span style="font-family:courier new,courier,monospace;">&lt;a&gt;</span>، ابحث عن قيمة خاصية البيانات الوصفية في <span style="font-family:courier new,courier,monospace;">href</span>"، لكنك تستطيع إضافة عنصر ليحتوي الفوضى السابقة، وتُضيف الخاصية <span style="font-family:courier new,courier,monospace;">url</span> إليه.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4367_22">
<span class="tag">&lt;table</span><span class="pln"> </span><span class="atn">itemscope</span><span class="pln"> </span><span class="atn">itemtype</span><span class="pun">=</span><span class="atv">"http://schema.org/Person"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;tr&gt;&lt;td&gt;</span><span class="pln">Name</span><span class="tag">&lt;td&gt;</span><span class="pln">Mark Pilgrim
  </span><span class="tag">&lt;tr&gt;&lt;td&gt;</span><span class="pln">Link</span><span class="tag">&lt;td&gt;</span><span class="pln">
    </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">itemprop</span><span class="pun">=</span><span class="atv">"url"</span><span class="tag">&gt;</span><span class="pln">
      </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">#</span><span class="pln"> </span><span class="atn">onclick</span><span class="pun">=</span><span class="pln">goExternalLink</span><span class="pun">()</span><span class="tag">&gt;</span><span class="pln">http://diveintomark.org/</span><span class="tag">&lt;/a&gt;</span><span class="pln">
    </span><span class="tag">&lt;/span&gt;</span><span class="pln">
</span><span class="tag">&lt;/table&gt;</span></pre>

<p>
	ولعدم وجود قاعدة خاصة تنطبق على العنصر <span style="font-family:courier new,courier,monospace;">&lt;span&gt;</span>، فستُستعمَل القاعدة الافتراضية "قيمة الخاصية هي المحتوى النصي الموجود ضمن العنصر". "المحتوى النصي" لا يعني "جميع الشيفرات داخل العنص" (كالتي تحصل عليها عبر خاصية innerHTML في DOM على سبيل المثال)، وإنما تعني "النص فقط". وفي هذه الحالة يكون المحتوى النصي لعنصر <span style="font-family:courier new,courier,monospace;">&lt;a&gt;</span> الموجود ضمن العنصر <span style="font-family:courier new,courier,monospace;">&lt;span&gt;</span> هو<strong> <a href="http://diveintomark.org/%E2%80%8E" ipsnoembed="true" rel="external nofollow">http://diveintomark.org/‎</a></strong>.
</p>

<h2>
	الخلاصة
</h2>

<p>
	يمكنك إضافة خاصية البيانات الوصفية إلى أي شيفرة. وإذا كنتَ تستعمل HTML بشكلٍ صحيح، فستجد أنَّ إضافة البيانات الوصفية أسهل وأيسر فيما لو كانت شيفرة HTML مشوهةً، لكنك تستطيع إضافة البيانات الوصفية إليها على أيّة حال.
</p>

<p>
	ترجمة -وبتصرّف- لفصل "<a href="http://diveinto.html5doctor.com/extensibility.html" rel="external nofollow">Microdata</a>" من كتاب <a href="http://diveinto.html5doctor.com/index.html" rel="external nofollow">Dive Into HTML5</a> لمؤلفه Mark Pilgrim.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/html/html5/%D8%AA%D9%88%D8%B5%D9%8A%D9%81-%D8%A7%D9%84%D8%A3%D8%B4%D8%AE%D8%A7%D8%B5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-metadata-%D9%81%D9%8A-html5-r377/" rel="">توصيف الأشخاص باستخدام metadata في HTML5</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/html/html5/%D8%A7%D9%84%D9%86%D9%85%D8%A7%D8%B0%D8%AC-forms-%D9%81%D9%8A-html5-r370/" rel="">النماذج (Forms) في HTML5</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">نحو فهم أعمق لتقنيات HTML5 </a>
	</li>
</ul>
]]></description><guid isPermaLink="false">375</guid><pubDate>Fri, 09 Sep 2016 18:55:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x646;&#x645;&#x627;&#x630;&#x62C; (Forms) &#x641;&#x64A; HTML5</title><link>https://academy.hsoub.com/programming/html/%D8%A7%D9%84%D9%86%D9%85%D8%A7%D8%B0%D8%AC-forms-%D9%81%D9%8A-html5-r370/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_08/html5-forms.png.ba83c388b381ba8c680332fbca75fe00.png" /></p>
<p>
	كلنا نعرف نماذج الويب، أليس كذلك؟ أنشِئ<span style="font-family:courier new,courier,monospace;"> &lt;form&gt;</span>، وبعض عناصر <span style="font-family:courier new,courier,monospace;">&lt;input type="text"‎&gt;</span>، وربما عنصر <span style="font-family:courier new,courier,monospace;">&lt;input type="password"‎&gt;</span> وإنهِ النموذج بزر <span style="font-family:courier new,courier,monospace;">&lt;input type="submit"‎&gt;</span>.
</p>

<p style="text-align: center;">
	<img alt="html5-forms.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18650" data-unique="ukcppsv73" src="https://academy.hsoub.com/uploads/monthly_2016_08/html5-forms.png.03f534fbca62746514256521abbdf9ae.png">
</p>

<p>
	معلوماتك السابقة منقوصة، إذ تُعرِّف HTML5 ثلاثة عشر نوع إدخالٍ جديدٍ التي تستطيع استعمالها في نماذجك. لاحظ أنني ذكرتُ كلمة "تستطيع" بصيغة المضارع، أي أنَّك تستطيع استخدامها الآن دون أيّة أمور التفافية أو إضافات مُخصَّصة. لكن لا تتحمس كثيرًا؛ فلم أكن أقصد أنَّ جميع تلك الميزات الرائعة مدعومة في كل متصفح؛ ما أقصده هو أنَّ تلك النماذج ستعمل بشكلٍ رائع في المتصفحات الحديثة، لكنها ستبقى تعمل في المتصفحات القديمة (بما في ذلك IE6) وإن لم يكن سلوكها مماثلًا لسلوكها في المتصفحات الحديثة.
</p>

<h2>
	النص البديل placeholder
</h2>

<center>
	<table border="1">
		<tbody>
			<tr>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					IE
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Fiefox
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Safari
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Chrome
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Opera
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					iPhone
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Android
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px; text-align: center;">
					10+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					3.7+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					11.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					2.3+
				</td>
			</tr>
		</tbody>
	</table>
</center>

<p>
	أول تحسين لنماذج الويب أتت به HTML5 هو القدرة على ضبط نص بديل (placeholder text) في حقل الإدخال. "النص البديل" هو النص الذي سيُعرَض داخل حقل الإدخال لطالما كان حقل الإدخال فارغًا، وسيختفي النص البديل بعد بدء الكتابة في الحقل.
</p>

<p>
	من المرجَّح أنَّك شاهدت نصًا بديلًا من قبل، فمتصفح Firefox فيه نصٌ بديلٌ في شريط العنوان مكتوبٌ فيه "Search Bookmarks and History" (النص البديل في الإصدارات الحديثة هو "Search" فقط):
</p>

<p style="text-align: center;">
	<img alt="1-location-bar-empty-unfocused.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18628" data-unique="1b16k8n18" src="https://academy.hsoub.com/uploads/monthly_2016_07/1-location-bar-empty-unfocused.png.92a35d4a52372a8ce0020e9b3b9b6a47.png">
</p>

<p>
	وعندما تهمُّ بكتابة أيّ شيءٍ فيه، فسيختفي النص البديل:
</p>

<p style="text-align: center;">
	<img alt="2-location-bar-empty-focused.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18629" data-unique="eprpaianr" src="https://academy.hsoub.com/uploads/monthly_2016_07/2-location-bar-empty-focused.png.beeb396c16fc43c438e991d0607cc7eb.png">
</p>

<p>
	هذه آلية تضمين النص البديل في نماذج الويب الخاصة بك:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2716_8"><span class="tag">&lt;form&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"q"</span><span class="pln"> </span><span class="atn">placeholder</span><span class="pun">=</span><span class="atv">"Search Bookmarks and History"</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"Search"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	ستتجاهل المتصفحاتُ التي لا تدعم النص البديل الخاصيةَ <span style="font-family:courier new,courier,monospace;">placeholder</span> ببساطة. انظر إلى الجدول أعلاه لمعرفة ما هي المتصفحات التي تدعم النص البديل.
</p>

<ul>
	<li>
		س: هل يمكنني وضع وسوم HTML في خاصية <span style="font-family:courier new,courier,monospace;">placeholder</span>؟ أريد أن أضيف صورةً أو أن أغيِّرَ الألوان.
	</li>
	<li>
		ج: لا يمكن أن تحتوي خاصية <span style="font-family:courier new,courier,monospace;">placeholder</span> إلا على نصٍ بسيط، ولا يُسمَح بوضع وسوم HTML فيها. لكن هنالك إضافات CSS تسمح لك بتنسيق النص البديل في بعض المتصفحات.
	</li>
</ul>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير واجهات المستخدم
		</p>

		<p class="banner-subtitle">
			ابدأ عملك الحر بتطوير واجهات المواقع والمتاجر الإلكترونية فور انتهائك من الدورة
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/front-end-web-development/" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة تطوير واجهات المستخدم" src="https://academy.hsoub.com/learn/assets/images/courses/front-end-web-development.png">
	</div>
</div>

<h2>
	التركيز التلقائي على الحقول autofocus
</h2>

<center>
	<table border="1">
		<tbody>
			<tr>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					IE
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Fiefox
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Safari
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Chrome
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Opera
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					iPhone
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Android
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px; text-align: center;">
					10+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					5.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					5.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					10.1+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					.
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					3.0+
				</td>
			</tr>
		</tbody>
	</table>
</center>

<p>
	يمكن لمواقع الويب استخدام JavaScript للتركيز على حقلٍ للإدخال في نموذج الويب تلقائيًا. على سبيل المثال، الصفحة الرئيسية لمحرك البحث Google ستُركِّز تلقائيًا (auto-focus) على حقل البحث لكي تستطيع البدء في كتابة عبارة البحث مباشرةً؛ وعلى الرغم من أنَّ هذا الأمر ملائمٌ للكثيرين، لكنه قد يُزعِج المستخدمين المتقدمين أو أولي الاحتياجات الخاصة؛ فلو ضغطتَ على زر المسافة (space) متوقعًا أن تُمرَّر الصفحة إلى الأسفل، فستفاجأ بعدم التمرير، لأنَّ مؤشر الكتابة موجودٌ في حقلٍ من حقول النموذج (سيُكتَب فراغ في ذاك الحقل بدلًا من التمرير). وإن ضغطت على حقل إدخالٍ مختلف أثناء تحميل الصفحة وبدأت الكتابة فيه، فسيأتي سكربت التركيز التلقائي (بعد اكتمال تحميل الصفحة) و"يُساعِدُك" وينقل التركيز إلى حقل الإدخال الأصلي، مما يجعلك تكتب في حقلٍ مختلف، ويقطع عليك «سلسلة أفكارك».
</p>

<p>
	ولمّا كان التركيز التلقائي يُنفَّذ عبر JavaScript، فمن الصعب التعامل مع كل الحالات الغريبة؛ وليس هنالك منقذٌ لِمَن يريدون تعطيل ميزة التركيز التلقائي.
</p>

<p>
	لحل هذه المشكلة، وفَّرَت HTML5 خاصية autofocus لجميع عناصر التحكم في نماذج الويب. عمل الخاصية <span style="font-family:courier new,courier,monospace;">autofocus</span> واضحٌ من اسمها: نقل التركيز إلى حقل إدخال مُعيّن في أقرب فرصة ممكنة عند تحميل الصفحة. ولكن لمّا كانت هذه الخاصية موجودة في HTML وليست مُطبَّقة عبر JavaScript، فسيكون سلوكها متماثلًا في جميع مواقع الويب وعلى جميع المتصفحات. وسيتمكن مطورو المتصفحات (أو مطورو الإضافات) من منح المستخدمين إمكانية تعطيل التركيز التلقائي تمامًا.
</p>

<p>
	هذا مثالٌ عن كيفية التركيز التلقائي عبر الخاصية <span style="font-family:courier new,courier,monospace;">autofocus</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2716_10"><span class="tag">&lt;form&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"q"</span><span class="pln"> </span><span class="atn">autofocus</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"Search"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	المتصفحات التي لا تدعم الخاصية <span style="font-family:courier new,courier,monospace;">autofocus</span> ستتجاهلها تمامًا. انظر إلى الجدول أعلاه لتعرف ما هي المتصفحات التي تدعم خاصية <span style="font-family:courier new,courier,monospace;">autofocus</span>.
</p>

<p>
	هل تريد أن تعمل ميزة التركيز التلقائي في جميع المتصفحات، وليس تلك التي تدعم HTML5 فقط؟ يمكنك الاستمرار في استخدام سكربت التركيز التلقائي، لكن عليك إجراء تعديلين بسيطين:
</p>

<ul>
	<li>
		أضف الخاصية <span style="font-family:courier new,courier,monospace;">autofocus</span> إلى شيفرة HTML
	</li>
	<li>
		اكتشف إذا كان المتصفح يدعم الخاصية <span style="font-family:courier new,courier,monospace;">autofocus</span>، وشغِّل سكربت التركيز التلقائي إن لم يكن يدعم المتصفح الخاصية <span style="font-family:courier new,courier,monospace;">autofocus</span> داخليًا.
	</li>
</ul>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2716_12"><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"f"</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"q"</span><span class="pln"> </span><span class="atn">autofocus</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;script&gt;</span><span class="pln">
		</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!(</span><span class="str">"autofocus"</span><span class="pln"> in document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">"input"</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
			document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">"q"</span><span class="pun">).</span><span class="pln">focus</span><span class="pun">();</span><span class="pln">
		</span><span class="pun">}</span><span class="pln">
	</span><span class="tag">&lt;/script&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"Go"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<h3>
	ضبط التركيز التلقائي في أقرب فرصة ممكنة
</h3>

<p>
	تنتظر العديد من صفحات الويب إلى أن يقع الحدث<span style="font-family:courier new,courier,monospace;"> window.onload</span> لكي تضبط التركيز؛ لكن الحدث <span style="font-family:courier new,courier,monospace;">window.onload</span> لا يُفعَّل إلا بعد تحميل جميع الصور؛ وإذا حوَت صفحتك على الكثير من الصور، فمن المحتمل أن السكربت الذي ستستخدمه سيؤدي إلى إعادة التركيز على حقل الإدخال المُعيّن بعد أن يبدأ المستخدم تفاعله مع قسمٍ آخر في صفحتك. هذا هو سبب كره المستخدمين المتقدمين لسكربتات التركيز التلقائي.
</p>

<p>
	وضعنا سكربت التركيز التلقائي في المثال الموجود في القسم السابق بعد حقل الإدخال مباشرةً؛ وهذا حلٌ مثاليٌ لمشكلتنا، لكن قد ترى أنَّ وضع شيفرة JavaScript في منتصف الصفحة هو أمرٌ سيئ (أو قد لا يسمح لك السند الخلفي [back-end] بذلك)؛ فإن لم تستطع وضع السكربت في منتصف الصفحة، فعليك أن تضبط التركيز أثناء وقوع حدث مخصص مثل ‎<span style="font-family:courier new,courier,monospace;">$(document).ready()</span>‎ في jQuery بدلًا من <span style="font-family:courier new,courier,monospace;">window.onload</span>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2716_14"><span class="tag">&lt;head&gt;</span><span class="pln">
	</span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">jquery.min.js</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
	</span><span class="tag">&lt;script&gt;</span><span class="pln">
		$</span><span class="pun">(</span><span class="pln">document</span><span class="pun">).</span><span class="pln">ready</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
		</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!(</span><span class="str">"autofocus"</span><span class="pln"> in document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">"input"</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
			$</span><span class="pun">(</span><span class="str">"#q"</span><span class="pun">).</span><span class="pln">focus</span><span class="pun">();</span><span class="pln">
		</span><span class="pun">}</span><span class="pln">
		</span><span class="pun">});</span><span class="pln">
	</span><span class="tag">&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/head&gt;</span><span class="pln">

</span><span class="tag">&lt;body&gt;</span><span class="pln">
	</span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"f"</span><span class="tag">&gt;</span><span class="pln">
		</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"q"</span><span class="pln"> </span><span class="atn">autofocus</span><span class="tag">&gt;</span><span class="pln">
		</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"Go"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	تُفعِّل مكتبة jQuery الحدث الخاص ready في أقرب فرصة تتوفر فيها شجرة DOM للصفحة، أي أنها تنتظر إلى أن ينتهي تحميل النص في الصفحة، لكنها لن تنتظر تحميل جميع الصور فيها. لكن هذا ليس حلًا مثاليًا، فإن كانت الصفحة كبيرةً جدًا أو كان الاتصال بطيئًا للغاية، فقد يبدأ المستخدم تفاعله مع الصفحة قبل تنفيذ سكربت التركيز التلقائي؛ إلا أنَّ هذا الحل أفضل بكثير من انتظار وقوع الحدث <span style="font-family:courier new,courier,monospace;">window.onload</span>.
</p>

<p>
	إذا كنت قادرًا على إضافة تعبير JavaScript وحيد في شيفرة صفحتك، فهنالك حلٌ وسطٌ بين الأمرين. يمكنك استخدام الأحداث الخاصة في jQuery لتعريف حدث خاص بك، ولنقل أنَّ اسمه هو <span style="font-family:courier new,courier,monospace;">autofocus_ready</span>. ثم تستطيع تفعيل هذا الحدث يدويًا بعد أن تُتاح خاصية <span style="font-family:courier new,courier,monospace;">autofocus</span> مباشرةً.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2716_22"><span class="tag">&lt;head&gt;</span><span class="pln">
	</span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">jquery.min.js</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
	</span><span class="tag">&lt;script&gt;</span><span class="pln">
	$</span><span class="pun">(</span><span class="pln">document</span><span class="pun">).</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'autofocus_ready'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
		</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!(</span><span class="str">"autofocus"</span><span class="pln"> in document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">"input"</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
			$</span><span class="pun">(</span><span class="str">"#q"</span><span class="pun">).</span><span class="pln">focus</span><span class="pun">();</span><span class="pln">
		</span><span class="pun">}</span><span class="pln">
	</span><span class="pun">});</span><span class="pln">
	</span><span class="tag">&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/head&gt;</span><span class="pln">

</span><span class="tag">&lt;body&gt;</span><span class="pln">
	</span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"f"</span><span class="tag">&gt;</span><span class="pln">
		</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"q"</span><span class="pln"> </span><span class="atn">autofocus</span><span class="tag">&gt;</span><span class="pln">
		</span><span class="tag">&lt;script&gt;</span><span class="pln">$</span><span class="pun">(</span><span class="pln">document</span><span class="pun">).</span><span class="pln">trigger</span><span class="pun">(</span><span class="str">'autofocus_ready'</span><span class="pun">);</span><span class="tag">&lt;/script&gt;</span><span class="pln">
		</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"Go"</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	هذا الحل مثاليٌ مثل الحل الأول، حيث يضبط التركيز إلى الحقل المُحدَّد في أقرب فرصة ممكنة، وذلك أثناء تحميل بقية نص الصفحة. لكنه ينقل تنفيذ التسلسل المنطقي لتطبيقك (التركيز على حقل الإدخال) من جسم الصفحة إلى ترويستها. يعتمد المثال السابق على مكتبة jQuery، لكن مفهوم الأحداث الخاصة ليس مقتصرًا على jQuery فحسب، فلدى مكتبات JavaScript الأخرى مثل YUI و Dojo إمكانياتٌ مشابهة.
</p>

<p>
	الخلاصة هي:
</p>

<ul>
	<li>
		من المهم ضبط التركيز التلقائي ضبطًا سليمًا.
	</li>
	<li>
		يُفضَّل أن تدع المتصفح يضبط التركيز التلقائي عبر خاصية <span style="font-family:courier new,courier,monospace;">autofocus</span> في حقل الإدخال الذي تريد التركيز تلقائيًا عليه إذا كان ذلك ممكنًا.
	</li>
	<li>
		إذا كنتَ تريد حلًا للمتصفحات القديمة، فاكتشف أولًا دعم المتصفح للخاصية <span style="font-family:courier new,courier,monospace;">autofocus</span> لكي تتأكد أنَّ السكربت الذي كتبتَه سيُنفَّذ على المتصفحات القديمة فقط.
	</li>
	<li>
		حاول ضبط التركيز التلقائي في أقرب فرصة ممكنة، حاول مثلًا أن تضع سكربت التركيز في شيفرة HTML بعد حقل الإدخال مباشرةً. فإن لم تستطع، فاستعمل مكتبة JavaScript تدعم الأحداث المُخصَّصة، وفعِّل الحدث المُخصَّص مباشرةً بعد شيفرة النموذج؛ وإن لم يكن ذلك ممكنًا، فاعتمد على حدثٍ مثل الحدث ‎<span style="font-family:courier new,courier,monospace;">$(document).ready()</span>‎ في مكتبة jQuery.
	</li>
	<li>
		لا تنتظر الحدث<span style="font-family:courier new,courier,monospace;"> window.onload</span> لكي يضبط التركيز تحت أيّ ظرفٍ كان.
	</li>
</ul>

<h2>
	عناوين البريد الإلكتروني
</h2>

<p>
	لفترةٍ تجاوزت العقد من الزمن، احتوت نماذج الويب على عدِّد قليلٍ من الحقول، وكان أكثرها شيوعًا:
</p>

<center>
	<table border="1">
		<tbody>
			<tr>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					نوع الحقل
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					شيفرة HTML
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					ملاحظات
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px;">
					مربع تأشير (checkbox)
				</td>
				<td style="padding: 5px 10px;">
					<span style="font-family:courier new,courier,monospace;">"input type="checkbox</span>
				</td>
				<td style="padding: 5px 10px;">
					يمكن تفعيله أو تعطيله
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px;">
					زر انتقاء (radio button)
				</td>
				<td style="padding: 5px 10px;">
					<span style="font-family:courier new,courier,monospace;">"input type="radio</span>
				</td>
				<td style="padding: 5px 10px;">
					يمكن تجميعه مع حقول أخرى
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px;">
					حقل كلمة مرور
				</td>
				<td style="padding: 5px 10px;">
					<span style="font-family:courier new,courier,monospace;">input type="password"‎</span>
				</td>
				<td style="padding: 5px 10px;">
					يُظهِر نقطًا بدلًا من المحارف التي تكتبها
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px;">
					قائمة منسدلة
				</td>
				<td style="padding: 5px 10px;">
					<span style="font-family:courier new,courier,monospace;">&lt;select&gt; &lt;/select&gt;</span>
				</td>
				<td style="padding: 5px 10px;">
					-
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px;">
					مُنتقي الملفات
				</td>
				<td style="padding: 5px 10px;">
					<span style="font-family:courier new,courier,monospace;">"input type="file</span>
				</td>
				<td style="padding: 5px 10px;">
					يُظهِر مربع حوار "اختيار ملف"
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px;">
					زر الإرسال
				</td>
				<td style="padding: 5px 10px;">
					<span style="font-family:courier new,courier,monospace;">"input type="submit</span>
				</td>
				<td style="padding: 5px 10px;">
					-
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px;">
					نص عادي
				</td>
				<td style="padding: 5px 10px;">
					<span style="font-family:courier new,courier,monospace;">‎input type="text"‎‎</span>
				</td>
				<td style="padding: 5px 10px;">
					يُمكن حذف الخاصية type
				</td>
			</tr>
		</tbody>
	</table>
</center>

<p>
	تعمل جميع أنواع الحقول السابقة في HTML5، فلو أردت "التحديث إلى HTML5" (ربما بتغيير نوع المستند <span style="font-family:courier new,courier,monospace;">DOCTYPE</span>)، فلن تحتاج إلى إجراء أيّة تعديلات على نماذج الويب عندك، والفضل بذلك يعود إلى توافقية HTML5 مع الإصدارات التي تسبقها.
</p>

<p>
	لكن HTML5 أضافت ثلاثة عشر نوعًا جديدًا من الحقول، ولأسبابٍ ستتضح لك بعد قليل، لا يوجد سببٌ يمنعك من استعمالها الآن.
</p>

<p>
	أول أنواع المدخلات الجديدة مخصصٌ لعناوين البريد، ويبدو كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2716_24"><span class="tag">&lt;form&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"email"</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"Go"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	أوشكتُ على كتابة جملةٍ مطلعها: "أما في المتصفحات التي لا تدعم <span style="font-family:courier new,courier,monospace;">type="email"‎</span>..." لكنني تداركتُ نفسي وتوقفت. لكن ما السبب؟ لأنني لستُ متأكدًا من ماذا يعني عدم دعم المتصفح للحقل type="email"‎، حيث «تدعم» جميع المتصفحات <span style="font-family:courier new,courier,monospace;">type="email"‎</span>‎، لكنها قد لا تفعل شيئًا خاصًا لها (سترى بعد قليل بعض الأمثلة عن المعاملة الخاصة لهذا الحقل)؛ لكن المتصفحات التي لا تتعرف على <span style="font-family:courier new,courier,monospace;">type="email"‎</span> ستعامله على أنَّه<span style="font-family:courier new,courier,monospace;"> type="text"‎</span> وسيظهر كحقلٍ نصيٍ عاديٍ.
</p>

<p>
	لا تسعني الكلمات للتعبير عن مدى أهمية ما سبق، لأنَّ في الويب ملايين النماذج التي تسألك أن تدخِل عنوان بريدك الإلكتروني، وجميعها تستعمل <span style="font-family:courier new,courier,monospace;">&lt;input type="text"‎&gt;</span> وستشاهد مربعًا نصيًا، ثم تُدخِل فيه عنوان بريدك، وانتهى. ثم أتت HTML5 التي أضافت <span style="font-family:courier new,courier,monospace;">type="email"‎</span>، فهل سترتبك المتصفحات؟ لا، يُعامِل كل متصفح على وجه هذا الكوكب القِيم غير المعروفة لخاصية <span style="font-family:courier new,courier,monospace;">type</span> على أنها <span style="font-family:courier new,courier,monospace;">type="text"</span>‎، بما في ذلك IE 6. لذلك تستطيع استعمال <span style="font-family:courier new,courier,monospace;">type="email"</span>‎ حالًا دون القلق حول دعم المتصفحات.
</p>

<p>
	لكن ماذا يعني أنَّ المتصفح "يدعم" الحقل <span style="font-family:courier new,courier,monospace;">type="email"</span>‎؟ حسنًا، قد يعني هذا عدِّة أشياء. لم تُحدِّد مواصفة HTML5 أيّة توصية حول الواجهة الرسومية التي تظهر للمستخدم لأنواع المدخلات الجديدة. ستعرضه أغلبية متصفحات سطر المكتب مثل Safari و Chrome و Opera و Firefox كحقلٍ نصيّ؛ ولهذا لن يُلاحِظ مستخدمو موقعك الفرق (إلى أن يُحاولوا إرسال النموذج).
</p>

<p>
	ثم ها قد أتت الهواتف المحمولة…
</p>

<p>
	ليس للهواتف المحمولة لوحة مفاتيح فيزيائية، فكل "الكتابة" تتم بالضغط على لوحة مفاتيح ظاهرة على الشاشة التي تُعرَض عند الحاجة لها (عند التركيز على حقل من حقول أحد النماذج في صفحة الويب على سبيل المثال). تتعرف متصفحات الهواتف المحمولة الذكية على العديد من أنواع المدخلات الجديدة في HTML5، وتُجري تعديلات ديناميكية على لوحة المفاتيح الظاهرة على الشاشة لكي تُلائم نوع المدخلات.
</p>

<p>
	مثلًا، عناوين البريد الإلكتروني هي نصوص، صحيح؟ بالطبع، لكنها نوع خاص من النصوص، فمثلًا يحتوي كل عنوان بريد إلكتروني (نظريًا) على رمز @ وعلى نقطة (.) واحدة على الأقل؛ ومن غير المحتمل أن يحتوي على فراغات؛ لذا لو كنتَ تستعمل هاتف iPhone وحاولت الكتابة في عنصر <span style="font-family:courier new,courier,monospace;">&lt;input type="email‎"‎&gt;</span>، فستظهر لوحة مفاتيح تحتوي على زر مسافة أصغر من المعتاد، بالإضافة إلى أزرار مخصصة لمحرفَي @ و . .
</p>

<p style="text-align: center;">
	<img alt="3-input-type-email.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18630" data-unique="3djpw6tb7" src="https://academy.hsoub.com/uploads/monthly_2016_07/3-input-type-email.png.7e704458c10d29b6c1feea4a42cf7b3e.png">
</p>

<p>
	لا توجد سلبيات لتحويل جميع الحقول التي تُمثِّل عناوين البريد الإلكتروني إلى <span style="font-family:courier new,courier,monospace;">type="email"‎</span> في الحال. فلن يلاحظ ذلك أحدٌ إلا مستخدمي الهواتف المحمولة، الذين أظن أنَّهم لن ينتبهوا لذلك أيضًا. لكن من سيلاحظ ذلك سيبتسم بصمت ويشكرك في قلبه لأنَّك سهلت عليه الأمر قليلًا.
</p>

<h2>
	عناوين الويب
</h2>

<p>
	عناوين مواقع الويب -التي يُسمّيها مهووسو المعايير "URLs"، إلا بعض المتحذلقين الذين يدعونها "URIs"- هي نوعٌ آخرٌ من النص المُخصَص؛ البنية العامة لعناوين الويب مرتبطة بمعايير الإنترنت ذات الصلة. إذا طلب منك أحدهم كتابة عنوان لموقع ويب في نموذج، فسيتوقعون منك كتابة شيءٍ مثل "http://www.google.com/‎" وليس "125 Farwood Road"؛ ومن الشائع استخدام الخط المائل / في العناوين (الخط المائل مذكورٌ ثلاث مرات في عنوان صفحة Google الرئيسية)؛ وينتشر استخدام النقط . أيضًا، لكن يُمنَع وضع فراغات في العنوان. لدى جميع عناوين الويب لاحقة للنطاق مثل "‎.com" أو "‎.org".
</p>

<p>
	تعرض أغلبية متصفحات الويب لسطح المكتب الحديثة حقل <span style="font-family:courier new,courier,monospace;">type="url"</span>‎ كحقلٍ نصيّ عادي، لذلك لن يُلاحظ مستخدمو موقعك ذلك إلى أن يحاولوا أن يُرسِلوا النموذج. ستُعامِل المتصفحات التي لا تدعم HTML5 الحقل <span style="font-family:courier new,courier,monospace;">type="url"‎</span> كحقل <span style="font-family:courier new,courier,monospace;">type="text"</span>‎ تمامًا، فلا بأس من استعمال هذا الحقل في صفحات الويب الحديثة عند الحاجة.
</p>

<p>
	ستُعدِّل الهواتف الذكية من طريقة عرض لوحة المفاتيح كما في حقل عنوان البريد الإلكتروني، لكن لوحة المفاتيح في هذه المرة ستُخصَّص لتسهيل إدخال عناوين الويب. ففي هواتف iPhone سيُزال زر المسافة تمامًا وسيُستعاض عنه بنقطة وخط مائل وزر "‎.com" (يمكنك الضغط مطولًا على زر "‎.com" للاختيار بين اللاحقات الشهيرة الأخرى مثل "‎.org" أو "‎.net")؛ وستُخصِّص هواتف أندرويد لوحة مفاتيحها بشكلٍ مشابه.
</p>

<p style="text-align: center;">
	<img alt="4-input-type-url.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18631" data-unique="dfvcwl7kp" src="https://academy.hsoub.com/uploads/monthly_2016_07/4-input-type-url.png.2f8ff88382ca755f1e972de05844783d.png">
</p>

<h2>
	<br>
	إدخال الأرقام
</h2>

<p>
	طلب إدخال الأرقام أصعب من طلب كتابة عنوان بريد إلكتروني أو موقع ويب؛ لأنَّ الأرقام معقدة أكثر مما تظن. اختر رقما ما بسرعة. -1؟ لا، كنت أقصد رقمًا بين 1 و 10. ‎7½‎؟ لا، ليس رقمًا كسريًا. π؟ لماذا تختار الأرقام العجيبة؟!
</p>

<p>
	الفكرة التي أود إيصالها هي أنَّك لا تسأل عن "رقمٍ ما"، فمن المحتمل أنَّك ستطلب من المستخدم إدخال رقم في مجال معيّن، ولا تريد إلا نوعًا محدَّدًا من الأرقام ضمن ذلك المجال، وقد تريد استبعاد الأعداد الكسرية أو العشرية، أو أن تسمح بإدخال الأرقام التي تقبل القسمة على 10. ستسمح لك HTML5 بكل هذا.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8704_9"><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"number"</span><span class="pln">
       </span><span class="atn">min</span><span class="pun">=</span><span class="atv">"0"</span><span class="pln">
       </span><span class="atn">max</span><span class="pun">=</span><span class="atv">"10"</span><span class="pln">
       </span><span class="atn">step</span><span class="pun">=</span><span class="atv">"2"</span><span class="pln">
       </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"6"</span><span class="tag">&gt;</span></pre>

<p>
	لنتحدث عن الخاصيات السابقة كلًا على حدة (يمكنك المتابعة مع المثال الحي إن شئت).
</p>

<ul>
	<li>
		الخاصية <span style="font-family:courier new,courier,monospace;">type="number"‎ </span>تعني أنَّ الحقل يقبل الأرقام.
	</li>
	<li>
		الخاصية<span style="font-family:courier new,courier,monospace;"> min="0"‎</span> تُحدِّد القيمة الدنيا المقبولة لهذا الحقل.
	</li>
	<li>
		الخاصية <span style="font-family:courier new,courier,monospace;">max="10"</span>‎ تُحدِّد القيمة القصوى المقبولة.
	</li>
	<li>
		الخاصية <span style="font-family:courier new,courier,monospace;">step="2"</span>‎ مجتمعةً مع قيمة الخاصية <span style="font-family:courier new,courier,monospace;">min</span> ستُعرِّف ما هي الأرقام المسموحة في المجال: 0 و 2 و 4 وهكذا إلى أن تصل إلى قيمة الخاصية max.
	</li>
	<li>
		الخاصية <span style="font-family:courier new,courier,monospace;">value="6"</span>‎ تُحدِّد القيمة الافتراضية. يُفترَض أن تكون هذه الخاصية مألوفةً لديك، فهي نفس الخاصية التي تستعملها دومًا لتحديد قيم حقول النموذج (ذكرتُ هذه النقطة هنا لكي أخبرك أنَّك لست بحاجة إلى <a href="https://academy.hsoub.com/programming/html/%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-html-r1702/" rel="">تعلم HTML</a> مرة أخرى، فإصدار HTML5 مبني على إصدارات HTML السابقة).
	</li>
</ul>

<p>
	هذه هي الشيفرة الخاصة بحقل الأرقام. ابقِ في ذهنك أنَّ جميع الخاصيات السابقة اختيارية. فإذا كانت لديك قيمة دنيا للمجال المقبول لكن دون وجود حد أقصى للأرقام، فيمكنك ضبط خاصية <span style="font-family:courier new,courier,monospace;">min</span> وعدم ضبط الخاصية <span style="font-family:courier new,courier,monospace;">max</span>. الخطوة الافتراضية هي 1، ويمكنك عدم ذكر الخاصية <span style="font-family:courier new,courier,monospace;">step</span> إلا إذا كانت قيمة الخطوة عندك مختلفةً عن 1. تستطيع إسناد سلسلة نصية فارغة إلى الخاصية <span style="font-family:courier new,courier,monospace;">value</span> إن لم تكن هنالك قيمةٌ افتراضيةٌ، أو بإمكانك حذف الخاصية تمامًا.
</p>

<p>
	لكن HTML5 لا تقف عند هذا الحد، حيث توفِّر لك دوال JavaScript للتحكم بهذا الحقل:
</p>

<ul>
	<li>
		الدالة<span style="font-family:courier new,courier,monospace;"> (input.stepUp(n </span>تزيد قيمة الحقل بمقدار<span style="font-family:courier new,courier,monospace;"> n</span>.
	</li>
	<li>
		الدالة<span style="font-family:courier new,courier,monospace;"> (input.stepDown(n </span>تنقص من قيمة الحقل مقدار<span style="font-family:courier new,courier,monospace;"> n</span>.
	</li>
	<li>
		الخاصية <span style="font-family:courier new,courier,monospace;">input.valueAsNumber</span> تُعيد القيمة الحالية للحقل كعدد ذي فاصلةٍ عشرية (تذكَّر أنَّ الخاصية <span style="font-family:courier new,courier,monospace;">input.value</span> تُعيد سلسلةً نصيةً دومًا).
	</li>
</ul>

<p>
	هل صَعُبَ عليك تخيل شكل هذا الحقل؟ حسنًا، طريقة عرض هذا الحقل عائدة تمامًا لمتصفحك، ويدعم مختلف مُصنِّعي المتصفحات هذا الحقل بطرائق مختلفة. فعلى هواتف iPhone -التي يصعب فيها كتابة المدخلات عمومًا- سيُحسِّن المتصفح من لوحة المفاتيح مرةً أخرى لكتابة الأرقام.
</p>

<p style="text-align: center;">
	<img alt="5-input-type-number.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18632" data-unique="hb382g5wz" src="https://academy.hsoub.com/uploads/monthly_2016_07/5-input-type-number.png.77d4a7ef9c1af80ee1ba2e79e8aabb43.png">
</p>

<p>
	أما في نسخة سطح المكتب من متصفح Opera، سيظهر نفس الحقل <span style="font-family:courier new,courier,monospace;">type="number"</span>‎ كعنصر "spinbox" الذي يملك أسهمًا صغيرةً للأعلى والأسفل تستطيع الضغط عليها لتغيير القيمة.
</p>

<p style="text-align: center;">
	<img alt="6-input-type-number-opera.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18636" data-unique="notl35m8q" src="https://academy.hsoub.com/uploads/monthly_2016_08/6-input-type-number-opera.png.d2524a9fd0205332c33eee0fffab494b.png">
</p>

<p>
	تحترم المتصفحات قيم الخاصيات <span style="font-family:courier new,courier,monospace;">min</span> و <span style="font-family:courier new,courier,monospace;">max</span> و <span style="font-family:courier new,courier,monospace;">step</span>، لذلك ستكون قيمة ذاك الحقل مقبولة دومًا، فلو وصلت إلى القيمة القصوى، فسيُعطَّل زر السهم العلوي ولن تستطيع زيادة الرقم الموجود.
</p>

<p style="text-align: center;">
	<img alt="7-input-type-number-at-max-opera.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18637" data-unique="ldwcgswm9" src="https://academy.hsoub.com/uploads/monthly_2016_08/7-input-type-number-at-max-opera.png.e3dce50d5b62458aa07e1d23458e8e12.png">
</p>

<p>
	وكما في بقية حقول الإدخال التي شرحناها سابقًا في هذا الدرس، المتصفحات التي لا تدعم<span style="font-family:courier new,courier,monospace;"> type="number"‎</span> ستُعامِل الحقل وكأنَّه <span style="font-family:courier new,courier,monospace;">type="text"</span>‎، وستظهر القيمة الافتراضية في الحقل النصي (لأنها مُخزَّنة في الخاصية <span style="font-family:courier new,courier,monospace;">value</span>)، لكن سيتجاهل المتصفح الخاصيات الأخرى مثل <span style="font-family:courier new,courier,monospace;">min</span> و <span style="font-family:courier new,courier,monospace;">max</span>؛ لكنك تستطيع إنشاء spinbox بنفسك، أو قد تستعمل مكتبة JavaScript تحتوي على هذا العنصر؛ لكن تذكَّر أن تتحقق من دعم المتصفح لهذا الحقل أولًا، على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_402_9"><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="typ">Modernizr</span><span class="pun">.</span><span class="pln">inputtypes</span><span class="pun">.</span><span class="pln">number</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	</span><span class="com">//لا يوجد دعم لحقول type=number</span><span class="pln">
	</span><span class="com">//ربما تجرِّب Dojo أو مكتبة JavaScript أخرى</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	تحديد الأرقام عبر المزلاج
</h3>

<p>
	هنالك آليةٌ أخرى لتمثيل المدخلات الرقمية، فمن المحتمل أنَّك رأيك "مزلاجًا" (slider) من قبل يُشبِه:
</p>

<p style="text-align: center;">
	<img alt="8-input-type-range.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18638" data-unique="vt2wra978" src="https://academy.hsoub.com/uploads/monthly_2016_08/8-input-type-range.png.4051e27c53ad4da0913514030925711d.png">
</p>

<p>
	يمكنك وضع المزلاج في نماذج HTML5 أيضًا، والشيفرة الخاصة به شبيهة جدًا بحقل spinbox:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_402_13"><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"range"</span><span class="pln">
       </span><span class="atn">min</span><span class="pun">=</span><span class="atv">"0"</span><span class="pln">
       </span><span class="atn">max</span><span class="pun">=</span><span class="atv">"10"</span><span class="pln">
       </span><span class="atn">step</span><span class="pun">=</span><span class="atv">"2"</span><span class="pln">
       </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"6"</span><span class="tag">&gt;</span></pre>

<p>
	جميع الخاصيات المتوفرة مماثلة لحقل <span style="font-family:courier new,courier,monospace;">type="number"‎ </span>(أي <span style="font-family:courier new,courier,monospace;">min</span> و <span style="font-family:courier new,courier,monospace;">max</span> و <span style="font-family:courier new,courier,monospace;">step</span> و <span style="font-family:courier new,courier,monospace;">value</span>)، ولها نفس المعنى. الفرق الوحيد هو في واجهة الاستخدام؛ فبدلًا من وجود حقل لكتابة الرقم، ستعرض المتصفحات الحديثة الحقل <span style="font-family:courier new,courier,monospace;">type="range"</span>‎ كمزلاج، بينما ستعرضه المتصفحات القديمة التي لا تدعم HTML5 كحقل <span style="font-family:courier new,courier,monospace;">type="text"‎</span>، لذا لا يوجد سبب يمنعك من البدء باستخدامه مباشرةً.
</p>

<h2>
	منتقي التاريخ Date picker
</h2>

<p>
	لم تتضمن HTML 4 حقلًا لاختيار التاريخ، لكن مكتبات JavaScript تداركت الأمر (Dojo و jQuery UI و YUI و Closure Library) لكن هذه الحلول كانت تتطلب الخوض في مكتبة JavaScript التي تدعم حقل مُنتقي التاريخ (date picker).
</p>

<p>
	أضافت HTML5 أخيرًا حقلًا لانتقاء التاريخ دون الحاجة إلى كتابته يدويًا عبر JavaScript؛ وفي الواقع، أضفات ستة حقول: واحد للتاريخ (date) وآخر للشهر (month) وآخر للأسبوع (week) وآخر للوقت (time) وآخر للتاريخ والوقت (date + time) وآخر للتاريخ والوقت لكن دون ذكر المنطقة الزمنية (date + time – timezone).
</p>

<p>
	لكن للأسف، هذا الحقل غير مدعوم من أغلبية المتصفحات. إذ يدعمه متصفح Opera منذ الإصدار التاسع و Chrome من الإصدار 20.
</p>

<p>
	هذه هي طريقة عرض متصفح Opera لحقل <span style="font-family:courier new,courier,monospace;">&lt;input type="date"‎&gt;</span>:
</p>

<p style="text-align: center;">
	<img alt="9-input-type-date.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18639" data-unique="bq20bvvxa" src="https://academy.hsoub.com/uploads/monthly_2016_08/9-input-type-date.png.0c3138b659c1b8eb49161f66c016efa9.png">
</p>

<p>
	وإذا أردت من المستخدم انتقاء الوقت والتاريخ، فهنالك حقل <span style="font-family:courier new,courier,monospace;">&lt;input type="datetime"‎&gt;</span>:
</p>

<p style="text-align: center;">
	<img alt="10-input-type-datetime.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18640" data-unique="r3iic04qt" src="https://academy.hsoub.com/uploads/monthly_2016_08/10-input-type-datetime.png.bd36ff2513620cb164fd51efa6af9293.png">
</p>

<p>
	أما لو كنت تحتاج إلى الشهر والسنة فقط (ربما تريد إدخال تاريخ انتهاء البطاقة الائتمانية)، فهنالك حقل <span style="font-family:courier new,courier,monospace;">&lt;input type="month"‎&gt;</span>:
</p>

<p style="text-align: center;">
	<img alt="11-input-type-month.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18641" data-unique="f9yxaz3nv" src="https://academy.hsoub.com/uploads/monthly_2016_08/11-input-type-month.png.5115fe56250fd856b4c6f593b24dcca4.png">
</p>

<p>
	ويتوفر أيضًا حقلٌ لانتقاء أسبوع معيّن في السنة –وإن لم يكن ذلك شائعًا– عبر الحقل <span style="font-family:courier new,courier,monospace;">&lt;input type="week"‎&gt;</span>:
</p>

<p style="text-align: center;">
	<img alt="12-input-type-week.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18642" data-unique="rm3txfbqa" src="https://academy.hsoub.com/uploads/monthly_2016_08/12-input-type-week.png.ccc78a0b13a0aab462edc9f06ae437df.png">
</p>

<p>
	أخيرًا وليس آخرًا، يمكنك اختيار الوقت عبر الحقل <span style="font-family:courier new,courier,monospace;">&lt;input type="time"‎&gt;</span>:
</p>

<p style="text-align: center;">
	<img alt="13-input-type-time.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18643" data-unique="bfhdohiml" src="https://academy.hsoub.com/uploads/monthly_2016_08/13-input-type-time.png.bdc61d2c0fb37ddaf7ad51bffe166615.png">
</p>

<p>
	من المحتمل أن تدعم المتصفحات حقول الإدخال السابقة تباعًا، لكن كما في حقل<span style="font-family:courier new,courier,monospace;"> type="email"‎</span> وغيره، ستُعرَض هذه الحقول كحقولٍ نصيةٍ بسيطةٍ في المتصفحات التي لا تدعم الحقل<span style="font-family:courier new,courier,monospace;"> type="date"‎</span> وأخوته. يمكنك ببساطة أن تستعمل الحقل<span style="font-family:courier new,courier,monospace;"> &lt;input type="date"‎&gt;</span> وأخوته لتوفِّر مُنتقي التاريخ لمستخدمي متصفحَي Opera و Chrome وتنتظر دعم بقية المتصفحات. أو أن تعتمد حلًا عمليًا هو استعمال<span style="font-family:courier new,courier,monospace;"> &lt;input type="date"‎&gt;</span> ثم تكتشف إن كان المتصفح يدعم مُنتقي التاريخ، ثم تستعمل حلًا برمجيًا إن لم يكن يدعمه (مثل Dojo و jQuery UI و YUI و Closure Library أو حلًا آخر).
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_402_7"><span class="tag">&lt;form&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"date"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span><span class="pln">

...

</span><span class="tag">&lt;script&gt;</span><span class="pln">
	</span><span class="kwd">var</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">"input"</span><span class="pun">);</span><span class="pln">
	i</span><span class="pun">.</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="str">"type"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"date"</span><span class="pun">);</span><span class="pln">

	</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">.</span><span class="pln">type </span><span class="pun">==</span><span class="pln"> </span><span class="str">"text"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
		</span><span class="com">//لا يوجد دعم لمنتقي التاريخ :-( </span><span class="pln">
		</span><span class="com">//استخدام مكتبة Dojo/jQueryUI/YUI/Closure لإنشاء واحد</span><span class="pln">
		</span><span class="com">//ثم استبدل حقل &lt;input&gt; ديناميكيًا</span><span class="pln">
	</span><span class="pun">}</span><span class="pln">
</span><span class="tag">&lt;/script&gt;</span></pre>

<h2>
	حقول البحث
</h2>

<p>
	حسنًا، وظيفة هذا الحقل واضحة من اسمه، لكن قد نحتاج إلى شرح آلية تطبيقه في المتصفحات.
</p>

<p>
	البحث لا يكون فقط في محركات البحث مثل Google أو Yahoo!‎، فمن الممكن أن يكون حقل البحث في أيّ صفحة وفي أيّ موقع؛ فهنالك واحدٌ في موقع أمازون، وآخر في موقع CNN، ويتواجد أيضًا في أغلبية المدونات. لكن ما هو الوسم المستخدم لتلك الحقول؟ <span style="font-family:courier new,courier,monospace;">&lt;input type="text"‎&gt;</span>، مثل بقية حقول النص الموجودة في الويب. لنحاول تصحيح الأمر…
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2716_20"><span class="tag">&lt;form&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"q"</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"search"</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"Find"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	ما رأيك بتجربة حقل <span style="font-family:courier new,courier,monospace;">&lt;input type="search"‎&gt;</span> في متصفحك. قد لا تلاحظ أيّة اختلافات بينه وبين الحقل النصي العادي؛ لكن إن كنتَ تستعمل Safari على نظام Mac OS X، فسيبدو الحقل كما يلي:
</p>

<p style="text-align: center;">
	<img alt="14-input-type-search-safari.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18644" data-unique="7pnp6rxey" src="https://academy.hsoub.com/uploads/monthly_2016_08/14-input-type-search-safari.png.3586140b6e6ab0e683caf136961664d3.png">
</p>

<p>
	هل لاحظت الفرق؟ لدى حقل البحث زوايا مدورة! أعلم أنَّك لا تستطيع احتواء نفسك من الفرح، لكن انتظر، فهنالك المزيد! عندما تبدأ الكتابة في حقل <span style="font-family:courier new,courier,monospace;">type="search"‎</span>، فسيضع المتصفح زر "x" صغير في الجانب الأيمن من الحقل؛ ويؤدي الضغط عليه إلى حذف محتويات الحقل (متصفح Chrome، الذي يتشارك مع Safari في البنية الداخلية، له نفس السلوك السابق). الغرض من التعديلات البسيطة السابقة هي إعطاء حقول البحث شكلًا وسلوكًا شبيهًا بحقول البحث في تطبيقات Mac OS X المكتبية مثل iTunes.
</p>

<p style="text-align: center;">
	<img alt="15-input-type-search-safari-typing.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18645" data-unique="k2vuaixpj" src="https://academy.hsoub.com/uploads/monthly_2016_08/15-input-type-search-safari-typing.png.a390a26b3e9d29a03f682d62fd1f3f6a.png">
</p>

<p>
	يستعمل موقع Apple.com الحقل <span style="font-family:courier new,courier,monospace;">&lt;input type="search"‎&gt;</span> لحقل البحث في الموقع لإعطائه شكلًا مألوفًا لمستخدمي Mac، لكن ذلك ليس خاصًا بنظام Mac فقط؛ إذ أنَّه شيفرة HTML فحسب، وبهذا يستطيع كل متصفح على كل منصة (أو نظام تشغيل) أن يعرض الحقل بشكلٍ مشابه لعناصر الواجهة الرسومية الخاصة بالمنصة. وكما هو الحال في بقية أنواع الحقول، المتصفحات التي لا تتعرف على حقل<span style="font-family:courier new,courier,monospace;"> type="search"‎</span> ستعامِله كأنَّه <span style="font-family:courier new,courier,monospace;">type="text"</span>‎؛ فلا يوجد سببٌ يمنعك من استخدام <span style="font-family:courier new,courier,monospace;">type="search"</span>‎ في حقول البحث حالًا.
</p>

<h2>
	منتقي الألوان
</h2>

<p>
	تُعرِّف HTML5 حقل <span style="font-family:courier new,courier,monospace;">&lt;input type="color"‎&gt;</span> الذي يسمح لك باختيار لونٍ ما ويُعيد التمثيل الست عشري للون المُختار؛ تأخرت المتصفحات في دعم هذا الحقل، حيث يدعمه Opera منذ الإصدار 17، و Firefox منذ الإصدار 29، و Chrome منذ الإصدار 20، وما زلنا في انتظار دعم بقية المتصفحات له. يندمج هذا الحقل جيدًا مع منتقي الألوان الموجود في نظامَيّ ويندوز و Mac، أما في لينُكس فهو يعرض مُنتقي ألوان أساسي. وهو يُعيد قيمة ست عشرية للون RGB الذي يمكن استخدامه في أي مكان يقبل ألوان CSS (جرِّب مُنتقي الألوان في متصفحك).
</p>

<p style="text-align: center;">
	<img alt="16-input-type-color.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18646" data-unique="yd7vlpr9j" src="https://academy.hsoub.com/uploads/monthly_2016_08/16-input-type-color.png.e8a10b04bd707f6ad6ff9af854525e3d.png">
</p>

<h2>
	التحقق من صحة مدخلات المستخدم
</h2>

<center>
	<table border="1">
		<tbody>
			<tr>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					IE
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Fiefox
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Safari
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Chrome
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Opera
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					iPhone
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Android
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px; text-align: center;">
					10+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					5.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					10.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					9.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.1+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
			</tr>
		</tbody>
	</table>
</center>

<p>
	تحدثت في هذا الفصل عن عددٍ من حقول الإدخال الجديدة وبعض الميزات المحدثة مثل التركيز التلقائي لحقلٍ من حقول النموذج، لكنني لم أذكر ما أعتبره أهم جزء من النماذج الحديثة في HTML5: التحقق التلقائي من صحة مدخلات المستخدم. خذ على سبيل المثال مشكلةً شائعةً هي إدخال عنوان بريد إلكتروني في نموذج ويب؛ ربما ستجري تحققًا من مدخلات المستخدم من طرف العميل عبر JavaScript، متبوعًا بتحققٍ من جهة الخادوم عبر PHP أو Python أو أيًّا كانت لغة البرمجة التي تستعملها. لن يُشكِّل التحقق من مدخلات المستخدم عبر HTML5 بديلًا عن التحقق من جهة الخادوم، لكن من المحتمل أن تشكِّل بديلًا عن سكربتات JavaScript التي تستعملها.
</p>

<p>
	هنالك مشكلتين كبيرتين في التحقق من البريد الإلكتروني عبر JavaScript:
</p>

<ul>
	<li>
		عددٌ كبيرٌ جدًا من زوار موقعك (حوالي 10% تقريبًا) يُعطِّلون JavaScript في متصفحهم
	</li>
	<li>
		ستفشل في التحقق من صحة البريد الإلكتروني
	</li>
</ul>

<p>
	أنا آسف لقول هذا، لكنك ستفشل في ذلك. فعملية تحديد فيما إذا كانت سلسلة نصية ما هي عنوان بريد إلكتروني معقدةٌ بشكلٍ لا يُصدَّق. فكلما أمعنت النظر في الأمر، لوجدت مدى تعقيده. هل ذكرتُ لتوي أنَّ الأمر معقدٌ جدًا جدًا؟ أليس من الأسهل إلقاء ذاك الحِمل والصداع الناتج عنه على عاتق المتصفح؟
</p>

<p style="text-align: center;">
	<img alt="17-input-type-email-validation.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18647" data-unique="1cfhmijk3" src="https://academy.hsoub.com/uploads/monthly_2016_08/17-input-type-email-validation.png.149e78d3190f6d0a2ac81f81b1811509.png">
</p>

<p>
	لقطة الشاشة السابقة مأخوذة من متصفح Opera 10، إلا أنَّ إمكانية التحقق من حقول النماذج متوفرة منذ الإصدار 9. ولدى Firefox 4 و Chrome 10 آليةٌ مشابهة. كل ما عليك فعله هو ضبط الخاصية <span style="font-family:courier new,courier,monospace;">type</span> إلى "<span style="font-family:courier new,courier,monospace;">email</span>". وعندما يحاول المستخدم إرسال (submit) نموذج فيه حقل <span style="font-family:courier new,courier,monospace;">&lt;input type="email"‎&gt;</span>، فسيتحقق المتصفح تلقائيًا من عنوان البريد الإلكتروني حتى لو كانت JavaScript معطَّلةً في المتصفح.
</p>

<p>
	توفِّر HTML5 أيضًا تحققًا من عناوين الويب المُدخَلة في حقول <span style="font-family:courier new,courier,monospace;">&lt;input type="url"‎&gt;</span>، والأرقام المدخلة في حقول <span style="font-family:courier new,courier,monospace;">&lt;input type="number"‎&gt;</span>؛ ستؤخذ قيم الخاصية <span style="font-family:courier new,courier,monospace;">min</span> و <span style="font-family:courier new,courier,monospace;">max</span> بعين الاعتبار عند التحقق من الأرقام، فلن تسمح لك المتصفحات بإرسال النموذج إذا أدخلتَ رقمًا كبيرًا أكبر من الحد الأقصى.
</p>

<p style="text-align: center;">
	<img alt="18-input-type-number-validation.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18648" data-unique="7nvk9fx7l" src="https://academy.hsoub.com/uploads/monthly_2016_08/18-input-type-number-validation.png.3887759c49eba5d710c60f4eb6c4b6f9.png">
</p>

<p>
	لا حاجة إلى وضع شيفرات لتفعيل التحقق من المدخلات في HTML5؛ حيث تكون مفعَّلة افتراضيًا، إلا أنَّك تستطيع تعطيلها عبر وضع الخاصية <span style="font-family:courier new,courier,monospace;">novalidate</span>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2716_18"><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">novalidate</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"email"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"addr"</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"Subscribe"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<h2>
	الحقول المطلوبة required
</h2>

<center>
	<table border="1">
		<tbody>
			<tr>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					IE
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Fiefox
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Safari
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Chrome
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Opera
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					iPhone
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: rgb(236, 240, 241);">
					Android
				</td>
			</tr>
			<tr>
				<td style="padding: 5px 10px; text-align: center;">
					10+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					5.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					10.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					9.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.1+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
			</tr>
		</tbody>
	</table>
</center>

<p>
	التحقق من مدخلات المستخدم في HTML5 ليس محدودًا بنوع الحقل، إذ تستطيع أيضًا أن تُشير إلى أنَّ بعض الحقول "مطلوبةٌ"؛ يجب تحديد قيم للحقول المطلوبة قبل أن ترسِل النموذج.
</p>

<p>
	شيفرة الحقول المطلوبة بسيطةٌ جدًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2716_16"><span class="tag">&lt;form&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"q"</span><span class="pln"> </span><span class="atn">required</span><span class="tag">&gt;</span><span class="pln">
	</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"Search"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	يمكنك تجربة حقل <span style="font-family:courier new,courier,monospace;">&lt;input required&gt;</span> في متصفحك.
</p>

<p>
	قد تُغيّر بعض المتصفحات الشكل الافتراضي للحقول المطلوبة. وإذا حاول المستخدم إرسال النموذج دون تعبئة الحقل المطلوب، فسيظهر إشعار يخبر المستخدم أنَّ من الضروري إدخال قيمة في الحقل وعدم تركه فارغًا (الصورة الآتية من متصفح Chrome):
</p>

<p style="text-align: center;">
	<img alt="19-input-required.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18649" data-unique="ig2z61iac" src="https://academy.hsoub.com/uploads/monthly_2016_08/19-input-required.png.e660bb1a204f3db597bb13a767a49903.png">
</p>

<p>
	ترجمة -وبتصرّف- للفصل "<a href="http://diveinto.html5doctor.com/forms.html" rel="external nofollow">HTML5 Forms</a>" من كتاب <a href="http://diveinto.html5doctor.com/index.html" rel="external nofollow">Dive Into HTML5</a> لمؤلفه Mark Pilgrim.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/html/html5/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D8%B5%D9%81%D9%8A%D8%A9-microdata-%D9%81%D9%8A-html5-r375/" rel="">مدخل إلى البيانات الوصفية (microdata) في HTML5</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/html/html5/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%8A-%D8%AA%D8%B9%D9%85%D9%84-%D8%AF%D9%88%D9%86-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%E2%80%93-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r442/" rel="">تطبيقات الويب التي تعمل دون اتصال – الجزء الثاني</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">نحو فهم أعمق لتقنيات HTML5 </a>
	</li>
</ul>
]]></description><guid isPermaLink="false">370</guid><pubDate>Mon, 01 Aug 2016 10:36:00 +0000</pubDate></item><item><title>&#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x648;&#x64A;&#x628; &#x627;&#x644;&#x62A;&#x64A; &#x62A;&#x639;&#x645;&#x644; &#x62F;&#x648;&#x646; &#x627;&#x62A;&#x635;&#x627;&#x644; &#x2013; &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62B;&#x627;&#x646;&#x64A;</title><link>https://academy.hsoub.com/programming/html/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%8A-%D8%AA%D8%B9%D9%85%D9%84-%D8%AF%D9%88%D9%86-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%E2%80%93-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r442/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_04/main.png.35c3e43247ead22c13780dc66d8304b4.png" /></p>

<p>
	تحدثنا في <a href="https://academy.hsoub.com/programming/html5/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%8A-%D8%AA%D8%B9%D9%85%D9%84-%D8%AF%D9%88%D9%86-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%E2%80%93-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r441/" rel="">الجزء الأول</a> من هذا الدرس عن أساسيات التخزين المحلي، وسنستمر في مشوارنا مع تطبيقات الويب التي تعمل دون اتصال، وسننشِئ مثالًا عمليًا عليها.
</p>

<p style="text-align: center;">
	<img alt="main.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22621" data-unique="erdn268tw" src="https://academy.hsoub.com/uploads/monthly_2017_04/main.png.244708c9e555bfae53976b66266db56a.png"></p>

<h3>
	تسلسل الأحداث
</h3>

<p>
	تحدثنا إلى الآن عن تطبيقات الويب التي تعمل دون اتصال، وعن ملف manifest للتخزين المؤقت، وعن مخزن التطبيق (appcache) بشكلٍ مبهم، وكأن الأمر يجري بطريقةٍ سحريةٍ. حيث تُنزَّل الملفات، وتقوم المتصفحات بمهامها على أتمِّ وجه، وكل شيء يعمل عملًا سليمًا! لكننا نتحدث هنا عن تطوير تطبيقات الويب، فلا يعمل أيّ شيءٍ من تلقاء نفسه.
</p>

<p>
	بدايةً، لنتكلم عن تسلسل الأحداث، تحديدًا أحداث DOM. عندما يزور متصفحك صفحةً تُشير إلى ملف manifest، فسيُطلِق سلسلةً من الأحداث في كائن window.applicationCache؛ أعلم أنَّ هذا قد يبدو معقدًا، لكن ثق بي، هذه أبسط نسخة تمكنت من كتابتها والتي لا تهمل أيّة معلومةٍ مهمةٍ.
</p>

<p>
	     <strong>1. </strong>بعد أن يلاحظ المتصفح خاصية manifest في عنصر &lt;html&gt;، فسيُطلِق الحدث checking مباشرةً (جميع الأحداث المذكورة هنا ستُفعَّل في الكائن window.applicationCache)، سيُفعَّل الحدث checking دومًا، حتى لو زرتَ هذه الصفحة من قبل أو كانت هنالك صفحاتٌ أخرى تشير إلى نفس ملف manifest.
</p>

<p>
	    <strong> 2.</strong> إن لم يتعامل متصفحك مع ملف manifest المُحدَّد من قبل…
</p>

<ul>
<li>
		سيُطلِق الحدث downloading، ثم سيبدأ بتنزيل الموارد المذكورة في ملف manifest للتخزين المؤقت.
	</li>
	<li>
		أثناء التنزيل، سيُطلِق متصفحك الحدث progress بين الحين والآخر، الذي يحتوي على معلوماتٍ عن عدد الملفات التي نُزِّلَت.
	</li>
	<li>
		بعد إكمال تنزيل جميع الموارد المذكورة في ملف manifest بنجاح، سيُطلِق المتصفح الحدث النهائي cached الذي يُشير إلى أنَّ تطبيق الويب قد خُزِّن مؤقتًا بشكلٍ كامل، وهو جاهز لكي يُستخدم دون اتصال.
	</li>
</ul>
<p>
	     <strong>3. </strong>في المقابل، إن زرتَ هذه الصفحة أو أي صفحة أخرى تُشير إلى إلى نفس ملف manifest من قبل، فسيعلم متصفحك عن ملف manifest؛ فربما خزَّن بعض الموارد في مخزن التطبيق (appcache)، وربما خزَّن كامل التطبيق. إذًا السؤال الآن هو: هل تغيّر ملف manifest منذ آخر مرة تحقق فيها المتصفح من ذلك؟
</p>

<ul>
<li>
		إذا كان الجواب: لا، لم يتغير ملف manifest؛ فسيُطلِق متصفحك الحدث noupdate، ولن يحتاج إلى اتخاذ خطواتٍ إضافية.
	</li>
	<li>
		إذا كان الجواب: نعم، تغيّر ملف manifest؛ فسيطلِق متصفحك الحدث downloading ويُعيد تنزيل كلُ موردٍ موجودٍ في ملف manifest.
	</li>
	<li>
		أثناء التنزيل، سيُطلِق متصفحك الحدث progress بين الحين والآخر، الذي يحتوي على معلومات عن عدد الملفات التي نُزِّلَت.
	</li>
	<li>
		بعد إعادة تنزيل كل الموارد الموجودة في ملف manifest بنجاح، سيُطلِق المتصفح الحدث النهائي updateready الذي يُشير إلى أنَّ النسخة الجديدة من تطبيق الويب قد خُزِّنت مؤقتًا بشكلٍ كامل، وهي جاهزة لكي تُستخدم دون اتصال. لكن انتبه إلى أنَّ النسخة الحديثة لن تُستعمَل فورًا، فلا تُبدَّل النسخة القديمة آنيًا، لكنك تستطيع استخدام النسخة الجديدة دون إجبار المستخدم على إعادة تحميل الصفحة باستدعاء الدالة window.applicationCache.swapCache()‎ يدويًا.
	</li>
	<li>
		إذا حدث أي شيء بشكلٍ خاطئ في أي نقطة في هذه المرحلة، فسيُطلِق متصفحك الحدث error وسيتوقف. هذه هي قائمة مختصرة بالأشياء التي قد تُسبِّب المشكلة:
	</li>
	<li>
		أعاد ملف manifest رسالة الخطأ HTTP 404 ‏(أي Page Not Found) أو 410 ‏(أي Permanently Gone).
	</li>
	<li>
		عُثِرَ على ملف manifest ولم يتغيّر، لكن فشل تنزيل صفحة HTML التي تُشير إلى الملف.
	</li>
	<li>
		تغيّر ملف manifest أثناء التحديث.
	</li>
	<li>
		عُثِرَ على ملف manifest وقد تغيّر، لكن المتصفح قد فشل بتنزيل أحد الموارد المذكورة فيه.
	</li>
</ul>
<h3>
	تنقيح الأخطاء
</h3>

<p>
	أريد أن أشير إلى نقطتين مهمتين هنا، أولهما هو شيءٌ قرأتَه لتوِّك لكنني متأكدٌ تمامًا أنَّك لم تعره اهتمامك، لذا دعني أكرره: إذا فشل تنزيل أحد الموارد الموجودة في ملف manifest تنزيلًا سليمًا، فستفشل عملية التخزين المؤقت لتطبيق الويب الذي يعمل دون اتصال بالكليّة، وسيُطلِق المتصفح الحدث error، لكن ليس هنالك أيّة إشارات إلى ماهية المشكلة. وهذا ما يجعل تنقيح (debugging) تطبيقات الويب التي تعمل دون اتصال معقدةً ومزعجةً أكثر من المعتاد.
</p>

<p>
	النقطة الثانية هي ليست –إذا ابتغينا الدقة التقنية– خطأً، لكنها ستبدو وكأنها علِّةٌ خطيرةٌ في المتصفح إلى أن تعلم ما الذي يجري. لهذه النقطة علاقةٌ بآليةِ تحققِ متصفحكَ فيما إذا تغيّر ملف manifest. وهي عمليةٌ تتألف من ثلاثِ خطواتٍ. هذه العملية مملةٌ لكنها مهمةٌ، لذا انتبه جيدًا لما سأتلوه عليك.
</p>

<ol>
<li>
		سيسأل متصفحك –عبر البنى الهيكلية الاعتيادية في HTTP– إذا انتهت صلاحية التخزين المؤقت لملف manifest. وكما في بقية الملفات التي تُخدَّم عبر HTTP، سيُضمِّن خادوم الويب عندك بشكلٍ اعتيادي بعض المعلومات حول الملف في ترويسات HTTP. بعض تلك الترويسات (Expires و Cache-Control) تخبِر متصفحك كيف يُسمَح له بتخزين الملف مؤقتًا دون سؤال الخادوم إذا تغيِّر أم لا. لا علاقة لهذه النوع من التخزين بتطبيقات الويب التي تعمل دون اتصال؛ وهو يحدث تقريبًا لكل صفحة HTML أو صفحة أنماط CSS أو سكربتٍ ما أو صورةٍ أو أي موردٍ آخر على الويب.
	</li>
	<li>
		إذا انتهت صلاحية ملف manifest المؤقت (وفقًا لترويسات HTTP الخاصة به)، فسيسأل متصفحُك الخادومَ إذا كانت هنالك نسخةٌ جديدةٌ من الملف؛ فإن وجِدَت، فسيُنزِّلها المتصفح. وللقيام بهذا، سيُرسِل متصفحك طلبية HTTP التي تتضمَّن تاريخ آخر تعديل لملف manifest المُخزَّن مؤقتًا، وهو نفسه الذي أرسله الخادوم في جواب HTTP ‏(HTTP response) في آخر مرّة نزَّل فيها متصفحك ملف manifest. إذا قال خادوم الويب أنَّ ملف manifest لم يتغير منذ ذاك الوقت، فسيُعيد الخادوم حالة 304 (أي Not Modified). أكرِّر أنَّ هذا لا علاقة له بتطبيقات الويب التي تعمل دون اتصال، وهو يحدث لكل نوع من أنواع الموارد الموجودة في الويب.
	</li>
	<li>
		إذا ظنَّ خادوم الويب أنَّ ملف manifest قد تغيّر منذ ذاك التاريخ، فسيُعيد الحالة HTTP 200 (أي OK) متبوعةً بمحتويات الملف الجديد بالإضافة إلى ترويسات Cache-Control جديدة وتاريخ جديد لآخر تعديل، لذا ستعمل الخطوتان 1 و 2 بشكلٍ سليم في المرة القادمة (بروتوكول HTTP جميل جدًا؛ إذ تُخطِّط خواديم الويب للمستقبل دائمًا، فإن كان على خادوم الويب إرسال ملفٍ إليك، فسيفعل ما بوسعه لكي يتأكَّد أنَّه لن يحتاج إلى إرساله لك مرتين دون داعٍ). بعد تنزيل ملف manifest الجديد، سيقارن المتصفح المحتويات مع النسخة التي نزَّلها آخر مرة. إذا كانت محتويات ملف manifest مماثلةً لمحتويات آخر نسخة، فلن يُعيد متصفحك تنزيل أيٌّ من الموارد المذكورة في الملف.
	</li>
</ol>
<p>
	قد تعترض إحدى الخطوات السابقة طريقك أثناء تطويرك واختبارك لتطبيق الويب الذي يعمل دون اتصال، على سبيل المثال، لنقل أنَّك أنشأتَ نسخةٌ من ملف manifest، ثم بعد 10 دقائق أدركت أنَّك تحتاج إلى إضافة مورد آخر إلى الملف. لا توجد مشكلة، صحيح؟ أضفت سطرًا جديدًا وجربت التطبيق، لكنه لم يعمل! إليك ما حدث: عندما أعدت تحميل الصفحة، لاحظ المتصفح خاصية manifest، وأطلق الحدث checking، لكنه لم يفعل شيئًا… أصرَّ متصفحك بعنادٍ أنَّ ملف manifest لم يتغير. لماذا؟ لأنَّ خادوم الويب –افتراضيًا– مضبوطٌ للطلب من المتصفحات أن تُخزِّن الملفات الثابتة مؤقتًا لعدِّة ساعات (وذلك عبر ترويسات Cache-Control في بروتوكول HTTP). وهذا يعني أنَّ متصفحك سيبقى عالقًا في الخطوة رقم 1 من الخطوات الثلاث السابقة. من المؤكَّد أنَّ خادوم الويب يعرف أنَّ الملف قد تغيّر، لكن متصفحك لن يحاول سؤال خادوم الويب. لماذا؟ لأنَّه في آخر مرة نزَّل متصفحك فيها ملف manifest، طلب الخادوم منه أن يُخزِّن الملف مؤقتًا لعدِّة ساعات، لكن متصفحك حاول إعادة طلب ذاك الملف بعد 10 دقائق.
</p>

<p>
	دعني أوضِّح لك أنَّ هذه ليست علّة وإنما ميزة. إذ يعمل كل شيءٍ كما يجب. إن لم تكن هنالك طريقة لخواديم الويب (وللخواديم الوسيطة [proxies]) لتخزين الملفات مؤقتًا، فسينهار الويب بين ليلةٍ وضحاها. لكن هذا ليس عزاءً لك بعد أن قضيت عدِّة ساعات محاولًا معرفة لماذا لم يلاحظ متصفحك أنَّ ملف manifest قد تعدَّل (من الطريف إن كنت قد انتظرت فترةً كافيةً ثم أعدتَ تحميل الصفحة فسيعمل الملف بشكلٍ سحري! ذلك لأنَّ فترة صلاحية الملف قد انتهت، كما قد حُدِّدَ لها تمامًا).
</p>

<p>
	هذا ما عليك فعله فوريًا: إعادة ضبط خادوم الويب عندك لكي لا يُخزَّن ملف manifest مؤقتًا عبر بروتوكول HTTP. إذا كنتَ تستعمل خادوم ويب مبني على أباتشي، فكل ما عليك فعله هو إضافة السطرين الآتيين إلى ملف ‎.htaccess:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2346_7">
<span class="pln">ExpiresActive On

ExpiresDefault "access"</span></pre>

<p>
	التعليمات السابقة ستُعطِّل التخزين المؤقت لكل ملف في ذاك المجلد وفي جميع المجلدات الفرعية، ومن المُرجَّح أنَّك لا تريد فعل هذا في خادومٍ إنتاجي؛ لذا عليك إما أن تضع التعليمات السابقة ضمن تعليمة &lt;Files&gt; لكي تؤثِّر على ملف manifest فقط، أو تُنشِئ مجلدًا فرعيًا لا يحتوي إلا على ملف manifest وملف ‎.htaccess فقط. وكالمعتاد، تختلف تفاصيل الضبط من خادومٍ إلى آخر، لذا راجع توثيق خادوم الويب الذي تستعمله لتفاصيلٍ حول كيفية التحكم بترويسات التخزين المؤقت لبروتوكول HTTP.
</p>

<p>
	بعد أن تُعطِّل التخزين المؤقت الخاص ببروتوكول HTTP على ملف manifest، ربما تواجهك مشكلة أخرى في أنَّك قد عدَّلت في أحد الموارد التي ستُخزَّن في مخزن التطبيق (appcache) لتُستعمَل دون اتصال، لكنها بقيت تملك نفس عنوان URL في خادومك. هنا ستعترض الخطوة رقم 2 من الخطوات الثلاث السابقة طريقك. إذا لم يتغير محتوى ملف manifest، فلن يلاحظ المتصفح أنَّ أحد الموارد المُخزَّنة مسبقًا قد تغيّر. ألقِ نظرةً إلى المثال الآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2346_9">
<span class="pln">CACHE MANIFEST

# rev 42

clock.js

clock.css</span></pre>

<p>
	إذا عدِّلتَ ملف الأنماط clock.css وجربت التطبيق، فلن تلاحظ وجود التعديلات التي أجريتها، وذلك لأنَّ ملف manifest نفسه لم يُعدَّل. في كل مرة تُجري فيها تعديلًا لموردٍ ما في تطبيق الويب الذي يعمل دون اتصال، فعليك أن تُعدِّل ملف manifest نفسه. وهذا بسيطٌ جدًا، فلا يلزمك إلا تغييرُ حرفٍ وحيد. أسهل طريقة وجدتها لفعل هذا هو تضمين تعليق فيه رقم النسخة أو المراجعة (revision). غيّر رقم النسخة الموجود في التعليق، ثم سيلاحظ متصفحك أنَّ محتوى الملف قد تغيّر وسيعيد تنزيل كل الموارد المذكورة فيه.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2346_11">
<span class="pln">CACHE MANIFEST

# rev 43

clock.js

clock.css</span></pre>

<h3>
	لننشِئ واحدًا!
</h3>

<p>
	هل تتذكر لعبة الضامة التي برمجناها في<a href="https://academy.hsoub.com/programming/html5/%D8%A7%D9%84%D8%B1%D8%B3%D9%85-%D8%B9%D8%A8%D8%B1-%D8%B9%D9%86%D8%B5%D8%B1-canvas-%D9%81%D9%8A-html5-r345/" rel=""> درس canvas</a> ثم حسّنّاها لاحقًا بحفظنا للتحركات عبر <a href="https://academy.hsoub.com/programming/html5/%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%AD%D9%84%D9%8A-local-storage-%D9%81%D9%8A-html5-r362/" rel="">التخزين المحلي</a>؟ ما رأيك أن نجعل اللعبة تعمل دون اتصال.
</p>

<p>
	علينا أن نُنشِئ ملف manifest يحتوي على قائمة بجميع الموارد التي تحتاج لها اللعبة. حسنًا، هنالك صفحة HTML رئيسية، وملف JavaScript وحيد الذي يحتوي على شيفرة اللعبة. لا توجد صور، لأننا رسمنا كل شيءٍ برمجيًا عبر الواجهة البرمجية لعنصر canvas. وجميع أنماط CSS موجودة في عنصر &lt;style&gt; في أعلى صفحة HTML.
</p>

<p>
	ها هو ذا ملف manifest الخاص باللعبة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2346_13">
<span class="pln">CACHE MANIFEST

halma.html

../halma-localstorage.js</span></pre>

<p>
	كلمة عن المسارات: أنشأتُ مجلدًا فرعيًا باسم offline/‎ في مجلد examples/‎، وملف manifest السابق موجودٌ هناك في المجلد الفرعي. ولأنَّ صفحة HTML ستحتاج إلى تعديلٍ بسيطٍ لكي تعمل دون اتصال (سآتيك به بعد دقيقة)، فأنشأتُ نسخةً منفصلةً من ملف HTML، الموجودةُ أيضًا في المجلد الفرعي offline/‎، ولعدم وجود أيّة تعديلات على شيفرة JavaScript منذ أن أضفنا دعمًا للتخزين المحلي، فسأستعمل ملفات ‎.js نفسها، الموجودة في المجلد الأب (examples/‎). ستبدو المسارات كالآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2346_16">
<span class="pln">/examples/localstorage-halma.html

/examples/halma-localstorage.js

/examples/offline/halma.manifest

/examples/offline/halma.html</span></pre>

<p>
	نريد الإشارة إلى ملفين في ملف manifest للتخزين المحلي (‎/examples/offline/halma.manifest)، أولهما هو النسخة التي تعمل دون اتصال لملف HTML (/examples/offline/halma.html) ولأن كلا الملفين في نفس المجلد، فمن الممكن ذكره في ملف manifest دون وجود سابقة للمسار. أما ثانيهما، فهو ملف JavaScript الموجود في المجلد الأب (‎/examples/halma-localstorage.js‎)، ويجب استخدام المسارات النسبية في ملف manifest:‏ ‎../halma-localstorage.js، وهذا مشابهٌ لاستعمالك لعنوان URL نسبي في خاصية &lt;img src&gt;. يمكنك أيضًا استعمال المسارات المطلقة (absolute paths، تلك التي تبدأ من المجلد الجذر للموقع) أو حتى عناوين URL المطلقة (التي تُشير إلى موارد موجودة على نطاقات أخرى).
</p>

<p>
	علينا إضافة خاصية manifest في ملف HTML لكي تُشير إلى ملف manifest للتخزين المؤقت:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2346_18">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">

</span><span class="tag">&lt;html</span><span class="pln"> </span><span class="atn">lang</span><span class="pun">=</span><span class="atv">"en"</span><span class="pln"> </span><span class="atn">manifest</span><span class="pun">=</span><span class="atv">"halma.manifest"</span><span class="tag">&gt;</span></pre>

<p>
	هذا كل ما عليك فعله! عندما تزور <a href="http://diveinto.html5doctor.com/examples/offline/halma.html" rel="external nofollow">صفحة اللعبة التي تعمل دون اتصال</a> بمتصفح حديث، فسينزِّل ملف manifest المُشار إليه في خاصية manifest ثم سيبدأ بتنزيل جميع الموارد الموجودة فيه ويضعها في مخزن التطبيق (appcache). ومن هنا ستتولى شيفرة الصفحة الأمر في كل مرة تزور فيها الصفحة. يمكنك اللعب دون اتصال وستُخزَّن بيانات اللعبة محليًا، لذا ستستطيع أن تُغلِق اللعبة ثم تعود إليها متى شئت.
</p>

<h3>
	كلمة أخيرة
</h3>

<p>
	أعلنت W3C أخيرًا أنَّها <a href="https://html.spec.whatwg.org/multipage/browsers.html#offline" rel="external nofollow">ستزيل هذه الميزة من معيار HTML5</a>، إلا أنَّ هذه العملية ستستغرق وقتًا طويلًا. ونصحت W3C باستخدام Service Workers بدلًا منها. المشكلة أنَّ ميزة Service Workers غير مدعومة من الغالبية العظمى من المتصفحات، والمتصفحات التي تتواجد فيها ميزة Service Workers تدعمها دعمًا جزئيًا فقط.
</p>

<p>
	تركت W3C المطورين بين المطرقة والسندان، لكنني أرى أنَّ عليك الاستمرار في استخدام هذه الميزة، مع متابعة أخبار دعم Service Workers لتنتقل إليها في المستقبل.
</p>

<h3>
	مصادر إضافية
</h3>

<p>
	<strong>المعايير</strong>:
</p>

<p>
	<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html" rel="external nofollow">Offline web applications</a> في مواصفة HTML5
</p>

<p>
	<strong>توثيقٌ من صانعي المتصفحات</strong>:
</p>

<p>
	<a href="https://developer.mozilla.org/En/Offline_resources_in_Firefox" rel="external nofollow">Offline resources in Firefox</a>
</p>

<p>
	<a href="http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/OfflineApplicationCache/OfflineApplicationCache.html" rel="external nofollow">HTML5 offline application cache</a>، التي هي جزءٌ من <a href="http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Introduction/Introduction.html" rel="external nofollow">Safari client-side storage and offline applications programming guide</a>
</p>

<p>
	<strong>الدروس التعليمية</strong>:
</p>

<p>
	<a href="http://googlecode.blogspot.com/2009/04/gmail-for-mobile-html5-series-using.html" rel="external nofollow">Gmail for mobile HTML5 series: using appcache to launch offline - part 1</a>
</p>

<p>
	<a href="http://googlecode.blogspot.com/2009/05/gmail-for-mobile-html5-series-part-2.html" rel="external nofollow">Gmail for mobile HTML5 series: using appcache to launch offline - part 2</a>
</p>

<p>
	<a href="http://googlecode.blogspot.com/2009/05/gmail-for-mobile-html5-series-part-3.html" rel="external nofollow">Gmail for mobile HTML5 series: using appcache to launch offline - part 3</a>
</p>

<p>
	<a href="http://jonathanstark.com/blog/2009/09/27/debugging-html-5-offline-application-cache/" rel="external nofollow">Debugging HTML5 offline application cache</a>
</p>

<p>
	<a href="http://hacks.mozilla.org/2010/02/an-html5-offline-image-editor-and-uploader-application/" rel="external nofollow">an HTML5 offline image editor and uploader application</a>
</p>

<p>
	ترجمة -وبتصرّف- لفصل <a href="http://diveinto.html5doctor.com/offline.html" rel="external nofollow">Offline Web Applications</a> من كتاب Dive Into HTML5 لمؤلفه Mark Pilgrim.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/html/html5/%D8%A7%D9%84%D9%86%D9%85%D8%A7%D8%B0%D8%AC-forms-%D9%81%D9%8A-html5-r370/" rel="">النماذج (Forms) في HTML5</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/html/html5/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%8A-%D8%AA%D8%B9%D9%85%D9%84-%D8%AF%D9%88%D9%86-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%E2%80%93-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r441/" rel="">تطبيقات الويب التي تعمل دون اتصال – الجزء الأول</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب ن<a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">حو فهم أعمق لتقنيات HTML5</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">442</guid><pubDate>Fri, 15 Jul 2016 21:00:00 +0000</pubDate></item><item><title>&#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x648;&#x64A;&#x628; &#x627;&#x644;&#x62A;&#x64A; &#x62A;&#x639;&#x645;&#x644; &#x62F;&#x648;&#x646; &#x627;&#x62A;&#x635;&#x627;&#x644; &#x2013; &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x623;&#x648;&#x644;</title><link>https://academy.hsoub.com/programming/html/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%8A-%D8%AA%D8%B9%D9%85%D9%84-%D8%AF%D9%88%D9%86-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%E2%80%93-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r441/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_04/main.png.04979381ff30b6fba1736d43c4f1f5ed.png" /></p>

<p>
	ما هي تطبيقات الويب التي تعمل دون اتصال؟ يبدو الأمر من الوهلة الأولى كأنَّ هنالك تضاربًا في المفاهيم. فهل هي صفحات الويب التي تنزِّلها ثم تفتحها بعد ذلك؟ لكن التنزيل يتطلب اتصالًا شبكيًا، فكيف ستستطيع تنزيل الصفحة عندما لا تكون متصلًا؟ لن تستطيع فعل ذلك بكل تأكيد، لكنك تستطيع تنزيل الصفحة عندما تكون متصلًا بالشبكة، وهذه هي آلية عمل تطبيقات HTML5 التي تعمل دون اتصال (offline web applications).
</p>

<p style="text-align: center;">
	<img alt="main.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22623" data-unique="jegcz4fdo" src="https://academy.hsoub.com/uploads/monthly_2017_04/main.png.ad7c8eb735a26b91f85e287565e607e3.png"></p>

<p>
	بأبسط الكلمات: تطبيق الويب الذي يعمل دون اتصال هو قائمةٌ بروابط URL التي تُشير إلى ملفات HTML أو CSS أو JavaScript أو الصور أو أيّ موردٍ آخر. تُشير الصفحة الرئيسية إلى تلك القائمة التي تُسمى «ملف manifest» الذي هو ملفٌ نصيٌ موجودٌ في مكانٍ ما على خادوم الويب، وسيقرأ متصفح الويب الذي يدعم تشغيل تطبيقات الويب دون اتصال قائمةَ روابطِ URL الموجودةَ في ملف manifest، ثم يُنزِّل تلك الموارد (resources)، ثم يُخزِّنها تخزينًا مؤقتًا محليًا (local cache)، ثم سيُحدِّث النسخ المحلية منها تلقائيًا في حال تغيرت. وعندما يحين وقت محاولتك الوصول إلى تطبيق الويب دون اتصالٍ شبكي، فسيحاول متصفحك عرض النسخة المُخزَّنة محليًا تلقائيًا.
</p>

<p>
	ومن هذه النقطة، سيُلقى الحِمل على عاتِقِكَ تمامًا –كمطوِّر ويب–؛ فهنالك رايةٌ (flag) في DOM تخبرك إذا كان المتصفح متصلًا بالشبكة أم لا، وهنالك أحداث (events) تُفعَّل عندما تتغير حالة الوصول إلى الشبكة (أي لو كنتَ تعمل دون اتصال، ثم توفَّر لديك بعد دقيقةٍ اتصالٌ شبكي؛ أو بالعكس). لكن إن كان تطبيقُك يولِّد بياناتٍ أو يحفظها، فالأمر متروكٌ لك لتخزين البيانات محليًا عندما لا تكون متصلًا بالشبكة ثم تزامنها مع الخادوم البعيد بعد أن تستعيد اتصالك به. بعبارةٍ أخرى، تمكّنك HTML من جعل تطبيقك يعمل دون اتصال، لكن ما يفعله تطبيقك في هذه المرحلة عائدٌ إليك تمامًا. 
</p>

<p style="text-align: center;">
	<strong>المتصفحات التي تدعم هذه الخاصية</strong>
</p>

<center>
	<table border="1"><tbody>
<tr>
<td style="padding: 5px 10px; text-align: center; background-color: #ecf0f1;">
					IE
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: #ecf0f1;">
					Firefox
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: #ecf0f1;">
					Safari
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: #ecf0f1;">
					Chrome
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: #ecf0f1;">
					Opera
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: #ecf0f1;">
					iPhone
				</td>
				<td style="padding: 5px 10px; text-align: center; background-color: #ecf0f1;">
					Android
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: center;">
					10+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					3.5+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					5.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					10.6+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					2.1+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					2.0+
				</td>
			</tr>
</tbody></table>
</center>

<h3>
	ملف Manifest
</h3>

<p>
	يتمحور تطبيق الويب الذي يعمل دون اتصال حول ملف manifest للتخزين المؤقت. إذًا ما هو ملف manifest؟ هو قائمة بكل الموارد (resources) التي يحتاج لها تطبيق الويب لكي يستطيع المستخدم الوصول إليه وهو غير متصلٍ بالشبكة. وعليك أن تُشير إلى ملف manifest باستعمالك لخاصية manifest في عنصر &lt;html&gt; لتمهيد الطريق لعملية تنزيل وتخزين تلك الموارد تخزينًا مؤقتًا.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4200_7">
<span class="dec">&lt;!DOCTYPE HTML&gt;</span><span class="pln">

</span><span class="tag">&lt;html</span><span class="pln"> </span><span class="atn">manifest</span><span class="pun">=</span><span class="atv">"/cache.manifest"</span><span class="tag">&gt;</span><span class="pln">

</span><span class="tag">&lt;body&gt;</span><span class="pln">

...

</span><span class="tag">&lt;/body&gt;</span><span class="pln">

</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يمكن أن يتواجد ملف manifest للتخزين المؤقت في أي مكان في خادوم الويب عندك، لكن يجب أن يُخدَّم بنوع text/cache-manifest؛ إذا كنتَ تستعمل خادوم ويب يعتمد على أباتشي (Apache)، فمكن المرجَّح أنَّ كل ما عليك فعله هو <a href="http://httpd.apache.org/docs/2.2/mod/mod_mime.html#addtype" rel="external nofollow">إضافة تعليمة AddType</a> في ملف ‎.htaccess في المجلد الجذر الذي يُخدَّم منه تطبيق الويب:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4200_10">
<span class="pln">AddType text/cache-manifest .manifest
</span></pre>

<p>
	تأكَّد أنَّ اسم ملف manifest للتخزين المؤقت ينتهي باللاحقة ‎.manifest؛ إن كنتَ تستعمل خادوم ويب آخر أو ضبطًا مختلفًا لأباتشي، فراجع التوثيق الخاص بالخادوم لمزيدٍ من المعلومات حول التحكم في ترويسة Content-Type.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix">
		<p>
			س: تطبيق الويب الخاص بي مُقسَّمٌ إلى عدِّة صفحات. هل أحتاج إلى إضافة خاصية manifest في كل صفحة، أم عليّ وضعها في الصفحة الرئيسية فقط؟
		</p>

		<p>
			ج: يجب وضع خاصية manifest في كل صفحة من صفحات موقعك، ويجب على تلك الخاصية أن تُشير إلى ملف manifest للتخزين المؤقت لكامل تطبيق الويب.
		</p>
	</div>
</blockquote>

<p>
	حسنًا، على كل صفحة من صفحات HTML أن تُشير إلى ملف manifest للتخزين المؤقت، ويجب أن يُخدَّم ملف manifest بترويسة Content-Type مناسبة. لكن ماذا يوجد داخل ملف manifest؟ ها قد بدأت الإثارة.
</p>

<p>
	أول سطر من أي ملف manifest هو:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4200_12">
<span class="pln">CACHE MANIFEST
</span></pre>

<p>
	وبعد هذا السطر، ستُقسَّم جميع ملفات manifest إلى ثلاثة أقسام: قسم «explicit»، وقسم «fallback» وقسم «online whitelist». لدى كل قسم ترويسةٌ مذكورةٌ في سطرٍ خاصٍ بها؛ وإن لم يحتوي ملف manifest على أيّة ترويسات، فهذا يعني ضمنيًا أنَّ كل الموارد المذكورة في الملف موجودةٌ في القسم «explicit». لا تحاول أن تطيل التفكير في الاصطلاحات السابقة، خشية أن ينفجر رأسك من الصداع.
</p>

<p>
	هذا ملف manifest سليمُ البنية، ويحتوي على ثلاثة موارد: ملف CSS، وملف JavaScript، وصورة JPEG.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4200_14">
<span class="pln">CACHE MANIFEST

/clock.css

/clock.js

/clock-face.jpg</span></pre>

<p>
	لا يحتوي ملف manifest السابق على ترويسات للأقسام، لذا ستكون جميع الموارد المذكورة فيه موجودة في قسم «explicit» افتراضيًا. ستُنزَّل الموارد المذكورة في قسم «explicit» وتُخزَّن تخزينًا مؤقتًا محليًا، وستُستعمَل مكان نظيراتها الموجودة على الشبكة في حال كان المستخدمُ غيرَ متصلٍ. وبهذا –وعند تحميل ملف manifest للتخزين المؤقت– سينُزِّل متصفح الويب الملفات clock.css و clock.js و clock-face.jpg من المجلد الجذر لخادوم الويب، ثم إذا أزلتَ مقبس الشبكة وأعدتَ تحديث الصفحة، فستبقى كل تلك الموارد متوفرةً دون اتصال.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix">
		<p>
			س: هل أحتاج إلى ذكر جميع صفحات HTML في ملف manifest؟
		</p>

		<p>
			ج: نعم ولا. إن كان تطبيق الويب محتوىً في صفحةٍ وحيدة، فعليك أن تتأكد أنَّ تلك الصفحة تُشير إلى ملف manifest باستخدام خاصية manifest. فعندما تفتح صفحة HTML تحتوي على خاصية manifest فستُعتَبَر الصفحةُ نفسهُا جزءًا من تطبيق الويب، ولستَ بحاجةٍ إلى وضعها ضمن ملف manifest.
		</p>

		<p>
			أما لو كان تطبيق الويب يمتد على أكثر من صفحة، فعليك حينها أن تذكر جميع صفحات HTML في ملف manifest، وإلا فلن يعلم المتصفح أنَّ هنالك صفحات HTML أخرى عليه تنزيلها وتخزينها تخزينًا مؤقتًا.
		</p>
	</div>
</blockquote>

<h3>
	قسم NETWORK
</h3>

<p>
	هذا مثالٌ أكثر تعقيدًا. لنقل أنَّك تريد من تطبيق الساعة الذي أنشأته أن يتتبع الزوار باستخدام سكربت tracking.cgi الذي سيُحمَّل ديناميكيًا في خاصية &lt;img src&gt;، إلا أنَّ تخزين هذا الملف تخزينًا مؤقتًا سيؤثر سلبًا على غرض ذاك السكربت (الذي هو تتبع المستخدمين آنيًا)، لذا لا يجب أبدًا تخزين هذا المورد مؤقتًا ولا يجوز أن يُتاح دون اتصال. هذه هي طريقة فعل ذلك:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4200_16">
<span class="pln">CACHE MANIFEST

NETWORK:

/tracking.cgi

CACHE:

/clock.css

/clock.js

/clock-face.jpg</span></pre>

<p>
	ملف manifest السابق يحتوي على ترويسات للأقسام، فالسطر الذي يحتوي على NETWORK:‎ هو بداية قسم «online whitelist»، والموارد المذكورة في هذا القسم لن تُخزَّن محليًا ولن تتوفر دون اتصال (محاولة تحميلها عند عدم توفر اتصال ستؤدي إلى خطأ). أما السطر CACHE:‎ فهو بداية قسم «explicit»، وبقية ملف manifest مماثلة للمثال السابق، حيث سيُنزَّل وسيُخزَّن كل مورد من الموارد المذكورة محليًا وسيُتاح للاستعمال دون اتصال.
</p>

<h3>
	قسم FALLBACK
</h3>

<p>
	هنالك نوعٌ آخر من الأقسام في ملف manifest: قسمfallback، الذي تُعرِّف فيه البدائل عن الموارد الموجودة على الشبكة التي –لسببٍ من الأسباب– لا يمكن تخزينها مؤقتًا أو لم يتم ذلك بنجاح. توفِّر مواصفة HTML5 حلًا ذكيًا لطريقة استخدام قسم fallback:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4200_18">
<span class="pln">CACHE MANIFEST

FALLBACK:

/ /offline.html

NETWORK:

*</span></pre>

<p>
	ماذا يفعل المثال السابق؟ أولًا، لنأخذ مثالًا موقعًا يحتوي ملايين الصفحات مثل ويكيبيديا؛ لا تستطيع تنزيل كامل الموقع، ومن المؤكد أنَّك لا ترغب بذلك. لكن لنقل أنَّك تريد أن تأخذ جزءًا منه وتجعله متوفرًا دون اتصال؛ لكن كيف ستقرر ما هي الصفحات التي تحتاج إلى تخزينها مؤقتًا؟ ماذا عن: كل صفحة زرتها في موقع ويكيبيديا –الذي افترضنا جدلًا أنَّه يدعم التشغيل دون اتصال– ستُنزَّل وستخزَّن مؤقتًا. وهذا يتضمن كل مُدخَلة من مدخلات الموسوعة التي زرتها، وكل صفحة نقاش (أي المكان الذي تتناقش فيه عن مُدخَلة معيّنة)، وكل صفحة تحرير (أي تلك الصفحة التي تُجري فيها تعديلاتٍ إلى مُدخلةٍ ما).
</p>

<p>
	هذا ما سيفعله ملف manifest السابق: لنفترض أنَّ كل صفحة HTML (صفحة المُدخلة أو النقاش أو التعديل أو تأريخ الصفحة) في ويكيبيديا تُشير إلى ملف manifest السابق؛ فعندما تزور أي صفحة تُشير إلى ملف manifest فسيقول متصفحك: «مهلًا، هذه الصفحة جزءٌ من تطبيق الويب يعمل دون اتصال، لكن هل أعرف شيئًا عن هذا التطبيق؟» إن لم يُنزِّل متصفحك ملف manifest المُحدَّد من قبل قط، فسيهِّيء «مخزن جديد للتطبيق» (appcache، اختصار للعبارة «application cache»)، وسيُنزِّل جميع الموارد المذكورة في ملف manifest، ثم سيُضيف الصفحة الحالية إلى مخزن التطبيق (appcache). إن كان يعرف متصفحك ملف manifest من قبل، فسيُضيف الصفحة الحالية إلى مخزن التطبيق (appcache) الموجود مسبقًا. وفي كلا الحالتين ستُضاف الصفحة التي زرتها إلى مخزن التطبيق. وهذا مهمٌ لأنَّه يعني أنَّك تستطيع بناء تطبيق ويب يُضيف الصفحات التي يزورها المستخدم تلقائيًا إلى مخزنه. فلستَ بحاجةٍ إلى وضع كل صفحة من صفحات HTML في ملف manifest للتخزين المؤقت.
</p>

<p>
	انظر الآن إلى قسم fallback في ملف manifest السابق، الذي يحتوي على سطرٍ وحيدٍ. القسم الأول من السطر (الذي يقع قبل الفراغ) ليس عنوان URL، وإنما نمط URL‏ (URL pattern)، حيث سيُطابِق المحرف / أي صفحة في موقعك وليس الصفحة الرئيسية فقط. فعندما تحاول زيارة صفحة ما عندما تكون غيرَ متصلٍ بالشبكة، فسيبحث متصفحك عنها في مخزن التطبيق (appcache)، فإن وجد المتصفحُ الصفحةَ في مخزن التطبيق (ﻷنك زُرتَها عندما كنتَ متصلًا بالشبكة، ومن ثم أُضيفَت الصفحة إلى مخزن التطبيق [appcache] في ذات الوقت)، فسيعرض المتصفح النسخة المُخزَّنة من الصفحة محليًا؛ إما إذا لم يجد متصفحك الصفحة في مخزن التطبيق، فبدلًا من عرض رسالة الخطأ، فسيعرض الصفحة ‎/offline.html التي تُمثِّل القسم الثاني في السطر المذكور في قسم fallback.
</p>

<p>
	في النهاية، لننظر إلى قسم الشبكة (network). يحتوي قسم الشبكة في ملف manifest السابق على سطرٍ فيه محرف وحيد (*)، هذا المحرف له معنىً خاص في قسم الشبكة. وهو يُدعى «online whitelist wildcard flag» وهي طريقة منمّقة لقول أنَّ كل شيءٍ غير موجودٍ في مخزن التطبيق (appcache) سيُنزَّل من عنوان الويب الأصلي لطالما هنالك اتصالٌ شبكيٌ بالإنترنت. هذا مهمٌ لتطبيقات الويب التي تعمل دون اتصال التي لا نريد تنزيلها كل صفحاتها ومواردها، وهذا يعني أنَّه أثناء تصفحك لموقع ويكيبيديا –الذي افترضنا جدلًا أنَّه يدعم العمل دون اتصال– مع اتصالٍ بالإنترنت، فسيحمِّل المتصفح الصور ومقاطع الفيديو والموارد الأخرى المضمَّنة بشكلٍ اعتيادي، حتى ولو كانت في نطاقٍ (domain) مختلف (هذا الأمر شائعٌ في المواقع الكبرى حتى لو لم تكن جزءًا من تطبيق ويب يعملُ دونَ اتصالٍ. صفحات HTML تولَّد وتُخدَّم محليًا في تلك الخواديم، لكن الصور والفيديو تُخدَّم عبر <a href="http://en.wikipedia.org/wiki/Content_delivery_network" rel="external nofollow">CDN</a> في نطاقٍ آخر). لكن دون هذا المحرف البديل (wildcard)، فسيتصرّف تطبيق ويكيبيديا الذي افترضنا أنَّه يعمل دون اتصال تصرفاتٍ غريبة عندما تكون متصلًا بالشبكة. بشكلٍ خاص: لن يستطيع تنزيل أي صور أو مقاطع فيديو مخزَّنة على نطاقٍ خارجي.
</p>

<p>
	هل هذا المثال كاملٌ؟ لا، لأنَّ ويكيبيديا أكثر من مجرد صفحات HTML. فهي تستعمل موارد CSS و JavaScript وصور مشتركة في كل صفحة. فيجب أن تُذكَر تلك الموارد بشكلٍ صريحٍ في قسم CACHE:‎ من ملف manifest، لكي تُعرَض الصفحات عرضًا صحيحًا وتسلك سلوكًا سليمًا عندما تُشغَّل دون اتصال. لكن الغاية من قسم fallback تكمن عندما لا تنزِّل كامل صفحات تطبيق الويب الذي يحتوي على موارد لم تذكرها بصراحة في ملف manifest.
</p>

<p>
	ترجمة -وبتصرّف- لفصل <a href="http://diveinto.html5doctor.com/offline.html" rel="external nofollow">Offline Web Applications</a> من كتاب Dive Into HTML5 لمؤلفه Mark Pilgrim.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/html/html5/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%8A-%D8%AA%D8%B9%D9%85%D9%84-%D8%AF%D9%88%D9%86-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%E2%80%93-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r442/" rel="">تطبيقات الويب التي تعمل دون اتصال – الجزء الثاني</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/html/html5/%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%AD%D9%84%D9%8A-local-storage-%D9%81%D9%8A-html5-r362/" rel="">التخزين المحلي (Local Storage) في HTML5</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">نحو فهم أعمق لتقنيات HTML5 </a>
	</li>
</ul>
]]></description><guid isPermaLink="false">441</guid><pubDate>Tue, 12 Jul 2016 21:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x62E;&#x632;&#x64A;&#x646; &#x627;&#x644;&#x645;&#x62D;&#x644;&#x64A; (Local Storage) &#x641;&#x64A; HTML5</title><link>https://academy.hsoub.com/programming/html/%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%AD%D9%84%D9%8A-local-storage-%D9%81%D9%8A-html5-r362/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_07/html5-local-storage.png.6cd0e4e6aedf627d353a5bd3cf9795bf.png" /></p>

<p>
	كانت البرمجيات المكتبية تتفوق على تطبيقات الويب بإمكانية تخزين المعلومات محليًا تخزينًا دائمًا؛ حيث يوفِّر نظام التشغيل عادةً طبقةً وسيطةً لتخزين وقراءة بيانات خاصة بالتطبيق مثل الإعدادات وحالة التشغيل، وقد تُخزَّن هذه القيم في سجل النظام (registry) أو ملفات ini أو ملفات XML أو في مكانٍ آخر وفقًا للتقاليد المُتبَعة في نظام التشغيل؛ أما لو احتاج التطبيق المكتبي إلى تخزينٍ محليٍ أكثر تعقيدًا من مجرد تخزين البيانات على شكل "المفتاح/القيمة"، فيمكنك أن تُضمِّن قاعدة البيانات الخاصة بتطبيقك، أو أن تبتكر صيغة ملفات للتخزين، أو غيره ذلك من الحلول.
</p>

<p>
	لكن على مرِّ التاريخ، لم تملك تطبيقات الويب هذا الامتياز، وعلى الرغم من ابتكار الكعكات (Cookies) في بدايات الويب لكن كان الغرض منها هو التخزين المحلي لكميةٍ قليلةٍ من البيانات، إلا أنَّ هنالك ثلاثة أسباب تمنعنا من استخدامها لهذا الغرض:
</p>

<ul>
<li>
		ستُضمَّن الكعكات في كل طلبية HTTP، مما يؤدي إلى حدوث بطء في تطبيق الويب بسبب نقل نفس البيانات مرارًا وتكرارًا دون داعٍ
	</li>
	<li>
		ستُضمَّن الكعكات في كل طلبية HTTP، وهذا يعني إرسال البيانات دون تشفير عبر الإنترنت (إلا إذا كان يُخدَّم تطبيق الويب عندك عبر طبقة <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr>)
	</li>
	<li>
		المساحة التخزينية للكعكات محدودة إلى حوالي 4 كيلوبايت من البيانات، وهي كافية لإبطاء تطبيقك (انظر أعلاه)، لكنها ليست كافية لتخزين شيءٍ مفيدٍ
	</li>
</ul>
<p>
	ما نحتاج له حقًا هو:
</p>

<ul>
<li>
		مساحة تخزينية كبيرة
	</li>
	<li>
		موجودة على جهاز العميل
	</li>
	<li>
		يمكن أن تبقى حتى بعد تحديث الصفحة
	</li>
	<li>
		لن تُنقَل طوال الوقت إلى الخادوم
	</li>
</ul>
<p>
	جميع المحاولات -قبل HTML5- لتحقيق ما سبق كانت غير مرضية لمختلف الأسباب.
</p>

<p style="text-align: center;">
	<img alt="html5-local-storage.png" class="ipsImage ipsImage_thumbnailed" data-fileid="18470" data-unique="xba02pf74" src="https://academy.hsoub.com/uploads/monthly_2016_07/html5-local-storage.png.0e10d1510d2e9dac7776ddc207f56a9b.png"></p>

<h2>
	لمحة تاريخية عن محاولات تخزين البيانات محليا قبل HTML5
</h2>

<p>
	لم يكن هنالك سوى متصفح Internet Explorer في بدايات الويب، أو على الأقل هذا ما حاولت مايكروسوفت إيهام العالم به، ولتحقيق هذه الغاية، وكجزءٍ من الحرب الكبرى الأولى للمتصفحات، ابتكرت مايكروسوفت ميزاتٍ كثيرة ووضعتها في متصفحها -Internet Explorer- الذي أنهى تلك الحرب. واحدة من تلك الميزات تُسمى "DHTML Behaviors" وكان أحد خصائصها يُدعى userData.
</p>

<p>
	تسمح ميزة userData لصفحات الويب أن تُخزِّن 64 كيلوبايت كحد أقصى لكل نطاق (domain)، وذلك عبر هيكلية تعتمد على XML (أما النطاقات الموثوقة، مثل مواقع إنترانت [intranet]، فتستطيع تخزين 10 أضعاف الكمية؛ وكانت 640 كيلوبايت في ذاك الوقت أكثر من كافية). لم يوفِّر IE أي مربع حوار لأخذ إذن المستخدم، ولم تكن هنالك إمكانية لزيادة كمية البيانات التي يمكن تخزينها محليًا.
</p>

<p>
	في عام 2002، أضافت شركة Adobe ميزةً في Flash 6 التي اكتسبت الاسم "Flash cookies"، لكن هذه الميزة كانت معروفةً ضمن بيئة Flash بالاسم Local Shared Objects؛ باختصار، تسمح هذه الميزة لكائنات Flash أن تُخزِّن 100 كيلوبايت من البيانات كحد أقصى لكل نطاق. طوَّر Brad Neuberg نموذجًا أوليًا لجسرٍ يربط تقنية Flash بلغة JavaScript أسماه AMASS (اختصار للعبارة AJAX Massive Storage System)، لكنه كان محدودًا بسبب بعض المشكلات في تصميم صيغة Flash. لكن في 2006، ومع مجيء ExternalInterface في Flash 8، أصبح من الممكن بسهولة وسرعة الوصول إلى الكائنات المشتركة المخزنة محليًا (Local Shred Objects أو اختصارًا LSOs) من JavaScript؛ ولهذا السبب أعاد Brad كتابة AMASS ودمجها مع Dojo Toolkit تحت الاسم dojox.storage. وبهذا مَنَحَ Flash كل نطاق 100 كيلوبايت من التخزين المحلي "مجانًا"، وستُطلَب موافقة المستخدم عند كل زيادة في تخزين البيانات (1 ميغابايت، 10 ميغابايت، وهكذا).
</p>

<p>
	في عام 2007، أصدرت Google إضافة <a href="http://gears.google.com/" rel="external nofollow">Gears</a>، التي هي إضافة مفتوحة المصدر للمتصفحات غرضها هو توفير إمكانيات إضافية إليها (تحدثنا سابقًا عن Gears في سياق /توفير واجهة برمجية لتحديد الموقع الجغرافي لمتصفح IE/). <a href="http://code.google.com/apis/gears/api_database.html" rel="external nofollow">توفِّر Gears واجهة برمجية (<abbr title="Application Programming Interface | واجهة برمجية">API</abbr>) للوصول إلى قاعدة بيانات SQL مدمجة فيها مبنيةٌ على محرك قواعد البيانات SQLite</a>. يمكن لإضافة Gears تخزين كمية غير محدودة من البيانات لكل نطاق في جداول قاعدة بيانات SQL بعد أخذ إذن المستخدم.
</p>

<p>
	في تلك الأثناء، أكمل Brad Neuberg وآخرون مشوارهم في تطوير dojox.storage لتوفير واجهة موحَّدة لمختلف الإضافات، وبحلول 2009 أصبح بمقدور dojox.storage أن تكتشف دعم (وتوفر واجهة موحدة) لبرمجية Adobe Flash و Gears و Adobe AIR والنموذج الأولي من التخزين المحلي في HTML5 الذي كان مُطبَّقًا في الإصدارات القديمة من Firefox فقط.
</p>

<p>
	عندما تنظر إلى تلك الحلول، فستكتشف أنَّ جميعها كان خاصًا بمتصفح معيّن أو كان يتبع لإضافة خارجية. وعلى الرغم من الجهود البطولية لتوحيد تلك الاختلافات (dojox.storage) إلا أنَّ تلك الحلول تملك واجهات برمجية مختلفة جذريًا عن بعضها، ولكلٍ منها حدود قصوى لمقدار المساحة التخزينية المتوفرة، ولكلٍ منها تجربة مستخدم مختلفة. هذه هي المشكلة التي أتت HTML5 لحلها: توفير واجهة برمجية معيارية، ومطبَّقة في جميع المتصفحات، دون الحاجة إلى استخدام إضافات خارجية.
</p>

<h2>
	مدخل إلى التخزين المحلي في HTML5
</h2>

<p>
	ما أشير إليه على أنَّه "التخزين المحلي في HTML5"‏ (HTML5 Storage) هو مواصفة باسم "<a href="http://dev.w3.org/html5/webstorage/" rel="external nofollow">Web Storage</a>" التي كانت جزءًا من معيار HTML5، لكنها انقسمت وأصبحت معيارًا مستقلًا لأسباب ليست مهمة. بعض الشركات المسؤولة عن المتصفحات تطلِق عليها الاسم "التخزين المحلي" (Local Storage) أو "تخزين DOM" ‏(DOM Storage). ازداد تعقيد موضوع التسميات خصوصًا بعد ظهور عدد من المعايير الجديدة التي سأناقشها في نهاية هذا الدرس.
</p>

<p>
	إذًا، ما هو التخزين المحلي في HTML؟ بشكل مبسّط: هو طريقة تتمكن صفحات الويب من خلالها أن تُخزِّن البيانات على شكل "المفتاح/القيمة" محليًا داخل متصفح الويب في حاسوب العميل. ومثل الكعكات، ستبقى البيانات موجودةً حتى بعد إغلاقك للسان الصفحة في المتصفح، أو إغلاق المتصفح. لكن على عكس الكعكات، لن تُرسَل البيانات تلقائيًا إلى خادوم الويب البعيد؛ وعلى النقيض من كل المحاولات السابقة لتوفير ميزة التخزين المحلي، هذه الميزة موجودة داخليًا في متصفحات الويب، لذلك ستكون متاحة للاستخدام حتى لو لم تتوفر إضافاتٌ خارجيةٌ للمتصفح.
</p>

<p>
	ما هي المتصفحات التي تدعمها؟ حسنًا، التخزين المحلي في HTML5 مدعومٌ من أغلبية المتصفحات، وحتى القديمة منها.
</p>

<center>
	<table border="1"><tbody>
<tr style="padding: 5px 10px; background-color: #ecf0f1;">
<td style="padding: 5px 10px; text-align: center;">
					<strong>IE</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Firefox</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Safari</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Chrome</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Opera</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>iPhone</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Android</strong>
				</td>
			</tr>
<tr style="padding: 5px 10px;">
<td style="padding: 5px 10px; text-align: center;">
					8.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					3.5+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					10.5+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					2.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					2.0+
				</td>
			</tr>
</tbody></table>
</center>

<p>
	تستطيع الوصول إلى التخزين المحلي في HTML5 في شيفرات JavaScript عبر الكائن localStorage الموجود في الكائن العام window؛ لكن قبل أن تستخدمها، عليك أن تكتشف دعم المتصفح لها.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_8">
<span class="kwd">function</span><span class="pln"> supports_html5_storage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
		</span><span class="kwd">return</span><span class="pln"> </span><span class="str">'localStorage'</span><span class="pln"> in window </span><span class="pun">&amp;&amp;</span><span class="pln"> window</span><span class="pun">[</span><span class="str">'localStorage'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">!==</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
	</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
		</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
	</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لكن بدلًا من كتابة الدالة السابقة يدويًا، يمكنك استخدام Modernizr لاكتشاف دعم التخزين المحلي في HTML5.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_11">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Modernizr</span><span class="pun">.</span><span class="pln">localstorage</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	</span><span class="com">// window.localStorage متوفرة!</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	</span><span class="com">// لا يوجد دعم للتخزين المحلي :(</span><span class="pln">
	</span><span class="com">// ربما تجرب dojox.storage أو مكتبة أخرى</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	استخدام التخزين المحلي في HTML5
</h2>

<p>
	يعتمد التخزين المحلي في أساسه على تخزين البيانات على شكل "مفتاح/قيمة". أي أنَّك تُخزِّن البيانات في مفتاح له اسم مُميِّز، ثم تستطيع الحصول على تلك البيانات مرةً أخرى باستخدام نفس المفتاح. ذاك المفتاح هو سلسلة نصية، ويمكن أن تكون البيانات المُخزَّنة من أي نوع تدعمه لغة JavaScript بما في ذلك السلاسل النصية والقيم المنطقية (true و false) أو الأعداد الصحيحة أو الأعداد العشرية؛ لكن في الواقع، ستُخزَّن البيانات كسلسلة نصية، وهذا يعني أنَّه لو لم تكن القيمة المُخزَّنة نصيةً فستحتاج إلى استعمال دوال مثل <span style="font-family:courier new,courier,monospace;">parseInt()‎ </span>أو<span style="font-family:courier new,courier,monospace;"> parseFloat()‎</span> لكي تحوِّل البيانات التي حصلت عليها إلى نوع البيانات الذي تريده.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_13">
<span class="pln">interface </span><span class="typ">Storage</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	getter any getItem</span><span class="pun">(</span><span class="pln">in </span><span class="typ">DOMString</span><span class="pln"> key</span><span class="pun">);</span><span class="pln">
	setter creator </span><span class="kwd">void</span><span class="pln"> setItem</span><span class="pun">(</span><span class="pln">in </span><span class="typ">DOMString</span><span class="pln"> key</span><span class="pun">,</span><span class="pln"> in any data</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	سيؤدي استدعاء الدالة <span style="font-family:courier new,courier,monospace;">setItem()‎ </span>مع تمرير مفتاح موجود مسبقًا إلى إعادة الكتابة فوق القيمة السابقة دون إشعار. وسيؤدي استدعاء الدالة <span style="font-family:courier new,courier,monospace;">getItem()‎</span> مع تمرير مفتاح غير موجود إلى إعادة <span style="font-family:courier new,courier,monospace;">null</span> بدلًا من رمي استثناء (throw an exception).
</p>

<p>
	وكما هو الحال مع بقية الكائنات في JavaScript، يمكنك أن تُعامِل الكائن <span style="font-family:courier new,courier,monospace;">localStorage</span> على أنَّه مصفوفة ترابطية (associative array). فبدلًا من استخدام الدالتين <span style="font-family:courier new,courier,monospace;">getItem()</span>‎ و <span style="font-family:courier new,courier,monospace;">setItem()</span>‎، تستطيع بكل بساطة أن تستعمل الأقواس المربعة (التي تستعملها للوصول إلى عناصر المصفوفات). يمكن على سبيل المثال أن نُعيد كتابة هذه الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_15">
<span class="kwd">var</span><span class="pln"> foo </span><span class="pun">=</span><span class="pln"> localStorage</span><span class="pun">.</span><span class="pln">getItem</span><span class="pun">(</span><span class="str">"bar"</span><span class="pun">);</span><span class="pln">
localStorage</span><span class="pun">.</span><span class="pln">setItem</span><span class="pun">(</span><span class="str">"bar"</span><span class="pun">,</span><span class="pln"> foo</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> foo </span><span class="pun">=</span><span class="pln"> localStorage</span><span class="pun">[</span><span class="str">"bar"</span><span class="pun">];</span><span class="pln">
localStorage</span><span class="pun">[</span><span class="str">"bar"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">;</span></pre>

<p>
	هنالك دوالٌ أخرى لحذف قيمة مرتبطة بمفتاح معيّن، ولحذف كل ما هو مُخزَّنٌ محليًا (وهذا يعني حذف كل المفاتيح والقيم معًا).
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_17">
<span class="pln">interface </span><span class="typ">Storage</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	deleter </span><span class="kwd">void</span><span class="pln"> removeItem</span><span class="pun">(</span><span class="pln">in </span><span class="typ">DOMString</span><span class="pln"> key</span><span class="pun">);</span><span class="pln">
	</span><span class="kwd">void</span><span class="pln"> clear</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لن يؤدي استدعاء الدالة<span style="font-family:courier new,courier,monospace;"> removeItem()‎</span> مع تمرير مفتاح غير موجود إلى فعل أي شيء.
</p>

<p>
	وأخيرًا، هنالك خاصية للحصول على العدد الكلي للقيم المُخزَّنة محليًا، ودالة للحصول على اسم كل مفتاح عبر تمرير فهرسه المكاني*.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_19">
<span class="pln">interface </span><span class="typ">Storage</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	readonly attribute </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> length</span><span class="pun">;</span><span class="pln">
	getter </span><span class="typ">DOMString</span><span class="pln"> key</span><span class="pun">(</span><span class="pln">in </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> index</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لو استدعيتَ الدالة<span style="font-family:courier new,courier,monospace;"> key()‎</span> مع فهرس لا يقع بين 0 - 1 فستُعيد الدالة <span style="font-family:courier new,courier,monospace;">null</span>.
</p>

<h2>
	تتبّع التغييرات في مساحة التخزين المحلي
</h2>

<p>
	إذا أردت أن تتبَّع التغييرات في مساحة التخزين (storage area) برمجيًا، فعليك أن تستعمل الحَدَث <span style="font-family:courier new,courier,monospace;">storage</span>، الذي يُفعَّل (fired) في الكائن العام <span style="font-family:courier new,courier,monospace;">window</span> في كل مرة تُستدعى فيها الدالة <span style="font-family:courier new,courier,monospace;">setItem()</span>‎ أو <span style="font-family:courier new,courier,monospace;">removeItem()‎ </span>أو <span style="font-family:courier new,courier,monospace;">clear()‎</span> وتجري تلك الدالة تغييرًا ما. فعلى سبيل المثال، لو أعدتَ ضبط قيمة موجودة مسبقًا وكانت القيمة الجديدة مساوية للقيمة القديمة، أو استدعيت الدالة <span style="font-family:courier new,courier,monospace;">clear()‎</span>‎ لكن لم تكن هنالك أيّة قيم في مساحة التخزين، فلن يُفعَّل الحدث <span style="font-family:courier new,courier,monospace;">storage</span>، لعدم تغيّر شيء في مساحة التخزين.
</p>

<p>
	الحدث <span style="font-family:courier new,courier,monospace;">storage</span> مدعوم في كل متصفح يدعم الكائن <span style="font-family:courier new,courier,monospace;">localStorage</span>، وهذا يتضمن Internet Explorer 8، لكن IE 8 لا يدعم الدالة المعيارية من W3C لمراقبة الأحداث <span style="font-family:courier new,courier,monospace;">addEventListener</span> (لكنها أُضيفت في نهاية المطاف في IE 9)؛ ولهذا، إذا أردت مراقبة تفعيل الحدث <span style="font-family:courier new,courier,monospace;">storage</span> فعليك أن تكتشف ما هي آلية الأحداث التي يدعمها المتصفح أولًا (إذا فعلتَ هذا من قبل مع الأحداث الأخرى، فيمكنك تخطي هذه الفقرة والانتقال إلى آخر القسم. مراقبة الحدث <span style="font-family:courier new,courier,monospace;">storage</span> مماثلة تمامًا لعملية مراقبة الأحداث الأخرى التي سبقَ وأن راقبتَها؛ وإذا كنتَ تُفضِّل استخدام jQuery أو مكتبة JavaScript أخرى لتسجيل دوال مراقبة الأحداث، فتستطيع فعل ذلك مع الحدث <span style="font-family:courier new,courier,monospace;">storage</span> أيضًا).
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_22">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">window</span><span class="pun">.</span><span class="pln">addEventListener</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	window</span><span class="pun">.</span><span class="pln">addEventListener</span><span class="pun">(</span><span class="str">"storage"</span><span class="pun">,</span><span class="pln"> handle_storage</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	window</span><span class="pun">.</span><span class="pln">attachEvent</span><span class="pun">(</span><span class="str">"onstorage"</span><span class="pun">,</span><span class="pln"> handle_storage</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	ستُستدعى الدالة <span style="font-family:courier new,courier,monospace;">handle_storage</span> مع تمرير كائن من نوع <span style="font-family:courier new,courier,monospace;">StorageEvent</span>، عدا في متصفح Internet Explorer حيث يُخزَّن الكائن في <span style="font-family:courier new,courier,monospace;">window.event</span>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_24">
<span class="kwd">function</span><span class="pln"> handle_storage</span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> e </span><span class="pun">=</span><span class="pln"> window</span><span class="pun">.</span><span class="pln">event</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيكون المتغير <span style="font-family:courier new,courier,monospace;">e</span> -عند هذه النقطة- كائنًا من نوع <span style="font-family:courier new,courier,monospace;">StorageEvent</span>، الذي لديه الخاصيات المبيّنة في الجدول الآتي:
</p>

<center>
	<table border="1"><tbody>
<tr style="padding: 5px 10px; background-color: #ecf0f1;">
<td style="padding: 5px 10px; text-align: center;">
					<strong>الخاصية</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>النوع</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>الشرح</strong>
				</td>
			</tr>
<tr style="padding: 5px 10px;">
<td style="padding: 5px 10px;">
					key
				</td>
				<td style="padding: 5px 10px;">
					سلسلة نصية
				</td>
				<td style="padding: 5px 10px;">
					مفتاح القيمة التي أُضيفَت أو حُذِفَت أو عدِّلَت
				</td>
			</tr>
<tr style="padding: 5px 10px;">
<td style="padding: 5px 10px;">
					oldValue
				</td>
				<td style="padding: 5px 10px;">
					أي نوع
				</td>
				<td style="padding: 5px 10px;">
					القيمة (التي كُتِبَ فوقها)، أو null إذا أُضيف عنصرٌ جديد
				</td>
			</tr>
<tr style="padding: 5px 10px;">
<td style="padding: 5px 10px;">
					newValue
				</td>
				<td style="padding: 5px 10px;">
					أي نوع
				</td>
				<td style="padding: 5px 10px;">
					القيمة الجديدة، أو null إن حُذِفَ عنصرٌ ما
				</td>
			</tr>
<tr style="padding: 5px 10px;">
<td style="padding: 5px 10px;">
					url*
				</td>
				<td style="padding: 5px 10px;">
					سلسلة نصية
				</td>
				<td style="padding: 5px 10px;">
					الصفحة التي تحتوي على الدالة التي أجرت هذا التغيير
				</td>
			</tr>
</tbody></table>
</center>

<p>
	<strong>ملاحظة</strong>: كان اسم الخاصية <span style="font-family:courier new,courier,monospace;">url</span> الأصلي هو <span style="font-family:courier new,courier,monospace;">uri</span>، وذلك لأنَّ بعض المتصفحات امتلكت هذه الخاصية قبل تغيير مواصفة التخزين المحلي. لأكبر قدر من التوافقية، عليك أن تتحقق من وجود الخاصية <span style="font-family:courier new,courier,monospace;">url</span>، فإن لم تكن موجودًا فتحقق من قيمة الخاصية <span style="font-family:courier new,courier,monospace;">uri</span>.
</p>

<p>
	لا يمكن إلغاء الأحداث في الحدث <span style="font-family:courier new,courier,monospace;">storage</span>. فلا توجد طريقة من داخل الدالة <span style="font-family:courier new,courier,monospace;">handle_storage</span> تستطيع إيقاف تغيير ما من الحدوث. بكل بساطة، هذه طريقة لكي يخبرك المتصفح: "هذا ما حصل لتوِّه، لا يمكنك فعل أي شيء تجاهه؛ كل ما أستطيع فعله هو إخبارك ما الذي حدث".
</p>

<h2>
	المحدوديات في المتصفحات الحالية
</h2>

<p>
	في حديثي عن اللمحة التاريخية عن محاولات تخزين البيانات محليًا باستخدام إضافات خارجية، حرصتُ على ذكر محدوديات كل تقنية من تلك التقنيات، مثل محدودية المساحة التخزينية. لكنني لم أذكر شيئًا عن محدوديات التخزين المحلي في HTML5 المعياري. سأعطيك الأجوبة أولًا ثم سأشرحها. الأجوبة هي -بترتيبها حسب الأهمية-: "5 ميغابايت"، و"QUOTA_EXCEEDED_ERR" و "لا".
</p>

<ul>
<li>
		"5 ميغابايت" هي المساحة التي يُسمَح لكل موقع بالحصول عليها افتراضيًا، وهذه القيمة متساوية -على غير العادة- بين المتصفحات، على الرغم من أنَّها مذكورة في مواصفة التخزين المحلي في HTML5 على أنَّها "اقتراح". ابقِ في ذهنك أنَّك تُخزِّن سلاسل نصية، ولا تخزِّن البيانات بصيغتها الأصلية، فلو كنت تُخزِّن الكثير من الأعداد الصحيحة (integers) أو العشرية (floats)، فسيكون الفرق في طريقة تمثيل البيانات مؤثرًا، إذ يُخزَّن كل رقم من عدد عشري كمحرف (character)، وليس بالتمثيل التقليدي لعدد عشري.
	</li>
	<li>
		"QUOTA_EXCEEDED_ERR" هو الاستثناء (exception) الذي سيُرمى (thrown) عندما تتجاوز حد 5 ميغابايت. أما "لا" فهو الجواب على السؤال البدهي الذي سيخطر ببالك: "هل يمكنني طلب المزيد من المساحة التخزينية من المستخدم؟" إلى حد الساعة، لا تدعم أيّة متصفحات أي آلية يتمكن خلالها مطورو الويب من طلب المزيد من المساحة التخزينية. لكن بعض المتصفحات (مثل Opera أو Firefox) تسمح للمستخدم أن يتحكم بالحدّ الأقصى للتخزين المحلي، لكن هذا منوطٌ بالمستخدم تمامًا، ولا يمكنك -كمطوِّر ويب- الاعتماد على ذلك لبناء تطبيقك.
	</li>
</ul>
<h2>
	مثال عملي عن استخدام التخزين المحلي
</h2>

<p>
	لنأخذ مثالًا عمليًا عن التخزين المحلي في HTML. هل تتذكر <a href="https://academy.hsoub.com/programming/html5/%D8%A7%D9%84%D8%B1%D8%B3%D9%85-%D8%B9%D8%A8%D8%B1-%D8%B9%D9%86%D8%B5%D8%B1-canvas-%D9%81%D9%8A-html5-r345/" rel="">لعبة الضامة التي بنيناها في الدرس الذي يتحدث عن canvas</a>؟ هنالك مشكلة صغيرة مع هذه اللعبة: ستخسر تقدّمك في اللعبة عندما تُغلِق نافذة المتصفح. لكن باستخدام التخزين في HTML5، سنستطيع حفظ التقدّم محليًا داخل المتصفح. هذا <a href="http://diveinto.html5doctor.com/examples/localstorage-halma.html" rel="external nofollow">مثالٌ حيّ للعبة بعد التعديل</a>. حرِّك بعض القطع، ثم أغلق لسان الصفحة (أو المتصفح)، ثم أعد فتح الصفحة. فإذا كان يدعم متصفحك التخزين المحلي، فيجب أن تتذكر الصفحة السابقة خطواتك التي أجريتها في اللعبة، بما في ذلك عدد الخطوات التي تحركت بها، ومكان كل قطعة على رقعة اللعب، وحتى آخر قطعة قمتَ بتحديدها.
</p>

<p>
	ما هي الآلية التي اتبعناها لفعل ذلك؟ سنستدعي الدالة الآتية في كل مرّة يطرأ فيها تغيير داخل اللعبة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_26">
<span class="kwd">function</span><span class="pln"> saveGameState</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">supportsLocalStorage</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

	localStorage</span><span class="pun">[</span><span class="str">"halma.game.in.progress"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> gGameInProgress</span><span class="pun">;</span><span class="pln">

	</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">var</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> kNumPieces</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
		localStorage</span><span class="pun">[</span><span class="str">"halma.piece."</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="str">".row"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> gPieces</span><span class="pun">[</span><span class="pln">i</span><span class="pun">].</span><span class="pln">row</span><span class="pun">;</span><span class="pln">
		localStorage</span><span class="pun">[</span><span class="str">"halma.piece."</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="str">".column"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> gPieces</span><span class="pun">[</span><span class="pln">i</span><span class="pun">].</span><span class="pln">column</span><span class="pun">;</span><span class="pln">
	</span><span class="pun">}</span><span class="pln">

	localStorage</span><span class="pun">[</span><span class="str">"halma.selectedpiece"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> gSelectedPieceIndex</span><span class="pun">;</span><span class="pln">
	localStorage</span><span class="pun">[</span><span class="str">"halma.selectedpiecehasmoved"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> gSelectedPieceHasMoved</span><span class="pun">;</span><span class="pln">
	localStorage</span><span class="pun">[</span><span class="str">"halma.movecount"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> gMoveCount</span><span class="pun">;</span><span class="pln">

	</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كما لاحظت، تستعمل الدالة السابقة الكائن <span style="font-family:courier new,courier,monospace;">localStorage</span> لتخزين أنَّ المستخدم قد بدأ اللعب (المفتاح <span style="font-family:courier new,courier,monospace;">gGameInProgress</span>، الذي هو قيمة منطقية [Boolean]). ثم ستدور حلقة for على جميع القطع (المتغير <span style="font-family:courier new,courier,monospace;">gPieces</span>، الذي هو مصفوفة في لغة JavaScript) ثم يحفظ رقم السطر والعمود لكل قطعة؛ ثم تحفظ الدالة بعض المعلومات الإضافية عن اللعبة، بما في ذلك القطعة التي تم تحديدها (القيمة <span style="font-family:courier new,courier,monospace;">gSelectedPieceIndex</span>، التي هي رقمٌ صحيح [integer])، وفيما إذا كانت القطعة في منتصف سلسلة من القفزات (القيمة <span style="font-family:courier new,courier,monospace;">gSelectedPieceHasMoved</span>، التي هي قيمة منطقية)، والعدد الكلي للحركات التي قام بها اللاعب (القيمة <span style="font-family:courier new,courier,monospace;">gMoveCount</span>، التي هي عدد صحيح).
</p>

<p>
	وعند تحميل الصفحة، وبدلًا من الاستدعاء التلقائي للدالة <span style="font-family:courier new,courier,monospace;">newGame()‎</span> التي ستُعيد ضبط جميع المتغيرات إلى قيم مُحدَّدة مسبقًا، فسنستدعي الدالة <span style="font-family:courier new,courier,monospace;">resumeGame()‎</span>. التي تتحقق -باستخدام التخزين المحلي في HTML5- فيما إذا كانت هنالك نسخة محفوظة من اللعبة مُخزَّنةٌ محليًا؛ فإن وُجِدَت، فستُستعاد تلك القيم باستخدام الكائن <span style="font-family:courier new,courier,monospace;">localStorage</span>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_28">
<span class="kwd">function</span><span class="pln"> resumeGame</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

	</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">supportsLocalStorage</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

	gGameInProgress </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">localStorage</span><span class="pun">[</span><span class="str">"halma.game.in.progress"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">"true"</span><span class="pun">);</span><span class="pln">

	</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">gGameInProgress</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
		gPieces </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Array</span><span class="pun">(</span><span class="pln">kNumPieces</span><span class="pun">);</span><span class="pln">
		</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">var</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> kNumPieces</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
			</span><span class="kwd">var</span><span class="pln"> row </span><span class="pun">=</span><span class="pln"> parseInt</span><span class="pun">(</span><span class="pln">localStorage</span><span class="pun">[</span><span class="str">"halma.piece."</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="str">".row"</span><span class="pun">]);</span><span class="pln">
			</span><span class="kwd">var</span><span class="pln"> column </span><span class="pun">=</span><span class="pln"> parseInt</span><span class="pun">(</span><span class="pln">localStorage</span><span class="pun">[</span><span class="str">"halma.piece."</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="str">".column"</span><span class="pun">]);</span><span class="pln">
			gPieces</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Cell</span><span class="pun">(</span><span class="pln">row</span><span class="pun">,</span><span class="pln"> column</span><span class="pun">);</span><span class="pln">
		</span><span class="pun">}</span><span class="pln">

	gNumPieces </span><span class="pun">=</span><span class="pln"> kNumPieces</span><span class="pun">;</span><span class="pln">
	gSelectedPieceIndex </span><span class="pun">=</span><span class="pln"> parseInt</span><span class="pun">(</span><span class="pln">localStorage</span><span class="pun">[</span><span class="str">"halma.selectedpiece"</span><span class="pun">]);</span><span class="pln">
	gSelectedPieceHasMoved </span><span class="pun">=</span><span class="pln"> localStorage</span><span class="pun">[</span><span class="str">"halma.selectedpiecehasmoved"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">"true"</span><span class="pun">;</span><span class="pln">
	gMoveCount </span><span class="pun">=</span><span class="pln"> parseInt</span><span class="pun">(</span><span class="pln">localStorage</span><span class="pun">[</span><span class="str">"halma.movecount"</span><span class="pun">]);</span><span class="pln">
	drawBoard</span><span class="pun">();</span><span class="pln">
	</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أهم فكرة في هذه الدالة هي تطبيق التحذير الذي ذكرته لك سابقًا في هذا الدرس، وسأكرره هنا: "ستُخزَّن البيانات كسلسلة نصية، وهذا يعني أنَّه لو لم تكن القيمة المُخزَّنة نصيةً فستحتاج إلى تحويل البيانات التي حصلت عليها إلى نوع البيانات الذي تريده". فعلى سبيل المثال، القيمة التي تُحدِّد فيما إذا كانت هنالك لعبة قيد اللعب (<span style="font-family:courier new,courier,monospace;">gGameInProgress</span>) هي قيمة منطقية، وفي الدالة <span style="font-family:courier new,courier,monospace;">saveGameState()‎</span> خزَّنا القيمة دون أن نلقي بالًا لنوعها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_30">
<span class="pln">localStorage</span><span class="pun">[</span><span class="str">"halma.game.in.progress"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> gGameInProgress</span><span class="pun">;</span></pre>

<p>
	لكن في دالة<span style="font-family:courier new,courier,monospace;"> resumeGame()‎ </span>علينا أن نُعامِل القيمة التي أخذناها من التخزين المحلي كسلسلةٍ نصيةٍ كالآتي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_32">
<span class="pln">gGameInProgress </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">localStorage</span><span class="pun">[</span><span class="str">"halma.game.in.progress"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">"true"</span><span class="pun">);</span></pre>

<p>
	وبشكلٍ مشابه، يُخزَّن عدد الخطوات في <span style="font-family:courier new,courier,monospace;">gMoveCount</span> كعددٍ صحيحٍ؛ فلقد خزَّناها ببساطة في الدالة <span style="font-family:courier new,courier,monospace;">saveGameState()‎</span>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_34">
<span class="pln">localStorage</span><span class="pun">[</span><span class="str">"halma.movecount"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> gMoveCount</span><span class="pun">;</span></pre>

<p>
	لكن في دالة <span style="font-family:courier new,courier,monospace;">resumeGame()</span>‎ علينا أن نحوِّل القيمة إلى عدد صحيح باستخدام الدالة <span style="font-family:courier new,courier,monospace;">parseInt()‎</span> الموجودة في JavaScript:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_36">
<span class="pln">gMoveCount </span><span class="pun">=</span><span class="pln"> parseInt</span><span class="pun">(</span><span class="pln">localStorage</span><span class="pun">[</span><span class="str">"halma.movecount"</span><span class="pun">]);</span></pre>

<h2>
	مستقبل التخزين المحلي في تطبيقات الويب
</h2>

<p>
	على الرغم من أنَّ الماضي كان مليئًا بالطرق الالتفافية، لكن الوضع الراهن للتخزين المحلي في HTML5 مشرقٌ، فهنالك واجهة برمجية (<abbr title="Application Programming Interface | واجهة برمجية">API</abbr>) جديدة قد وُضِعَ لها معيارٌ وطبِّق هذا المعيار في جميع المتصفحات الرئيسية على مختلف المنصات والأجهزة. فهذا أمرٌ لا تراه كل يوم كمطوِّر ويب، أليس كذلك؟ لكن ألا تتطلع إلى أكثر من "5 ميغابايت من الثنائيات على شكل "مفتاح/قيمة"؟ حسنًا، هنالك عدد من الرؤى التنافسية لمستقبل التخزين المحلي.
</p>

<p>
	إحدى تلك الرؤى هي اختصارٌ تعرفه بالتأكيد: SQL. أطلقَت Google في عام 2007 إضافة Gears المفتوحة المصدر التي تعمل على مختلف المتصفحات والتي احتوت على قاعدة بيانات مُضمَّنة فيها مبنية على <a href="http://www.sqlite.org/" rel="external nofollow">SQLite</a>. أثَّر هذا النموذج الأولي لاحقًا على إنشاء مواصفة Web SQL Database، والتي كانت تعرف رسميًا باسم "WebDB" التي توفر طبقةً للوصول إلى قاعدة بيانات SQL، سامحةً لك بالقيام بأشياء شبيهة بما يلي عبر JavaScript (لاحظ أنَّ الشيفرة الآتية حقيقية وتعمل على أربعة متصفحات):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2867_38">
<span class="pln">openDatabase</span><span class="pun">(</span><span class="str">'documents'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'1.0'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Local document storage'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">*</span><span class="lit">1024</span><span class="pun">*</span><span class="lit">1024</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">db</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	db</span><span class="pun">.</span><span class="pln">changeVersion</span><span class="pun">(</span><span class="str">''</span><span class="pun">,</span><span class="pln"> </span><span class="str">'1.0'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">t</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
		t</span><span class="pun">.</span><span class="pln">executeSql</span><span class="pun">(</span><span class="str">'CREATE TABLE docids (id, name)'</span><span class="pun">);</span><span class="pln">
	</span><span class="pun">},</span><span class="pln"> error</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	كما لاحظت، ما يهم في الشيفرة السابقة هو السلسلة النصية التي مررتها إلى الدالة <span style="font-family:courier new,courier,monospace;">executeSql</span>، ويمكن أن تحتوي تلك السلسلة النصية على أيّة تعليمات SQL مدعومة، بما في ذلك <span style="font-family:courier new,courier,monospace;">SELECT</span> و <span style="font-family:courier new,courier,monospace;">UPDATE</span> و <span style="font-family:courier new,courier,monospace;">INSERT</span> و <span style="font-family:courier new,courier,monospace;">DELETE</span>. الأمر هنا شبيهٌ ببرمجة قواعد البيانات بلغةٍ مثل PHP، إلا أنَّك تقوم بذلك عبر JavaScript!
</p>

<p>
	طُبِّقت مواصفات Web SQL Database من أربعة متصفحات ومنصات.
</p>

<center>
	<table border="1"><tbody>
<tr style="padding: 5px 10px; background-color: #ecf0f1;">
<td style="padding: 5px 10px; text-align: center;">
					<strong>IE</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Firefox</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Safari</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Chrome</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Opera</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>iPhone</strong>
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					<strong>Android</strong>
				</td>
			</tr>
<tr style="padding: 5px 10px;">
<td style="padding: 5px 10px; text-align: center;">
					.
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					.
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					4.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					10.5+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					3.0+
				</td>
				<td style="padding: 5px 10px; text-align: center;">
					2.0+
				</td>
			</tr>
</tbody></table>
</center>

<p>
	وبكل تأكيد، لو سبق وأن استخدمت أكثر من مُحرِّك لقواعد البيانات في حياتك، فأنت تعلم أنَّ "SQL" هي مصطلح تسويقي أكثر من كونها معيارًا متكاملًا (قد يقول البعض أنَّ HTML5 كذلك، لكن لا تأبه بقولهم). حسنًا، هنالك معيار للغة SQL (يسمى SQL-92) لكن لا يوجد خادوم قواعد بيانات في العالم يتوافق تمامًا مع ذاك المعيار. فهنالك نسخة SQL لقواعد بيانات Oracle، ونسخة أخرى لقواعد MSSQL، ونسخة أخرى لقواعد بيانات MySQL، وأخرى لقواعد بيانات PostgreSQL، ولا ننسَ نسخة SQL لقواعد بيانات SQLite. وحتى كل منتج من تلك المنتجات يُضيف ميزات SQL جديدة على مرّ الزمن، وبهذا يكون قولنا "نسخة SQL لقواعد بيانات SQLite" ليس كافيًا لتحديد ما نتحدث عنه بدقّة. فعليك أن تقول "نسخة SQL التي تأتي مع قواعد بيانات SQLite ذات الإصدار X.Y.Z".
</p>

<p>
	كل ما سبق أدى إلى الإعلان الآتي، التي يقبع الآن في أعلى صفحة مواصفة Web SQL Database:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix">
		<p>
			"واجهت هذه المواصفة طريقًا مسدودًا: جميع المتصفحات التي طبَّقت هذه المواصفة استخدمت نفس السند الخلفي (backend) لقواعد البيانات (الذي هو SQLite)، لكننا نحتاج إلى عدِّة تطبيقات مختلفة إضافية للإكمال في مسار تحويلها إلى معيار. وريثما يحين ذاك الوقت، فستشير "نسخة" (dialect) SQL المستخدمة في هذا المعيار إلى SQLite، لكن هذا ليس مقبولًا بالنسبة لمعيار قياسي."
		</p>
	</div>
</blockquote>

<p>
	وعلى ضوء هذا، سأعرِّفك على رؤية تنافسية أخرى لتخزينٍ محليٍ متقدم وثابت لتطبيقات الويب: Indexed Database <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> المعروفة رسميًا باسم "WebSimpleDB" التي اشتهرت باسم "IndexedDB".
</p>

<p>
	تحتوي IndexedDB على ما يُسمى "مخزن الكائنات" (object store)، الذي يتشارك مع قاعدة بيانات SQL في الكثير من المفاهيم؛ فهنالك "قواعد بيانات" (databases) فيها "سجلات" (records)، ويملك كل سجل عددًا من "الحقول" (fields)، وكل حقل له نوع بيانات معيّن، الذي يُعرَّف عند إنشاء قاعدة البيانات. تستطيع أيضًا تحديد مجموعة فرعية من السجلات، ثم تعرضها عبر "مؤشر" (cursor)، ويتم التعامل مع التغييرات على مخزن الكائنات عبر "التحويلات" (transactions).
</p>

<p>
	إذا سبق وأن برمجتَ قليلًا بأي نوع من أنواع قواعد بيانات SQL ، فمن المرجح أن تبدو المصطلحات السابقة مألوفةً لديك. الفرق الرئيسي هو أنَّ "مخزن الكائنات" ليس لديه "لغة استعلام بنيوية"، لا تستطيع كتابة عبارات مثل <span style="font-family:courier new,courier,monospace;">"SELECT * from USERS where ACTIVE = 'Y'‎" </span>لكنك تستطيع استخدام الدوال التي يوفرها مخزن الكائنات لفتح "مؤشر" (cursor) في قاعدة البيانات "USERS"، ثم تمر عبر السجلات، وتستبعد سجلات المستخدمين غير النشيطين، ثم تستخدم دوالًا للوصول إلى قيم كل حقل في السجلات المتبقية. 
</p>

<p>
	دعم IndexedDB موجودٌ في Firefox منذ الإصدار 4.0 (صرَّحَت Mozilla أنَّها لن تدعم Web SQL Database في متصفحها)، وChrome منذ الإصدار 11، وحتى Internet Explorer أصبح يدعم IndexedDB منذ الإصدار 10.
</p>

<p>
	ترجمة -وبتصرّف- لفصل "<a href="http://diveinto.html5doctor.com/storage.html" rel="external nofollow">Local Storage</a>" من كتاب <a href="http://diveinto.html5doctor.com/index.html" rel="external nofollow">Dive Into HTML5</a> لمؤلفه Mark Pilgrim.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/html/html5/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%8A-%D8%AA%D8%B9%D9%85%D9%84-%D8%AF%D9%88%D9%86-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%E2%80%93-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r441/" rel="">تطبيقات الويب التي تعمل دون اتصال – الجزء الأول</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/html/html5/%D8%AA%D8%AD%D8%AF%D9%8A%D8%AF-%D8%A7%D9%84%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D8%AC%D8%BA%D8%B1%D8%A7%D9%81%D9%8A-geolocation-%D9%81%D9%8A-html5-r359/" rel="">تحديد الموقع الجغرافي (GeoLocation) في HTML5</a>
	</li>
	<li>
		النسخة العربية الكاملة من كتاب <a href="https://academy.hsoub.com/files/13-%D9%86%D8%AD%D9%88-%D9%81%D9%87%D9%85-%D8%A7%D9%94%D8%B9%D9%85%D9%82-%D9%84%D8%AA%D9%82%D9%86%D9%8A%D8%A7%D8%AA-html5/" rel="">نحو فهم أعمق لتقنيات HTML5 </a>
	</li>
</ul>
]]></description><guid isPermaLink="false">362</guid><pubDate>Sun, 10 Jul 2016 13:57:00 +0000</pubDate></item></channel></rss>
