I use a loop through the node elements to get the ID from the clicked element. Until then all good and it works. Now I want to call an another function in my class & get this error:
this._PreLoad is not defined at HTMLElement.s.onclick
this._joinnews.forEach((node) => {
node.onclick = function(){
const requestData = `newsid=${node.id}`;
// some code //
this._PreLoad(true); // ERROR
// _PreLoad(true); not working
// this._PreLoad(true).bind(this); not working (I am not yet familiar with the bind function)
}
});
Are the functions inside a node loop unknown ?
The correct place to bind this is here:
node.onclick = function() {
const requestData = `newsid=${node.id}`;
// some code //
this._PreLoad(true);
}.bind(this); // bind here!
Alternatively, use an arrow function which preserves this as whatever it was at the time of the function declaration:
node.onclick = () => {
const requestData = `newsid=${node.id}`;
// some code //
this._PreLoad(true);
}
Related
I want to remove listener. When i add listener, it works. But when i try to remove it doesn't remove it and listener still works. How can i remove listener properly? Can someone help me?
Here is the function with parameters to add Listener and remove Listener. It also includes the listener function which could be used later.
Edit1: If i try to RemoveListener after adding it. It is works. But if i try to use it dynamically with parameters. It doesn't work.
// In DoSomething.js
function Channel(ChannelName,Op)
{
//This function will be listened. The reason i am using this inside of another function is to use for ChannelName parameter. I don't want to use that "ChannelName" parameter within (from,message) part.
var ChannListener = function ChannFunc(from,message)
{
if(typeof message === 'undefined') return;
ChannelName = ChannelName + "something";
//snip
}
Channel.ChannListener = ChannListener;
switch(Op)
{
case 1:
{
bot.addListener('msg'+ChannelName.toLowerCase(),ChannListener);
break;
}
case 0:
{
bot.removeListener('msg'+ChannelName.toLowerCase(),ChannListener);
break;
}
}
}
It is adding listener function. After loop, depending on the value of JSON, listeners are adding via Channel function.
// In DoSomething.js
var GetFromJsonFunction = function()
{
const Data = fs.readFileSync('/path/to/something.json', {encoding:'utf8'});
var TempData = JSON.parse(Data);
for(var i=0;i<TempData.Block.length;i++)
{
Channel(TempData.Block[i]._textValue,1);
}
}
GetFromJsonFunction();
In here, i want to remove that listener. So i used the same function with 0/1 parameter. 0 is executing RemoveListener, 1 is executing AddListener command in the Channel function.
// In DoSomething.js
/*
* #param1 Channel Name - String
* #param2 Callback - String
*/
exports.DeleteChann = function(IncomingMessage, CallBack)
{
//snip
Channel(IncomingMessage,0);
CallBack("success");
//snip
}
This one is to used for DeleteChann function from another file.
// In index.js
OtherFile.DeleteChann(SendMessage, function(CallBack)
{
//snip
console.log(CallBack);
//snip
});
So pub-sub paradigm or these kind of eventemitter work:
When a function is added as listener it adds it to an array.
When it is removed it checks for the function and removes it.
In your case everytime Channel(..) is called, a new ChannListener is created. So when you try to remove it as the memory location(pointer) is different it never finds the function that it needs to remove.
So, you need to shift ChannListener outside so that only 1 function is created. Remember, only the SAME function can be removed.
EDIT:
As you said you need it inside, you can create a Map outside of the function that holds the function.
like,
var ChannListener = function ChannFunc(from,message)
{
if(typeof message === 'undefined') return;
ChannelName = ChannelName + "something";
}
channelMap["some_uniq_thing"] = ChannListener;
# and after that remove it:
bot.removeListener(..., channelMap["some_uniq_thing]);
EDIT
A primitive example would be (you probably need to find the edge cases):
/// In DoSomething.js
const listenerMap = {};
function Channel(ChannelName, Op) {
//This function will be listened. The reason i am using this inside of another function is to use for ChannelName parameter. I don't want to use that "ChannelName" parameter within (from,message) part.
var ChannListener = function ChannFunc(from, message) {
if (typeof message === 'undefined') return;
ChannelName = ChannelName + "something";
//snip
}
Channel.ChannListener = ChannListener;
if(!listenerMap[ChannelName]) // don't overwrite functions.
listenerMap[ChannelName] = ChannListener;
switch (Op) {
case 1:
{
bot.addListener('msg' + ChannelName.toLowerCase(), listenerMap[ChannelName]);
break;
}
case 0:
{
bot.removeListener('msg' + ChannelName.toLowerCase(), listenerMap[ChannelName]);
break;
}
}
}
The main reason why I want it is that I want to extend my initialize function.
Something like this:
// main.js
window.onload = init();
function init(){
doSomething();
}
// extend.js
function extends init(){
doSomethingHereToo();
}
So I want to extend a function like I extend a class in PHP.
And I would like to extend it from other files too, so for example I have the original init function in main.js and the extended function in extended.js.
With a wider view of what you're actually trying to do and the context in which you're doing it, I'm sure we could give you a better answer than the literal answer to your question.
But here's a literal answer:
If you're assigning these functions to some property somewhere, you can wrap the original function and put your replacement on the property instead:
// Original code in main.js
var theProperty = init;
function init(){
doSomething();
}
// Extending it by replacing and wrapping, in extended.js
theProperty = (function(old) {
function extendsInit() {
old();
doSomething();
}
return extendsInit;
})(theProperty);
If your functions aren't already on an object, you'd probably want to put them there to facilitate the above. For instance:
// In main.js
var MyLibrary = {
init: function init() {
}
};
// In extended.js
(function() {
var oldInit = MyLibrary.init;
MyLibrary.init = extendedInit;
function extendedInit() {
oldInit.call(MyLibrary); // Use #call in case `init` uses `this`
doSomething();
}
})();
But there are better ways to do that. Like for instance, providing a means of registering init functions.
// In main.js
var MyLibrary = (function() {
var initFunctions = [];
return {
init: function init() {
var fns = initFunctions;
initFunctions = undefined;
for (var index = 0; index < fns.length; ++index) {
try { fns[index](); } catch (e) { }
}
},
addInitFunction: function addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
}
}
};
})();
Here in 2020 (or really any time after ~2016), that can be written a bit more compactly:
// In main.js
const MyLibrary = (() => {
let initFunctions = [];
return {
init() {
const fns = initFunctions;
initFunctions = undefined;
for (const fn of fns) {
try { fn(); } catch (e) { }
}
},
addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
// Or: `Promise.resolve().then(() => fn());`
// (Not `.then(fn)` just to avoid passing it an argument)
}
}
};
})();
There are several ways to go about this, it depends what your purpose is, if you just want to execute the function as well and in the same context, you can use .apply():
function init(){
doSomething();
}
function myFunc(){
init.apply(this, arguments);
doSomethingHereToo();
}
If you want to replace it with a newer init, it'd look like this:
function init(){
doSomething();
}
//anytime later
var old_init = init;
init = function() {
old_init.apply(this, arguments);
doSomethingHereToo();
};
The other methods are great but they don't preserve any prototype functions attached to init. To get around that you can do the following (inspired by the post from Nick Craver).
(function () {
var old_prototype = init.prototype;
var old_init = init;
init = function () {
old_init.apply(this, arguments);
// Do something extra
};
init.prototype = old_prototype;
}) ();
Another option could be:
var initial = function() {
console.log( 'initial function!' );
}
var iWantToExecuteThisOneToo = function () {
console.log( 'the other function that i wanted to execute!' );
}
function extendFunction( oldOne, newOne ) {
return (function() {
oldOne();
newOne();
})();
}
var extendedFunction = extendFunction( initial, iWantToExecuteThisOneToo );
2017+ solution
The idea of function extensions comes from functional paradigm, which is natively supported since ES6:
function init(){
doSomething();
}
// extend.js
init = (f => u => { f(u)
doSomethingHereToo();
})(init);
init();
As per #TJCrowder's concern about stack dump, the browsers handle the situation much better today. If you save this code into test.html and run it, you get
test.html:3 Uncaught ReferenceError: doSomething is not defined
at init (test.html:3)
at test.html:8
at test.html:12
Line 12: the init call, Line 8: the init extension, Line 3: the undefined doSomething() call.
Note: Much respect to veteran T.J. Crowder, who kindly answered my question many years ago, when I was a newbie. After the years, I still remember the respectfull attitude and I try to follow the good example.
This is very simple and straight forward. Look at the code. Try to grasp the basic concept behind javascript extension.
First let us extend javascript function.
function Base(props) {
const _props = props
this.getProps = () => _props
// We can make method private by not binding it to this object.
// Hence it is not exposed when we return this.
const privateMethod = () => "do internal stuff"
return this
}
You can extend this function by creating child function in following way
function Child(props) {
const parent = Base(props)
this.getMessage = () => `Message is ${parent.getProps()}`;
// You can remove the line below to extend as in private inheritance,
// not exposing parent function properties and method.
this.prototype = parent
return this
}
Now you can use Child function as follows,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
We can also create Javascript Function by extending Javascript classes, like this.
class BaseClass {
constructor(props) {
this.props = props
// You can remove the line below to make getProps method private.
// As it will not be binded to this, but let it be
this.getProps = this.getProps.bind(this)
}
getProps() {
return this.props
}
}
Let us extend this class with Child function like this,
function Child(props) {
let parent = new BaseClass(props)
const getMessage = () => `Message is ${parent.getProps()}`;
return { ...parent, getMessage} // I have used spread operator.
}
Again you can use Child function as follows to get similar result,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
Javascript is very easy language. We can do almost anything. Happy JavaScripting... Hope I was able to give you an idea to use in your case.
Use extendFunction.js
init = extendFunction(init, function(args) {
doSomethingHereToo();
});
But in your specific case, it's easier to extend the global onload function:
extendFunction('onload', function(args) {
doSomethingHereToo();
});
I actually really like your question, it's making me think about different use cases.
For javascript events, you really want to add and remove handlers - but for extendFunction, how could you later remove functionality? I could easily add a .revert method to extended functions, so init = init.revert() would return the original function. Obviously this could lead to some pretty bad code, but perhaps it lets you get something done without touching a foreign part of the codebase.
I need to identify specific event on the document in events object. For example
$(document).click(function () {
console.log(1)
});
$(document).click(function () {
console.log(2)
});
var events = $._data(document, "events");
console.log(events);
And when i log all "click" events, there are no difference between it:
How can i add custom ID to each events? Maybe i can use namespace or i can change guid?
I need to check: "is the specific event exist?"
You can bind and pass argument to the call-back listener to identify the type
$(document).click(function (type) {
console.log(type)
}.bind(this,"i-am-click"));
$(document).click(function (type) {
console.log(type)
}.bind(this,"i-am-another-click"));
var events = $._data(document, "events");
console.log(events);
UPDATE
To Identify the specific event object in yours events array you can do the following hack.
$(document).click(
(function(){
var fn = function(){ // Your callback function
console.log('i-am-click');
};
fn.event_id=1; // Adding id to the callback.
return fn; // returning the function after adding id
})()
);
$(document).click(
(function(){
var fn = function(){ // Your callback function
console.log('i-am-another-click');
};
fn.event_id=2; // Adding id to the callback.
return fn; // returning the callback function after adding id
})()
);
var events = $._data(document, "events");
// Find the events in the event array using filter
// This will return an array of match event with id in events array
events.click.filter(function(ev){return ev.handler.event_id==1;}); // event id you are looking for
You've clarified to say:
I want to know [if the]...event handler has been registered
Use a flag:
var handlersRegistered = {};
$(document).click(function() {
console.log("a");
});
handlersRegistered["a"] = true;
$(document).click(function() {
console.log("b");
});
handlersRegistered["b"] = true;
If at some point you need to know whether handler "a" was registered:
if (handlersRegistered["a"]) {
// Yes it is
} else {
// No, it isn't
}
No need to go mucking about in the internals of jQuery.
(I'm using handlersRegistered["a"] rather than handlersRegistered.a in case you want to use labels for these that aren't valid identifiers.)
well i'm confuse about the line witch says "$.Recup ..." I don't know why it is named the same as the plugin name and what it's for.
(function ($) {
$.fn.Recup = function () {
var parametros = {
};
var tsic = true;
$.Recup = function (opciones) {
var Metodos = {
};
return Metodos;
};
$.Recup.anterior = function () {
};
$.Recup.siguiente = function () {
}
})(jQuery);
I'm refering to this code, What does $.Recup exactly do?it would be perfect if someone gives me an example please
$.Recup = function (opciones) {
var Metodos = {
};
return Metodos;
};
In this case it appears to be a questionable plugin design - especially since $.Recup is not assigned until $.fn.Recup is first called.
However, if it is "appropriately and/or well written" is another question that requires context of (intended) usage. For what it is worth, I would reject this code as written as it smells of misunderstood design and widely scoped side-effects.
Anyway, the way the function is assigned determines how the method can be called.
// let $ be jQuery, then:
$.fn.foo = function () { console.log("foo") }
$.bar = function () { console.log("bar") }
$.foo() // TypeError: $.foo is not a function
$.bar() // -> "bar"
$("sel").foo() // -> "foo"
$("sel").bar() // TypeError: $(..).bar is not a function
That is, $.fn.foo is like .each() - it does something based on the currently selected elements (which are represented by this). On the other hand, $.bar is like jQuery.each() - it provides a way to iterate over a general collection but is not related to a specific set of (previously) selected elements.
In general, a plugin should only add a single entry to $.fn, but directly adding to $ may be useful to expose utility functions - it should definitely be done with care.
Here are two approaches that fix the issue of incorrectly leaked data:
$.fn.Recup = function () {
var parametros = ..
var tsic = true;
// Most trivial change; then use recup in this scope
// (or child scopes) only. There is no $.Recup - yay!
var recup = function (opciones) {
};
// ..
}
Or, just expose as local methods:
$.fn.Recup = function () {
var parametros = ..
var tsic = true;
function anterior () {
}
function siguiente () {
}
// Just use simple functions in scope
}
This is a jQuery plugin.
jQuery.fn is an alias to jQuery's prototype. So this line lets you call the Recup function on instances of jQuery :
$('#myid').Recup();
Here's the documentation on creating jQuery plugins.
The main reason why I want it is that I want to extend my initialize function.
Something like this:
// main.js
window.onload = init();
function init(){
doSomething();
}
// extend.js
function extends init(){
doSomethingHereToo();
}
So I want to extend a function like I extend a class in PHP.
And I would like to extend it from other files too, so for example I have the original init function in main.js and the extended function in extended.js.
With a wider view of what you're actually trying to do and the context in which you're doing it, I'm sure we could give you a better answer than the literal answer to your question.
But here's a literal answer:
If you're assigning these functions to some property somewhere, you can wrap the original function and put your replacement on the property instead:
// Original code in main.js
var theProperty = init;
function init(){
doSomething();
}
// Extending it by replacing and wrapping, in extended.js
theProperty = (function(old) {
function extendsInit() {
old();
doSomething();
}
return extendsInit;
})(theProperty);
If your functions aren't already on an object, you'd probably want to put them there to facilitate the above. For instance:
// In main.js
var MyLibrary = {
init: function init() {
}
};
// In extended.js
(function() {
var oldInit = MyLibrary.init;
MyLibrary.init = extendedInit;
function extendedInit() {
oldInit.call(MyLibrary); // Use #call in case `init` uses `this`
doSomething();
}
})();
But there are better ways to do that. Like for instance, providing a means of registering init functions.
// In main.js
var MyLibrary = (function() {
var initFunctions = [];
return {
init: function init() {
var fns = initFunctions;
initFunctions = undefined;
for (var index = 0; index < fns.length; ++index) {
try { fns[index](); } catch (e) { }
}
},
addInitFunction: function addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
}
}
};
})();
Here in 2020 (or really any time after ~2016), that can be written a bit more compactly:
// In main.js
const MyLibrary = (() => {
let initFunctions = [];
return {
init() {
const fns = initFunctions;
initFunctions = undefined;
for (const fn of fns) {
try { fn(); } catch (e) { }
}
},
addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
// Or: `Promise.resolve().then(() => fn());`
// (Not `.then(fn)` just to avoid passing it an argument)
}
}
};
})();
There are several ways to go about this, it depends what your purpose is, if you just want to execute the function as well and in the same context, you can use .apply():
function init(){
doSomething();
}
function myFunc(){
init.apply(this, arguments);
doSomethingHereToo();
}
If you want to replace it with a newer init, it'd look like this:
function init(){
doSomething();
}
//anytime later
var old_init = init;
init = function() {
old_init.apply(this, arguments);
doSomethingHereToo();
};
The other methods are great but they don't preserve any prototype functions attached to init. To get around that you can do the following (inspired by the post from Nick Craver).
(function () {
var old_prototype = init.prototype;
var old_init = init;
init = function () {
old_init.apply(this, arguments);
// Do something extra
};
init.prototype = old_prototype;
}) ();
Another option could be:
var initial = function() {
console.log( 'initial function!' );
}
var iWantToExecuteThisOneToo = function () {
console.log( 'the other function that i wanted to execute!' );
}
function extendFunction( oldOne, newOne ) {
return (function() {
oldOne();
newOne();
})();
}
var extendedFunction = extendFunction( initial, iWantToExecuteThisOneToo );
2017+ solution
The idea of function extensions comes from functional paradigm, which is natively supported since ES6:
function init(){
doSomething();
}
// extend.js
init = (f => u => { f(u)
doSomethingHereToo();
})(init);
init();
As per #TJCrowder's concern about stack dump, the browsers handle the situation much better today. If you save this code into test.html and run it, you get
test.html:3 Uncaught ReferenceError: doSomething is not defined
at init (test.html:3)
at test.html:8
at test.html:12
Line 12: the init call, Line 8: the init extension, Line 3: the undefined doSomething() call.
Note: Much respect to veteran T.J. Crowder, who kindly answered my question many years ago, when I was a newbie. After the years, I still remember the respectfull attitude and I try to follow the good example.
This is very simple and straight forward. Look at the code. Try to grasp the basic concept behind javascript extension.
First let us extend javascript function.
function Base(props) {
const _props = props
this.getProps = () => _props
// We can make method private by not binding it to this object.
// Hence it is not exposed when we return this.
const privateMethod = () => "do internal stuff"
return this
}
You can extend this function by creating child function in following way
function Child(props) {
const parent = Base(props)
this.getMessage = () => `Message is ${parent.getProps()}`;
// You can remove the line below to extend as in private inheritance,
// not exposing parent function properties and method.
this.prototype = parent
return this
}
Now you can use Child function as follows,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
We can also create Javascript Function by extending Javascript classes, like this.
class BaseClass {
constructor(props) {
this.props = props
// You can remove the line below to make getProps method private.
// As it will not be binded to this, but let it be
this.getProps = this.getProps.bind(this)
}
getProps() {
return this.props
}
}
Let us extend this class with Child function like this,
function Child(props) {
let parent = new BaseClass(props)
const getMessage = () => `Message is ${parent.getProps()}`;
return { ...parent, getMessage} // I have used spread operator.
}
Again you can use Child function as follows to get similar result,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
Javascript is very easy language. We can do almost anything. Happy JavaScripting... Hope I was able to give you an idea to use in your case.
as I understand it, you are trying to fetch the applications connected to the user account. You can do this by making a request on the API, I don't know if discord.js covers this part of the API
endpoint: https://discord.com/api/users/#me/connections
Request type: GET Header:
Authorization: "Beareryou token"
response: [
{...}
]
Use extendFunction.js
init = extendFunction(init, function(args) {
doSomethingHereToo();
});
But in your specific case, it's easier to extend the global onload function:
extendFunction('onload', function(args) {
doSomethingHereToo();
});
I actually really like your question, it's making me think about different use cases.
For javascript events, you really want to add and remove handlers - but for extendFunction, how could you later remove functionality? I could easily add a .revert method to extended functions, so init = init.revert() would return the original function. Obviously this could lead to some pretty bad code, but perhaps it lets you get something done without touching a foreign part of the codebase.