There are several elements on HTML page which triggers a js function HardCoded().
I cannot modify HardCoded() function.
I want to run some custom js code after the HardCoded() function is getting called. How can I do that? Is there any handlers for js functions?
I'm building a chrome extension that's why I cannot modify page source code.
I have access to JQuery.
One way is to find all elements who are calling HardCoded() and attach events to those elements but I would like to avoid this method.
You could do something like this:
var oldFn = HardCoded;
window.HardCoded = function(){
var res = oldFn.apply(this, arguments);
// New Code ....
return res;
}
What this does is to create a reference to the HardCoded function, redefine this function and then call the old implementation using the previously created reference.
Related
Can I retrieve and modify a previously assigned event function?
For example I originally add an onclick event handler to a node, like this :
var someNode = document.getElementByID('someNode');
someNode.onclick = function(){
//some stuff
};
Ideally later I would need to get back this event and modify the "some stuff" code content.
Is it doable in javascript?
You can modify the onclick event. Simply assign that to a new function will do. However, similar to most dynamic languages, function is not a data structure that you can easily modify. So keeping the same function but modifying it is AFAIK impossible.
The way I would suggest is to create a new function for your use, and assign it to the onclick property. However, JS is a very nice language that provide closure to your variables. So you can make a function that return a function to fit your need if you need some flexibility.
It's not really clear what you are trying to accomplish. But do you mean something like that ?
var someNode = document.getElementByID('someNode');
let customizablePart = function (e) {
// do some stuff
}
someNode.onclick = function (e) {
// unchangeable instructions
customizablePart.call(this, e)
}
// later ...
customizablePart = function (e) {
// do new stuff
}
What's the best way of unbinding event handlers in the destroy method of a plain JS plugin? The following (non working) code shall demonstrate what I mean:
var myPlugin = (function(){
function myPlugin(selector){
var elems = document.querySelectorAll(selector);
for (var i=0; i<elems.length; i++) {
function _handler(){ console.log('Hello'); }
elems[i].addEventListener("click", _handler);
}
this.destroy = function(){
document.removeEventListener("click", _handler);
};
}
return myPlugin;
})();
So, I iterate over a set of elements and do something with them, including attaching an event handler function. The problem: In plain JS, I need a reference to the original handler in order to remove it when the plugin instance gets destroyed.
This snippet naturally cannot work, because the event handler function is written over and over again with each selected element.
One way of handling this: Creating functions with a dynamic/unique name, as described here: Creating functions dynamically in JS.
The function needs to be globally set on the window object. Then, I just need to remember the name (e.g. by using a data attribute on the selected element) and with that, it's possible to unbind the event later on.
However, this approach is clumsy and I run into issues on IE8, when using such function with attachEvent. Is there a better way or any best practice for that?
After discovering about Javascript namespaces, I tried to implement them but I run into a problem while trying to attach a namespace method to an element's onclick.
I used this method to wrap up my functions/methods/classes (a simplified concept, not my actual code):
;(function(window, undefined) {
//my namespace
var NS = {};
NS.test = {
f : function(param) {
alert(param);
}
}
NS.test.('test 2');
})(window);
Inside, everything works fine and "test 2" is prompted.
However, when I try to attach that function to a click event, by doing something like this:
<a href-"#" onclick="NS.test.f('test');">Click me!</a>
it doesn't work, just like it doesn't work when I call that function after the })(window); part.
I tried it calling it window.NS.test.f('test'); but with no effect.
How can I make an onclick event call my function?
I could attach an event listener inside my wrapper, like I do for other html elements with no difficulty, but it would be problematic in this case since I'm generating the links with javascript and I find it easier and simpler to just add onclick="doSomething" for all my links, instead of creating them, then cache them and add event listeners.
Call me lazy, but in this particular case I prefer to do
someDiv.innerHTML = my_Generated_Html_Code_With_OnClick;
instead of
//demo code, ignore the flaws and the fact it won't work on IE
someDiv.innerHTML = my_generated_Html_code;
myLink = document.getElementById(id);
myLink.addEventListener('mousedown', NS.test.f('test'));
I do not use any framework nor do I wish to, since I'm trying to get a better understanding of the so-called vanilla javascript first.
I set up a jsfiddle here.
P.S. I must admit I didn't understand namespaces completely so if I'm doing something wrong here or applying the concept in a way I am not supposed to, I would appreciate any tips or corrections
That's because NS is declared inside and hence only exists inside the function:
function(window, undefined) {
var NS = {};
// NS exists here ...
}
// ... but not here
If you want to make it available to the rest of the page, then you can do:
function(window, undefined) {
var NS = window.NS = {};
// NS and window.NS exist here ...
}
// ... and window.NS exists here.
Wondering if there is an elegant way to listen for a function in JavaScript and/or jQuery.
Rather than listening for a $('#mything').click(function(){ //blah }) I'd like to listen for when a specific function is fired off. I don't want to edit the function as it's within a library that I don't want to hack directly.
I did find this: http://plugins.jquery.com/project/jqConnect which connects functions.
But wondering about a better technique.
The only way to do this is to override the function (ie, hack the library):
(function() {
var oldVersion = someLibrary.someFunction;
someLibrary.someFunction = function() {
// do some stuff
var result = oldVersion.apply(this, arguments);
// do some more stuff
return result;
};
})();
Edit: To run your code after the library function has run, just call the library function first, storing the result in a variable. Then, run your code, and finally return the previously stored result. I've updated my example above to accomodate running code either before or after the library function.
UPDATE: The back-end service was powered by an ASP.Net AJAX Web Service proxy.
1) The main page has two global objects, one for the back end connections (Svc) and another for handling the DOM (Main). It also dynamically loads documents into an iframe.
2) These iframes need to access services provided by Svc, and also supply a callback function.
3) The problem - passing a function created in the iframe to the parent frame, it's treated as an object not a function and cannot be invoked.
Can anyone provide a better solution than what I've got currently in the iframe:
var Main = parent.Main,
Svc = parent.Svc;
Svc.method(data, Main.createCallback(
function(response) {}
));
and in the parent frame:
Main.createCallback = function(func) {
return function() {
func.apply(func, arguments);
}
}
if you override the iFrame's function from the main, the main scope will then be used.
The inverse problem can be seen here, in your case, you just override the frame's function itself i.e:
document.getElementById('yourFrameID').contentWindow.targetFunctionInFrame = targetFunctionInMain;
Bonus: if you can modify the iFrame's code, I would suggest to:
In the frame:
make a placeholder function callbackParent() {}
add a call to this function into your iframe code, so that you just have to override the callbackParent from your main.
In the main:
make the function which should be invoked function doStuff() {}
override the function as described above document.getElementById('yourFrameID').contentWindow.callBackParent = doStuff;
I use iframes to modularize my app too.They are a kind of includes embedding all CSS, HTML and JS for a module.
My first attempts were by returning a function too, but then I found it quite hard for sharing scopes.
Now I make directly a reference to the main parent object in the iframe.
eg:
var Svc = parent.Svc, JSON = parent.JSON, $ = parent.$;
Svc.module1 = {
method1:function(arg){
...
},
...
}
The global var JSON and jQuery references are here to have them available inside the methods.
My guest is that Svc.method is making some checks to see if the callback has some criteria before calling it. This criteria might be that the callback function must created by the same framework (here it's ASP.Net). You have to find what that criteria is. if "Main.createCallback" works, it's because it's meeting that criteria.
Sorry but your all wrong... add this....
const event = new CustomEvent('MSGSent', { detail: "fff variable" });
Call it like this....use a global variable for detail... like an array []
window.dispatchEvent(event);
Now after the iframe loads add this code and you get an Object back in the main page....
iframe.onload = function() {
try {
iframe.contentWindow.addEventListener('MSGSent',function(e){
alert(e.detail);
});
} catch (error) {
}
};
The problem is ASP.Net AJAX Web Service proxies, which don't appear to support calling the web service from an iframe with an inline callback function.