Add console.profile statements to JavaScript/jQuery code on the fly - javascript

We have a thick client app using jQuery heavily and want to profile the performance of the code using firebug's console.profile API. The problem is, I don't want to change the code to write the profile statements. Take this example:
var search=function(){
this.init=function(){
console.log('init');
}
this.ajax=function(){
console.log('ajax');
//make ajax call using $.ajax and do some DOM manipulations here..
}
this.cache=function(){
console.log('cache');
}
}
var instance=new search();
instance.ajax();
I want to profile my instance.ajax method, but I dont want to add profile statements in the code, as that makes it difficult to maintain the code.
I'm trying to override the methods using closures, like this: http://www.novogeek.com/post/2010/02/27/Overriding-jQueryJavaScript-functions-using-closures.aspx but am not very sure how I can achieve. Any pointers on this? I think this would help many big projects to profile the code easily without a big change in code.
Here is the idea. Just run the below code in firebug console, to know what I'm trying to achieve.
var search=function(){
this.init=function(){
console.log('init');
}
this.ajax=function(){
console.log('ajax');
//make ajax call using $.ajax and do some DOM manipulations here..
}
this.cache=function(){
console.log('cache');
}
}
var instance=new search();
$.each(instance, function(functionName, functionBody){
(function(){
var dup=functionBody
functionBody=function(){
console.log('modifying the old function: ',functionName);
console.profile(functionName);
dup.apply(this,arguments);
console.profileEnd(functionName);
}
})();
console.log(functionName, '::', functionBody());
});
Now what I need is, if i say instance.ajax(), I want the new ajax() method to be called, along with the console.profile statements. Hope I'm clear with the requirement. Please improvise the above code.
Regards,
Krishna,
http://www.novogeek.com

If you only want to modify the single instance of "search" then this should work:
$.each(instance, function(name, method){
if (typeof method !== 'function') return;
instance[name] = function() {
console.profile(name);
var ret = method.apply(this, arguments);
console.profileEnd(name);
return ret;
};
});

I know this is from a long time ago but I wanted to add this in case other people find this answer. You can make anonymous/private functions work by adding a name to each one. The other comments mention doing it manually bit I wanted to explain how to:
$('.stuff').each(function() { ... });
to
$('.stuff').each(function workOnStuff() { ... });

Related

Jquery plugin to work on multiple elements

I've been developing a simple plugin for jquery, I have managed to get it to work perfectly for singular elements but I can't get it to work for use on more than one element on a page.
How do I construct the function to work on multiple elements?
Here's my construct, its really basic.
(function($){
$.fn.pluginName= function(prop){
var params = $.extend({
// param default set here
},prop);
// functions added here
return this;
}
})(jQuery);
This works fine for a singular use on page but if I wanted to make this work for multiple elements how would I do that?
The function is meant to change input fields so would need to work for multiple instances on a page.
I tried adding a this.each(function(){ ... }) to wrap around main content but this returned the same result.
Any help would be greatly appreciated as I'm not sure where to go with this and other tutorials will make me strip out the entire code and start again.
Thanks
EDIT
I've edited my code, I can not get the function to call through.
(function($){
$.fn.colorChange= function(params){
var defaults= {
backgroundColor: 'red'
};
var params = $.extend(defaults, params);
return this.each(function(){
changeColor();
function changeColor(defaults){
$(this).css({
'background-color' : defaults.backgroundColor
});
}
});
}
})(jQuery);
If I don't wrap this in a function and just create it as an anonymous function it works fine. However I intend to have many functions and the code could get a bit sloppy.
For some reason this is not working, any help?

autoload function vs json object is javascript

I was thinking about what is best for my JavaScript code.
I have a HTML page that contains some forms. So I bring life to it with JavaScript here we go.
I was thinking about what the best way to exploit my JavaScript code.
First to create a JSON object that has all attributes and methods I need.
For example
var myObject={
menuBtn: null,
init: function(){
$(document).ready(function(){
/* the code will be executed after the load */
});
},
listenToMenuButton: function(){
/* add a listener to the button */
}
};
myObject.init(); // to start working
or instead of that
(function($){
var me = this;
me.menuBtn = null;
me.listenToMenuButton = function(){
/* add a listener to the button */
};
me.init=function(){
/* code to init all elements */
};
})(jQuery);
Can any one advise me what is best and what are the advantages (of the two approaches)?
For example I know that the first implementation allows me to call a method as many times as I want. But the drawback of it is that the user can do some hack on it and call it (from firebug for example) and apply a behavior that was a fake one/
And when should I develop an extension (jQuery)?
I hope you guys can help me to design well my code.
I understand how you feel. I felt like that for a long time until I found this:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/

Prevent function from re-rendering template

Solved.
It turned out to be something else completely.
Thanks for everyone that tried to help, you guys rule!
I'll take a guess here but would need to see your code to make sure I'm giving you a good answer :-). You can't prevent a reactive data source from triggering an invalidation, but you can run some code in a nonreactive callback to make sure that code is NOT rerun.
Here are two examples to illustrate what's happening.
Template.myTemplate.helpers({
post: function () {
var someReactiveVar = Session.get('value');
return Posts.findOne({_id: 5});
}
});
In the above example, a change to post 5, or to Session's value will trigger the template to re-run. Let's say we want the template to re-run only for changes to the post, but not for the session variable. We could do this:
Template.myTemplate.helpers({
post: function () {
var someNonReactiveVar = Deps.nonreactive(function () { return Session.get('value'); });
return Post.findOne({_id: 5});
}
});
Now, just because we call Session.set('value', 'some other value') the template will not be re-run because we wrapped the get call inside a Deps.nonreactive callback.
Have you seen the answer to this question? Sounds like what you are looking for
Meteor.js - temporarily prevent a template from re-rendering (disable reactivity)

How do i execute a callback in a jQuery Plugin code

This may sound really like a newbie .. But i used the jQuery Boilerplate on this page - http://stefangabos.ro/jquery/jquery-plugin-boilerplate-revisited/ and created a plugin. Everything works fine, except now i want to add a callback. I want to execute this -
$.Alerter({'message':'this is a test','onSuccess':function(data) { alert(data); } });
The onSuccess is a callback function which is added to the defaults.
My question is – how do i send the output to the onSuccess. I want it to return back a TRUE or FALSE value after certain steps have been executed in the init()
Something like this:
plugin.result = null;
plugin.init = function() {
// do stuff
...
// save _result in public variable result
plugin.result = _result;
}
If you are writing this plugin for dom operations, you could also use it like plugin.data('result',_result);
Since I don't know anything else I can't give further insight.
Hope this will help you.

How to 'queue' piece of code in javascript

I've made a class that, when initialized, starts to download a JSON file.
However, the downloading runs asynchronously.
So after I declare it I start working with it, but it fails because it hasn't loaded the file yet.
I could turn async off, but is there another way without freezing the browser?
I'm currently working around it with a setTimeout option, but that seems like an ugly hack.
var d;
$(document).ready(function() {
d = new Duk('element');
d.getBlueprint('hud.json');
setTimeout(start, '2000');
});
function start(){
test = new d.Dialog(d.blueprint.screens.test);
test.draw();
}
You have to attach event handler to the object load completion event. The library you are working with must supply this event. I don't know what a Duk is, or what getBlueprint() does, but you should check the documentation for whatever that class and method is, and see if there is an oncomplete callback. If there is, you'd do something like this:
$(document).ready(function() {
d = new Duk('element');
d.getBlueprint('hud.json', {
onComplete: function() {
test = new d.Dialog(d.blueprint.screens.test);
test.draw();
}
});
});
Obviously, I just made that up. I don't know if your library has an onComplete method defined like this, but I hope you see what I mean. Without knowing more about the library you are using, I can't give a better example.
Timeouts are not the way to solve this problem.
You want to set up a callback function alongside the request so that the object handling the request knows what to do when the response comes in.
It is unclear from your code what framework you're using (I can't make any sense of getBlueprint, which seems to be the call that initializes the remote request), so if you could provide more information on this, we can provide more customized help.
You want your getBlueprint() method to be able to accept a callback which is run when the file is finished downloading.
function getBlueprint(file, callback)
{
// do whatever to get the file
// ...
// trigger the callback
callback();
}
$(document).ready(function() {
var d;
function start(){
test = new d.Dialog(d.blueprint.screens.test);
test.draw();
}
d = new Duk('element');
d.getBlueprint('hud.json', start);
setTimeout(start, '2000');
});
I agree that a callback function is the proper way. If this is code you cannot modify, you can do something like this, but seriously, use a callback!
function wait_for_load(expr, func)
{
var interval = window.setInterval(function()
{
if(eval(expr))
{
window.clearInterval(interval);
func();
}
}, 20);
}
var d;
$(document).ready(function() {
d = new Duk('element');
d.getBlueprint('hud.json');
wait_for_load('d.blueprint', start);
});

Categories

Resources