> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aftersell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# السكربتات المخصصة

> شغّل JavaScript مخصصًا في Aftersell Cart عبر خانتي السكربت Initialization وOn cart update.

تتيح لك السكربتات المخصصة تشغيل JavaScript الخاص بك على السلة باستخدام [Cart SDK](/ar/aftersell/cart/sdk-overview). أضفها في محرر السلة تحت **Cart settings → Custom script**، حيث تبدّل قائمة منسدلة بين خانتين: **Initialization** و**On cart update**.

اكتب JavaScript عاديًا في هذين المحررين، دون وسوم `<script>`. لخانة **On cart update** إجراء **Reset to default** يعيد قالبها الأولي؛ أما **Initialization** فلا، لذا احتفظ بنسختك الخاصة قبل مسحها.

<Note>
  كثير مما اعتاد التجار كتابته كسكربتات أصبح الآن إعدادًا مدمجًا. راجع [قبل أن تكتب سكربتًا](/ar/aftersell/cart/sdk-use-cases#before-you-write-a-script) أولًا: الإعداد يستمر في العمل عبر عمليات إعادة تصميم السلة، أما سكربتك فقد لا يستمر.
</Note>

<div id="which-slot-to-use">
  ## أي خانة تستخدم
</div>

|                  | Initialization                                                                                                                                                            | On cart update                                              |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| **يعمل**         | مرة واحدة، عند تحميل السلة.                                                                                                                                               | عند كل تغيير في السلة بعد التحميل الأول.                    |
| **ما تكتبه**     | السكربت بأكمله.                                                                                                                                                           | جسم المعالج فقط. غلاف `cart_updated` مقفل.                  |
| **استخدمه لأجل** | تسجيل السلوك مرة واحدة: [`configure`](/ar/aftersell/cart/sdk-configure) و[`events.on`](/ar/aftersell/cart/sdk-events) و[`hooks.register*`](/ar/aftersell/cart/sdk-hooks). | القواعد التي يجب إعادة تقييمها مقابل محتويات السلة الحالية. |
| **مثال**         | إخفاء أسطر الهدايا المجانية عبر تحويل أسطر.                                                                                                                               | إبقاء هدية مجانية متزامنة مع عتبة إنفاق.                    |

<div id="initialization">
  ## Initialization
</div>

يعمل سكربت **Initialization** **مرة واحدة عند تحميل السلة**. وهو نقطة دخولك لإعداد الأمور: تكوين سلوك السلة والاشتراك في الأحداث وتسجيل الخطافات (hooks). يتوفر [SDK](/ar/aftersell/cart/sdk-overview) عبر `window.aftersell.cart`.

استدعاءات الإعداد التي تجريها هنا ([`configure(...)`](/ar/aftersell/cart/sdk-configure) و[`events.on(...)`](/ar/aftersell/cart/sdk-events) و[`hooks.*`](/ar/aftersell/cart/sdk-hooks)) آمنة الاستدعاء في أعلى السكربت حتى قبل اكتمال إقلاع السلة؛ فهي تُخزَّن مؤقتًا وتُطبَّق بمجرد اكتماله. أما الإجراءات التي تقرأ السلة أو تغيّرها (مثل [`addItem`](/ar/aftersell/cart/sdk-actions#additemvariantid-quantity) أو [`getCart`](/ar/aftersell/cart/sdk-actions#getcart)) فينبغي تشغيلها داخل [`ready()`](/ar/aftersell/cart/sdk-overview#ready) أو داخل معالج حدث.

تبدأ الخانة بثلاثة أمثلة **معلّقة (commented-out)** — فتح الدرج عند كل إضافة، والتفاعل مع `cart_loaded`، وإخفاء أسطر الهدايا المجانية — لذا فإن سكربت Initialization غير المعدَّل لا يفعل شيئًا. أزل التعليق عن أحدها لتجربته، أو استبدلها.

الشكل الطبيعي لهذه الخانة هو **تسجيل لمرة واحدة دون أحداث**: سجّل السلوك مرة واحدة ودع السلة تطبّقه من ذلك الحين. إخفاء أسطر الهدايا المجانية من الدرج، دون تغيير الإجمالي، هو المثال المشحون لذلك:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerLineTransform((line) => {
  if (line.finalLinePrice === 0) line.setHidden(true);
});
```

يعمل [`registerLineTransform`](/ar/aftersell/cart/sdk-hooks#registerlinetransform) لكل سطر أثناء عرضه، و`setHidden` مخصص للعرض فقط، لذا يبقى السطر في السلة ويظل محتسبًا في الإجمالي، لكنه لا يظهر في الدرج فحسب. راجع [إخفاء أسطر السلة وإعادة تسميتها](/ar/aftersell/cart/sdk-use-case-hide-lines) لمزيد مما يمكن للتحويل فعله.

الإجراءات التي تقرأ السلة توضع داخل `ready()`:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.ready().then(() => {
  const state = window.aftersell.cart.actions.getCart();
  console.log('Cart loaded with', state.itemCount, 'items');
});
```

الوصول إلى DOM السلة يحتاج الانتظار نفسه، ويحتاج [`shadowRoot`](/ar/aftersell/cart/sdk-overview#shadowroot): تُعرض السلة داخل shadow root، لذا لا يمكن لـ `document.querySelector` رؤية أي شيء في الدرج.

<Tip>
  هل تتفرع حسب السوق أو البلد أو العملة **قبل** تحميل السلة؟ اقرأ [`context`](/ar/aftersell/cart/sdk-overview#context) بدلًا من ذلك. فهو متاح بشكل متزامن، دون الحاجة إلى `ready()`، لتتمكن من تخطي تسجيل المعالجات كليًا للمتسوقين الذين لا تنطبق عليهم القاعدة.
</Tip>

<div id="on-cart-update">
  ## On cart update
</div>

يعمل سكربت **On cart update** في كل مرة تتغير فيها السلة. وهو غلاف مقفل حول اشتراك `cart_updated`، فلا تحرر إلا الجسم، ويستقبل كودك كائن `cart` المحدّث.

هذه الخانة للقواعد التي يجب **إعادة تقييمها عند كل تغيير في السلة**. عتبة الهدية المجانية هي الحالة الكلاسيكية (أنفق 75\$ واحصل على حقيبة مجانية) لأن الإجابة تعتمد على المحتويات الحالية ولا شيء آخر يمكنه إخبارك بموعد تغيرها:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.events.on('cart_updated', (cart) => {
  const GIFT_VARIANT_ID = 1234567890;
  const THRESHOLD = 7500;   // $75.00, in cents

  let giftLine = null;
  let subtotal = 0;
  (cart.items ?? []).forEach((line) => {
    if (line.variantId === GIFT_VARIANT_ID) giftLine = line;
    else subtotal += line.finalLinePrice;   // the gift itself never counts toward the threshold
  });

  const shouldHaveGift = subtotal >= THRESHOLD;
  const hasGift = Boolean(giftLine);

  // Bail when the cart already matches. This is the part that matters: adding or
  // removing an item fires cart_updated again, so without this check the handler
  // re-enters itself forever.
  if (shouldHaveGift === hasGift) return;

  if (shouldHaveGift) window.aftersell.cart.actions.addItem(GIFT_VARIANT_ID, 1);
  else window.aftersell.cart.actions.removeItem(giftLine.key);
});
```

<div id="keeping-the-cart-in-a-desired-state">
  ### إبقاء السلة في الحالة المرغوبة
</div>

السطر `if (shouldHaveGift === hasGift) return;` هو ما يجعل هذا آمنًا، وهو يعمّم على كل سكربت يُبقي السلة في حالة مرغوبة. هذه الخانة تتفاعل مع تغييرات السلة وتسبّبها معًا، لذا فإن كل `addItem` أو `removeItem` يعيد الدخول إليها. صِف الحالة التي تريدها، وقارنها بالحالة الموجودة، وعُد مبكرًا عندما تتفقان بالفعل، ليصل المعالج إلى الاستقرار بعد مرور واحد بدلًا من الدوران في حلقة. راجع [القاعدتين](/ar/aftersell/cart/sdk-events#the-two-rules) للنسخة غير المحمية الواجب تجنبها ولماذا الحمولة للقراءة فقط.

في متجر أبطأ يُستحسن أيضًا الاحتفاظ براية "قيد التنفيذ" على مستوى الوحدة، حتى لا يبدأ تغييران متسارعان عملية إضافة قبل هبوط الأولى.

<Note>
  لا يُطلق `cart_updated` إلا عند التغييرات **بعد** التحميل الأول ([توقيت الأحداث](/ar/aftersell/cart/sdk-events#cart_updated))، لذا لن يصحح سكربت في هذه الخانة سلة مؤهلة أصلًا عند تحميل الصفحة. لنسخة تعالج الحالتين، اشترك في `cart_loaded` و`cart_updated` بالدالة نفسها من خانة **Initialization**. راجع [إضافة هدية مجانية تلقائيًا عند عتبة](/ar/aftersell/cart/sdk-use-case-free-gift).
</Note>

<div id="when-a-script-breaks">
  ## عندما يتعطل سكربت
</div>

تعمل كل خانة في بيئة معزولة خاصة بها، لذا لا يمكن لسكربت **Initialization** معطوب أن يوقف تشغيل **On cart update**، ولا يمكن لأي منهما تعطيل السلة نفسها.

لكن داخل الخانة الواحدة، **يتوقف التنفيذ عند أول خطأ**. كل ما تحت ذلك السطر يُتخطى، ما يعني أن أي `configure` أو `events.on` أو `hooks.register*` أدناه لا يُسجَّل أبدًا. هذا هو التفسير المعتاد لـ"معالجي لا يعمل أبدًا" عندما يبدو الكود صحيحًا.

تذكر السلة السطر المتعطل في وحدة تحكم المتصفح، وتعمل كل خانة باسم ملف خاص بها (`aftersell-cart-init.js` و`aftersell-cart-cart-update.js`)، لذا يمكنك فتح أيهما من لوحة Sources في DevTools ووضع نقاط توقف. راجع [تصحيح الأخطاء](/ar/aftersell/cart/sdk-overview#debugging) للرسائل الدقيقة، ولقناة التصحيح التي تلتقط أخطاء الخطافات المحجوبة عن وحدة التحكم.

ولأن `cart_loaded` [يُعاد بثه للمشتركين المتأخرين](/ar/aftersell/cart/sdk-events#cart_loaded)، لا يهم ترتيب التسجيل أبدًا. أسلم بنية هي تسجيل كل شيء أولًا وتنفيذ العمل الخطر داخل المعالجات، حيث يُعزل أي خطأ يُرمى في ذلك المعالج وحده.

<div id="where-to-go-next">
  ## إلى أين تتجه بعد ذلك
</div>

* **[Cart SDK](/ar/aftersell/cart/sdk-overview)**: السكربتات المخصصة هي وسيلتك لتشغيل كود SDK. راجع مراجع [configure](/ar/aftersell/cart/sdk-configure) و[events](/ar/aftersell/cart/sdk-events) و[actions](/ar/aftersell/cart/sdk-actions) و[hooks](/ar/aftersell/cart/sdk-hooks) للسطح الكامل، و[كائن السلة](/ar/aftersell/cart/sdk-cart-object) لبنية ما تستقبله المعالجات، و[حالات الاستخدام](/ar/aftersell/cart/sdk-use-cases) لمقتطفات جاهزة.
* **[بلوكات الكود المخصص](/ar/aftersell/cart/custom-code-blocks)**: لإضافة ترميز إلى السلة. لاحظ أن وضع HTML في بلوك الكود المخصص **لا** يشغّل JavaScript؛ استخدم السكربتات المخصصة (أو وضع React في البلوك) للمنطق.
