Javascript onload wird nicht ausgelöst

Hey Leute,

Das ist vielleicht eine etwas grundlegende Frage, ich bin eher Backend-orientiert. Momentan versuche ich, einige JavaScript-Code mit einem Frontend-Element zu verbinden. Das Problem ist, dass mein window.onload (und document.onload, ich habe beide ausprobiert) nie feuert. Mein JavaScript befindet sich im Plugin-Init-Ordner ([plugin]/assets/javascripts/initializers/[plugin].js.es6).

export default {
  name: "meritmoot",
  initialize() {

    // Meine Initialisierungsfunktion
    function initializeMeritmoot(api) {
      console.log("inside initializeMeritmoot")

      // Funktion bei Tastenanschlag hoch
      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("Past Function Def");
      
      // window load (passiert nicht)
      window.onload = () => {
        console.log("PageLoaded") <-----------------------------------das wird nie ausgegeben
        document.getElementById('rep-input').onkeyup = repInputKeyUp;
      };
      console.log('leaving initializeMeritmoot');
    }
    console.log("MeritMoot Javascript In Default")
    withPluginApi("0.8.37", api => initializeMeritmoot(api));
  }
};

Irgendwelche Gedanken dazu, warum das so sein könnte? Ist dieses JavaScript in Bezug auf Discourse korrekt eingerichtet? Oder ist das eher eine allgemeine JavaScript-Frage?

Edit: Versuche addEventListener…

Edit: Ersetze onload durch:

  window.addEventListener('onload', function() {
    console.log("PageLoaded")
    document.getElementById('rep-input').onkeyup = repInputKeyUp;
  }, false);

hat auch nicht funktioniert

Du arbeitest hier mit EmberJS, nicht mit Vanilla JavaScript. Es verhält sich nicht gleich.

Am besten befolgst du die EmberJS-Best-Practices.

Ich würde empfehlen, deine Logik an eine bestehende Komponente anzubinden oder eine Komponente zu einem Plugin-Outlet hinzuzufügen und den didInsertElement-Hook zu verwenden.

Lies die EmberJS-Anleitungen

Danke! Ich habe gesehen, dass Ember ein großer Teil von Discourse ist, aber nicht realisiert, dass es Vanilla überschreibt. Ich werde mir die Zeit nehmen, es zu lernen.

Edit: Ich verwende das Plugin-Element discovery-list-container-top und verbinde mich mit einer Ruby-Backend-Plugin-Architektur.

Edit: Wie ist die Beziehung zwischen ember-rails und Discourse? Ember an sich scheint eine Full-Stack-Umgebung zu sein. Schaut man sich GitHub - emberjs/ember-rails: Ember for Rails 3.1+ · GitHub an…

ember-rails ist ein Ruby-Gem, das tatsächlich in Discourse verwendet wird.

Die Discourse-Mitarbeiter können dies besser kommentieren, aber grob gesagt kümmert sich EmberJS um das Frontend und Ruby on Rails um das Backend. Natürlich verfügt Discourse über Elemente einer maßgeschneiderten Architektur, und die genaue Konfiguration ist wie bei jeder großen Anwendung zumindest teilweise einzigartig.

Eine schöne Beschreibung der Funktionsweise finden Sie hier: Creating Routes in Discourse and Showing Data

Die API-Dokumentation ist hier verfügbar: https://docs.discourse.org

Ich habe in letzter Zeit viel über Ember.js gelernt – aber es scheint, als hätte ich die falsche Version verwendet. Soweit ich feststellen konnte, verwendet Discourse Ember.js 1.9 (basierend auf der ember-rails-Dokumentation und der Syntax im Quellcode). Die aktuelle Version von Ember.js ist 3.17. Der Leitfaden, dem gefolgt werden sollte, ist dieser hier. Die Syntax ist ziemlich unterschiedlich, aber ich habe die Grundlagen verstanden. Sobald ich fertig bin, werde ich den oben stehenden Code in Ember.js konvertiert veröffentlichen.

Das Ausführen einer Dev-Instanz im Browser zeigt dies in der JavaScript-Konsole:

DEBUG: -------------------------------
DEBUG: Ember  : 3.12.2 
DEBUG: jQuery : 3.4.1 
DEBUG: ------------------------------- 

Aber du hast recht, einige der Discourse-Konventionen spiegeln nicht die allerneueste Syntax in den Anleitungen wider :slight_smile:

Danke für die Hilfe, Robert! Ich war eine Weile etwas überfordert. Wie versprochen, hier ist das Endergebnis. Ich habe schließlich die onload-Funktion verwendet, die ausgelöst wird, nachdem das DOM geladen ist. Ich habe kurz versucht, jQuery zu nutzen, bis ich hörte, dass Ember.js es veraltet erklärt hat.

import { ajax } from 'discourse/lib/ajax';
// Man könnte das Highlight auch auf split(" ") erweitern. Wenn man Lust dazu hat.

export default Ember.Component.extend({
  runOnceRan: false,
  myAws: "",
  subbedReps: [],
  // Aktualisiert die vorgeschlagenen Optionen für Vertreter im Eingabefeld
  updatePossibles: function (substr) {
    var compContext = this; // Komponentenkontext
    if (substr == "") {
      return;
    }
    // Vorschläge abrufen
    substr = encodeURIComponent(substr);
    ajax(`meritmoot/reps/search/${substr}.json`, { type: "GET" }).then( result => {
      result = result.api;
      let pv = []; // Mögliche Werte
      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;
      // Interne Logik von Awesomplete aktualisieren
      compContext.myAws.evaluate();
      // Awesomplete-Vorschläge anzeigen
      compContext.myAws.open();
    });
  },
  runOnce: function () {
    // Bestätigung, dass es ausgeführt wurde...
    console.log("in runOnce")
    const substrInput = document.getElementById("rep-input");
    const compContext = this;
    
    // Benutzerdefiniertes Awesomplete (Optionsliste) für substrInput (rep-input) erstellen.
    this.myAws = new Awesomplete(substrInput);
    console.log(substrInput)

    // Alle Listenelemente sollten angezeigt werden, da sie bei Änderung des substr-Werts mit Vorurteilen ausgewählt werden
    this.myAws.filter = function (text, input) {
      return true
    }

    // Immer anzeigen, Autocomplete aktivieren.
    this.myAws.minChars = 0;
    this.myAws.autocomplete = "on";

    // Bei Auswahl einer Option diese verarbeiten.
    document.addEventListener('awesomplete-selectcomplete', function(e) {
        if(e.srcElement == substrInput) {
          let id = e.text.value;
          substrInput.value = "";
          
          // Auswahl an Backend senden
          let uriid = encodeURIComponent(id)
          ajax(`meritmoot/reps/${uriid}`, {type: "PUT" }).then( result => {
            console.log("PUT erfolgreich zurückgegeben:");
            console.log(result);
          });

          // Auswahl im Frontend aktualisieren
          let l = compContext.get("subbedReps");
          l.pushObject(id) // pushObject wird benötigt statt push (https://github.com/emberjs/ember.js/issues/10405)
          compContext.set("subbedReps", l);

          // 1. DONE: Eine Tabelle erstellen, die Benutzer-ID mit abonnierten Vertretern verknüpft.
          // 2. DONE: Eine Möglichkeit schaffen, abonnierte Vertreter zu dieser Tabelle hinzuzufügen. In Arbeit (GET, PUT, DELETE benötigt)
          // 3. Vertreter neben substrInput anzeigen
          // 3. Eine Möglichkeit schaffen, Stimmen neben Themen anzuzeigen.
          // 4. Nach all dem diesen Mechanismus zur Anzeige von Stimmen hier aktualisieren.
        }
      }, false);
    
    // Gespeicherte Vertreter des Benutzers abrufen und anzeigen.
    ajax(`meritmoot/reps`, {type: "GET"}).then( result => {
      console.log("GET erfolgreich zurückgegeben:");
      console.log(result);
      compContext.set("subbedReps", result.mmfollows);
      console.log("subbedReps")
      console.log(compContext.get("subbedReps"));
    });

    // Bei Eingabe Vorschläge aktualisieren
    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);
    }
  }
});