Google Sheets: custom functions in JavaScript



Later… hm, this thing runs like a dog (an unhealthy dog, to be clear). Obviously it has to go back up to the server and back, well, I assume. Presumably Google will either get it right soon… or pull it.



AWS Lambda testing: dump of notes so far

Lessons: node 6.10.3. Don’t try the current version – it won’t work.
In my js/noob world, Lambda-tester is looking the simplest way so far to test AWS Lambdas. I’m not quite there yet, but will return to this very soon.

  Id CommandLine
 -- -----------
 1 node -v
 2 npm -v
 3 function prompt(){}
 6 pwd
 7 cd C:\Github\Alexa\MagContact\src\PackageSet\test
 8 pwd
 9 ls
 10 mocha
 11 cd ..
 12 pwd
 13 mocha
 15 npm install lambda-tester --save-dev
 16 npm install nonsense --save-dev
 17 npm install nonsensex --save-dev
 18 npm install lambda-tester --save-dev
 19 ls
 20 mocha
 21 npm install mocha -g
 23 mocha
 24 Get-History


Windows 32-bit Installer:
Windows 64-bit Installer:
Windows 32-bit Binary:
Windows 64-bit Binary:



JavaScript and ES6: looping

As I am pretty much a noob at JavaScript (Alexa-related posts passim), I thought makes sense to incorporate the use of ES6 from the start. So I need to loop through an array… does ES6 bring anything new to the table on that? Googled that, found this.

The author and the series looks a good place to consult for ES6, so will return to his posts.

And for looping, this is the answer:

for (var value of myArray) {


JavaScript: some lessons learned

Checking for valid dates

A naive solution:

Minimal web server

As discussed yesterday, and not related to JS as such, but useful:

Get a count of the instances of a given “class” in the DOM

You have to walk those instances 1 by 1, getting the innerHTML or innerTEXT. As far as I can see, you can’t just aggregate it all up:

ES6 syntax: for / let /of

Sorting an array of objects by a single attribute, in this case:


Do stuff with an object, then add it to the array:

The 2 parts needed to make sense of a linked HTML:

'use strict';
// entry point...
(function () {
var link;
var content;
var composers = [];


var composerSetCount = content.getElementsByClassName("ComposerSet").length;

for (var index = 0; index < composerSetCount; index++) {
var composerSet = content.getElementsByClassName("ComposerSet")[index].innerHTML;
var composersAsElements = htmlToElements(composerSet);

for (let composerAsElements of composersAsElements) {
convertComposerTextToObject(composerAsElements, composers);

composers.sort(function(a,b) {return (a.lastName > b.lastName) ? 1 :
((b.lastName > a.lastName) ? -1 : 0);});

for (let comp of composers) {
var dates = [];
dates = validateComposerDates(comp);

<h1>" + comp.lastName + "</h1>
<h4>" + comp.firstNames + " " + comp.lastName + " " +
dates["Birth"] + " " + dates["Death"] + "</h4>

// functions...
function htmlToElements(html) {
var template = document.createElement('template');
template.innerHTML = html;
return template.content.childNodes;

function convertComposerTextToObject(composer, composersx) {
var composerText = composer.innerText;
if (composerText === undefined) {
// Treat the characters , and [ and - and ] as delimiters for splitting the string into tokens.
// An example of a string to be split:
// SMITH, John [4/21/1712-7/9/1768]
var separators = [',', '\\[', '\\-', '\\]']
var composerParts = composerText.split(new RegExp('[' + separators.join('') + ']', 'g'));

var theComposer = {};
theComposer.lastName = composerParts[0];
theComposer.firstNames = composerParts[1];
var dob = new Date(composerParts[2]);
if (dob.isValid()) {
theComposer.dateOfBirth = dob;

var dod = new Date(composerParts[3]);
if (dod.isValid()) {
theComposer.dateOfDeath = dod;


} // convertComposerTextToObject

function importComposers() {
link = document.querySelector('link[rel="import"]');
content = link.import;

function validateComposerDates(currentComposer) {
var composerDates = [];
composerDates['Birth'] = currentComposer.dateOfBirth === undefined ? "[unknown]" : currentComposer.dateOfBirth.toLocaleDateString('en-GB');
composerDates['Death'] = currentComposer.dateOfDeath === undefined ? "[unknown]" : currentComposer.dateOfDeath.toLocaleDateString('en-GB');
return composerDates;



HTML, Angular, Json

This is a variation on an earlier page that actually has a purpose. I used to chuck my favourite links into a piece of html.. well I’m still doing that, but at least I’ve separated the data from the code. I wanted to have a separate file for the Json, but in static pages, you can’t easily do that for security reasons, and I don’t want to spin up IIS etc for something so simple.

This is the end result (so you just keeping adding to the Json):

<pre><!DOCTYPE html>
<html ng-app="linksApp">
<title>My name is John</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" href="">
<body ng-controller="linksCtrl as ctrl">
<div class="container" ng-cloak>
<h2>{{ctrl.Summary}} (Count:{{ctrl.Links.length}})</h2>
<table class="table table-condensed">
<tr ng-repeat="links in ctrl.Links">
<td><a href="{{links.URL}}">{{links.Name}}</a></td>
<script src=""></script>
 <script type="application/javascript">
 var linksApp = angular.module("linksApp",[]);
 linksApp.controller("linksCtrl", [function() {
 vm = this;
 vm.Summary = "A Set of Links";
 vm.Links = Links;

<!-- data... -->
 var Links = [
 {"Name" : "My blog", "URL" : ""},
 {"Name" : "Foreigner - Double Vision - YouTube", "URL" : ""},
 {"Name" : "Acer 27\" monitor", "URL" : ""},
 {"Name" : "Chords for Hazard", "URL" : ""},