皆さん、こんにちは
これは少し初歩的な質問かもしれません。私はどちらかと言えばバックエンド担当です。現在、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 のいくつかの慣習は、ガイドの最新構文を反映していません 
「いいね!」 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