Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Monday, December 17, 2012

Overriding The Console Functions

The console functions are the most common functions that developers can use when developing and debugging a web application using JavaScript. Actually, the `console.log` function is the one to use when trying to find an annoying bug. Yet, the console object includes other functions that can help us to trace and debug operations in our applications.

The `console.warn` function can be used when we want to show a message in the console, just like the `console.log` function but with a warning sign next to it.

The `console.error` can be used to console an object with a message (in a red color), along with the message we get the stack trace, showing us where the error came from.

Other cool functions are the `console.time` and `console.timeEnd`. These functions allow us to measure a time frame between operations in order to find and make our algorithm more efficient.

You can explore the `console` object in order to find out about more cool functions inside.

In this post I will talk about how to override the console functions and preserved the original functionality. You asking why? Well, I'm glad you asked... :)

I'm currently working on a system that combines web and mobile clients, I will not go into details, but think about having a web application on a mobile device and you want to trace all the console.log's that comes from it, we all know that we can enable the console messages (known as 'developer mode') on the mobile side, however, it will be a bit annoying to read those messages on the mobile side. So, my goal is to catch every `console.log` call, send it to my Node.js/Socket.io server and transmit it to my desktop web application.
The simple way to achieve this task is to simply override the `console.log` function like so:

console.log = function() {
    //send data to server...
}

When using this process, I can send the data to my server every time `console.log` is called on the mobile web application. But what if I want to preserve the original action of the `console.log` function? I don't want to destroy the real function, just to add some functionality into it.

This is the correct way to override and preserve the `console.log` functionality:

(function(){
    //saving the original console.log function
    var preservedConsoleLog = console.log;

    //overriding console.log function
    console.log = function() {

        //we can't just call to `preservedConsoleLog` function,
        //that will throw an error (TypeError: Illegal invocation)
        //because we need the function to be inside the
        //scope of the `console` object so we going to use the
        //`apply` function
        preservedConsoleLog.apply(console, arguments);

        //and lastly, my addition to the `console.log` function
        if(application.socket){
            application.socket.emit('console.log', arguments);
        }
    }
})();

Now you can take any function of the `console` object and override it in this way, add your functionality and achieve what you want.

Sunday, November 18, 2012

Extending jQuery functions

When developing with jQuery or any other JavaScript framework, sometimes we want to do more with the framework core functions. For example, many times, when I'm adding or removing a class to/from a jQuery element I want to call a function. If I'll call a function every time I'm adding or removing classes right after the addClass or removeClass it will be hard to maintain the code.

In this post I'll show how to expand jQuery core functions, as an example I will demonstrate how to add addClass and removeClass events to each jQuery element.

Let's start by creating a closure to avoid variable conflicts:
(function(){
    // code goes here...
})();

Now, before the core functions override, we need to save them in order to call them later inside the expanded function
(function(){
    // saving the core functions
    var coreAddClass = jQuery.fn.addClass;
    var coreRemoveClass = jQuery.fn.removeClass;
})();

Core functions saved, now we can override them
(function(){
    // saving the core functions
    var coreAddClass = jQuery.fn.addClass;
    var coreRemoveClass = jQuery.fn.removeClass;

    // overriding the addClass function
    jQuery.fn.addClass = function(){

    }

    // overriding the removeClass function
    jQuery.fn.removeClass = function(){

    }
})();

If you will run the code we wrote so far and try to $().addClass() or $().removeClass() nothing will happen. The next step is to add our new logic to the functions and then to call the core functions so we will keep the original behaviors
(function(){
    // saving the core functions
    var coreAddClass = jQuery.fn.addClass;
    var coreRemoveClass = jQuery.fn.removeClass;

    // overriding the addClass function
    jQuery.fn.addClass = function(){
        // every time the addClass function is called
        // for this $element, trigger the addClass event
        $(this).trigger('addClass', arguments);

        // calling the core function
        coreAddClass.apply(this, arguments);
    }

    // overriding the removeClass function
    jQuery.fn.removeClass = function(){
        // every time the removeClass function is called
        // for this $element, trigger the removeClass event
        $(this).trigger('removeClass', arguments);

        // calling the core function
        coreRemoveClass.apply(this, arguments);
    }
})();

By applying the core function at the end of the function we are able to keep the original behavior of the core.

Simple client to test the code:
<!DOCTYPE html>
<html>
    <head>
        <title></title>
  
        <script type="text/javascript" src="jquery.min.js"></script>
        <script type="text/javascript" src="jquery.events.js"></script>
        <script type="text/javascript">
            $(function(){

                // add event listener to the element addClass event
                $('.cube').on('addClass', function(e, className){
                    console.log(e);
                    console.log(className);
                });

                // add event listener to the element removeClass event
                $('.cube').on('removeClass', function(e, className){
                    console.log(e);
                    console.log(className);
                });
    
                $('button').on('click', function(){
                    // toggle a class on the element, the events are fired
                    $('.cube').toggleClass('color');
                });
            });
        </script>
  
        <style type="text/css">
            .cube{width:100px;height:100px;background:yellow;}
            .color{background:red !important;}
        </style>
    </head>
    <body>
        <div class="cube"></div>
        <button>toggle red</button>
    </body>
</html>