Ciao a tutti,
Questa potrebbe essere una domanda un po’ basilare, sono più orientato al back-end. Attualmente sto cercando di collegare del codice JavaScript a un elemento del front-end. Il problema è che il mio window.onload (e anche document.onload, ho provato entrambi) non viene mai eseguito. Il mio JavaScript si trova nella cartella di inizializzazione del plugin ( [plugin]/assets/javascripts/initializers/[plugin].js.es6 )
export default {
name: "meritmoot",
initialize() {
//la mia funzione di inizializzazione
function initializeMeritmoot(api) {
console.log("dentro initializeMeritmoot")
//funzione al rilascio del tasto
function repInputKeyUp() {
inputBox = document.getElementById("rep-input")
console.log("in 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("Dopo la definizione della funzione");
//caricamento della finestra (non succede)
window.onload = () => {
console.log("PaginaCaricata") <-----------------------------------questo non viene mai stampato
document.getElementById('rep-input').onkeyup = repInputKeyUp;
};
console.log('uscita da initializeMeritmoot');
}
console.log("JavaScript MeritMoot nel default")
withPluginApi("0.8.37", api => initializeMeritmoot(api));
}
};
Qualche idea sul perché ciò possa accadere? Il JavaScript è configurato correttamente in relazione a Discourse? O è più un problema generale di JavaScript?
Modifica: sto provando con addEventListener…
Modifica: sostituendo onload con:
window.addEventListener('onload', function() {
console.log("PaginaCaricata")
document.getElementById('rep-input').onkeyup = repInputKeyUp;
}, false);
anche questo non ha funzionato.
Stai lavorando con EmberJS, non con JavaScript puro. Il comportamento non sarà lo stesso.
È meglio seguire le migliori pratiche di EmberJS.
Potresti valutare di integrare la tua logica in un componente esistente o aggiungerne uno a un’area di estensione (plugin outlet) utilizzando l’hook didInsertElement.
Leggi le Guida a EmberJS
Grazie! Ho visto che Ember è una parte importante di Discourse, ma non avevo capito che sovrascrivesse il vanilla. Prenderò del tempo per impararlo.
Modifica: Sto usando l’elemento del plugin discovery-list-container-top e mi sto collegando a un’architettura di plugin backend in Ruby.
Modifica: Qual è la relazione tra ember-rails e Discourse? Ember di per sé sembra essere un ambiente full stack. Guardando GitHub - emberjs/ember-rails: Ember for Rails 3.1+ · GitHub
ember-rails è un gem Ruby che viene effettivamente utilizzato in Discourse.
I membri dello staff di Discourse sono più qualificati per commentare, ma in generale, EmberJS gestisce il front-end, mentre Ruby on Rails si occupa del back-end. Naturalmente, Discourse presenta elementi di un’architettura su misura e la configurazione esatta, come per qualsiasi grande applicazione, è almeno in parte unica.
Una descrizione dettagliata del funzionamento è disponibile qui: Creating Routes in Discourse and Showing Data
La documentazione API è disponibile qui: https://docs.discourse.org
Ho imparato molto su Ember.js nell’ultimo periodo, ma sembra che sia sulla versione sbagliata. Per quanto riesco a capire, Discourse utilizza Ember.js 1.9 (guardando la documentazione di ember-rails e la sintassi del codice sorgente). La versione attuale di Ember.js è la 3.17, quindi la guida da seguire è questa. La sintassi è piuttosto diversa, ma ho afferrato le basi. Quando avrò finito, pubblicherò il codice sopra convertito per Ember.js.
Eseguire un’istanza di sviluppo in un browser rivela quanto segue nella console JavaScript:
DEBUG: -------------------------------
DEBUG: Ember : 3.12.2
DEBUG: jQuery : 3.4.1
DEBUG: -------------------------------
Ma hai ragione, alcune convenzioni di Discourse non riflettono la sintassi più recente delle guide 
Grazie per l’aiuto, Robert. Per un po’ mi sono sentito un po’ sopraffatto! Comunque, ecco cosa ho ottenuto alla fine, come promesso. Alla fine ho utilizzato la funzione onload, che viene attivata dopo il caricamento del DOM. Ho provato a usare jQuery per un po’, finché non ho saputo che Ember.js stava deprecandolo.
import { ajax } from 'discourse/lib/ajax';
// Potrei aggiornare l'evidenziazione per gestire anche la divisione con split(" "). Se, sai, ne avessi voglia.
export default Ember.Component.extend({
runOnceRan: false,
myAws: "",
subbedReps: [],
// Aggiorna le opzioni suggerite da seguire per i rappresentanti nella casella di input
updatePossibles: function (substr) {
var compContext = this; // contesto del componente
if (substr == "") {
return;
}
// Ottieni i suggerimenti
substr = encodeURIComponent(substr);
ajax(`meritmoot/reps/search/${substr}.json`, { type: "GET" }).then( result => {
result = result.api;
let pv = []; // valori possibili
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;
// Aggiorna la logica interna di Awesomplete
compContext.myAws.evaluate();
// Mostra i suggerimenti di Awesomplete
compContext.myAws.open();
});
},
runOnce: function () {
// Facci sapere che è stato eseguito...
console.log("in runOnce")
const substrInput = document.getElementById("rep-input");
const compContext = this;
// Crea un Awesomplete personalizzato (elenco di opzioni) per substrInput (rep-input).
this.myAws = new Awesomplete(substrInput);
console.log(substrInput)
// Tutti gli elementi dell'elenco devono essere mostrati, poiché vengono selezionati con pregiudizio al cambiamento del valore di substr
this.myAws.filter = function (text, input) {
return true
}
// Mostra sempre, attiva l'autocompletamento.
this.myAws.minChars = 0;
this.myAws.autocomplete = "on";
// Alla selezione di un'opzione, gestiscila.
document.addEventListener('awesomplete-selectcomplete', function(e) {
if(e.srcElement == substrInput) {
let id = e.text.value;
substrInput.value = "";
// Invia la selezione al backend
let uriid = encodeURIComponent(id)
ajax(`meritmoot/reps/${uriid}`, {type: "PUT" }).then( result => {
console.log("put passato indietro:");
console.log(result);
});
// Aggiorna la selezione nel frontend
let l = compContext.get("subbedReps");
l.pushObject(id) // pushObject è necessario invece di push (https://github.com/emberjs/ember.js/issues/10405)
compContext.set("subbedReps", l);
// 1. FATTO: crea una tabella che associa l'ID utente ai rappresentanti sottoscritti.
// 2. FATTO: crea un modo per aggiungere i rappresentanti sottoscritti a quella tabella. in corso (necessari GET, PUT, DELETE)
// 3. visualizza i rappresentanti accanto a substrInput
// 3. crea un modo per visualizzare i voti accanto ai topic.
// 4. dopo tutto ciò, aggiorna il meccanismo di visualizzazione dei voti qui.
}
}, false);
// Ottieni i rappresentanti salvati dall'utente e mostrali.
ajax(`meritmoot/reps`, {type: "GET"}).then( result => {
console.log("get passato indietro:");
console.log(result);
compContext.set("subbedReps", result.mmfollows);
console.log("subbedReps")
console.log(compContext.get("subbedReps"));
});
// All'input, aggiorna i suggerimenti
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);
}
}
});