986Displaying Text Data in a New Window

Problem: Data is stored in an array, you can not reload the page, you need to export it from the JS console.

Solution:

Create a New Window

var w = window.open()

Add a basic HTML header

w.document.writeln("<html><body><pre>")

Add your data

Assuming your data lives in an array called data, and has a sub-array with 2 values.

data.forEach(d => { w.document.writeln(d[0] + ", " + d[1])  })

Add a CSV Header

w.document.writeln("timestamp, temp")

Clear

w.document.body.innerHTML = "";

970Parsing Body JSON for quick inspection

An API dumps its output as string in the HTML body. Not really much use, not really easy to inspect it. The solutions? Parse the body with JSON.parse an inspect it in the console.

JSON.parse(document.body.textContent)
[{"id":115,"date":"2020-11-09T02:57:48","date_gmt":"2020-11-09T02:57:48","guid":{"rendered":"http:\/\/127.0.0.1\/aaa\/?
post_type=jobs&#038;p=115"},"modified":"2020-11-09T05:22:55","modified_gmt":"2020-11-09T05:22:55","slug":"another-test-
job","status":"publish","type":"jobs","link":"http:\/\/127.0.0.1\/aaa\/jobs\/another-test-job\/","title":{"rendered":"Another Test 
Job"},"parent":0,"menu_order":0,"template":"","_links":{"self":[{"href":"http:\/\/127.0.0.1\/aaa\/wp-
json\/wp\/v2\/jobs\/115"}],"collection":[{"href":"http:\/\/127.0.0.1\/aaa\/wp-json\/wp\/v2\/jobs"}],"about":
[{"href":"http:\/\/127.0.0.1\/aaa\/wp-json\/wp\/v2\/types\/jobs"}],"wp:attachment":[{"href":"http:\/\/127.0.0.1\/aaa\/wp-
json\/wp\/v2\/media?parent=115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},
{"id":96,"date":"2020-11-09T02:48:51","date_gmt":"2020-11-09T02:48:51","guid":{"rendered":"http:\/\/127.0.0.1\/aaa\/?
post_type=jobs&#038;p=96"},"modified":"2020-11-09T05:23:30","modified_gmt":"2020-11-09T05:23:30","slug":"test-
job","status":"publish","type":"jobs","link":"http:\/\/127.0.0.1\/aaa\/jobs\/test-job\/","title":{"rendered":"Test 
Job"},"parent":0,"menu_order":0,"template":"","_links":{"self":[{"href":"http:\/\/127.0.0.1\/aaa\/wp-
json\/wp\/v2\/jobs\/96"}],"collection":[{"href":"http:\/\/127.0.0.1\/aaa\/wp-json\/wp\/v2\/jobs"}],"about":
[{"href":"http:\/\/127.0.0.1\/aaa\/wp-json\/wp\/v2\/types\/jobs"}],"wp:attachment":[{"href":"http:\/\/127.0.0.1\/aaa\/wp-
json\/wp\/v2\/media?parent=96"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}]

964Gettting HTML Content from index.html into Vue

Vue index.html:

  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <div id="modalContent" style="display:none">
      <div id="modal1">
        Hello Modal Content Hello Modal Content
      </div>
    </div>
  </body>

Why add another hidden div to index.html? To be able to edit/add content without rebuilding and running npm run build.

In Vue:

  document.getElementById('modal1').innerHTML

Actually basic JS, nothing special to Vue.

963General JS Variables in Vue

Accesses JS from outside Vue:

index.html

...
<script>
  var test = "test";
</script>
...

In Vue:

  window.test

Obvious, but nevertheless

874CodeMirror – A Browser-based Text Editor

https://codemirror.net/

825Prototypal Inheritance and it’s Problem with Objects

Prototypal inheritance in Javascript is one of these features that sets it apart from other languages. A quick reminder:

var myDog = {};
myDog.legs = 4;
myDog.type = "Dachshund";
myDog.color = "brown";
myDog.says = "wau wau wau";

var yourDog = Object.create(myDog);
yourDog.says = "wan wan wan";

console.log(yourDog.type, yourDog.says);
> "Dachshund", "wau wau wau";

console.log(myDog.type, myDog.says);
> "Dachshund", "wan wan wan";

myDog is the prototype for yourDog, together they for a prototype chain. Any properties that would be added in myDog would also be accessible in yourDog. If yourDog adds a property with the same name (yourDog.says), this new property is returned when called. If a property is not defined, but present in the prototype, it will shine through.

So far so good.

Let's say we have an Array of dogs and we would like to prototypal inherit that whole array.

var myDogs = []
// fill array with dog objects

Following the pattern from above, the way to make a yourDogs array should be like that:

var yourDogs = Object.create(myDogs);

Let's update the first dog of the new yourDogs array to say something else:

yourDogs[0].says = "wow wow wow";

One would expect, that - because of the prototypal inheritance - that the changed value would only hide the original value. Let's check:

console.log(myDogs[0].says);
> "wow wow wow";

Ouch. The value was not as expected added to the prototypal branch only, but also to the original object. The prototype object and its chained offspring have the same object. Why is that? The answer is, that only variable types of Number, String, Boolean, etc are passed by value. Objects - and Arrays are objects - are passed by reference. (Check with typeof() to confirm the type of a variable.). That means the objects in our arrays are one and the same, and therefore any change in would will also occur in the other.

Seems logical, but still expectations are betrayed.

Let's consider the following case, this time without dogs. You have an array with objects and you want to apply a filter to some properties of the objects, which should be collected in another array. But - and this is crucial - you don't want the original array objects to change.

var original = [];
// add many, many objects

Because we saw before, that any changes in a new object would also reflect in the old one, we might be tempted to make a deep copy of the new one and then make our changes.

var copy = [];
$.extend(true, copy, original);     // Yes, that's jQuery
copy.map(function(element) {
    // make our changes to element
    //return element;
}

It's works, but it's rather kludgy. It takes quite a long time to make the deep copy and the prototypal chain breaks by doing that. Note also that the return of the map() function is not assigned to a new variable, and that the function does not need to return anything actually - because we are operating on the object directly.

A better solution would be this:

var better = copy.map(function(element) {
    var protoype = Object.create(element);  // create prototypal inheritance
    // make our changes to element
    return protoype;
}

better is now an array of objects which are prototypal linked to the original array. Any newly added properties will only be added to the new array - covering any properties which are already present in the original one.

console.log(original[0].dog.says);
> "wau wau wau"
console.log(better[0].dog.says);
> "wau wau wau"

better[0].dog.says = "wuff wuff wuff";

console.log(original[0].dog.says);
> "wau wau wau"
console.log(better[0].dog.says);
> "wuff wuff wuff"

That would I would have expected in the beginning. The nice things about Javascript is, that even when in works in unexpected ways, it's usually fairly trivial to align it again with your imagination. And sorry for bringing the dogs back.

819Single, Multiple Files and Javascript’s FileReader API

Getting a single file (with convenience jQuery event handler)
		
$('#open #chooseFile').change(function(e){
	var fileList = e.target.files;
	// get the one and only file
	var file = fileList[0];
	// further process file content...
	var reader = new FileReader();
	reader.readAsText(file, "text/plain");		
	reader.onload = localLoaded;
	reader.onerror = localError;
	// ...
});
Getting multiple files:
			

$('#open #chooseFile').change(function(e){
	var fileList = e.target.files;
	// loop over the files

	for (var i=0, file; file=fileList[i]; i++) {
		var reader = new FileReader();
		reader.readAsText(file, "text/plain");		
		reader.onload = localLoaded;
		reader.onerror = localError;
		// ...
	}
});

814Swapping Array Items in Javascript

var myArray = ["a", "c", "b"];
myArray.swap(1, 2);
console.log(myArray);
// ["a", "b", "c"];

Array.prototype.swap=function(a, b) {
    this[a]= this.splice(b, 1, this[a])[0];
    return this;
}
It could also be done with a temp var, but this solution seems to be the most elegant. The key to this is in the additional arguments the splice() function can accept.
splice(start, itemCount, additionalItems ...)
splice() removes elements denominated by the start and itemCount argument, and – if specified – inserts additional items at the same position. Also important to note is that splice() returns an array. And to turn that array into an item again we need to select it directly with [0].

813Copying Arrays in Javascript with slice(0)

Using Arrays in Javascript retain their values by references.
var oneArray = ["a", "b", "c"];
var anotherArray = oneArray;
anotherArray[0] = "z";

console.log(oneArray, anotherArray);
// ["z", "b", "c"], ["z", "b", "c"]
Ok, but let’s say you’ll need to make a copy of the array. How do you do that?
var oneArray = ["a", "b", "c"];
var anotherArray = oneArray.slice(0);
anotherArray[0] = "z";

console.log(oneArray, anotherArray);
// ["a", "b", "c"], ["z", "b", "c"]
If you’d really, really want you could also wrap it into a prototype function. Although the code-characters savings are minimal.
Array.prototype.copy = function() {
	return this.slice(0);
}

var anotherArray = oneArray.slice(0);
//vs
var anotherArray = oneArray.copy();
Minimal, but maybe contextually for self-explaining.

809Measuring Text in Canvas

HTML Canvas allows for the drawing of text with
ctx.fillStyle = "666";		// text color
ctx.textAlign = "center";		// alignment
ctx.font = "normal 12px Helvetica Neue";		// font
ctx.fillText("my Text, x , y);		// draw
Sometimes, you might want to draw a border around the text. Getting the textHeight should not present a problem, after all we can set the font size directly. But textWidth is not fixed in that way, because it depends (nnnn) on the actual text that is being displayed. ctx.measureText takes the text as an argument and returns an object with a width property, describing the width of the text.
var texttWidth = ctx.measureText(columnName).width;
width is for now the only inhabitant of that object, but it would be a fair guess, that it might be more densely populate in the future.