How to redefine JS function keeping previous in chain - javascript

This is common task coming from object oriented programming, I would like to change behavior of JavaScript program by overriding existing function with possible calling it as well. I remember Windows introduced that as writing hooks and chaining them. So what I want, I have a web page which calls some onload hook which finally calls function initFields. I want to redefine this function however keep previous implementation. If I simply define my JS function as
function initFields() {
// do some stuff ...
// I do not know how to call super.initFields() here
}
I read something like you can write
initFields.prototype = function() {
// do some stuff ...
// but still have no idea how to call the original one
};
Can somebody help?

One option is
var initFieldsInitial = initFields;
function initFields() {
// your stuff
initFieldsInitial.apply(this, arguments);
}

You could try the wrap() function from the underscore.js library.
http://documentcloud.github.com/underscore/#wrap
var initFields = function() {
// do something
console.log('initFields');
}
initFields = _.wrap(initFields, function(initial) {
// do some stuff
console.log('wrapper');
initial();
});
$(document).ready(function() {
initFields();
});

Related

Doing a function when another one has loaded using JQuery

I have two functions that I want to load them one by one. They are like this:
<script>
//first function
load_ajax_select(id);
//second fucntion
fadeIn_that_div();
</script>
I want to know how the second function can be done after the first one has loaded.
Thanks.
Let's assume that load_ajax_select looks something like this:
function load_ajax_select() {
$.get("/some/url", function(stuff) {
$("some selector").html(stuff);
});
}
or
function load_ajax_select() {
$("some selector").load("/some/url");
}
or similar, probably with some other logic. In order for it to make it possible for other things to get notification when it's done, the most flexible thing it can do is return a promise. Depending on what it does, it may be simplest to return the promise it already has from the $.get:
function load_ajax_select() {
return $.get("/some/url", function(stuff) {
$("some selector").html(stuff);
});
}
...or sometimes it's useful to create your own:
function load_ajax_select() {
var d = $.Deferred();
$("some selector").load("/some/url", function() {
d.resolve();
});
return d.promise();
}
...although normally if you have one already, creating your own is an anti-pattern.
Code that doesn't care about knowing when the result occurs can just ignore the return value. But your code that needs to know can use it:
load_ajax_select().then(fadeIn_that_div);
or sometimes you may need
load_ajax_select().then(function() { fadeIn_that_div(); });
...if for some reason you can't call fadeIn_that_div directly via then.

call vs passing object in javascript

ive been using call a bit recently in some tutorials I've been following but am more used to passing the object. I was wondering is it best to use call. What's the most efficient way?
var editor = function(someParam){
//do something with this
}
var testFunction function(someParam){
editor.call(this, someParam);
}
or
var editor = function(obj, someParam){
var self = obj;
}
var testFunction function(someParam){
editor(this, someParam);
}
I would stick with passing the object to the function as long as you can structure the function that way.
I see call more like a utility if the function cannot be changed anymore and you really have to inject a different this context.
Also, consider using the prototype approach if your function is bound very close to some object that you want to call the function on.
Also, call will be less performant than passing the object to the function, as the injection of a different this has some overhead.
In some cases call is very useful, for example when adding event handler:
window.addEventListener('load', function(){
var cb = document.getElementById('myCheckBox');
cb.addEventListener('change', onchange);
onchange.call(cb); // sets `cb` as `this` in `onchange` function
});
function onchange(){
// I'm using 'this' for current element
if(this.checked)
alert('checked');
}
In this case onchange will be called on window load and every time checkbox checked state changes

Function listener in JavaScript and/or jQuery

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.

How to call a function when a function execution is completed? - Javascript

I am working with a user control that has set of javascript functions that are called when an action is performed. This user control is used in a lot of places in the application.
When one of the inbuilt JS function completes execution, I need to fire a custom JS function on my page.
Is there a way for me to attach a function to be fired when another function completes execution? I don't want to update the inbuilt JS function to call this page JS function.
Hope this makes sense.
There are a couple design patterns you could use for this depending upon the specific code (which you have not shared) and what you can and cannot change:
Option 1: Add a callback to some existing code:
function mainFunction(callbackWhenDone) {
// do other stuff here
callbackWhenDone();
}
So, you can call this with:
mainFunction(myFunction);
Option 2: Wrap previous function:
obj.oldMethod = obj.mainFunction;
obj.mainFunction = function() {
this.oldMethod.apply(this, arguments);
// call your stuff here after executing the old method
myFunction();
}
So, now anytime someone does:
obj.mainFunction();
it will call the original method and then call your function.
You're basically trying to do callbacks. Since you're not mentioning what functions you're talking about (as in code), the best thing to do would be basically to wrap the function, -quick and dirty- and make it work with callbacks.
That way you can pass it a Lambda (Anonymous Function) and execute anything you want when it's done.
Updated to demonstrate how to add Callbacks:
function my_function($a, $callback) {
alert($a);
$callback();
}
my_function('argument', function() {
alert('Completed');
});
The ugliest and best solution is to monkey-patch the built-in function. Assume the built-in function is called "thirdParty":
// first, store a ref to the original
var copyOfThirdParty = thirdParty;
// then, redefine it
var thirdParty = function() {
// call the original first (passing any necessary args on through)
copyOfThirdParty.apply(this, arguments);
// then do whatever you want when it's done;
// custom code goes here
customFunction();
};
We've essentially created a modified version of the built-in function without ever touching the original version.
Since Javascript is highly dynamic you can modify the original function without modifying its source code:
function connect_after(before, after){
return function(){
before.apply(this, arguments);
after();
};
}
var original_function = function(){ console.log(1); }
original_function = connect_after(original_function, function(){ console.log(2); })

Binding anonymous functions all over the place

I generally write code that looks like this (but with many more handlers).
$(document).ready(function() {
$("#next").click(function() {
doStuff();
});
$("#prev").click(function() {
doSomeOtherStuff();
});
$("#link").hover(function() {
doSomeTotallyOtherStuff();
});
});
Is this the best way of doing this? Should I do it differently? Paul Irish's presentation suggests it's a bad idea. Is that true?
We like to use the object literal pattern and named functions. I'd rewrite your example like this:
$(function() {
Example.somegrouping.init();
});
var Example.somegrouping = {
init: function() {
// set up listeners
$("#next").click(this.onNextClick);
$("#prev").click(this.onPrevClick);
$("#link").hover(this.onLinkHover);
},
onNextClick: function() {
// do some stuff
},
onPrevClick: function() {
// do some stuff
},
onLinkHover: function() {
// do some stuff
}
};
Why? Well, it makes it easier to reuse event handlers in other places without resorting to triggers. The naming of the function can help self-document your code. Testing/debugging is easier. The object literal only adds one entry to the global namespace, so there is little chance for collisions with other scripts your page might be using.
One reason that it's useful to define your functions the old boring way is that you get names to look at in stack traces.
$(function() {
function nextClickHandler() { ... };
$('#next-button').click(nextClickHandler);
});
It's not safe to use a function name in a function expression:
$('#next-button').click(function nextClickHandler() { // DO NOT DO THIS
});
which is sort-of unfortunate but there you go.
This should be fine as long you don't do it in a loop or some other code that runs more than once (i.e. a recurring function call). Otherwise there's not much difference between one anon function and one named function. it's when you have 100 identical anonymous functions that's a problem.
ex:
$("#someID").click(function(){})
is okay,
for (var i in somelistofIDs) {
$(i).click(function(){})
}
is not, because you've created 100 anonymous functions instead of one named function.
EDIT
of course, if you're wrapping a single function call in a closure, you're doing it wrong, you can just pass the function itself.

Categories

Resources