Browser power from the command line

If you require the ability to programmatically access the full power of the web browser without ever opening a web browser you should take a look at PhantomJS http://phantomjs.org/. Want even more power ? Combine it with CasperJS http://casperjs.org/.

With these technologies you can run automated scripts that don’t require any desktop UI or browser and that (as far as the remote HTTP server is concerned) are the same as opening a web browser and doing whatever tasks you would have manually done on it. You can programmatically invoke JavaScript within the context of the remote page, download files, even take screen shots of the page that is being viewed and to think that all this can be done as some background script on a GUIless virtual machine running somewhere on the cloud – isn’t technology something ? 🙂

quick installation on Ubuntu

This is for version 1.9.2 – use the one that’s relevant for you:

cd ~
wget https://phantomjs.googlecode.com/files/phantomjs-1.9.2-linux-i686.tar.bz2
tar jxvf phantomjs-1.9.2-linux-i686.tar.bz2
ln -s `pwd`/phantomjs-1.9.2-linux-i686/bin/phantomjs /usr/local/bin/phantomjs

git clone git://github.com/n1k0/casperjs.git
ln -sf `pwd`/casperjs/bin/casperjs /usr/local/bin/casperjs

Install Apache, MySQL, PHP on OS/X Mountain lion

Nice guide here

I was unaware that Apache comes preinstalled with OS/X

In a nutshell

  • All the relevant files are at /etc/apache2

  • Starting, stopping, restarting the service is done with
sudo apachectl start
sudo apachectl stop
sudo apachectl restart
  • The default document root is at /Library/WebServer/Documents/ but you can create a different document rule for your user by creating <username>.cnf at /etc/apache2/users/

  • The following fixes a problem of connecting to MySQL from PHP:
sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock

For more details, check the above link.

Quick http server

So you want to quickly test some static files from an http server ? Just cd to the folder where these files are and:

Using Python 2.x:

python -m SimpleHTTPServer 8000

Using Python 3.x:

python -m http.server 8000

Another option, if you have PHP installed is:

php -S localhost:8000

Where is my car ?

Someone already made something similar: http://software.intel.com/en-us/articles/where-is-my-car-web-app-and-phonegap-app

At this point I’m looking for a good cordova.js stub file – seems others are also looking for something like that but there aren’t any to be found in the small search I’ve made – only the Ripple chrome extension which only supports Cordova 2.0 and didn’t really work all that well with my basic App. If I wont find a cordova.js stub I’ll create it myself.

Brilliant JavaScript file upload function

I’ve seen various attempts to use JavaScript to customise the file upload button. The browsers historically do not lend themselves to making this easy to achieve due to security considerations – the idea is not to make it simple for anyone to upload a file from the PC to a remote website without the user knowing about it. However, the problem is that from a UI perspective, you are stuck with what the browser supplies.

All the attempts I’ve seen to try and hack the browser file upload input tag have been quite bad. They mostly involve trying to put some other element over the browser created button, catching clicks on that element and then forwarding them to the original button. The mileage for this method varies with the browser used and also requires creating your specific image to cover the button, which gets tiresome if you want to change languages or colours.

Enter upload-at-click. A brilliant piece of work that works with every browser (even including IE6 !). Take a look at it and you’ll see why I’m impressed.

Cordova sample running on iOS

When running the project via xCode, the reason there was no access to the device sensors on iOS from JavaScript became apparent from the logs:

ios ERROR: Plugin Compass not found, or is not a CDVPlugin. Check your plugin mapping in config.xml

Of course, the config.xml was just fine, but at least this gave me a lead. A search yielded a similar problem others had been having which was solved by deleting the ./plugins/ios.json file, removing the ./platforms/ios directory, re-adding the cordova ios platform for the project via cordova platform add ios and rebuilding the project.

After this, I could finally see the compass heading on my iPhone.

On ios 7 and higher, the status bar interferes with the top part of the html view of the cordova application. This can be resolved by

cordova plugin add org.apache.cordova.device

an then

    function onDeviceReady() {
        // a few examples that can be returned from device.platform are:
        //   - "Android"
        //   - "BlackBerry"
        //   - "iOS"
        //   - "WinCE"
        //   - "Tizen"
        if (device.platform == "iOS" && parseFloat(device.version) >= 7.0)
            document.body.style.marginTop = "20px";
        
        // your stuff goes here
    }

Trying to get cordova sample running on iPhone

To run our Cordova sample on iOS, I’m using a Mac OS/X Maverics with Xcode 5.02 installed.

To add ios support in our compass application, from within the compass directory, issue:

cordova platform add ios

This went smoothly.

Next, building the project:

cordova build ios

This also went smoothly.

Finally:

cordova run ios

This yielded:

Error: An error occurred while running the ios project.Error: ios-deploy was not found. Please download, build and install version 1.0.4 or greater from https://github.com/phonegap/ios-deploy into your path. Or 'npm install -g ios-deploy' using node.js: http://nodejs.org/

I opted for the 2nd option which seemed to go ok:

npm http GET https://registry.npmjs.org/ios-deploy
npm http 200 https://registry.npmjs.org/ios-deploy
npm http GET https://registry.npmjs.org/ios-deploy/-/ios-deploy-1.0.4.tgz
npm http 200 https://registry.npmjs.org/ios-deploy/-/ios-deploy-1.0.4.tgz

> ios-deploy@1.0.4 preinstall /usr/local/lib/node_modules/ios-deploy
> make ios-deploy

rm -rf *.app demo ios-deploy
gcc -o ios-deploy -framework CoreFoundation -framework MobileDevice -F/System/Library/PrivateFrameworks ios-deploy.c
/usr/local/bin/ios-deploy -> /usr/local/lib/node_modules/ios-deploy/ios-deploy
ios-deploy@1.0.4 /usr/local/lib/node_modules/ios-deploy

running cordova run ios ended with ‘Platform “ios” ran successfully.’ with one minor problem: Nothing happened on my ios device. No application was loaded to the device, let alone launched.

It immediately occurred to me that Apple won’t let you do shit without paying something first (With the iPhone, unlike Windows Phone 8 and Android, I couldn’t even get the phone OS operating without putting in a working SIM card, and also unlike them, you can’t just start uploading applications to your device without coughing up $99/year for a Apple Developer’s ID).

Luckily I had an Apple developer’s id I could use so I imported the certificate by opening the Xcode project that Cordova created and following the directions.

After than again cordova run ios, and now finally I saw the icon of the cordova compass application. Launching the application showed the basic html but the heading and geolocation were not displayed.

Looking at the cordova documentation for iOS for the compass, I saw that the following was needed in the config.xml file:

<feature name="Compass">
    <param name="ios-package" value="CDVLocation" />
</feature>

so I added it. At the same opportunity I also added the following for the geolocation access:

<feature name="Geolocation">
    <param name="ios-package" value="CDVLocation" />
</feature>

and repeated:

cordova build ios
corova run ios

and again, nothing. Tomorrow we go back to basics and try to make a minimal cordova sample of reading the compass.

By the way, to run the iOS emulator from the command line (at least on Cordova 3.2.0):

cordova run --emulator ios