مرحباً يا رفاق،
قد يكون هذا السؤال بسيطاً بعض الشيء، فأنا أكثر تخصصاً في الخلفية (back-end). حالياً أحاول ربط كود جافا سكريبت بعنصر في الواجهة الأمامية. المشكلة هي أن window.onload (وأيضاً document.onload، جربتهما معاً) لا يتم تفعيلها أبداً. كود الجافا سكريبت الخاص بي موجود في مجلد تهيئة الإضافة ( [plugin]/assets/javascripts/initializers/[plugin].js.es6 )
export default {
name: "meritmoot",
initialize() {
//دالة التهيئة الخاصة بي
function initializeMeritmoot(api) {
console.log("داخل initializeMeritmoot")
//دالة عند رفع الإصبع عن المفتاح
function repInputKeyUp() {
inputBox = document.getElementById("rep-input")
console.log("في rep input key up")
ajax("/reps/search/" + inputBox.value +".json", {type: 'GET'}).then((result) => {
console.log(result)
result = JSON.parse(result)
repList = document.getElementById("rep-list")
repList.innerHTML = ""
result.forEach(op => {
var x = document.createElement("INPUT");
x.setAttribute("info-tag-id", op.id)
x.setAttribute("value", op.mm_reference_str)
repList.appendChild(x)
});
console.log(repList)
});
};
console.log("بعد تعريف الدالة");
//تحميل النافذة (لا يحدث)
window.onload = () => {
console.log("تم تحميل الصفحة") <-----------------------------------هذا لا يظهر أبداً
document.getElementById('rep-input').onkeyup = repInputKeyUp;
};
console.log('مغادرة initializeMeritmoot');
}
console.log("جافا سكريبت MeritMoot في الـ Default")
withPluginApi("0.8.37", api => initializeMeritmoot(api));
}
};
أي أفكار حول سبب ذلك؟ هل إعداد الجافا سكريبت هذا صحيح فيما يتعلق بـ Discourse؟ أم أن المشكلة عامة في الجافا سكريبت؟
تعديل: جربت إضافة مستمع الحدث (addEventListener)…
تعديل: استبدلت onload بـ:
window.addEventListener('onload', function() {
console.log("تم تحميل الصفحة")
document.getElementById('rep-input').onkeyup = repInputKeyUp;
}, false);
ولكن لم ينجح ذلك أيضاً
أنت تعمل هنا مع EmberJS، وليس JavaScript العادي. لن يتصرف بنفس الطريقة.
الأفضل هو اتباع أفضل الممارسات في EmberJS.
أقترح عليك دمج منطقك في مكون موجود أو إضافة مكون جديد إلى منفذ المكونات (plugin outlet) واستخدام خطاف didInsertElement.
اقرأ دليل EmberJS
شكرًا لك! لقد رأيت أن إمبر كان جزءًا كبيرًا من ديسكورد، لكنني لم أدرك أنه يتجاوز النسخة الأصلية. سأخصص وقتًا لتعلمه.
تعديل: أنا أستخدم عنصر الإضافة discovery-list-container-top وأربطه بهيكلية إضافة في الخلفية بلغة روبي.
تعديل: ما هي العلاقة بين إمبر-ريلز وديسكورد؟ يبدو أن إمبر بحد ذاتها بيئة متكاملة. عند النظر إلى GitHub - emberjs/ember-rails: Ember for Rails 3.1+ · GitHub
ember-rails هي مكتبة Ruby تُستخدم فعليًا في Discourse.
إن موظفي Discourse هم الأكثر أهلية للتعليق، ولكن بشكل عام، يتعامل EmberJS مع الواجهة الأمامية، بينما يتولى Ruby-on-Rails الواجهة الخلفية. بالطبع، يحتوي Discourse على عناصر من بنية مخصصة، والتكوين الدقيق، مثل أي تطبيق كبير، فريد إلى حد ما على الأقل.
يمكنك العثور على وصف جميل لكيفية عمل الأشياء هنا: Creating Routes in Discourse and Showing Data
وثائق API متاحة هنا: https://docs.discourse.org
تعلمت الكثير عن Ember.js مؤخرًا، لكن يبدو أنني تعلمته على إصدار غير صحيح. насколько我能فهمه، يستخدم Discourse إصدار 1.9 من Ember.js (بناءً على مراجعة توثيق ember-rails وبناءً على صياغة الكود المصدري). أما الإصدار الحالي من Ember.js فهو 3.17. لذا فإن الدليل الذي يجب اتباعه هو هذا. الصياغة مختلفة تمامًا، لكنني استوعبت الأساسيات. سأقوم بنشر الكود المذكور أعلاه بعد تحويله إلى Ember.js عند الانتهاء.
تشغيل مثيل تطوير في المتصفح يكشف هذا في وحدة تحكم JavaScript:
DEBUG: -------------------------------
DEBUG: Ember : 3.12.2
DEBUG: jQuery : 3.4.1
DEBUG: -------------------------------
لكنك محق، بعض تقاليد Discourse لا تعكس أحدث بناء جملة في الأدلة 
شكرًا لك على المساعدة يا روبرت، لقد كنتُ خارج حدودي قليلًا في هذا الأمر! على أي حال، إليك ما توصلتُ إليه في النهاية كما وعدتُ. لقد انتهيتُ باستخدام دالة onload، التي تُفعّل بعد تحميل DOM. حاولتُ استخدام jQuery لفترة قصيرة حتى سمعتُ أن Ember.js يتخلى عن دعمها.
import { ajax } from 'discourse/lib/ajax';
// يمكن تحديث التمييز ليُطبّق أيضًا على split(" ")، إذا ما شعرتُ بالرغبة في ذلك.
export default Ember.Component.extend({
runOnceRan: false,
myAws: "",
subbedReps: [],
// تحديث الخيارات المقترحة لمتابعة الممثلين في مربع الإدخال
updatePossibles: function (substr) {
var compContext = this; // سياق المكون
if (substr == "") {
return;
}
// الحصول على الاقتراحات
substr = encodeURIComponent(substr);
ajax(`meritmoot/reps/search/${substr}.json`, { type: "GET" }).then( result => {
result = result.api;
let pv = []; // القيم الممكنة
for(let i = 0; i < result.length; i++) {
let newItem = {
label: result[i].mm_reference_str,
value: result[i].id,
id: result[i].id,
}
pv.push(newItem);
}
console.log(pv)
compContext.myAws.list = pv;
// تحديث المنطق الداخلي لـ Awesomplete
compContext.myAws.evaluate();
// إظهار اقتراحات Awesomplete
compContext.myAws.open();
});
},
runOnce: function () {
// إعلامنا بأنها قد نُفذت...
console.log("في runOnce")
const substrInput = document.getElementById("rep-input");
const compContext = this;
// إنشاء Awesomplete مخصص (قائمة الخيارات) لـ substrInput (rep-input).
this.myAws = new Awesomplete(substrInput);
console.log(substrInput)
// يجب إظهار جميع عناصر القائمة، حيث يتم تحديدها مع التحيز عند تغيير قيمة substr
this.myAws.filter = function (text, input) {
return true
}
// إظهار في أي وقت، وتفعيل الإكمال التلقائي.
this.myAws.minChars = 0;
this.myAws.autocomplete = "on";
// عند اختيار خيار، التعامل معه.
document.addEventListener('awesomplete-selectcomplete', function(e) {
if(e.srcElement == substrInput) {
let id = e.text.value;
substrInput.value = "";
// إرسال الاختيار إلى الخادم الخلفي
let uriid = encodeURIComponent(id)
ajax(`meritmoot/reps/${uriid}`, {type: "PUT" }).then( result => {
console.log("تم إرسال PUT بنجاح:");
console.log(result);
});
// تحديث الاختيار في الواجهة الأمامية
let l = compContext.get("subbedReps");
l.pushObject(id) // يُستخدم pushObject بدلاً من push (https://github.com/emberjs/ember.js/issues/10405)
compContext.set("subbedReps", l);
// 1. تم إنشاء جدول يطابق معرف المستخدم بالممثلين المشتركين.
// 2. تم إنشاء طريقة لإضافة الممثلين المشتركين إلى ذلك الجدول. قيد التنفيذ (يحتاج إلى GET و PUT و DELETE)
// 3. عرض الممثلين بجانب substrInput
// 3. إنشاء طريقة لعرض الأصوات بجانب المواضيع.
// 4. بعد كل ذلك، تحديث آلية عرض الأصوات هنا.
}
}, false);
// الحصول على الممثلين المحفوظين للمستخدم وعرضهم.
ajax(`meritmoot/reps`, {type: "GET"}).then( result => {
console.log("تم استلام GET بنجاح:");
console.log(result);
compContext.set("subbedReps", result.mmfollows);
console.log("subbedReps")
console.log(compContext.get("subbedReps"));
});
// عند الإدخال، تحديث الاقتراحات
document.addEventListener('input', function(e) {
if(e.explicitOriginalTarget == substrInput) {
compContext.updatePossibles(substrInput.value);
}
}, false)
console.log(this.myAws);
},
didRender() {
this._super(...arguments);
if( ! this.runOnceRan ) {
this.runOnce();
this.set("runOnceRan", true);
}
}
});