Copy With Style: JavaScript Curios
Tags: javascript, clipboard, webdev
Published: 2021-12-27 11:53:47

As I progress with the notes I took driving [The Thing Is ...](https://dev.to/thumbone/the-thing-is-on-awesomeness-and-motivation-2i0j) and I approach completion, slowly I reach the point were we need to look at more specific code examples, and it is time therefore for the great unveiling ... The code rests on github:

https://github.com/bernd-wechner/Copy-with-Style

and we will digress quickly from the[ exploration of detecting changes in the DOM](https://dev.to/thumbone/monitoring-performance-1l7i), to introduce the basic implementation and cover some of the JavaScript curios uncovered in implementing it. These are notes I took while implementing it, meaning they constituted learning for me, and struck me as not very intuitive warranting a specific mention and memory jog).

# A JavaScript Class
It's convenient to capture feature-provision such as this (copying an HTML buffer to the system clipboard with styles intact) in a JavaScript Class. Convenient because classes encapsulate code and isolate it from the broader JavaScript environment providing a clean interface.

JavaScript classes are fairly customary and familiar in modern languages, and Javascript offers them in a fairly familiar manner. There's a great introduction on [mozilla.org](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes).  

The main surprise we touched on in this little library is that members are not declared in the customary manner. That is:

* **Properties** need no `var`, `const` or `let` are just assigned a value. In a truly Pythonesque manner.
* **Methods** also need no `function` in fact won't accept them. They are declared otherwise, just a functions are, but without the `function` keyword. Go figure.

I have to admit, this is a most puzzling feature of JavaScript syntax if ever I have seen one.

## Private Members

[Private members](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields) are a relative (and welcome) newcomer to JavaScript, and are declared simply by using `#` as the first character in the name of the property or method. Alas being relatively new this causes havoc with some of the [linters](https://www.testim.io/blog/what-is-a-linter-heres-a-definition-and-quick-start-guide/), [beautifiers](https://codebeautify.org/formatters-and-beautifiers) and [editors](https://www.javatpoint.com/javascript-code-editors) out there. Let's hope that goes away soon (confident it will). For the record I use [Eclipse](https://www.eclipse.org/ide/) with [Wild Web Developer](https://projects.eclipse.org/projects/tools.wildwebdeveloper), the [Atom editor](https://atom.io/) as beautifier and online JavaScript linters.

Still privacy is a thing well worth requesting and respecting and one of features Python classes lack. It is a welcome additions to JavaScript.

## `this` is a Thing

`this` is a  keyword with different meanings in different contexts. As far as we were concerned, inside a class it refers to the instance of the class. And so `this.property` is how to refer to a property of this instance of the class. 

Unfortunately in event handlers, `this` is an event instance, and if the handler is a class method, well ... when it refers to `this.property` no joy is had, as this is an event and not an instance of the class. Python handles "this" much more elegantly in my opinion making the instance references explicit arguments to methods, but this is not a piece on Python.

The solution in JavaScript is the `bind()` method, which functions have, and which provides the value for `this`.

So `method` passed as an event handler will have `this` holding an event, not the class instance, but `method.bind(object)` will have `object` as `this` when it runs. Of course, if we want it have the class instance as `this` it's simply `method.bind(this)` which is a kind of JavaScript custom it turns out.

This ([double entendre](https://en.wikipedia.org/wiki/Double_entendre) inescapable) is seen clearly in the `#copy_to_clipboard()` method in Copy With Style but also in a couple of schedulers and an observer.

This then is the heart of Copy With Style in a sense:

```javascript
#copy_to_clipboard() {
    function handler(event) {
    if (this.debug) console.log(`copy event handler triggered...`)
        event.clipboardData.setData('text/html', this.HTML);
        event.clipboardData.setData('text/plain', this.text);
        event.preventDefault();
        document.removeEventListener('copy', handler, true);
    }

    document.addEventListener('copy', handler.bind(this), true);
    document.execCommand('copy');
}
```

As you can see, it wants `this.HTML` and `this.text` which are Copy With Style instance properties set by `this.prepare_copy()` and so we make the class instance available in `this` by passing not `handler` but `handler.bind(this)` to the copy event listener.

That is another JavaScript curio that takes some getting used to. The binding of this to this ... 

# `async` is a Thing Too

The `async` keyword is rather misleading alas. As JavaScript is essentially single threaded and it alludes to, well, [multithreading](https://en.wikipedia.org/wiki/Multithreading_(computer_architecture)) or [multiprocessing](https://en.wikipedia.org/wiki/Multiprocessing) but it is not to be. As discussed above, all async does is flag a function as a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). That is, a function runs and returns, but an async function just returns having put the function on the end of an [event loop queue](https://javascript.info/event-loop). It will run then, as soon as possible after everything else that was queued runs. What this does is free the event loop up to run the functions already ahead of this newly queued async function.

But if we `await` the function when we call it, then it does not return immediately. It queues the async function as before, but not before telling the promise to call back right here when it's done. That is `await` provides a means to continue running at this line as if we'd never left (state preserved), while permitting the queued promise to run (by saving its state and returning).

To summarise, if we have two functions:

```javascript
function normal() { console.log("I'm normal"); return "I'm done"; }
async function oddball() {console.log("I'm an oddball"); return "I'm done"; }
```

then calls to these functions operate as follows:

`result = normal()` runs `normal()` and returns when it's done. result contains "I'm done".

`result = await oddball()` puts `oddball()` at the end of the event loop queue, and waits for its turn to come round, and for it to run and then returns with result containing "I'm done" (the mechanism of that wait is though, to save state, and register with the promise a call-back to this line with state intact when it's done - creating the local illusion of a blocking call while actually returning - and it's because await returns, and only returns a promise that it can only be used in `async` functions, which are functions that return promises.

`result = oddball()` puts `oddball()` at the end of the event loop queue, and returns immediately, with `result ` now a Promise object. Not much use if we want its returned value. We can't get hold of it's returned value this way.

We can though, get hold of the returned value of the function `oddball()` ... which is "I'm done" by attaching a function to it via `.then(function_to_call_with_return_value_of_oddball_as_an argument)` sort of like this:

`oddball().then(return_value => { result = return_value })`

In case it's not clear this `return_value => { result = return_value }` is just an anonymous function, we could as well write the above line:

```javascript
function noname(return_value) { result = return_value; }
oddball().then(noname);
```

 This will set the value of `result` when `oddball()` returns.

There's one problem. If we don't give `oddball()` a chance to run first it won't complete. For example if we do this:

```javascript
let result = "nothing"
function noname(return_value) { result = return_value; }
oddball().then(noname);
console.log(result)
```

Then on the console we will see:

```
nothing
I'm an oddball
```

That is, result, has the value "nothing" not the value that `oddball()` returned ("I'm done") because we didn't give `oddball()` a chance to run before we logged the result to the console. We need to pause our run, put ourselves on the event queue, let `oddball()` run then if we check `result` it will contain "I'm done". And that looks like this:

```javascript
result = "nothing"
function noname(return_value) { result = return_value; }
result_is_ready = oddball().then(noname);
await result_is_ready;
console.log(result)
```

Where `await` is the "pause" that puts our continuation onto the end of the event queue, and returns, and (calling code willing) lets `oddball()` run. To wit, this will produce on the console:

```
I'm an oddball
I'm done
```

I wrote "Calling code willing" because `await` returns, all it can do is cede control to whoever called the function it is in. it is not until this bubbled to the top of the JavaScript processing stack if you will that JavaScript is free to run tasks on the event queue.

That is consider this:

```javascript
result = "nothing"
async function outer() {
    async function inner() {
        function noname(return_value) { result = return_value; }
        result_is_ready = oddball().then(noname);
        await result_is_ready;
        console.log(result)
    }
    inner();
    while (true) {}; // An infinite - neverending - loop
}

outer();
// JavaScript is done now.
```

`oddball()` never runs, and it never calls back to the state-preserved `await` because outer() never returns and the JavaScript engine remains occupied evermore with `while (true) {};`. And while that's an extreme and artificial example, the point is that any code in place of that infinite loop or analogously placed after the promise was queued but running before JavaScript finished (like any code after `outer()` and before `// JavaScript is done now.`) will run before `oddball()` ever does. Because JavaScript has to fall idle before it will take the next task off the queue. Running code always has the option and runs the risk, of hogging all of the JavaScript engine's attention!

An voila! This may appear convoluted, and it certainly is a little, but the central idea is that a Promise schedules the function to run by placing it at the end of an event queue, and  when it runs, we can ask it to run a function of our choosing that receives its return value as an argument. But unless we take a break and pop ourselves onto the same event queue behind the promised function we will never see it fulfilled, this is the single-threaded nature of JavaScript on display.

In summary, `async` means a function no longer returns its return value, but instead returns a Promise, and the return value can be accessed either by using `await` or by offering the promise a function to call with the return value as an argument (using `.then(function)`).

## `async` chains :link:

Because an async function does not return the function's return value but a Promise object, to get the result we must `await` it. Therein lies a small domino effect. `await` can only be used in an `async` function. That's nice little JavaScript rule there, a tautology even, as await returns a promise and `async` is the keywords that flags a function as a promise returning function (and not a value returning function). 

Which all means that if we want a result from an `async` function we can only get it in an `async` function (i.e. we can only await a result in an async function). And so one async begets another and they chain ... and next thing you know it all your functions are `async` ;-).

In Copy_With_Style, this chain of `async` bubbles all the way up to the button click handlers `copy()` and `to_clipboard()`. At which point we breathe a sigh of relief because the click handler can accept an `async` function, in no small part because it really doesn't care about a return value.

I see [Jim](https://stackoverflow.com/users/8427/jim) provided [a little insight](https://stackoverflow.com/a/128966/4002633) into that on [Stack Overflow](https://stackoverflow.com/). Namely that this area is not well documented and standardised to begin with (i.e. what the return value of event handlers does if anything). Either way we can take for granted and be thankful that the click handler is happy to have an async function. 

Still, what does that mean? Consider this, click the button and your handler is called and runs. That's the normal scenario. 

Now with an async function, click the button and the async function runs. But all that means is it puts the actual function on to the end of a event queue and it will run when its turn comes around. In short it doesn't run immediately and the return value isn't accessible in the same way. 

In practice this means very little because, as it happens, JavaScript has a dedicated queue for promises, and resolves all the code generated promises before it looks at UI events, which have their own queue. These are generally called the micro and macro task queues, with the macro queue only consulted when the micro queue is empty and the micro queue only consulted when the JavaScript engine falls idle (has nothing else to do), and promises generally occupying the micro queue and UI events the macro queue. 

Which is why, as we [discussed earlier](https://dev.to/thumbone/deferring-to-the-user-interface-3fi9) and see in the implementation of:

```javascript
#defer_to_UI(how_long = 0) {
    return new Promise(resolve => setTimeout(resolve, how_long));
}
```

A simple promise is not sufficient to see UI events processed, because promises are queued on the micro queue and executed before any UI events on the macro queue get to be handled. Which is where the browser supplied `setTimeout()` function comes in which queues a function on the macro queue! In fact it should be names `PutOnMacroQueue(function)` ...

# The Object as an Argument

Discussed under [Bringing it All Together](#bringing-it-all-together) essentially the way JavaScript supports (or better said does not support) named function arguments with default values and optional provision by the caller (all Python does natively) it requires you to replace all arguments with a single object that has properties. And there's a syntax that is tolerable but fluffy. 

# The Width of `<progress>`

I'm pleased to implement a `<progress>` element here, as the lack of one had been a long standing gripe with HTML with umpteen 3rd party solutions. Finally standardised and stylable. It's great to see HTML and JavaScript evolving.

To use it sensibly though we wanted to restrict updates to then and when it would cause a visible change, and so we needed a measure of elements to process (cycles in our function) per pixel of progress bar width. The former we know, the latter is tricky.

Turns out it has no property to tells us that. The nearest thing available is [.clientWidth](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth) which strangely includes padding, and so we have to write:

```javascript
#bar_width(progress_bar) {
    const style = window.getComputedStyle(progress_bar);
    return progress_bar.clientWidth - parseFloat(style.paddingLeft) - parseFloat(style.paddingRight)
}
```

removing the padding. But to make sure I got it right I checked the width this returned and took screenshots of the progress bar in Chromium and Firefox and lo and behold both returned the self same width (133 pixels) and I measured the bar on Firefox as 133 pixels (tick ✔) but Chromium renders it 146 pixels wide (bzzzt ✘). Go figure. Little can done about that, but it seems browser support in this space might be a little variable if, in the ideal, close to the mark. And for my purposes the smaller value (the consistently returned 133) is fine as not only is the difference small, this is the conservative value yielding more cycles per pixel and fewer updates.