# كيفية إطلاق النار على كل تحميل تذييل (أو تحميل صفحة؟)

**URL:** https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404
**Category:** Development
**Created:** [29 يونيو 2021، 7:39م UTC](https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404 "2021-06-29T19:39:33Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [29 يونيو 2021، 7:39م UTC](https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404/1 "2021-06-29T19:39:33Z")

</div>

أحاول تحميل نموذج JavaScript في التذييل.

لدي هذا في الرأس:

```xml
<script type="text/discourse-plugin" version="0.8">
  let loadScript = require("discourse/lib/load-script").default;

  api.onPageChange(() => {
    loadScript("//js.hsforms.net/forms/current.js").then(() => {
      console.log("doing the thing");
      hbspt.forms.create({
        portalId: "229276",
        formId: "a86ca9cc",
        submitButtonClass: "button orange-button hubspot-button",
        target: ".subscription-form"
      });
    });
  });
</script>

```

وهذا في التذييل:

```xml
<div class="subscription-form clearfix">
  <h5>اشترك في مدونتنا</h5>
</div>

```

في المرة الأولى التي يتم فيها تحميل الصفحة، يعمل كل شيء بشكل صحيح. أما الصفحات اللاحقة (معظمها على الأقل)، فإنها تفشل في تحميل النموذج وتظهر رسالة خطأ:

```plaintext
Couldn't find target container .subscription-form for HubSpot Form a86ca9cc. Not rendering form onto the page

```

أعتقد أن التذييل ربما يتم تحميله بعد تنفيذ السكربت؟

لذلك أحتاج بطريقة ما إلى تأخير تنفيذ السكربت حتى يتم تحميل التذييل.

يُظهر ملف `plugin-api.js` ما يلي:

```javascript
// Listen for a triggered `AppEvent` from Discourse.

api.onAppEvent("inserted-custom-html", () => {
  console.log("a custom footer was rendered");
});

```

ربما أحتاج فقط إلى معرفة أي `AppEvent` يجب البحث عنه؟

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [30 يونيو 2021، 7:25ص UTC](https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404/2 "2021-06-30T07:25:06Z")

</div>

هناك بعض المعلومات حول هذا الأمر هنا.

[Javascripts targeting the footer doesn't work after page transitions - #4 by Johani](https://meta.discourse.org/t/javascripts-targeting-the-footer-doesnt-work-after-page-transitions/180012/4?u=johani)

عند استخدامك لما يلي

```javascript
api.onAppEvent("inserted-custom-html", () => {
  // بعض الأكواد
});

```

يجب عليك تحديد نوع HTML المخصص الذي تريد استهدافه، حيث تُفعّل أحداث مختلفة بناءً على ذلك.

في هذه الحالة، تريد استهداف التذييل. هل يمكنك تجربة هذا والتحقق مما إذا كان يعمل معك؟

```javascript
api.onAppEvent("inserted-custom-html:footer", () => {
  // بعض الأكواد
});

```

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [30 يونيو 2021، 11:59ص UTC](https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404/3 "2021-06-30T11:59:10Z")

</div>

> [@Johani](#):
>
> ```plaintext
> api.onAppEvent("inserted-custom-html:footer", () => {
> 
> ```

ها! لقد نجح الأمر! (بالطبع، كان ذلك _بعد_ أن أقنعتهم بأن ما كانوا يحاولون فعله في التذييل لا يستحق القيام به من الأساس). أنا متحمس تمامًا لأنني تمكنت من حل هذه المشكلة وأقدر مساعدتك؛ فأنا أتقدم ببطء نحو فهم هذه الأمور. (وأعتقد أنهم الآن سيقومون بحذف التذييل بالكامل.)

> [@Johani](#):
>
> [Javascripts targeting the footer doesn’t work after page transitions - #4 by Johani](https://meta.discourse.org/t/javascripts-targeting-the-footer-doesnt-work-after-page-transitions/180012/4)

آها! لست متأكدًا من السبب في أنني لم أفكر في البحث عن “footer”! 🤷‍♂️

إذن، يشير `inserted-custom-html` إلى أي شيء في السمات؟ ثم يمكنني إضافة `:footer` أو `:header` أو ربما `:head_tag`؟ هل هذه هي السحر؟ هل أنا الوحيد، أم أن

[https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/lib/plugin-api.js#L516](https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/lib/plugin-api.js#L516)

كان سيكون أكثر فائدة لو كان مكتوبًا بدلاً من ذلك كالتالي:

```
   api.onAppEvent('inserted-custom-html:footer', () => {

```

يُعد JavaScript و Ember أصعب الأشياء بالنسبة لي لفهمها منذ… ربما عندما تعلمت Lisp في منتصف الثمانينيات، لذا لا زلت لا أستطيع تحديد ما يُعتبر “واضحًا” بدقة.

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [1 يوليو 2021، 4:14م UTC](https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404/4 "2021-07-01T16:14:34Z")

</div>

> [@pfaffman](#):
>
> إذن، يشير `inserted-custom-html` إلى أي شيء في السمات (themes)؟ ثم يمكنني إضافة `:footer` أو `:header` أو ربما `:head_tag`؟

ليس تمامًا. يحدث هذا الحدث فقط عند عرض مكون `custom-html` **ember**.

إذن، أين نستخدم مكون ember هذا، وماذا يفعل؟

نستخدمه بشكل رئيسي في قالب [التطبيق](https://github.com/discourse/discourse/blob/a0bbc346cb5d5b89d1a3efdfa89869349a8b067f/app/assets/javascripts/discourse/app/templates/application.hbs) الرئيسي لعرض حقلين من سمات التصميم.

علامة التبويب `after_header` في السمة

> <https://github.com/discourse/discourse/blob/a0bbc346cb5d5b89d1a3efdfa89869349a8b067f/app/assets/javascripts/discourse/app/templates/application.hbs#L17>

علامة التبويب التذييل (footer) في السمة

> <https://github.com/discourse/discourse/blob/a0bbc346cb5d5b89d1a3efdfa89869349a8b067f/app/assets/javascripts/discourse/app/templates/application.hbs#L31>

لاحظ أننا نستخدمه في أماكن أخرى، لكنها لا تهم في هذا السياق.

لاحظ كيف يحتوي التذييل أيضًا على `triggerAppEvent="true"`.

ولهذا السبب يمكنك استخدام:

```javascript
api.onAppEvent("inserted-custom-html:footer", () => {
  // بعض الأكواد
});

```

لا يمكنك فعل الشيء نفسه مع علامة التبويب `after_header`. لا يقوم Discourse بإطلاق حدث لذلك. لذا، لن يعمل هذا.

```javascript
api.onAppEvent("inserted-custom-html:top", () => {
  // بعض الأكواد
});

```

الآن، لماذا نستخدم مكون ember هذا لعرض بعض حقول السمة؟

الإجابة البسيطة هي أنه يمنحنا تحكمًا أكبر بكثير في توقيت عرضه.

مثالان على ذلك… قائمة المواضيع وصفحة المسؤول.

لا نريد عرض التذييل في قائمة المواضيع بينما لا تزال هناك مواضيع سيتم تحميلها عبر التمرير اللانهائي.

كما لا نريد عرض أي لافتات أو علامات تجارية للموقع في صفحة المسؤول المضافة في علامة التبويب `after_header`.

لذا، يمنحنا استخدام مكون `custom-html` ember تحكمًا أدق في أشياء من هذا القبيل.

الآن، نعود إلى سؤالك. إذا كان هناك بعض العمل الذي تحتاج إلى القيام به عند عرض التذييل، فهذا هو الغلاف الذي تحتاجه:

```javascript
api.onAppEvent("inserted-custom-html:footer", () => {
  // بعض الأكواد
});

```

> [@pfaffman](#):
>
> هل أنا الوحيد، أم أن […] ستكون أكثر فائدة لو كانت تقول بدلاً من ذلك:
> 
> ```plaintext
> api.onAppEvent('inserted-custom-html:footer', () => {
> 
> }
> 
> ```

تعمل طريقة واجهة برمجة التطبيقات (API) هذه لجميع أحداث التطبيق. لذا، على الرغم من أن المثال الموجود فيها غير مكتمل حقًا، فهو مجرد مثال. هناك العديد من `AppEvents` الأخرى التي يمكنك استخدامها في هذه الطريقة. على سبيل المثال، يمكنك التحقق من هنا:

> **[Build software better, together](https://github.com/search?q=repo%3Adiscourse%2Fdiscourse+%22appEvents.%22&type=code)**
>
> GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.

لمشاهدة أسماء بعض الأحداث التي يتم إطلاقها.

```javascript
this.appEvents.trigger("EVENT_NAME")

```

وكيفية ربطنا بها لإجراء تغييرات أخرى:

```javascript
this.appEvents.on("EVENT_NAME")

```

يمكنك ربط أي حدث يطلقه جوهر (core) Discourse في سمة التصميم الخاصة بك. لذا، إذا أردت تشغيل بعض الأكواد مباشرة قبل فتح محرر الرد (composer)،

[discourse/app/assets/javascripts/discourse/app/components/composer-editor.js at 1c38b4abf1fab8d67aaaa4b9f2810add64b709c4 · discourse/discourse · GitHub](https://github.com/discourse/discourse/blob/1c38b4abf1fab8d67aaaa4b9f2810add64b709c4/app/assets/javascripts/discourse/app/components/composer-editor.js#L256).

يمكنني إضافة شيء مثل هذا إلى سمة التصميم الخاصة بي:

```javascript
api.onAppEvent("composer:will-open", () => {
  console.log("هذا يتم تشغيله مباشرة قبل فتح محرر الرد");
});

```

مع ذلك، أنا أتفق معك. يجب أن نستخدم مثالًا مختلفًا لتلك الطريقة في ملف واجهة برمجة التطبيقات (API). لقد قمت بتدوين ملاحظة لتحسين هذا المثال.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [1 يوليو 2021، 5:00م UTC](https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404/5 "2021-07-01T17:00:33Z")

</div>

هذا رد رائع وواضح جدًا لدرجة أنني تمكنت من فهمه حتى أنا.

تتكرر مشكلة “كيفية جعل شيء ما يُفعّل” بشكل متكرر. ربما يجد الناس إجاباتهم هنا، لكن منشورك الأخير بحد ذاته يمكن أن يكون موضوعًا مستقلًا، وربما يُضاف أو يُربط به في أدلة السمات و/أو الإضافات.

وبما أن مصطلح “سمة” أصبح يشير في الغالب إلى “إمبر”، و"إضافة" تشير في الغالب إلى “ريلز”، فقد يكون من المنطقي أن يفكر شخص ما في إعادة هيكلة هذه الأقسام قليلاً. يبدو أنه عندما كانت الأمور في بدايتها، كان هناك الكثير من محتوى إمبر الذي يتطلب إضافة، وهو ما يمكن الآن إنجازه في مكون سمة، أليس كذلك؟ والآن يمكنك إنجاز عمل إمبر في إضافة **أو** في مكون سمة.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [3 يوليو 2021، 2:28م UTC](https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404/6 "2021-07-03T14:28:27Z")

</div>

مرحبًا @Johani، إذن هناك إصدار آخر من هذه المشكلة المتعلقة بـ “كيف يتم تشغيل أو كيف يتم تحفيز”، وهو أنني أستخدم نسخة من [Custom Header Links](https://meta.discourse.org/t/custom-header-links/90588) في إضافة. تقوم هذه الإضافة بربط بعض العناصر (“الخوادم”) التي تم إنشاؤها في نموذج منفصل تضيفه إضافتي. عند إنشاء `خادم`، أريد إعادة بناء روابط الرأس لربطها بأحدث خادمين تم إنشاؤهما. أقوم بذلك حاليًا في مُهيئ (initializer) ويعمل بشكل جيد، إلا أنه لتحديث الروابط بعد إضافة خادم، يجب إعادة تحميل الصفحة.

لقد أخبرتني كيفية إضافة ومراقبة المحفزات (triggers)، فظننت أنني قد أستطيع حل هذه المشكلة، لكن الصفحة التي تقوم بالعمل موجودة في `discourse-subscriptions`. ربما ما أريده هو تقديم طلب دمج (PR) إلى `discourse-subscriptions` يضيف:

```
 this.appEvents.trigger("purchase-complete")

```

بعد اكتمال عملية الشراء (حيث يؤدي الشراء إلى إضافة المستخدم إلى مجموعة، مما يؤدي بدوره إلى إنشاء خادم وإزالة المستخدم من المجموعة). أو، إذا كان بإمكاني ببساطة إعادة تحميل الصفحة بعد اكتمال الشراء، أو عند النقر على “موافق” في نافذة “اكتمال الشراء” المنبثقة، فسيكون ذلك كافيًا، لكنني لا أعرف كيف أفعل ذلك أيضًا (ما حاولته أعاد تحميل الصفحة إلى الأبد…)

لذا ربما هنا:

[https://github.com/discourse/discourse-subscriptions/blob/main/assets/javascripts/discourse/controllers/s-show.js.es6#L71-L81](https://github.com/discourse/discourse-subscriptions/blob/main/assets/javascripts/discourse/controllers/s-show.js.es6#L71-L81)

أريد إضافة:

```
 this.appEvents.trigger("successful-transaction")

```

بعد تعيين المتغير `loading` إلى `false`، ثم يمكنني أن أضيف في مُهيئتي:

```
 this.appEvents.on("successful-transaction")

```

لإجراء التعديل على الروابط؟

أعتقد أنه بمجرد القيام بذلك، سأحتاج إلى فعل شيء مختلف لأنني أخشى أن:

```plaintext
      api.decorateWidget("header-buttons:before", (helper) => {
        return helper.h("ul.pfaffmanager-header-links", headerLinks);
      });

```

تضيف إلى `header-buttons:before` بدلاً من استبدالها، وبالتالي سأحصل على روابط إضافية في كل مرة يتم فيها استدعاؤها؟

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [31 يوليو 2024، 2:45م UTC](https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404/7 "2024-07-31T14:45:50Z")

</div>

> [@Johani](#):
>
> ```plaintext
> api.onAppEvent("inserted-custom-html:top", () => {
> // some code
> });
> 
> ```

لقد ساعدني هذا مرة أخرى! ما احتجت إلى فعله هو تحميل نص برمجي عند تحديث تدفق المنشورات. كانت جميع الأمثلة التي وجدتها في مكونات كان لديها وصول إلى `appEvent` من خلال `this`. لقد وجدت هذا أخيرًا والآن في `apiInitializer` يمكنني

```plaintext
  api.onAppEvent('post-stream:refresh', args => {
   // do some stuff!!!
  });

```

والآن يتم تحميل تلك الإعلانات عند تحميل كل دفعة من المنشورات. لقد قمت بالفعل بالإعجاب بمنشورك، لذلك كان عليّ أن أكتب شكرًا أكثر تفصيلاً. 😉

---

<div class="post-metadata">

### Author: ![Don](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/don/32/228726_2.png) [@Don](https://meta.discourse.org/u/Don)
#### Post date: [3 أغسطس 2024، 7:20ص UTC](https://meta.discourse.org/t/how-to-fire-on-every-footer-load-or-page-load/195404/8 "2024-08-03T07:20:18Z")

</div>

هذا أحد مواضيعي المفضلة ❤ أعود إلى هنا من وقت لآخر 😅 أقدر هذا حقًا! 🤗
