JQuery each loops and performance

In a project where I am one of the developers we had JavaScript code that was really slow. I started to analyze the code and I found out that we had a lot of jQuery each loops in the code. I thought that they could be a big part of the performance issue. I tried to replace all jQuery each loops with classic JavaScript for loops. After I replaced all loops the code was running on a few milliseconds instead of a few seconds. In must cases you will not se a boost like this, but we hade several nested loops and handled pretty big amount of data.

$(items).each(index,item)
{
      DoStuff(item);
}

was replaced with:

 
for(var index = 0; index < items.length; index++)
{
      var item = items[index];
      DoStuff(item);
}

The conclusion is that JQuery each loops could be a big performance thief and it better to use a classic JavaScript for loop.

Glyphicons on Windows Phone

If you using Twitter Bootstrap and glyphicons and having problem that the glyphicons is not showing up on Windows Phone you need to add the MIME-type to your web.config.

<System.webServer>
    <staticContent>
       <mimeMap fileExtension=".woff" mimeType="font/x-woff" />
    </staticContent>
</system.webServer>

Get coordinates from photo with JavaScript

When you take a photo with your mobile phone, photos will be geotagged. This information could be used for to show on a map where the photo is taken. This post will show you how to read this information with HTML5 and JavaScript.

To help me with this I using to external librarys written by Jacob Seidelin, binaryajax and exif-js.

To read the input file I using FileReader API in HTML5.

The coordinates returned from the EXIF data is in WGS84 degrees/minutes/seconds, for to show them on a map they need to be converted to WGS84 decimal.

//Get the photo from the input form
var input = document.getElementById('Files');
var files = input.files;
for(var i = 0; i < files.length; i++)
{
            var file = files[0];
            var reader = new FileReader; // use HTML5 file reader to get the file
 
            reader.onloadend = function () {
                // get EXIF data
                var exif = EXIF.readFromBinaryFile(new BinaryFile(this.result));
 
                var lat = exif.GPSLatitude;
                var lon = exif.GPSLongitude;
 
                //Convert coordinates to WGS84 decimal
                var latRef = exif.GPSLatitudeRef || "N";  
                var lonRef = exif.GPSLongitudeRef || "W";  
                lat = (lat[0] + lat[1]/60 + lat[2]/3600) * (latRef == "N" ? 1 : -1);  
                lon = (lon[0] + lon[1]/60 + lon[2]/3600) * (lonRef == "W" ? -1 : 1); 
 
               //Send the coordinates to your map
                Map.AddMarker(lat,lon);
            } 
            reader.readAsBinaryString(file);   
}

Back button and tabs in Bootstrap

If you are using the tabs component in Twitter Bootstrap and want to navigate to a specific tab when the browsers back button is pressed you can use the onhashchange event to detect when the button is pressed. The code example below is navigating back to first tab when back button is pressed.

In the example code for Bootstrap tabs they added preventDefault to the click event handler for the tabs. To get this solution to work you need to remove preventDefault from the event handler.

var currentHash = null;
 
            window.onhashchange = function () {
                if (currentHash === location.hash) {
                    $("#tabs a:first").tab('show');
                    window.onhashchange = null;
                }
            };
 
            currentHash = location.hash;

Improved developer tools in Internet Explorer 11

I have run Windows 8.1 for a couple of weeks now. One of the news in Windows 8.1 is Internet Explorer 11. I have not used Internet Explorer as my main browser, but of course I wanted to try it out.

One of the reason I don’t have used Internet Explorer so much is that I think that Firebug had been much better than developer tools in Internet Explorer. But for Internet Explorer 11, they have done big improvements. You can for example debug with the windows pinned in the browser window, you do not need to press start for starting the debugger, it is just to add a breakpoint. An another thing I like in the new developer tools is that you do not need to refresh page, when a javascript has changed the DOM, it is updating in real time.

You also get help to see if elements are in line when you selecting an element (see image below). I think that could be a very helpful tool.

Internet Explorer 11 Developer Tools

The only thing that I miss is that I can nott set Internet Explorer in compability view. When working for a customer that use older versions of Internet Explorer is has been a very good feature to change document mode. When using Internet Explorer 11 I need to use a virtual machine to test websites on other browser versions than 11. Microsoft links to a tool that is called Browser Stack. I signed up for a evaluation account, but it dosen’t work well, it was lagging so it was very hard to do the testing.

IE 11 Developer Tools

Real time communication with signalR

If you need realtime communication and don’t want to use long polling ajax calls for example for an game or a chat and also want fallback if WebSockets not is supported, signalR is a good library. This is a short tutorial on how to use signalR in an ASP.NET MVC application.

If you want to use a WebSocket connection if it is supported by the client you need to use IIS8 and enable the WebSocket Protocol, read this post for a step by step guide.

If websocket is not supported, signalR has fallback to server side events and ajax long polling, so web browsers without support for websockets can also use signalR.

Add signalR libraries

The easiest way to add signalR to your web application is to use NuGet. It will add the assemblies and javascript libraries needed to the web project.

Install-Package Microsoft.AspNet.SignalR

Server side

First you need to set “aspnet:UseTaskFriendlySynchronizationContext” to true in settings in your Web.config if you want to use websocket.

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
  </appSettings>

Next step is to create a new class that inherits from PersistentConnection

public class MyConnection : PersistentConnection
{
}

In this new class you can override the methods OnConnected, OnReceived and OnDisconnected.

OnConnected
This method is called when a client connecting. Here can you for an example add users to users online lists.

OnReceived
This method is called when a message from the client is received, you send it further to your buisness logic or an other user (or users).

OnDisconnected
This method is called when a client disconnecting. Here can you for an example remove users from users online lists.

In my example I have a player object that handles logic for a player. To keep the player object alive I add a static dictionary with the connection id as key.

public class MyConnection : PersistentConnection
{
        private static Dictionary<string, Player> _players;
 
        protected override System.Threading.Tasks.Task OnConnected(IRequest request, string connectionId)
        {
            if (_players == null)
            {
                _players = new Dictionary<string, Player>;();
            }
 
            var player = new Player();
 
            _players.Add(connectionId, player);
 
            player.SomethingHappend += (sender, args) =&gt; Connection.Send(connectionId, "Hello!");
 
            return base.OnConnected(request, connectionId);
        }
 
        protected override System.Threading.Tasks.Task OnReceived(IRequest request, string connectionId, string data)
        {
            var player = _players[connectionId];
            player.DoStuff(data);
 
            return base.OnReceived(request, connectionId, data);
        }
 
        protected override System.Threading.Tasks.Task OnDisconnected(IRequest request, string connectionId)
        {
            var player = _players[connectionId];
 
            player.Dispose();
 
            return base.OnDisconnected(request, connectionId);
}
        }

Before you can start using your signalR server you need to map a route in Global.asax.cs. Add the route to the Application_Start method before other route mappings.

protected void Application_Start()
{
            RouteTable.Routes.MapConnection<MyConnection>("connection", "/my");
}

The url to the signalR server will now be http://pageurl/connection/my.

Connection.Send(connectionId,message) sending a message to a specific user using the connection id. It make’s it possible to have communications between two clients.

If you want to send a message to all connected users you should use Connection.Broadcast(message).

Client side

Start to add a reference to the signalR javascript library.

Connect
To connect to the signalR server use the relative url that you created with the mapping in Global.asax.cs.
If you want to know when the connection has successfully established use callback on the start function.
Use the stateChanged event if you want to know when states changes on the connection. For example you can use it for to tell users that connection has been lost.

The connection has four states:

  • Connecting
  • Connected
  • Reconnecting
  • Disconnected
var myConnection = $.connection('/connection/my');
myConnection.start(callback);
        myConnection.stateChanged(function (change) {
            if (change.newState === $.signalR.connectionState.connected) {
 
            }
        });

Send message
To send a message use the send(message) method on the connection object.

myConnection.Send(message);

Received

myConnection.received(function (message) {
     //Handle the message here.
});

That is all. It is not harder than that to use real time communication in your web application.

Browser mode in Internet Explorer

We building a web version of WordRoom, today when I tested the game on Surface RT it doesn’t look like expected. I tested in desktop and I had same issue there as I had in the Windows store app of Internet Explorer. But in desktop mode I could use Internet Explorer developer tools. It shows that Internet Explorer was in IE7-mode. Because we use a lot of HTML5 features, we want to run it in IE10-mode from start.

I searched the web for solution and I found a meta tag that fixed my issue.

<meta http-equiv="x-ua-compatible" content="IE=10" />

If you want to read more about this, read this page, http://msdn.microsoft.com/en-us/library/jj676915%28v=vs.85%29.aspx