Thursday 17 July 2014

Javascript debugging in the browser console.

When browsers first introduced console windows I was over the moon.  No longer did I have to rely on clunky alerts in order to perform simple debugging tasks.

Then came another concern.  Whilst I'm developing, or debugging an issue after release, I want to be able to access debug information without having to make any changes to a site or included scripts.  In order to do this I created a debug object that has the same methods as the console object, but can be enabled and disabled via the console.  This means that you can slap as many debug statements into your script as you like and they will never show unless you open the browser console and enable them.

Here's the code for the debug object...
// global debug object
window.debug = {};
window.debug.__defineGetter__("enabled", function () {
    return localStorage.getItem("_debug") === "true";
});
window.debug.__defineSetter__("enabled", function (value) {
    localStorage.setItem("_debug", value);
    if (value === true) {
        window.debug.dir = console.dir.bind(console);
        window.debug.error = console.error.bind(console);
        window.debug.log = console.log.bind(console);
        window.debug.warn = console.warn.bind(console);
    }
    else {
        window.debug.dir = function () { };
        window.debug.error = function () { };
        window.debug.log = function () { };
        window.debug.warn = function () { };
    }
});
window.debug.enabled = Boolean(window.debug.enabled);


In order to use it, just add debug function calls wherever you want them.  I tend to put them at the top of function calls so that I can get a step-by-step log of what was called and what parameters were passed, like this...
function AddNumbers(a, b) {
    debug.log("AddNumbers", arguments);
    return a + b;
}


If you call that with debugging disabled then it will just run as normal and log nothing.  If, however, you run it with debugging enabled then you'll get a log of what took place...


AddNumbers(2, 5)
7

debug.enabled = true
true

AddNumbers(2, 5)
AddNumbers [2, 5]
7

Once you include this in your projects, debugging is disabled by default.  Simply open the console and enable as above and it will start to show everything you've logged.

Since the enabled state of the debug object is stored in local storage, you are enabling and disabling it for that website, for that browser.  You can turn on debugging at any point in the page's life-cycle so you don't even need to reload the page in order to see debug statements that you've put in event handlers (for example).

The only other feature worth noting is the fact that I used bind to assign the console methods to the debug object.  Doing this means that the console shows the file and line number where the call to the debug object was made, and not where the debug object code is.

Monday 9 June 2014

Debug a Windows Service with Visual Studio

I was just working on a Windows Service in Visual Studio 2010 and needed to debug it.  I went to the debug menu and selected "Attach to process", but the executable was greyed out.  I did a bit of Googling and found this most awesome single line of code...
System.Diagnostics.Debugger.Launch();

It tells Windows to ask if you want to debug the application, and you simply select the running version of Visual Studio and you're in the code.



If you're remote debugging then add this code to the startup of the service and it will make the service wait till you attach to it from Visual Studio (using remote debugging) before continuing...

while (!System.Diagnostics.Debugger.IsAttached)
{
    System.Threading.Thread.Sleep(1000);
}

Bosh!

Monday 19 May 2014

How to build Android apps online.

Please note: The process described below could be used to develop apps for both iOS and Windows Phone 8, as well as Android, but as I don't use either of those platforms I wouldn't be able to explain the installation process, once the project had been built.  That's the only part that differs though.  The setup described here is totally platform independent.

I recently got myself a Chromebook and, as a developer, immediately found that there were things I couldn't do with it.  I certainly wasn't going to be installing Visual Studio or Eclipse on it.  Sure, I could have installed Linux on it, but I bought it purely to experience Chrome OS so that wasn't going to happen.


I'd used Cordova to create Android applications in the past, as my most relevant development experience is HTML, CSS & Javascript.  It meant that I could build apps immediately, without having to learn the Java framework and the UI aspect of Java apps (which is totally alien to me as a long-time Windows developer).


I'd also come across Adobe Phonegap Build before, which is an online service where you can build apps for the major mobile platforms.  You can point it at your GitHub account and it will allow you to build directly from the source code hosted there, which is very useful indeed!  All I needed to do was use PhoneGap instead of Cordova, and at the moment they're pretty much identical.


The last part of the puzzle was to find an online IDE that allowed me to update GitHub with my changes.  That's where Cloud9 came in.  It's exactly what I needed.


In order to get any of this working, you'll need accounts at GitHub, Cloud9 and Adobe PhoneGap Build.  Thankfully, you can sign in to the latter 2 with a GitHub account, so there's actually only 1 account required.  Go to GitHub and sign up there...


http://www.github.com



Once you have an account, go to the other 2 sites and log in using your GitHub details...

https://c9.io/


https://build.phonegap.com


Now you're ready to start building your first app.


I found a template PhoneGap project on GitHub and forked it to my own repository.  Obviously you can make your own or find something different (Google is your friend), but here's the one I used...


https://github.com/phonegap/phonegap-start



Go to that page, click the "fork" button at the top right and you've got your own copy.  I renamed mine to PhonegapTemplate, but it's up to you what it's called - it's neither her nor there.


Once you've done that, open Cloud9 IDE, go to the dashboard and click the big green button that says "create new workspace".  You'll get a dropdown with 2 options in it - select "Clone from URL".  In there you need to paste the URL of your template repository on GitHub (right-click the repository name and copy the link address).  Select "Custom" from the boxes below.  The first time you do this it will automatically take the repository name as your project name.  For any future projects it won't let you use the same name again and you should then be told to "Change workspace name".


Once the workspace has been created, highlight it and click "Start editing".


At the moment you have a copy of the template, but it is still linked to the original in GitHub.  We need to create a new repository and link the workspace to that.  To create the repository go back to GitHub and click the "Repositories" near the top of the page.  Click the "New" button and enter a name and, if you want to, a description, then click the "Create repository" button.  (I tend to use the same name for the workspace on Cloud9 and the repository on GitHub, purely so I know they're the same thing.)


On the new repository page, near the bottom of the right-hand menu you'll see an input box that says "SSH clone URL" above it.  Click the button to the right of that.  It copies a link to your clipboard that you'll need in a minute.


Go back to Cloud9 and, in the terminal which should be open at the bottom of the screen, enter the following...


git remote set-url origin **Paste the previously copied text here**



So, for example, I would do something like this...


git remote set-url origin git@github.com:johncmolyneux/phonegaptest01



That links your new workspace to your new repository, rather than the template repository that you got it from.


Then all that's left to do is to push your code to GitHub, which you do by entering the following command in the terminal...


git push -u origin master




That's it for Cloud9 and GitHub (for this example, anyway).  Go to Adobe PhoneGap Build next and we can build the application.


If it doesn't take you directly there, go to the apps page and click the "new app" button in the top-right.  Click the box in the right of the input that says "find existing repo / paste .git repo" and select your project from the dropdown.  That will download the source from GitHub to the build server, and add it to your app list.  Once that's finished and it's ready, you should see a button saying "Ready to build".  Click that and the build process will begin.  Once it's complete you can simply click the Android icon under the app to download the apk.  I usually open that page on my phone to make it easier to download and install it, otherwise you need to copy it from your computer to your phone.


And that's it.  You've built an Android application online, without the need of Java, the Android SDK or Eclipse/ADT.  As long as you have an internet connection you can now build apps to your heart's content on any device.



Monday 23 December 2013

How to extend jQuery on() and add custom events.

Note: The code for this can be found in the js-extend library, on GitHub...

https://github.com/johncmolyneux/js-extend



I recently wrote a piece of code to handle what I termed as a custom event.  It was a plugin that would trigger a function when the enter key was pressed in a selected element.  After I'd done that I was curious about turning it into an event that I could assign an event handler to, using jQuery's built-in methods, so I came up with this...

// custom event container
$._customEvents = {};
$.createEvent = function (trigger, notifier) {
    $._customEvents[trigger] = notifier;
};

// extend .on() so custom events can be handled
$.fn._on = $.fn.on;
$.fn.on = function () {
    for (var event in $._customEvents) {
        if (event == arguments[0]) {
            $._customEvents[event](this, arguments[1]);
            return this;  // return the element so we can chain as normal
        }
    }
    return $.fn._on.apply(this, arguments);
};
What that does is extend jQuery's on() function so that you can create your own events that can be attached to elements.  Like this, for example...
// fires when the enter key is pressed within a selected element (must accept keyup)
$.createEvent("enterkey", function (element, callback) {
    var $element = $(element);
    $element.on("keyup", function(e) {
        var code = (e.keyCode ? e.keyCode : e.which);
        if (code == 13) {
            callback();
        }
    });
});
That's the enter key pressed event I mentioned above, but added to the on() function using the new function, createEvent().

Once the above is done then you can use that event wherever you like.  You can attach that to any relevant element and assign an event handler, like this...

$("input").on("enterkey", function() {
    console.log("enter key pressed");
});
As you can see, it's simple to add the event handler code now, just like any of the standard events that are included in jQuery.  This would make it very easy to create custom events that you could use throughout your code, just by having a common javascript file included.  You can obviously create any event you like.

The example above is just one I needed for an application I was working on.  Further custom methods will be added to the source which is available from the GitHub link at the top of this post.


Hopefully this will help others keep code tidy, segregated and easy to understand.

Wednesday 28 November 2012

Reference Asp.Net control in JavaScript

It can be a pain to reference an Asp.Net control in JavaScript.  I find myself inspecting rendered HTML and looking for the assigned ID (ClientID) of the control.  I decided the other day that I've had enough of doing that so I wrote this simple and small function...
public static void AddClientIDReference(System.Web.UI.Control Control)
{
    System.Web.UI.Page Page = HttpContext.Current.CurrentHandler as System.Web.UI.Page;
    System.Web.UI.ScriptManager.RegisterStartupScript(Page, typeof(System.Web.UI.Page),
        "ClientIDReference_" + Control.ID,
        "var " + Control.ID + " = \"" + Control.ClientID + "\"; ",
        true);
}
This can be called like this...
AddClientIDReference(txtMyTextBox);
This inserts a line of JavaScript that creates a global variable called txtMyTextBox, with a value of the textbox's ClientID.  You can then reference txtMyTextBox in JavaScript like this...
document.getElementById(txtMyTextBox);
or using jQuery...
$("#" + txtMyTextBox);
Like I said, simple and small :o)

Friday 23 December 2011

Simple jQuery accordian

Here's yet another animated image thing in jQuery. This one's a simple version of the popular accordian.  View source on the example page to see how to construct it.  There's a bit of css and 1 javascript call.


http://www.johnmolyneux.co.uk/examples/accordian.html



Just put the mouse over it to see what it does.

Wednesday 14 December 2011

Custom scroll box

And here's another scrolling jQuery thing (it seems I spend my life scrolling things with jQuery these days!)
I've made this as customisable as I could think of at the time, but it should be relatively easy to add new features so either feel free to do so, or leave a comment with suggestions.
As always, fee free to take and use in any way you see fit.

http://www.johnmolyneux.co.uk/examples/new-scroller.html


Here's the options explained...
Option Default Meaning
width 500 The overall width of the scroller (does not include padding).
height 100 The overall height of the scroller (does not include padding).
padding 5 Padding inside the scroller, around the left/right buttons and around each image.
increment 500 The number of pixels that 1 click of an arrow will move the images.
speed 300 The time, in milliseconds, for each scroll.
reverse false Reverses the action of the left/right buttons. (I couldn't decide which way I prefer them.)
tolerance 50 How close, after a scroll, you need to be to the beginning or end of the images before just going to it. This is so that you don't get small scrolls at the end of a list, say you scroll 400 and the list is actually 410 wide. Without this tolerance you would need to scroll another 10 pixels to be sure you're at the end, and it just looks silly!


Rather than using the traditional { option: "value" } method, I wanted to make the code run without the need to add script to the page when adding the scroller div itself.  So, it automatically runs on every div with the class "scroller".  See the source code of the linked example to see how to set options.