0

I am trying to use web dev tools to inspect the java script on web pages, but I am finding it difficult to see which sections of a site are using JS.

It is not like with CSS or HTML where you can see each section that a site uses these languages.

When I do manage to find any JS, I try deleting some of it, but it does not seem to alter the functionality of the site (not like when you change the CSS or HTML.)

Are there any easy ways to detect, extract, test, and evaluate a site's javascript, and to see which section of the site is using a particular script?

Here is a specific example:

There is a site with a jquery library called jquery.parallax: http://stephband.info/jparallax/

When you inspect the html and css of the image, you get:

<div class="parallax-viewport" id="parallax">

        <!-- parallax layers -->
        <div class="parallax-layer" style="width: 860px; height: 273px; top: 77.08854166666667%; margin-top: -210.45171875px; left: 0%; margin-left: 0px;">
            <img src="images/parallax_sketch/0_sun.png" alt="" style="position:absolute; left:300px; top:-12px;">
        </div>
        <div class="parallax-layer" style="width: 920px; height: 274px; top: 77.08854166666667%; margin-top: -211.22260416666666px; left: 0%; margin-left: 0px;">
            <img src="images/parallax_sketch/1_mountains.png" alt="">
        </div>
        <div class="parallax-layer" style="width: 1100px; height: 284px; top: 77.08854166666667%; margin-top: -218.93145833333332px; left: 0%; margin-left: 0px;">
            <img src="images/parallax_sketch/2_hill.png" alt="" style="position:absolute; top:40px; left:0;">
        </div>
        <div class="parallax-layer" style="width: 1360px; height: 320px; top: 77.08854166666667%; margin-top: -246.68333333333334px; left: 0%; margin-left: 0px;">
            <img src="images/parallax_sketch/3_wood.png" alt="" style="position:absolute; top:96px; left:0;">
        </div>

        <!-- Rounded corners -->
        <img src="http://stephband.info/images/corner_white_tl.png" class="tl">
        <img src="http://stephband.info/images/corner_white_tr.png" class="tr">
        <img src="http://stephband.info/images/corner_white_bl.png" class="bl">
        <img src="http://stephband.info/images/corner_white_br.png" class="br">
    </div

**OK, now there is a specific jquery file that controls the parallax function:**

// jquery.jparallax.js
// 1.0
// Stephen Band
//
// Project and documentation site:
// webdev.stephband.info/jparallax/
//
// Repository:
// github.com/stephband/jparallax
//
// Dependencies:
// jquery.event.frame
// webdev.stephband.info/events/frame/

(function(jQuery, undefined) {

    // Plugin name
    var plugin = "parallax";

    // VAR

    var options = {
            mouseport:  'body',    // jQuery object or selector of DOM node to use as mouse detector
            xparallax:  true,      // boolean | 0-1 | 'npx' | 'n%' - Sets axis of reaction and by how much they react
            yparallax:  true,      //
            xorigin:        0.5,       // 0-1 - Sets default alignment. Only has effect when parallax values are something other than 1 (or true, or '100%')
            yorigin:        0.5,       //
            decay:          0.66,      // 0-1 (0 instant, 1 forever) - Sets rate of decay curve for catching up with target mouse position
            frameDuration:  30,    // Int (milliseconds)
            freezeClass:    'freeze' // String - Class added to layer when frozen
        },

        value = {
            left: 0,
            top: 0,
            middle: 0.5,
            center: 0.5,
            right: 1,
            bottom: 1
        },

        regex = {
            px:         /^\d+\s?px$/,
            percent:    /^\d+\s?%$/
        },

        frameEvent = 'frame.'+plugin,

        abs = Math.abs,

        pointer = [0, 0];

    // FUNCTIONS

    function parseValue(value) { return this.lib[value]; }
    parseValue.lib = value;

    // Converts numbers or numbers in strings to boolean
    function parseBool(x) {
        return typeof x === "boolean" ? x : !!( parseFloat(x) ) ;
    }

    function parseCoord(x) {
        return (regex.percent.exec(x)) ? parseFloat(x)/100 : x;
    }

    // CONSTRUCTORS

    function Mouse(xparallax, yparallax, decay, pointer){

        // Convert parallax options to boolean values
        var parallax = [xparallax, yparallax];

        this.ontarget = false;
        this.decay = decay;
        this.pointer = pointer || [0.5, 0.5];
        this.update = function(pointer, threshold){
            var lagPointer, x;

            // Pointer is already on target
            if (this.ontarget) {
                this.pointer = pointer;
            }

            // Pointer has arrived within the target thresholds
            else if ((!parallax[0] || abs(pointer[0] - this.pointer[0]) < threshold[0]) &&
                    (!parallax[1] || abs(pointer[1] - this.pointer[1]) < threshold[1])) {
                this.ontarget = true;
                this.pointer = pointer;
            }

            // Pointer is nowhere near the target
            else {
                lagPointer = [];
                x = 2;

                while (x--) {
                    if ( parallax[x] ) {
                        lagPointer[x] = pointer[x] + this.decay * (this.pointer[x] - pointer[x]);
                    }
                }

                this.pointer = lagPointer;
            }
        };
    }

    function Port(object, options){
        var self = this,
            elem = object instanceof jQuery ? object : jQuery(object) ,
            // Convert parallax options to boolean values
            parallax = [parseBool(options.xparallax), parseBool(options.yparallax)],
            // State of mouse position (0 - outside, 1 - inside, 2 - just gone outside)
            inside = 0,
            // Stores mouse position on mouseleave event
            leaveCoords;

        this.pointer = [0, 0];
        this.active = false;
        this.activeOutside = (options && options.activeOutside) || false;
        this.update = function(coords){
            var pos = this.pos,
                size = this.size,
                pointer = [],
                x = 2;

            // Is mouse inside port?
            // Yes.
            if ( inside > 0 ) {
                // But it just went outside, so make this the last move
                // Use leaveCoords stored by mouseleave event
                if ( inside === 2 ) {
                    inside = 0;
                    if (leaveCoords) {
                        coords = leaveCoords
                    };
                }

                while (x--) {
                    if ( parallax[x] ) {
                        pointer[x] = (coords[x] - pos[x]) / size[x] ;
                        pointer[x] = pointer[x] < 0 ? 0 : pointer[x] > 1 ? 1 : pointer[x] ;
                    }
                }

                this.active = true;
                this.pointer = pointer;
            }
            // No.
            else {
                this.active = false;
            }
        };
        this.updateSize = function(){
            var width = elem.width(),
                height = elem.height();

            self.size = [width, height];
            self.threshold = [ 1/width, 1/height ];
        };
        this.updatePos = function(){
            var offset = elem.offset() || {left: 0, top: 0},
                left = parseInt(elem.css('borderLeftWidth')) + parseInt(elem.css('paddingLeft')),
                top = parseInt(elem.css('borderTopWidth')) + parseInt(elem.css('paddingTop'));

            self.pos = [offset.left + left, offset.top + top];
        };

        // Update mouseport dimensions on window resize
        jQuery(window)
        .bind('resize.'+plugin, self.updateSize)
        .bind('resize.'+plugin, self.updatePos);

        // Detect entry and exit of mouse
        elem
        .bind('mouseenter.'+plugin, function(e){
            inside = 1;
        })
        .bind('mouseleave.'+plugin, function(e){
            inside = 2;
            leaveCoords = [e.pageX, e.pageY];
        });

        // Set up layer
        this.updateSize();
        this.updatePos();
    }

    function Layer(elem, options){
        var px = [],
            parallax = [],
            offset = [],
            position = [];

        this.update = function(pointer){
            var pos = [],
                cssPosition,
                cssMargin,
                x = 2,
                css = {};

            while (x--) {
                if ( parallax[x] ) {
                    pos[x] = parallax[x] * pointer[x] + offset[x];

                    // We're working in pixels
                    if ( px[x] ) {
                        cssPosition = position[x];
                        cssMargin = pos[x] * -1;
                    }
                    // We're working by ratio
                    else {
                        cssPosition = pos[x] * 100 + '%';
                        cssMargin = pos[x] * this.size[x] * -1;
                    }

                    // Fill in css object
                    if ( x === 0 ) {
                        css.left = cssPosition;
                        css.marginLeft = cssMargin;
                    }
                    else {
                        css.top = cssPosition;
                        css.marginTop = cssMargin;
                    }
                }
            }

            // Set css
            elem.css(css);
        };

        this.setParallax = function(xp, yp, xo, yo){
            var p = [ xp || options.xparallax, yp || options.yparallax ],
                origin = [ xo || options.xorigin, yo || options.yorigin ],
                i = 2,
                css = {};

            while (i--) {
                // Set px flag
                px[i] = regex.px.test(p[i]);

                // Convert origin to numbers
                if (typeof origin[i] === 'string') {
                    origin[i] = origin[i] === undefined ? 1 :
                                value[ origin[i] ] || parseCoord(origin[i]) ;
                }

                // We're dealing with pixel dimensions
                if ( px[i] ) {
                    // Set parallax
                    parallax[i] = parseInt(p[i]);

                    // Set offset
                    offset[i] = origin[i] * ( this.size[i] - parallax[i] );

                    // Set css position constant
                    position[i] = origin[i] * 100 + '%';
                }

                // We're dealing with ratios
                else {
                    // Set parallax, converting to ratio where necessary
                    parallax[i] = p[i] === true ? 1 : parseCoord(p[i]);

                    // Set offset
                    offset[i] = parallax[i] ? origin[i] * ( 1 - parallax[i] ) : 0 ;
                }
            }
        };

        this.getPointer = function(){
            var viewport = elem.offsetParent(),
                pos = elem.position(),
                position = [],
                pointer = [],
                i = 2;

            // Reverse calculate ratio from layer's current position
            while (i--) {
                if ( px[i] ) {
                    // TODO: reverse calculation for pixel case
                    position[i] = 0;
                }
                else {
                    position[i] = pos[ i === 0 ? 'left' : 'top' ] / (viewport[ i === 0 ? 'outerWidth' : 'outerHeight' ]() - this.size[i]) ;
                }

                pointer[i] = (position[i] - offset[i]) / parallax[i] ;
            }

            return pointer;
        };

        this.setSize = function(x, y){
            this.size = [ x || elem.outerWidth(), y || elem.outerHeight() ];
        };

        this.setSize(options.width, options.height);
        this.setParallax(options.xparallax, options.yparallax, options.xorigin, options.yorigin);
    }

    // EVENT HANDLERS

    function update(e){

        var elem = jQuery(this),
            global = e.data.global || e.data,
            local = e.data.local || elem.data(plugin),
            port = global.port,
            mouse = global.mouse,
            localmouse = local.mouse,
            process = global.timeStamp !== e.timeStamp;

        // Global objects have yet to be processed for this frame
        if ( process ) {
            // Set timeStamp to current time
            global.timeStamp = e.timeStamp;

            // Process mouseport
            port.update(pointer);

            // Process mouse
            if ( port.active || !mouse.ontarget ) {
                mouse.update(port.pointer, port.threshold);
            }
        }

        // Layer has it's own mouse
        if ( localmouse ) {

            // Process mouse
            localmouse.update( local.freeze ? local.freeze.pointer : port.pointer, port.threshold );

            // If it hits target
            if ( localmouse.ontarget ) {

                delete local.mouse;

                // Stop animating frozen layers
                if (local.freeze) {
                    elem
                    .unbind(frameEvent)
                    .addClass(global.freezeClass);
                }
            }

            // Use localmouse in place of mouse
            mouse = localmouse;
        }
        // Layer is responding to global mouse
        else {
            // When no longer active, unbind
            if ( mouse.ontarget && !port.active ) {
                elem.unbind(frameEvent);
            }
        }

        local.layer.update(mouse.pointer);
    }

    jQuery.fn[plugin] = function(o){
        var global = jQuery.extend({}, jQuery.fn[plugin].options, o),
            args = arguments,
            layers = this,
            optionsArray = [];

        if (undefined === jQuery.event.special.frame) {
            throw "jquery.parallax requires jquery.event.frame.";
        }

        // Turn mouseport into jQuery obj
        if ( !(global.mouseport instanceof jQuery) ) {
            global.mouseport = jQuery(global.mouseport); 
        }

        global.port = new Port(global.mouseport, global);
        global.mouse = new Mouse(parseBool(global.xparallax), parseBool(global.yparallax), global.decay);

        global.mouseport
        .bind("mouseenter", function(e){
            var i = layers.length,
                layer;

            global.mouse.ontarget = false;

            // Animate unfrozen layers
            while (i--) {
                layer = layers[i];

                if (!jQuery.data(layer, plugin).freeze) {
                    jQuery.event.add(this, frameEvent, update, {
                        global: global,
                        local: optionsArray[i]
                    });
                };
            }
        });

        return layers.each(function(i){
            var elem = jQuery(this),

                // Construct layer options from extra arguments
                layerOptions = args[i+1] ? jQuery.extend({}, global, args[i+1]) : global ,

                // Set up layer data. Give it a local mouse 
                // initialises it to start smoothly from current position
                layer = new Layer(elem, layerOptions),
                local = {
                    layer: layer,
                    mouse: new Mouse(parseBool(layerOptions.xparallax), parseBool(layerOptions.yparallax), layerOptions.decay, layer.getPointer())
                };

            elem.data(plugin, local);
            optionsArray.push(local);

            // Bind freeze and unfreeze actions directly to layers using
            // jQuery.event.add(node, type, fn, data)

            jQuery.event.add(this, 'freeze', function(e){
                var elem = jQuery(this),
                    global = e.data.global,
                    local = e.data.local,
                    mouse = local.mouse || local.freeze || global.mouse,
                    coords = coords = [
                        e.x === undefined ? mouse.pointer[0] : parseCoord(e.x),
                        e.y === undefined ? mouse.pointer[1] : parseCoord(e.y)
                    ],
                    decay = e.decay;

                // Store position
                local.freeze = { pointer: coords };

                // Create local mouse, passing in current pointer with options
                local.mouse = new Mouse(parseBool(global.xparallax), parseBool(global.yparallax), global.decay, mouse.pointer);

                if (decay !== undefined) { local.mouse.decay = decay; }

                // Start animating
                jQuery.event.add(this, frameEvent, update, global);
            }, {
                global: global,
                local: local
            });

            jQuery.event.add( this, 'unfreeze', function(e){
                var elem = jQuery(this),
                    global = e.data.global,
                    local = e.data.local,
                    decay = e.decay,
                    pointer;

                if (!local.freeze) { return; }

                // Create local mouse, passing local freeze pointer with options
                pointer = local.mouse ? local.mouse.pointer : local.freeze.pointer ;
                local.mouse = new Mouse(parseBool(global.xparallax), parseBool(global.yparallax), global);
                local.mouse.pointer = pointer;

                // Override decay with decay passed as e.decay
                if (decay !== undefined) local.mouse.decay = decay;

                // Destroy local.freeze
                delete local.freeze;

                // Remove freeze class and start animating
                elem.removeClass(options.freezeClass);

                // Start animating
                jQuery.event.add(this, frameEvent, update, global);
            }, {
                global: global,
                local: local
            });
        });
    };

    // EXPOSE

    jQuery.fn[plugin].options = options;

    // RUN

    jQuery(document).ready(function(){
        // Pick up and store mouse position on jQuery(document)
        // IE does not register mousemove on jQuery(window)
        jQuery(document)
        .mousemove(function(e){
            pointer = [e.pageX, e.pageY];
        });
    });

`enter code here`}(jQuery));

When I alter and delete the javascript, the parallax functionality does not go away! So what role does this particular javascript play on the image, if it is still fully functional without the javacript?

Edward K.
  • 67
  • 2
  • 9
  • 2
    It's not hard to see all scripts that are loaded in a given site to look at them. The "sources" tab in the Chrome debugger contains all scripts for a given page. I don't know what you mean by "detect, extract, test" beyond looking at the scripts or setting breakpoints in them to step through parts of them. – jfriend00 Apr 22 '15 at 07:30
  • I see the sources tab, and all the java script files, but the problem is, I am not detecting where these scripts are being used on the page. I would like to alter and test them, just like we can do with the CSS. When you edit the CSS, real time changes happen on the site. I'd like to see in real time changes happening with the java script, or at the very least, seeing on the page where each section of the site is using the JS. – Edward K. Apr 22 '15 at 07:40
  • I think @EdwardK. would like a system with a magnifying glass like the one used to inspect html/css. The fact that JavaScript isn't "visible", and can process wherever on the page make his "detection" hard. You have to understand the code used, I don't see any other way. – Anwar Apr 22 '15 at 07:46
  • @Zeratops Yes. For example there is a site I am looking at right now that has a slider function that uses JS. When I inspect the slider, I don't immediately see the javascript behind it. As a test, I tried deleting all the javascripts to see if it would stop sliding, but even when I delete the javascript the functionality is not lost, it kept sliding. – Edward K. Apr 22 '15 at 07:59
  • @EdwardK., slider Full CSS exists too ! – Anwar Apr 22 '15 at 08:00
  • But there is a JS file on the site that says "slider" and somehow it is connected, but when I try altering it, nothing changes. So I'd like to be able to see the functionality behind every java script with web developer tools. – Edward K. Apr 22 '15 at 08:03

1 Answers1

3

There are easy ways to see what scripts are present in a page. The sources tab in the Chrome debugger will show you all scripts that are presently loaded in a given document. Beyond seeing the scripts, the rest of what you're asking for isn't available in an easy, automated way. Understanding what scripts are doing or what scripts are influencing a piece of a page will involve study, understanding of the scripts, probably some breakpoints and debugging to trace program flow, etc...

I am trying to use web dev tools to inspect the java script on web pages, but I am finding it difficult to see which sections of a site are using JS.

Yes, understanding what JS is doing in a page is not a simple process. You have to study the code to fully understand it. If the scripts are large or spread out or use unfamiliar libraries, this can be a fair amount of work. It is ultimately doable, but is not a beginner task and while you can use tools such as debuggers, there are not tools that provide you automated answers.

It is not like with CSS or HTML where you can see each section that a site uses these languages.

Correct, it is not like those. Javascript is a full-fledged programming language and is is very different from CSS and HTML.

When I do manage to find any JS, I try deleting some of it, but it does not seem to alter the functionality of the site (not like when you change the CSS or HTML.)

Correct, Javascript doesn't work the same way as CSS or HTML and there are limitations in how much dynamic changing/reloading of Javascript can be done and some situations (such as live closures) where you can't really do it at all without reinitializing the page from scratch. Remember, Javascript has live run-time state that is the product of all the code that has run so far. You can't just replace the code with new code and keep the state you had.

You can, however, set breakpoints in the existing code and when the debugger stops at one of those breakpoints, you can inspect all variables within scope and you can even modify the values of those variables. You can also execute your own code in the console while stopped at a breakpoint.

Are there any easy ways to detect, extract, test, and evaluate a site's javascript, and to see which section of the site is using a particular script?

As was explained above, there are relatively easy ways to inspect the code of the various scripts active in a page. Beyond that, there are not easy ways to do any of the other things you ask for. They involve the hard work of studying the scripts and understanding what they do and how they do it.

Your question is very generic and you didn't specify any specific thing you're trying to diagnose or understand. That makes your question pretty open ended and harder to offer specific advise. If, for example, you wanted to find out what code executes when a button is pushed, there are techniques you can use to try to find the code that runs when a button is pushed. For example, most debuggers will show a list of event handlers that are attached to a particular DOM element. That may allow you to find the code that runs when those events occur. You could then study that code to try to figure out what it does.

But, even that isn't necessarily straightforward because the DOM supports event propagation and event delegation so event handlers for a given DOM item might be attached to a parent object, not necessarily to the actual object. And, if the code uses any sort of library (like jQuery), the event handling code will likely be some generic event handling function, not the code you want to see and it can be significantly more work to find out which code gets called by the generic event handler.

Ultimately, one skilled in the art of Javascript and Javascript debugging and the DOM can ultimately figure out everything that the code in a page does, but it can take a lot of time and some learning how to do this. It is an acquired skill learned through hours and hours and hours of practice and attempting to understand and figure out other people's code.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I'll have to use a specific example next time, I can't do it on here, not enough characters left. Thanks for the answer, it did touch on a lot of the things I was trying to figure out. – Edward K. Apr 22 '15 at 08:23
  • @EdwardK - you can use the "edit" link below your question to add more specifics to your question (where you can post longer things and format them) and then post a comment pointing out that you've updated your question. – jfriend00 Apr 22 '15 at 08:26
  • Ok this was the main issue I was having, I posted it up top with the code. – Edward K. Apr 22 '15 at 08:38
  • @EdwardK. - OK, now you've narrowed it down to a block of code. What exactly is your question about that code? – jfriend00 Apr 22 '15 at 08:52
  • Ok, so using chrome web developer, if I delete the js.parallax script, it does not keep the image from still using a parallax type of functionality. So it makes it very hard to see exactly what that script is doing, if even when I delete it, the image still uses the parallax technique, and nothing changes. This is what I meant by not really being able to find exactly what a javascript function does, if even when you alter it, things keep working. – Edward K. Apr 22 '15 at 08:58
  • @EdwardK. - If you edit the page source and remove the parallax script and then reload the page, then the parallax script will no longer be present in the page. You can't delete code that has already been loaded into the page. The browser does not support that feature for a variety of reasons. – jfriend00 Apr 22 '15 at 08:59
  • @EdwardK. - as the code indicates, the documentation for this plugin is here: http://stephband.info/jparallax/. Beyond the documentation, one learns about what the script is doing by studying the code and understanding what it does. I'm not sure what other technique you are expecting to discover. – jfriend00 Apr 22 '15 at 09:05
  • Ok so the developer tools doesn't really support real time changes with javascript? – Edward K. Apr 22 '15 at 09:06
  • @EdwardK. - You can change the state of variables. You can't remove or edit code from a live page in the browser. There are proxy tools that will let you substitute an edited version of a piece of code (usually loaded from a local source) instead of the regular piece of code when the page is loaded, but the browser won't do that out of the box. – jfriend00 Apr 22 '15 at 09:07