Category Archives: Javascript

Adding a New Screen to the React Template Project

In this post I started looking into ReactJS. Following getting the sample project running, I decided that I’ve try adding a new screen. Since it didn’t go as smoothly as I expected, I’ve documented my adventures.

The target of this post is to create a new screen, using the sample project inside Visual Studio.

Step 1

Create a brand new project for React:

If you run this out of the box (if you can’t because of missing packages then see this article), you’ll get a screen that looks like this:

Step 2

Add a new tsx file to the components:

Here’s some code to add into this new file:

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
 
 
export class NewScreen extends React.Component<RouteComponentProps<{}>, {}> {
    public render() {
        return <div>
            <h1>New Screen Test</h1>
        </div>;
    }
}
 

The Javascript as HTML above is one of the things that makes ReactJS an appealing framework. Combine that with Typescript, and you get a very XAML feel to the whole web application.

Step 3

Add a link to the Navigation Screen (NavMenu.tsx):

<div className='navbar-collapse collapse'>
    <ul className='nav navbar-nav'>
        <li>
            <NavLink to={ '/' } exact activeClassName='active'>
                <span className='glyphicon glyphicon-home'></span> Home
            </NavLink>
        </li>
        <li>
            <NavLink to={ '/counter' } activeClassName='active'>
                <span className='glyphicon glyphicon-education'></span> Counter
            </NavLink>
        </li>
        <li>
            <NavLink to={ '/fetchdata' } activeClassName='active'>
                <span className='glyphicon glyphicon-th-list'></span> Fetch data
            </NavLink>
        </li>
        <li>
            <NavLink to={'/newscreen'} activeClassName='active'>
                <span className='glyphicon glyphicon-th-list'></span> New screen
            </NavLink>
        </li>
 
    </ul>
</div>

If you run this now, you’ll see the navigation entry, but clicking on it will give you a blank screen. It is just that scenario that motivated this post!

Step 4

Finally, the routes.tsx file needs updating so that it knows which screen to load when:

import * as React from 'react';
import { Route } from 'react-router-dom';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { FetchData } from './components/FetchData';
import { Counter } from './components/Counter';
import { NewScreen } from './components/NewScreen';
 
export const routes = <Layout>
    <Route exact path='/' component={ Home } />
    <Route path='/counter' component={ Counter } />
    <Route path='/fetchdata' component={FetchData} />
    <Route path='/newscreen' component={NewScreen} />
</Layout>;

Forcing an NPM Restore

I’ve recently started looking into the Javascript library ReactJS. Having read a couple of tutorials and watched the start of a Pluralsight video, I did the usual and started creating a sample application. The ReactJS template in VS is definitely a good place to start; however, the first issue that I came across was with NPM.

Upon creating a new web application, I was faced with the following errors:

The reason being that, unlike NuGet, npm doesn’t seem to sort your dependencies out automatically. After playing around with it for a while, this is my advice to my future self on how to deal with such issues.

The best way for force npm to restore your packages seems to be to call

npm install

either from Powershell, or from the Package Manager Console inside VS.

Powershell

On running this, I found that, despite getting the error shown above, the packages were still restored; however, you can trash that file:

Following that, delete the node_modules directory and re-run, and there are no errors:

Package Manager Console

In Package Manager Console, ensure that you’re in the right directory (you’ll be in the solution directory by default, which is the wrong directory):

References

https://stackoverflow.com/questions/12866494/how-do-you-reinstall-an-apps-dependencies-using-npm

Playing multiple videos simultaneously using HTML5

I was interested to see how playing multiple videos simultaneously affected the performance of a web page. This probably seems a little like a time machine back to 1995 – I’ll soon be posting about flashing red text and Dreamweaver!

However, playing short videos with only a few frames can be a way to draw attention to a particular part of the page; for example, if you’re browsing a clothing catalogue and one of the models moves when you hover over.

It’s worth pointing out that the entire page will be local, and so I have no network considerations whatsoever. This isn’t, however, about having three Netflix streams running at the same time – it’s short, and small videos.

The video that I’m using came from here. I’m creating an effect whereby you hover over an image of a space ship and it explodes.

MP4

It’s worth bearing in mind that most video formats are not supported by most browsers. MP4 is the exception, so it looks like this is the way to go for video encoding. I used this tool to convert the file.

HTML

Here’s the HTML for a single icon:

<head>
  <script src="HoverAnimate.js"></script>
</head>
<body onload="loaded()">
  <div id="ship1" style="background-image: url('assets/titan.png'); background-repeat: no-repeat; background-size: 50px 50px; width: 50px; height: 50px">
    <video  width="50" height="50" id="ship1-video" 
            style="visibility: hidden">
      <source src="assets/explosion.mp4" type="video/mp4" />
    </video>
  </div>
</body>

Clearly this could be neater if the CSS was separated, but essentially what we have is a div element with a scaled background image, which contains a video (currently hidden). The next thing is the Javascript that plays the video:

function loaded() {
    var imgs = document.getElementsByTagName("div");
    [].forEach.call(imgs, function (item) {
        if (item.style.backgroundImage !== "") {
            item.addEventListener('mouseover', hoverImg, false);
        }
    });
   
}

function hoverImg(e) {      
    var vid = document.getElementById(this.id + "-video");
    vid.onended = function() {        
        vid.style.visibility = 'hidden';
    }
        
    vid.style.visibility = 'visible';
    vid.play();
}

This iterates through all the div elements and, for those that has a background image, hooks up a hover event. I’ve also assumed that the div element will be named using the format “{imagename}-video”.

Conclusion

I tried this with seven videos simultaneously, and didn’t see any jerking of the animations. Whether this would stand up under networked conditions, it’s hard to say, but with the video locally available, performance is fine.

References

https://www.w3schools.com/html/html_media.asp

http://www.online-convert.com/

https://www.w3schools.com/html/html5_video.asp

http://www.dreamincode.net/forums/topic/281583-video-plays-on-mouse-over-but-not-with-multiple-videos/

https://stackoverflow.com/questions/10881678/html-play-a-video-inside-an-image

Rotate a Shape Around an Axis Using HTML5 and Javascript

Imagine, for a minute, that you want to rotate a red square around its centre… on a web page. Following on from my previous post about games using HTML5 / JS this post details how to do such a thing.

Context

Before drawing a rectangle, rotating it, or anything else, you need a context:

var canvas = document.getElementById("mainCanvas");
var ctx = canvas.getContext("2d");

Now you have a context, you can do things like clear the canvas; for example:

ctx.clearRect(0, 0, windowWidth, windowHeight);

fillRect

In HTML5, you have three methods that will be of use, and the first, and probably most important, is fillRect. It is impossible to rotate a square around its centre without a square. The syntax for fillRect is probably as you would expect:

ctx.fillRect(x, y, width, height);

rotate

The syntax for rotation is this:

ctx.rotate(rotationDegree * Math.PI / 180);

Whilst I may, during my school years, have been able to explain the sum above – I just copied it from the internet. Given the number of places where is looks exactly alike, I would guess that I’m not the first person to do that.

Just using the three lines above will give you a rotating rectangle; however, the rotation axis will be 0, 0. It took me a while to understand exactly how this works, but the key is `translate`.

translate

To me, this function is completely counter-intuitive. What it does it to offset the centre of the context by the parameters given. If the initial centre is 0, 0 (which it is by default), the following line will make it 10, 10:

ctx.translate(10, 10);

The centre of the context is 10, 10; if I call it a second time:

ctx.translate(10, 10);

The centre of the context is now 20, 20! There are two ways to reset the offset – you can simply negate the offset (by calling it with negative values), or you can call ctx.save() before the change, and ctx.restore() afterwards.

Putting it all together

So, what does all this look like in a single coherent piece of code:

        var canvas = document.getElementById("mainCanvas");
        var ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, windowWidth, windowHeight);

        var halfWidth = (iconWidth / 2);
        var halfHeight = (iconHeight / 2);

        var centreX = x - halfWidth;
        var centreY = y - halfHeight;

        ctx.fillStyle = "#FF0000";
        ctx.translate(centreX, centreY);
        ctx.rotate(rotationDegree * Math.PI / 180);
        ctx.fillRect(-halfWidth, -halfHeight, iconWidth, iconHeight);

        ctx.translate(-centreX, -centreY);

The key part to note here is the call to fillRect. Because the translate has now set the centre to be the centre of the drawn image, the image needs to be positioned at -(image width / 2).

… and you, too can have a spinning red rectangle on your screen.

References

http://www.w3resource.com/html5-canvas/html5-canvas-translation-rotation-scaling.php

https://gist.github.com/geoffb/6392450

Basic Game Using HTML5 and Javascript

This article discusses how to go about creating a basic game loop in HTML5 / JS and to implement control over a sprite.

Introduction

A few years ago, when Microsoft released the idea of WinJS, I wrote a game in HTML5/JS (or WinJS – they are not exactly the same).

I recently decided to see if I could write a web game, using just HTML5 and Javascript. This article covers the initial POC and results in a small red square navigating around the screen:

Game Loop

Looking at established game frameworks, they all basically give you the same things:
– A game loop, consisting of an update and draw phase
– Some helper methods for manipulating graphics, or rendering them to the screen

My attempt will be different, I’ll just provide a game loop; here it is:

(function MainGame() {    

    setInterval(function() {
        Update();
        Draw();
    }, 20);
})();

The loop executes every 20ms, meaning that there are 50 frames per second.

HTML

Basically, what the HTML gives us here is a canvas; so the page is very simple:

<head>    
    <script type="text/javascript" src="./gamelogic.js" ></script>
</head>
<body onresize="onResizeGameWindow()">    
    <canvas id="mainCanvas" style="width: 100%; height: 100%"
        onkeydown="onKeyDown()" tabindex="0">
    </canvas>
</body>

There are two events handled here, because there are two things that the player can do: they can interact with the game (i.e. press a key), and they can resize the browser window. We need to react to both.

Draw

Let’s have a look at the draw function next. All this is, is a way of displaying all the objects on the screen in a controlled fashion:

    function Draw() {
        var canvas = document.getElementById("mainCanvas");
        var ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, windowWidth, windowHeight);

        ctx.fillStyle = "#FF0000";
        ctx.fillRect(x, y, iconWidth, iconHeight);
    }

As you can see, there are effectively two parts to this function: firstly, the canvas is cleared, and then the items (in this case, a single item) are drawn to the screen. The important variables here are x and y, because that dictates where the square is drawn; the rest could be hard-coded values.

Update

    function Update() {        
        if (initialised == 0) {
            initialise();
        }

        // Bounce
        if (x >= (windowWidth - iconWidth) 
            && directionX > 0)
            directionX = -1;
        else if (x <= 0 && directionX < 0)
            directionX = 1;

        if (y >= (windowHeight - iconHeight)
            && directionY > 0)
            directionY = -1;
        else if (y <= 0 && directionY < 0)
            directionY = 1;

        // Move
        x += directionX * speed;
        y += directionY * speed;
    }

There are three parts to the Update. The first is to perform any initialisation: in my case, I focus on the canvas and call the resize event here. This potentially could be done on an event, but you would still have to check inside this loop if it had been done. The second is to stop the player leaving the screen; and finally, we adjust the player position.

Events

As you saw earlier, there are two events that are handled; the first is the user resizing the screen:

function onResizeGameWindow() {
    var canvas = document.getElementById("mainCanvas");
    
    windowWidth = canvas.width;
    windowHeight = canvas.height;
}

This basically ensures that the game adjusts to the browser dimensions. This might also be where you would determine if the window was made so small that the game could no longer be played.

The second event was the keydown event. This effectively provides the control for the player:

function onKeyDown(e) {
    if (!e) e = window.event;     

    if (e.keyCode == 39) {
        directionX++;
    }
    else if (e.keyCode == 37) {
        directionX--;
    }

    if (e.keyCode == 38) {        
        directionY--;
    }
    else if (e.keyCode == 40) {        
        directionY++;
    }
}

The top line is because the parameter comes through as null.

Conclusion

If you run this game, you’ll see that you can move the square around the screen, increase and decrease its speed, and stop. Not exactly the next Call Of Duty, I’ll grant you, but the foundation of a game, certainly.

Bing Maps – Finding an Address from Longitude / Latitude

Oddly, finding an address from given coordinates is not as straightforward as it first appears. The key seems to be to use the SearchManager.

SearchManager

The following is a typescript implementation that will populate an input element called myLocationText:

function GetMap(position): void {    
    map = new Microsoft.Maps.Map(
        document.getElementById('map'),
        { credentials: "MyKey" });

    Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
        var searchManager = new Microsoft.Maps.Search.SearchManager(map);
        var location = new Microsoft.Maps.Location(position.latitude, position.longitude);
    
        var mapOptions = {        
            center: location,        
            mapTypeId: Microsoft.Maps.MapTypeId.aerial,
            zoom: 10,        
            showScalebar: false        
        }    

        var reverseGeocodeRequestOptions = {
            location: location,
            callback: function (answer, userData) {
                map.setView(mapOptions);
                var myLocation = <HTMLInputElement>document.getElementById('myLocationText');                
                myLocation.value = answer.address.formattedAddress;
            }
        }
        searchManager.reverseGeocode(reverseGeocodeRequestOptions);
    });

If you want to get it to show your current location, then try this:

function findMe(position) : void {
   
    var latlong = new Microsoft.Maps.Location(position.coords.latitude,
        position.coords.longitude);

    GetMap(latlong);
    
}

Shows the correct address

References

http://www.bing.com/api/maps/sdkrelease/mapcontrol/isdk#searchByPoint+JS

http://bingmapsv8samples.azurewebsites.net/#Calculate%20Distance%20From%20Route

https://www.nuget.org/packages/Microsoft.BingMaps.V8.TypeScript/

TypeScript

Javascript is a dynamic, interpreted language. What that means is that, if you mis-type or mis-spell a variable, or even if you don’t bother to declare it, you won’t get notified at compile time (because, for a start, there is no compile time).

One possible way around this is to use one of the languages that compile down to Javascript. That does seem like a bizarre notion – that you should compile down to a second language; but it does mean (as the name suggests) that you can introduce some static typing into your Javascript.

The following was with VS2017, but you can use VS2015. I believe earlier versions don’t support Typescript out of the box (but I could be wrong).

Javascript

The first thing we’ll do is create a new web project and create some Javascript:

Create new project

Create new project

Create a basic html page:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    
</head>
<body>
    <div>
        <input id="testInput" type="text" />
    </div>
    <div>
        <p id="testOutput">Output</p> 
    </div>
    <div>
        <button onclick="buttonClicked()">Test</button>
    </div>

    <script src="typescript.js"></script>

    
</body>

And the Javascript:

function buttonClicked() {
    var input = getElementById("testInput");
    var ouput = getElementById("testOutput");

    output.value = input.value;

}

This code will run (the web-site will appear), but it will not do what it’s supposed to.

Typescript

Now we have a project, the next thing to do is to add .ts file to project. This gets compiled into a .js file, and can be referenced with a .js extension. Just copy the code:

Code sample

As you can see, the code no-longer “compiles”. The correct Typescript looks more like this:

function buttonClicked() {
    var input = <HTMLInputElement>document.getElementById("testInput");
    var output = document.getElementById("testOutput");

    output.innerText = input.value;

}

The <> brackets are typescript casts. Once you build this typescript file, it will compile down to Javascript:

Project tree

The compiled Javascript now looks like this:

function buttonClicked() {
    var input = document.getElementById("testInput");
    var output = document.getElementById("testOutput");
    output.innerText = input.value;
}
//# sourceMappingURL=typescript.js.map

The typescript.js.map file tells it where your file really is and, from looking at the debugger, we can see that the typescript file is being used:

All works well:

But why

As you can see, above; we had a piece of Javascript code that didn’t work, but it ran. Any statically typed language would have simply failed to compile. Typescript means that you can benefit from this additional check before runtime. There is a cost here, and that is that you lose the dynamic typed capability of Javascript; for example, the following won’t compile:

IMHO, this is a good thing, but I’m aware there are people out there in the world that think otherwise.

References

http://stackoverflow.com/questions/34888434/how-to-reference-a-typescript-file-from-a-web-page

http://stackoverflow.com/questions/12686927/typescript-casting-htmlelement

Create a Web Page to Find an Address Using Bing Maps 6.3

This post discusses how you might implement an address search with Bing Maps.

Disclaimer

I know that Bing Maps 6.3 is shortly to be deprecated. When I get around to signing up for v8 I might post an update to this.

Display the map

Below is a basic HTML page that has a map control. For details on how that works, please see here.

    <form class="row">
        </div>                

        <div class="overlay">
            <input type="text" id="destination" placeholder="Where do you want to go?" 
                   class="input-overlay" oninput="ChangeDestination(this.value);" />
        </div>        
    </form>

    <script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.3"></script>
    <script type="text/javascript" src="~/Scripts/MyScript.js"></script>

There’s not too much to note in this HTML, with the possible exception of the oninput function. I spent a while trying to get onchange and onkeypress to work, but oninput is a HMTL5 specific feature, and it fires when there is a change in the input box; onchange does not. onkeypress does, but you’re always a key-stroke behind.

Here’s the Javascript function in MyScript.js (referenced above):

function ChangeDestination(text) {
    map.Find("", text);
}

This causes Bing Maps to go looking for the address that you pass it. It still needs work, as you will see if you start typing any place name – it’ll match whatever you’ve typed as best it can… and you’ll travel the world before you get where you’re going.

Further Thought

One possible work around for this might be to poll the text from javascript every second and determine whether it changed; however, there is another approach:

First, change the HTML to point to a caller function:

            <input type="text" id="destination" placeholder="Where do you want to go?" 
                   class="input-overlay" oninput="callChangeDestination(this.value);" />

And then, set a timeout, so that the function is only called if we don’t re-call it within a second:

var timeout;
function callChangeDestination(text) {
    
    clearTimeout(timeout);
    timeout = setTimeout(function () { ChangeDestination(text); }, 1000);       
}

Change the ChangeDestination function itself to clear the timeout:

function ChangeDestination(text) {
    clearTimeout(timeout);
    …

Now, as you type, it will only update the map when you pause.

References

http://stackoverflow.com/questions/20420429/what-the-difference-between-window-settimeout-and-settimeout

Find user’s current location and display on Bing maps (v6.3)

Using Bing Maps to display the user’s current position should be an easy task. As with everything in Javascript, this kind of thing is only easy if you know the magic text.

HTML

<body onload="LoadMap();">
    <div class="row">
        <div>
            <h2>Where do you want to go?</h2>
        </div>
    </div>

    <div class="row">        
        <div id="pnlMap" style="position:relative">
        </div>
    </div>

There are a few points here: first one is that you need a name for the pnlMap (referenced later is the javascript), and style=”position:relative” prevents the map from just displaying in a random location.

Javascript

var map;

function LoadMap() {        
    map = new VEMap('pnlMap');    
    navigator.geolocation.getCurrentPosition(findMe);
}

function findMe(position) {
          
    var latlong = new VELatLong(position.coords.latitude,
        position.coords.longitude);
    map.LoadMap(latlong, 10);
}

LoadMap() sets up the map variable and associates it to the relevant HTML control, and then getCurrentPosition calls back to findMe(). The second number on LoadMap is the zoom level; 1 shows me as living on the earth, and 20 goes right into the road that I live on.

The output is a map that centres on your current location:

Slightly offset to avoid hordes of angry JS programmers beating down my door and suggesting that dynamically typed languages are as good as statically typed ones!

V6.3

As you will see from the references below, the latest version is v8. If you use v8, then you have to register for a key… but I didn’t want to… and I still got a map. I suppose I’ve done a bad thing.

References

https://www.w3schools.com/html/html5_geolocation.asp

https://msdn.microsoft.com/en-us/library/bb259692.aspx

https://msdn.microsoft.com/en-us/library/cc161074.aspx

https://social.technet.microsoft.com/wiki/contents/articles/34568.bing-maps-v6-3-to-v8-migration-guide.aspx

http://stackoverflow.com/questions/42607156/using-bing-maps-with-bootstrap

WinRT Contact Picker

One of the best features of Windows 8 is that it allows you to store all your contacts in one place. This means you can link your e-mail, Linked-in, Facebook, Twitter and Google+ contacts in a single list. If you want to access this programatically, it’s surprisingly simple.

The first thing to do is to create a contact picker

        // Create the picker
        var picker = new Windows.ApplicationModel.Contacts.ContactPicker();
        picker.commitButtonText = "Select" ;

The commitButtonText allows you to say what the dialog’s OK button will say. The next function is called to make the contact selection. In Windows 8 this was pickMultipleContactsAsync (there was also a pickSingleContactAsync), but both are deprecated for 8.1, and you should use the following:

     // Open the picker for the user to select contacts
     picker.pickContactsAsync();

Or

     // Open the picker for the user to select a contact
     picker.pickContactAsync();

This needs to be inside a promise, to ensure that the app doesn’t become unresponsive while you select contacts:

    function pickContacts() {

         // Create the picker
        var picker = new Windows.ApplicationModel.Contacts.ContactPicker();
        picker.commitButtonText = "Select";

        var emailsPromise = new WinJS.Promise( function (complete, error, progress) {

            // Open the picker for the user to select contacts
            picker.pickContactsAsync().then( function (contacts) {
                if (contacts.length > 0) {
                    // Iterate through the contacts collection and do something
                    
                    complete(); // Call complete to exit the promise
                } else {
                    complete(); // Call complete to exit the promise
                }
            });
        });

        return emailsPromise;
    };

This works, with one slight caveat – it gives you every single contact. But say you just want the e-mail address? The following will return only the contacts for which you have an e-mail address:

         picker.desiredFieldsWithContactFieldType.append(Windows.ApplicationModel.Contacts.ContactFieldType.Email);

(Note, this replaces the deprecated desiredFields property in Windows 8.0)

So, the final cut looks like this:

    function pickContacts() {

         // Create the picker
        var picker = new Windows.ApplicationModel.Contacts.ContactPicker();
        picker.commitButtonText = "Select";
        picker.desiredFieldsWithContactFieldType.append(
               Windows.ApplicationModel.Contacts.ContactFieldType.Email);

        var emailsPromise = new WinJS.Promise( function (complete, error, progress) {

            // Open the picker for the user to select contacts
            picker.pickContactsAsync().then( function (contacts) {
                if (contacts.length > 0) {
                    // Iterate through the contacts collection and do something
                    
                    complete(); // Call complete to exit the promise
                } else {
                    complete(); // Call complete to exit the promise
                }
            });
        });

        return emailsPromise;
    };

So, what does this look like in C#? IMHO, it looks a lot neater:

             // Create the picker
            Windows.ApplicationModel.Contacts. ContactPicker picker = new Windows.ApplicationModel.Contacts.ContactPicker ();
            picker.CommitButtonText = "Select";
            picker.DesiredFieldsWithContactFieldType.Add(
               Windows.ApplicationModel.Contacts. ContactFieldType .Email);

            // Open the picker for the user to select contacts
            var contacts = await picker.PickContactsAsync();
            if (contacts.Count() > 0)
            {
                //...
            }

Final Note

It’s also worth noting that when you get the contacts, the e-mail addresses for each are a collection (each contact can have many); so you’ll need to do something like this:

contacts.forEach( function (contact) {
    contact.emails.every( function (email) { output += email.address + "," ; });
});

Or

foreach( var em in c.Emails)
{
    System.Diagnostics. Debug.WriteLine( "{0} email {1}" , c.Name, em.Address);
}