Luke_Clancy is having trouble with the window.onload event not firing in their JavaScript code, which is part of a Discourse plugin. They are using the plugin element discovery-list-container-top and connecting to a Ruby backend plugin architecture.
Merefield points out that Discourse uses EmberJS, which overrides vanilla JavaScript behavior. They recommend following EmberJS best practices, such as using the didInsertElement hook or piggybacking onto an existing component.
Luke_Clancy learns about EmberJS and its version used in Discourse (1.9) and starts converting their code to EmberJS. However, they realize that the current version of EmberJS is 3.17, and the syntax has changed.
Merefield reveals that the Discourse instance is actually running Ember 3.12.2, not 1.9.
Luke_Clancy shares their converted code, which uses Ember Component and the didRender hook to execute the code after the DOM is loaded. They also use the ajax function from discourse/lib/ajax to make requests to the backend.
This may be a bit of a basic question, I am more of a back-end guy. Currently I am trying to connect some java-script code to a front end element. The issue is that my window.onload (and document.onload, I tried them both) never fires. my javascript is in the plugin init folder ( [plugin]/assets/javascripts/initializers/[plugin].js.es6 )
export default {
name: "meritmoot",
initialize() {
//my initialization function
function initializeMeritmoot(api) {
console.log("inside initializeMeritmoot")
//function on key up
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 (doesnt happen)
window.onload = () => {
console.log("PageLoaded") <-----------------------------------this never prints
document.getElementById('rep-input').onkeyup = repInputKeyUp;
};
console.log('leaving initializeMeritmoot');
}
console.log("MeritMoot Javascript In Default")
withPluginApi("0.8.37", api => initializeMeritmoot(api));
}
};
Any thoughts on why this may be? Is this javascript setup correctly in relation to discourse? Or is this more of a general javascript thing?
ember-rails is a Ruby gem that is actually used in Discourse.
Discourse staffers are far better to comment, but broadly, EmberJS deals with the front-end, and Ruby-on-Rails, the back end. Of course, Discourse has elements of a bespoke architecture and the exact configuration is, like any big application, at least somewhat unique.
Learned a lot of emberjs over the last bit - but it looks like on the wrong version. As far as I can tell Emberjs 1.9 is used by discourse (by looking at the ember-rails docs and source code syntax). Current version of Emberjs is 3.17 So the guide that should be followed is this one. The syntax is quite diffrent, but I got the basics down. I will post the above code converted to emberjs when finished
Thanks for the help Robert, I was kind of out of my depth on this for a bit! Anyway, here is what I got in the end as promised. I ended up using the onload function, which triggers after the DOM is loaded. I tried to use jquery for a bit until I heard that emberjs was depreciating it.
import { ajax } from 'discourse/lib/ajax';
//could update the highlight to hit on the split(" ") aswell. If, you know, i feel like it.
export default Ember.Component.extend({
runOnceRan: false,
myAws: "",
subbedReps: [],
//update the suggested options to follow for representatives in the input box
updatePossibles: function (substr) {
var compContext = this; //component context
if (substr == "") {
return;
}
//get suggestions
substr = encodeURIComponent(substr);
ajax(`meritmoot/reps/search/${substr}.json`, { type: "GET" }).then( result => {
result = result.api;
let pv = []; //possible values
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;
//update Awesomplete internal logic
compContext.myAws.evaluate();
//show Awesomplete suggestions
compContext.myAws.open();
});
},
runOnce: function () {
//let us know it ran...
console.log("in runOnce")
const substrInput = document.getElementById("rep-input");
const compContext = this;
//create custom Awesomplete (options list) for substrInput (rep-input).
this.myAws = new Awesomplete(substrInput);
console.log(substrInput)
//all list items should be shown, as they are selected with predjudice on substr value change
this.myAws.filter = function (text, input) {
return true
}
//show whenever, turn autocomplete on.
this.myAws.minChars = 0;
this.myAws.autocomplete = "on";
//on selection of option, handle it.
document.addEventListener('awesomplete-selectcomplete', function(e) {
if(e.srcElement == substrInput) {
let id = e.text.value;
substrInput.value = "";
//send selection backend
let uriid = encodeURIComponent(id)
ajax(`meritmoot/reps/${uriid}`, {type: "PUT" }).then( result => {
console.log("put passed back:");
console.log(result);
});
//update selection frontend
let l = compContext.get("subbedReps");
l.pushObject(id) //pushObject is needed instead of push (https://github.com/emberjs/ember.js/issues/10405)
compContext.set("subbedReps", l);
//1. DONE create a table that matches user id to subscribed reps.
//2. DONE create a way to add subscribed reps to that table. in progress (need GET PUT DELETE)
//3. view reps next to substrInput
//3. create a way to view votes next to topics.
//4. after all that, refresh that mechanism of viewing votes here.
}
}, false);
//get users saved representatives, show them.
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"));
});
//on input, update suggestions
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);
}
}
});