Category Archives: Javascript

CORS Errors while playing with the HTML Canvas

In this post, I wrote about how you might draw a graph using the HTML canvas; my next step was to make that more efficient; however, upon trying to import a Javascript module into my script:

import animatedGraphics from './animatedGraphics';

I started getting this error:

Access to script at ‘file:///C:/repos/webanimations/animated-columns-optimised/columns.js’ from origin ‘null’ has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

After a bit of digging, I uncovered a feature of ES6 that prevents opening this directly in a browser.

Hosting the site locally

The issue is caused because the file is being opened directly; so there seemed to be a couple of ways around this: one is to disable the security in Chrome, although try as I might, I couldn’t manage to get it to give up the ghost: I tried various combinations around the –disable-web-security flag of Chrome.

The second option is to host the site locally. For a brief moment I considered using something like IIS Express; but fortunately, I came across this tool that hosts a site locally for you.

It can be installed as an npm package:

npm install --global http-server

Once installed, you just navigate to the relevant directory, and type http-server:

C:\repos\webanimations\animated-columns-optimised>http-server
Starting up http-server, serving ./
Available on:
  http://192.168.1.79:8080
  http://127.0.0.1:8080
  http://172.17.230.225:8080
Hit CTRL-C to stop the server

You can then navigate to your specific page; for example:

http://127.0.0.1:8080/columns

And no more CORS error (doesn’t quite work yet, but that’s a whole different story).

Drawing Custom Graphs in HTML and Javascript

While recently playing with the HTML Canvas again, it occurred to me that this power could be used for evil (or statistics are it is commonly known these days).

In this post, I’m going to draw an animated chart using the HTML Canvas and Javascript.

Let’s start with the HTML:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="test.css">
    <script src="test.js"></script>
</head>
<body onload="doDrawing()">
    <canvas id="canvas">
    </canvas>
</body>
</html>

Again, as with my previous post (linked above), I’ll remind you that this will not cope with screen resizing. The CSS, again, isn’t much to write home about:

* { 
    margin:0; 
    padding:0; 
}
canvas {  
    display: block;    
}

Javascript

Finally, we come to the Javascript: this is a bit more involved, so I’ll break it down into the individual functions; we’ll start with the top level one:

const doDrawing = () => {
    var c = document.getElementById("canvas");
    
    c.width = window.innerWidth;
    c.height = window.innerHeight;
    var ctx = c.getContext("2d");    
    drawGraphTop(50, 5, 500);
    drawColumn(100, 500, 4, 'January');
    drawColumn(150, 350, 5, 'February');
    drawColumn(200, 150, 6, 'March');
}

All we’re doing here is getting a handle to the canvas, setting the height and width so that we fill the screen, and then calling some functions to do the drawing. The helper method to get the context is trivial, but for completeness:

function getContext() {
    var c = document.getElementById("canvas");    
    var ctx = c.getContext("2d");        
    return ctx;
}

There’s not much to explain here, we’re just getting the context from the canvas and returning it – thereby saving 3 lines of code each time we do that. The drawGraphTop function is a little more interesting:

const drawGraphTop = (top, interval, width) => {
    let ctx = getContext();
    ctx.beginPath();
    ctx.rect(1, top, width, 2);
    let stage = width / interval;
    for (let i = 0; i <= interval; i++) {
        ctx.rect(i * stage, top, 2, 5);
    }
    ctx.stroke();
}

The idea here is that we display a flat, horizontal line across the top of the screen, with markers. There is no line method on the canvas context, so a flat rectangle is the best we can do.

The more complex method is the drawColumn method (technically, it isn’t actually drawing columnns – but they still feel like columns – at least, more than rows):

const drawColumn = (top, target, speed, label) => {
    let ctx = getContext();
    let x = 10;    
    let directionHorizontal = speed;

    let intervalHandle = setInterval(() => {
        const buffer = 15;
        const height = 30;
        let showText = false;
        ctx.beginPath();
        ctx.clearRect(1, top - 1, target + buffer + Math.abs(directionHorizontal) + 2, height + 2);

        if (directionHorizontal === 1 && x <= target + buffer) {
            
        } else if (directionHorizontal > 0 && x >= target + buffer) {
            directionHorizontal = -1;
        } else if (directionHorizontal < 0 && x <= target) {
            clearInterval(intervalHandle);
            directionHorizontal = 0;
            showText = true;            
        }

        x += directionHorizontal;
        ctx.rect(1, top, x, height);
        ctx.stroke();

        if (showText) {                        
            ctx.fillText(label, 10, top + 20);
        }
    }, 1);
    
}

There is quite a lot to this; let’s focus on the interval; we take a handle to the interval, so that we can cancel it when we’ve finished drawing.

The first thing we do with the context is call beginPath – this allows us to group a series of updates into a single screen update; then we’re clearing an area, just wide of, the size of the rectangle.

We then have a conditional check – if we’re heading right, and have yet to reach the target (which has a small buffer appended for the purpose of animation), then this drops through to the code below; if we’ve reached that then we change direction; and when we’re back to the actual target, we cancel the update and set a flag to make the text appear.

Subsequently, we draw the (horizontal) column and, if we’ve finished, display the text.

Output and Caveats

It’s worth bearing in mind that the way this code is structured is probably not the best for performance – ideally, you would have a sort of game loop and draw, and then update the entire screen in one go.

Code

You can find the code for this here.

Playing with the HTML Canvas Again

I’ve previously written about how you can write games using tools like React. I’ve also written about creating a basic game in Html and Javascript, and things like rotating shapes.

In this post, I’m going to demonstrate a sort of Etch A Sketch type program.

The HTML is very simple here:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="test.css">
    <script src="test.js"></script>
</head>
<body onload="doDrawing()">
    <canvas id="canvas">
    </canvas>
</body>
</html>

Basically just bringing in a Javascript file, CSS and putting a canvas on the screen. I’m also calling a function onload – it’s worth bearing in mind that, as it goes, this won’t resize should you change the size of the browser. If you want that behaviour, then have a look at one of my previous posts mentioned above.

The CSS is even simpler:

* { 
    margin:0; 
    padding:0; 
}
canvas {  
    display: block;    
}

All we’re doing here is removing the default margin, and stopping scroll bars from appearing.

Javascript

The Javascript is where everything is happening; let’s start with some variables:

let x = 10;
let y = 10;
let directionHorizontal = 1;
let directionVertical = 0;

The four variables determine the position that we want to draw in, and which way we’re heading. We can now render this to the screen like this:

const doDrawing = () => {
    var c = document.getElementById("canvas");
    
    c.width = window.innerWidth;
    c.height = window.innerHeight;

    var ctx = c.getContext("2d");
    setInterval(() => {
        ctx.fillRect(x, y, 1, 1);
        x += directionHorizontal;
        y += directionVertical;
    }, 10);
}

The canvas width and height are the first things to note: when I started playing with this, I made the mistake of trying to set this in CSS; if you do, it actually doesn’t change the size of the canvas, but stretches it across the screen; this was the only way that I could get the canvas to display full screen without that stretching effect (if you know another / better way, please say so in the comments!)

Next we get the context from the canvas – this allows us to render to it, and then we simply set-up an interval, and draw a rectangle 1px x 1px each iteration.

Summary

That it – as with previous posts, there’s not a whole lot to using the HTML canvas, but I do like to re-experiment every so often.

Using XMLHttpRequest from Javascript to Call a .Net Core Api

Imagine you have the following API endpoint:

https://localhost:1234/doStuff

The controller method for this might look like this:

[HttpPost]
public IActionResult DoStuff([FromBody]Data data)

If, for example, you create the sample .Net Core React app, you’ll see it getting the data using a construct like this:

const response = await fetch('doStuff');

This works fine if you’re retrieving data, but if you want to send some data through to the endpoint body, XMLHttpRequest allows you to send data in the body like this:

const xhr = new XMLHttpRequest();

xhr.open('POST', 'doStuff')
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({ 
  data1: this.state.data1,
  data2: this.state.data2
}));

Unsupported Media Type

If, in the above code, you were to use:

const xhr = new XMLHttpRequest();

xhr.open('POST', 'doStuff')
//xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({ 
  data1: this.state.data1,
  data2: this.state.data2
}));

You would be sending form data through to the controller. The call would not work, and you would get the following error from F12:

{"type":"https://tools.ietf.org/html/rfc7231#section-6.5.13","title":"Unsupported Media Type","status":415,"traceId":"|c86a375c-41ba2fd85652022a."}

There are two ways around this: the first, you’ve seen above, you set the content type; but you can also change the controller method to look like this:

[HttpPost]
public IActionResult DoStuff([FromForm]Data data)

References

https://stackoverflow.com/questions/39519246/make-xmlhttprequest-post-using-json

https://attacomsian.com/blog/http-requests-xhr

Calling an Azure Signalr Instance from an Azure function

I’ve been playing around with the Azure Signalr Service. I’m particularly interested in how you can bind to this from an Azure function. Imagine the following scenario:

You’re sat there on your web application, and I press a button on my console application and you suddenly get notified. It’s actually remarkably easy to set-up (although there are definitely a few little things that can trip you up – many thanks to Anthony Chu for his help with some of those!)

If you want to see the code for this, it’s here.

Create an Azure Signalr Service

Let’s start by setting up an Azure Signalr service:

You’ll need to configure a few things:

The pricing tier is your call, but obviously, free is less money than … well, not free! The region should be wherever you plan to deploy your function / app service to, although I won’t actually deploy either of those in this post, and the ServiceMode should be Serverless.

Once you’ve created that, make a note of the connection string (accessed from Keys).

Create a Web App

Follow this post to create a basic web application. You’ll need to change the startup.cs as follows:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR().AddAzureSignalR();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            //app.UseDefaultFiles();
            //app.UseStaticFiles();

            app.UseFileServer();
            app.UseRouting();
            app.UseAuthorization();

            app.UseEndpoints(routes =>
            {
                routes.MapHub<InfoRelay>("/InfoRelay");
            });
        }

Next, we’ll need to change index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    
    <script src="lib/@microsoft/signalr/dist/browser/signalr.js"></script>
    <script src="getmessages.js" type="text/javascript"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">

</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-2">
                <h1><span class="label label-default">Message</span></h1>
            </div>
            <div class="col-4">
                <h1><span id="messageInput" class="label label-default"></span></h1>
            </div>
        </div>
        <div class="row">&nbsp;</div>
    </div>
    <div class="row">
        <div class="col-12">
            <hr />
        </div>
    </div>
</body>

</html>

The signalr package that’s referenced is an npm package:

npm install @microsoft/signalr

Next, we need the getmessages.js:

function bindConnectionMessage(connection) {
    var messageCallback = function (name, message) {
        if (!message) return;

        console.log("message received:" + message.Value);

        const msg = document.getElementById("messageInput");
        msg.textContent = message.Value;
    };
    // Create a function that the hub can call to broadcast messages.
    connection.on('broadcastMessage', messageCallback);
    connection.on('echo', messageCallback);
    connection.on('receive', messageCallback);
}

function onConnected(connection) {
    console.log("onConnected called");
}

var connection = new signalR.HubConnectionBuilder()
    .withUrl('/InfoRelay')
    .withAutomaticReconnect()
    .configureLogging(signalR.LogLevel.Debug)
    .build();

bindConnectionMessage(connection);
connection.start()
    .then(function () {
        onConnected(connection);
    })
    .catch(function (error) {
        console.error(error.message);
    });

The automatic reconnect and logging are optional (although at least while you’re writing this, I would strongly recommend the logging).

Functions App

Oddly, this is the simplest of all:

    public static class Function1
    {       
        [FunctionName("messages")]
        public static Task SendMessage(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post")] object message,
            [SignalR(HubName = "InfoRelay")] IAsyncCollector<SignalRMessage> signalRMessages)
        {
            return signalRMessages.AddAsync(
                new SignalRMessage
                {
                    Target = "broadcastMessage",
                    Arguments = new[] { "test", message }
                });
        }
    }

The big thing here is the binding – SignalRMessage binding allows it to return the message to the hub (specified in HubName). Also, pay attention to the Target – this needs to match up the the event that the JS code is listening for (in this case: “broadcastMessage”).

Console App

Finally, we can send the initial message to set the whole chain off – the console app code looks like this:

        static async Task Main(string[] args)
        {
            Console.WriteLine($"Press any key to send a message");
            Console.ReadLine();

            HttpClient client = new HttpClient();
            string url = "http://localhost:7071/api/messages";
            
            HttpContent content = new StringContent("{'Value': 'Hello'}", Encoding.UTF8, "application/json");

            HttpResponseMessage response = await client.PostAsync(url, content);
            string results = await response.Content.ReadAsStringAsync();

            Console.WriteLine($"results: {results}");
            Console.ReadLine();
        }

So, all we’re doing here is invoking the function.

Now when you run this (remember that you’ll need to run all three projects), press enter in the console app, and you should see the “Hello” message pop up on the web app.

References

https://docs.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-3.1

https://docs.microsoft.com/en-us/aspnet/core/signalr/dotnet-client?view=aspnetcore-3.1&tabs=visual-studio

https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-signalr-service?tabs=csharp

Download file from Azure storage using Javascript

.Net is an excellent framework – if you want proof of that, try to do, even very simple things, in Javascript. It feels a bit like getting out of a Tesla and travelling back in time to drive a Robin Reliant (I’ve never actually driven either of these cars, so I don’t really know if it feels like that or not!)

If you were to, for example, want to download a file from a Blob Storage container, in .Net you’re looking at about 4 lines of strongly typed code. There’s basically nothing to do, and it consistently works. If you want to do that in Javascript, there’s a Microsoft Javascript Library.

In said library, there is a function that should get a download URL for you; it’s named getUrl:

const downloadLink = blobService.getUrl(containerName, fileId, sasKey);            

If you use this (at least, when I used this), it gave me the following error:

Signature did not match

To get around this, you can build the download link manually like this:

const downloadLink = blobUri + '/' + containerName + '/' + fileId + sasKey;

Comparing the two, the former appears to escape the question mark in the SAS.

To actually download the file, you can use this:

        // https://stackoverflow.com/questions/3749231/download-file-using-javascript-jquery
        function downloadURI(uri, name) 
        {
            var link = document.createElement("a");
            link.download = name;
            link.href = uri;
            link.click();
        }

And the final download function looks like this:

        function downloadFile(sas, storageUri,
            containerName, fileId, destinationFileName) {

            var blobService = AzureStorage.Blob.createBlobServiceWithSas(storageUri, sas);
            
            const downloadLink = storageUri +'/' + containerName + '/' + fileId + sas;

            downloadURI(downloadLink, destinationFileName);
        }

React Tips: 4 – Propagating State

One thing that’s worth remembering about React is that when you’re updating state, only the Render method gets re-executed.

It’s easy (as I did) to fall into the trap of doing something like this:

    const myStyle = {
        background: this.props.backgroundFlag == 1 ? "blue" : "yellow",
        display: 'inline-block',
        height: '100%',
    }

    public render() {
        return <>
            <div className="myDiv" style={myStyle}>
        </>
    }

Imagine that this.props.backgroundFlag is actually the state of the containing component; when you change it, you would expect your component to reflect your change. However, in the case above, what will actually happen is nothing – because only the render method is re-evaluated when the virtual DOM changes.

To correct this, you need whatever needs to be re-evaluated inside the render method; for example:

    public render() {
	    const myStyle = {
	        background: this.props.backgroundFlag == 1 ? "blue" : "yellow",
	        display: 'inline-block',
	        height: '100%',
	    }

        return <>
            <div className="myDiv" style={myStyle}>
        </>
    }

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