JavaScript の onload イベントが発火しない

皆さん、こんにちは

これは少し初歩的な質問かもしれません。私はどちらかと言えばバックエンド担当です。現在、JavaScript コードをフロントエンドの要素に接続しようとしています。問題は、window.onload(および document.onload、両方試しました)が一度も発火しないことです。私の JavaScript はプラグインの init フォルダ([plugin]/assets/javascripts/initializers/[plugin].js.es6)にあります。

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

    // 初期化関数
    function initializeMeritmoot(api) {
      console.log("inside initializeMeritmoot")

      // キーアップ時の関数
      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(発生しません)
      window.onload = () => {
        console.log("PageLoaded") <-----------------------------------ここは決して出力されません
        document.getElementById('rep-input').onkeyup = repInputKeyUp;
      };
      console.log('leaving initializeMeritmoot');
    }
    console.log("MeritMoot Javascript In Default")
    withPluginApi("0.8.37", api => initializeMeritmoot(api));
  }
};

なぜこのようなことが起こるのか、ご意見はありますか?Discourse に対してこの JavaScript の設定は正しいのでしょうか?それとも一般的な JavaScript の問題でしょうか?

編集:addEventListener を追加してみましたが…

編集:onload を以下に置き換えてみました:

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

これも機能しませんでした

ここではバニラ JavaScript ではなく EmberJS を使用しています。そのため、同じように動作するわけではありません。

EmberJS のベストプラクティスに従うことをお勧めします。

既存のコンポーネントにロジックを乗っけるか、プラグインアウトレットにコンポーネントを追加し、didInsertElement フックを使用することを検討してください。

EmberJS ガイドをご覧ください。

「いいね!」 3

ありがとうございます!Ember が Discourse の重要な部分を占めていることは知っていましたが、Vanilla を上書きしているとは知りませんでした。時間をかけて学んでみます。

編集:プラグイン element discovery-list-container-top を使用し、Ruby バックエンドのプラグインアーキテクチャに接続しています。

編集:ember-rails と Discourse の関係は何でしょうか?Ember 自体はフルスタック環境のようです。GitHub - emberjs/ember-rails: Ember for Rails 3.1+ · GitHub を参照しています。

ember-rails は、Discourse でも実際に使用されている Ruby の gem です。

Discourse のスタッフの方が詳しくコメントできると思いますが、概して EmberJS はフロントエンドを、Ruby on Rails はバックエンドを担当します。もちろん、Discourse には独自アーキテクチャの要素もあり、大規模なアプリケーションであれば当然ながら、正確な設定も少なくともある程度は独自のものになっています。

仕組みについてのわかりやすい説明はこちらです:Creating Routes in Discourse and Showing Data

API ドキュメントはこちらです:https://docs.discourse.org

「いいね!」 2

最近、Ember.js について多くを学びましたが、どうやら間違ったバージョンを扱っていたようです。ember-rails のドキュメント やソースコードの構文を確認する限り、Discourse は Ember.js 1.9 を使用しているようです。現在の Ember.js のバージョンは 3.17 です。したがって、従うべきガイドはこちらです。構文はかなり異なりますが、基本的な部分は理解できました。完了したら、上記のコードを Ember.js 向けに変換したものを投稿します。

「いいね!」 2

ブラウザで開発用インスタンスを実行すると、JavaScript コンソールに以下が表示されます:

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

しかし、おっしゃる通り、Discourse のいくつかの慣習は、ガイドの最新構文を反映していません :slight_smile:

「いいね!」 2

ロバート、ありがとう。少しはこの分野に詳しくなかったんだ!とにかく、約束した通り、最終的にこれを得ました。結局、DOM が読み込まれた後にトリガーされる onload 関数を使用しました。emberjs が jquery を非推奨としていると聞いたまで、少しは jquery を使おうとしました。

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("in runOnce")
    const substrInput = document.getElementById("rep-input");
    const compContext = this;
    
    // substrInput (rep-input) のためのカスタム Awesomplete(オプションリスト)を作成
    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 passed back:");
            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. 完了:ユーザー ID と購読した代表者を一致させるテーブルを作成
          // 2. 完了:購読した代表者をそのテーブルに追加する方法を作成。進行中(GET、PUT、DELETE が必要)
          // 3. substrInput の隣に代表者を表示
          // 3. トピックの隣に投票を表示する方法を作成
          // 4. その後、ここで投票を表示するメカニズムをリフレッシュ
        }
      }, false);
    
    // ユーザーの保存された代表者を取得し、表示
    ajax(`meritmoot/reps`, {type: "GET"}).then( result => {
      console.log("get passed back:");
      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);
    }
  }
});

「いいね!」 2