JavaScript: Parsing dates with the destructuring assignment syntax

As I was scraping some stuff in a node module I got dates that were either full dates with time (“2017-01-01 12:00”) or just dates without time (“2017-01-01”) but I wanted to do some checking with months and days before sending back a proper Date-object, so I had to parse it out. Using the new ES6 destructuring assignment syntax it got really good looking:

/**
 * Converts a standard format date string, such as "2017-01-03 12:30" or "2017-05-06"
 */
module.exports = (dateRaw) => {
    if(dateRaw === undefined) {
        throw new Error('Invalid date provided!');
    }

    // Returns ['2017-01-03', '12:30']
    const [date, time] = dateRaw.trim().split(' '); 

    // Returns ['2017', '01', '03']
    const [year, month, day] = date.split('-'); 

    // Returns either the time, or, it it's missing, 0 hours and 0 minutes
    const [hours, minutes] = (time !== undefined) ? time.split(':') : [0, 0]; 

    // Do stuff...

    // To get the timezone correct, use Date.UTC
    return new Date(Date.UTC(year, month - 1, day, hours, minutes));
};

Just thought I’d share, because this used to get slightly ugly in ES5…

Javascript: Translating a page or app

Today when working a HTML5 app I realized that it would be sweet to translate it into other languages. It suited perfect for translation as it was a small app with little text and so I googled the subject and came into contact with a jQuery library called i18n which I found on github. It looked sweet and I tested it out using its small but concise guid (found here).

In short I created a structure that looked like this:


www/
- bundle/
--- resources_en.properties
--- resources_se.properties
- js/
--- jquery.i18n.properties.js
--- app.js
- index.htm

The translations were added into a file called XXX_LANG.properties which followed ISO-639 and ISO-3166 language and country code standard (such as resource_en.properties).
The process of fetching the translation was quite simple (as explained in their example):

resources_en.properties

#General stuff
general_save = Save
general_cancel = Cancel

#Home stuff
home_header = Welcome to my site!

resources_se.properties

#General stuff
general_save = Spara
general_cancel = Avbryt

#Home stuff
home_header = Välkommen till min sida!

Index.html

<body>
	<h1 id="home_header"></h1>
	...
	<button id="save_stuff" class="general_save"></button>
	<button id="cancel_stuff" class="general_cancel"></button>
</body>

app.js

//This will loop through all ID´s and classes it
//can find in its arrays and exchange their content with
//the translated content
var translationLoop = function ()
{
	//Translate all id´s
	var ids = ["home_header"];

	for (var i = 0; i < ids.length; i++)
	{
		var id = ids[i];
		jQuery.i18n.prop('generalHeader');
		$("#" + id)
			.text(window[id]);
	}

	//Translate all classes
	var classes = ["general_save", "general_cancel"];

	for (var i = 0; i < classes.length; i++)
	{
		var c = classes[i];
		jQuery.i18n.prop('generalHeader');
		$("." + c)
			.text(window);
	}
};

var generalTranslation = function (language)
{
	jQuery.i18n.properties({
		name: 'resources',
		path: 'bundle/',
		mode: 'both',
		language: language,
		callback: function () {
			//Once the translation file is found and loaded,
			//run the translation for our content
			translationLoop();
		}
	});
};

$(document)
	.ready(function ()
	{
		generalTranslation("se");
	});

JavaScript: Using Underscore.js to handle collections

As I was having to match two collections of objects in a project I was working on I faded out for a minute or two thinking of LINQ and the simplicities of working with collections in C#. I then woke up to horrid, nested for-loops in javascript and realized I had to do something. I googled around and found Underscore.js. This was a simple and fast javascript library for working with collections.

I made an example where I had a list of people and another list with some of the people I had already saved. I wanted a new list with the non-saved people. One way is to create a new list, loop over the list with all the people and within it loop through the list with saved people and compare it and add to the new list.
Or you can do as I did with Underscore.js:

http://jsfiddle.net/maffelu/2jCH9/

var people = [
    {name: "Magnus", "Age": 30},
    {name: "Fadangus", "Age": 29},
    {name: "Laban", "Age": 42},
    {name: "Bintje", "Age": 3}
    ];

var saved = [
   {name: "Fadangus", "Age": 29}
    ];

var result = _.filter(people, function(p)
                      {
                         return _.findWhere(saved, p) === undefined;
                      });

//result: [Object { name="Magnus", Age=30}, Object { name="Laban", Age=42}, Object { name="Bintje", Age=3}]

Development suggestions

I offer the following descriptive image to Rasmus Lerdorf, Anders Hejlsberg, Brendan Eich and all other people who might be maintaining, developing or creating new languages. Programming can be cold, logical and too intuitive (varies massively between languages). I offer a possible solution to this dilemma:
Language improvements

I hope some of you will implement these features in the future. Leave a comment if you do!

JavaScript: Calculate font-size on mobile devices

As I am making a HTML5 app for android devices using the Intel XDK I ran into a problem with the fonts. I use only em thinking that would work great on any screen size since its relative. I soon realized that it didn’t and that the text got reeeaally small on my phone when I uploaded the app. The reason seems to be zoom-related but I can’t swear to what the problem is aside from the fact that the screen has around 800px width and the standard font-size is still 16px which makes it unreadable. So I had to calculate the size myself and I found that the following formula worked like a charm:

 

var fontSize = Math.round(window.innerWidth * 0.04);
$('body').css('font-size', fontSize + "px");

This sets your font to a relatively easy reading size. Change the percentage if you need to alter the size!

PhoneGap: Attempt to call getDuration without a valid mediaplayer

I use phone-gap to handle the gap between HTML 5 and Android and I’ve been very pleased with the framework thus far. Today, however, I had a very annoying issue with the Media-object found in PhoneGap. I got the following error:

10-27 20:02:14.039: E/MediaPlayer(16984): error (-19, 0)
10-27 20:02:14.039: V/MediaPlayer(16984): callback application
10-27 20:02:14.039: V/MediaPlayer(16984): back from callback
10-27 20:02:14.039: V/MediaPlayer(16984): getDuration_l
10-27 20:02:14.039: E/MediaPlayer(16984): Attempt to call getDuration without a valid mediaplayer
10-27 20:02:14.039: V/MediaPlayer(16984): message received msg=100, ext1=-38, ext2=0
10-27 20:02:14.039: E/MediaPlayer(16984): error (-38, 0)

The Attempt to call getDuration without a valid mediaplayer part of the error seemed to be the most usable and I googled it. It turned out that android can only run a finite amount of sound instances. From the PhoneGap documentation:

Function media.release is a synchronous function that releases the underlying operating systems audio resources. This function is particularly important for Android as there are a finite amount of OpenCore instances for media playback. Developers should call the ‘release’ function when they no longer need the Media resource.

So, I added release() to my code, like this:

var change = new Media("change.wav");
change.setVolume = GlobalSettings.EffectVolume;
change.play();
change.release();

And, instead I got the following error in my catalog:

10-27 20:10:26.049: D/AudioPlayer(21033): renaming /storage/emulated/0/tmprecording.3gp to change.wav
10-27 20:10:26.049: E/AudioPlayer(21033): FAILED renaming /storage/emulated/0/tmprecording.3gp to change.wav

The problem seemed to be that the file wasn’t finished playing (obviously) so it crashed. I then tested to place the release after the sound had finished playing:

var change = new Media("/android_asset/www/sound/effects/Change.wav", function()
{
	this.release();
});
change.setVolume = GlobalSettings.EffectVolume;
change.play();

This has worked well and has caused no crashes. The second, optional, parameter of the Media object takes a callback that will be called when the sound has finished playing.