Skip to content

yotsumoto/casperjs-goto

Repository files navigation

CasperJS: Navigation Step Flow Control by label() and goto()

###You can realize infinite loop, break, continue, switch case, etc... on CasperJS###

BACKGROUND

I am using CasperJS for some my projects. Thank you very much, Nicolas.

By the way, sometimes, I would like to describe the logic, like infinite loop and conditional break.

For example:

while(true) {
  DO SOMETHING
  if( CHECK CONDITION ) { break; }
  DO SOMETHING
}

However, I can not find out the solution in current CasperJS.

Of course, I studied that CasperJS has repeat() function, and tried it. But it seems that we have to provide finite number, and we can not describe the conditional break out form the loop.

As a solution so far, Nicolas seems to suggest the sample dynamic.js. But it's too complicated. The script dynamic.js is using recursive function. That is not easy and memory problem occurs frequently. I think that the original purpose of CasperJS is making it simple than PhantomJS script. But I don't think that dynamic.js is simple.

So, I tried to solve this problem by my own way.

SOLUTION

According to source code of the CasperJS , it adds navigation step to Array steps with then() function or equivalent, like thenOpen() and thenEvaluate(). After that, CasperJS executes those steps in order and one by one synchronously. This is the CasperJS' mechanism of synchronous execution system. (Wow! Great!)

Current CasperJS, however, the step execution is only sequentially. That is why even repeat() function has to expand the navigation step sequentially. This means that CasperJS can not realize the infinite loop. (If you have infinite memory, you can, maybe :-)

Therefore, I developed two new functions, label() and goto() for manipulating the navigation step execution order, and dumpSteps() for debugging.

  • label() can affix label on a point of navigation step.

  • goto() can jump to the labeled point of navigation step.

  • dumpSteps() can display the all information about navigation steps, including the label information.

In order to realize them, I revised the original function then() and checkStep() as extending Casper functions.

Even though the label() and goto() are very primitive functions, by making full use of those functions, we can realize the any execution flow control, like infinite loop, conditional break or continue, switch case, and so on.

SAMPLE

I prepared following three sample scripts in this repository.

I checked above scripts on PhantomJS 1.6.1 + CasperJS 1.0.0-RC1

infiniteloop.js

This infiniteloop.js sample is showing the minimum infinite loop by label() and goto(). The script is like following.

casper.start();

    casper.label( "LOOP_START" );

        casper.then(function() {
            this.echo( "Showing This Message Forever !" );
        });

    casper.then(function() {
        this.goto( "LOOP_START" );
    });

casper.run();

do_while.js

This do_while.js sample script is showing Display 1 to 10 by loop like do{...}while(...). It includes conditional jump by goto() with if(). In addition, this is showing Dump Navigation Steps by dumpSteps() at the end of script. The script and output screen shot are following.

casper.start();

    casper.then(function() {
        this.echo( "Display 1 to 10 by loop like  do{...}while(...)" );
    });

    var counter=0;
    casper.label( "LOOP_START" );

        casper.then(function() {
            counter++;
            this.echo( counter );
        });

    casper.then(function() {
        if( counter<10 ){ this.goto( "LOOP_START" ); }
    });

casper.run( function() {
  this.dumpSteps( true );
  this.exit();
});

do_while.js screen shot

googleranking.js

This googleranking.js sample is more useful. You can get Google Ranking of your site. In this sample, it shows ranking of site http://casperjs.org from the Google multiple search result pages of key word PhantomJS. The result screen shot is like following. Of course, you can change those parameters if you like.

googleranking.js screen shot

INSTALLATION

The above three sample scripts have following two function groups of extending casper object.

  • label(), goto(), then() and checkStep()

  • dumpSteps()

You can just copy and paste these two function groups between var casper = require('casper').create({...}); and casper.start(); on your script.

HOW TO USE

label()

label() have one label text as argument, and affix the label on that navigation step point. You can jump into this navigation step point by goto()

Example:

casper.label( "LOOP_START" ); 

For performance and easy coding, it does not have label duplication check routine now.

Another important point is that you DO NOT put label() inside then() function. Because label() is automatically making new empty step and affix the label on it. If you put label() inside then(), this means then() function will be nested, and problems will occur. Please take care.

BAD Example

NG:  casper.then(function() {
NG:    casper.label( "LOOP_START" );
NG:  });

goto()

goto() also have one label text as argument that you want to go to. If the label dose not exist, goto() does nothing.

Important point is that goto() function, contrary to label(), must be described inside then() function.

Example: unconditional jump

casper.then(function() {
    this.goto( "LOOP_START" );
});

Example: conditional jump with if()

casper.then(function() {
    if( counter<10 ){ this.goto( "LOOP_START" ); } 
});

Another important point is that even when goto() is executed, rest of code in that STEP will be executed.

Example

casper.then(function() {
    this.echo( "Before goto()" );
    this.goto( "LOOP_START" );    // Unconditionally, this goto() is executed.
    this.echo( "After goto()" );  // This line also will be executed unconditionally.
});

Because goto() is just changing the pointer of next step, and it continues the current step execution until the end of that step.

dumpSteps()

dumpSteps() can display the all information about navigation steps, including the label information. The argument is Boolean. If it is true, it shows function source code inside the step. If not, it does not show the source code.

For debugging, you can write a following line at any location on your script, then you can get the dump of navigation steps at that point.

casper.dumpSteps( true );  casper.exit();

Or you can put dumpSteps() at run() function in onComplete function like following.

casper.run( function() {
    this.dumpSteps( true );
    this.exit();
});

QUIZ

This is special additional quiz about CasperJS Navigation Step System for your fun.

QUESTION: Which is the character display order?

A-B-C-D-E-F or F-E-D-C-B-A or ..... ?

casper.start();

    casper.thenOpen( "http://google.com",  function() {
        casper.echo( "A" );
    });

    casper.echo( "B" );

    casper.then(function() {
        casper.then(function() {
            casper.echo( "C" );
        });
       casper.echo( "D" );
    });

    casper.echo( "E" );

    casper.then(function() {
        casper.echo( "F" );
    });

casper.run();

Thank you.

About

CasperJS: Navigation Step Flow Control by label() and goto()

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published