[en] Creating HTML Elements from JavaScript

If you want to create dynamic application in Java Script without frameworks like React or Vue.JS (and sometimes even with these), you will face the problem: how to create HTML elements dynamically in JavaScript.

First approach – bad

First approach you can do is to create string with HTML code. Then you can put it to innerHTML property.

let elements = '<p class="sample-class">First paragraph</p>';
document.querySelector('.container').innerHTML = elements;
//or with JQuery
$('.container').html(elements);

But this approach has two problems. First: if you want to generate content more dynamically (using ifs or loops) your code will be very ugly:

let elements = '<ul>';
for(let i=0;i<10;i++){
    elements+=`<li class="${i%2==0:'even':'odd'}">Element</li>`;
}
elements+='</ul>';

Second problem: if you want to use any variable inside, you need proper escaping, so content of this variables won’t be treated as HTML. Otherwise:

let title = "a+b<c";
let elements = `<h1>${title}</h1>`;
console.log(elements)// => "<h1>a+b<c</h1>"

Omitting escaping can lead also to security problems (XSS)

Second approach – good

Second approach is to use proper DOM’s methods to create elements.

let element = document.createElement('p');
element.classList.add('sample-class');
element.textContent = 'First paragraph';
document.querySelector('.container').append(element);

You don’t need to worry about XSS.

let title = "a+b<c";
let element = document.createElement('h1');
element.textContent=title;
console.log(element.outerHTML)// => "<h1>a+b&lt;c</h1>"

But problem is, that in this approach code starts to be long and writing starts to be tiring

My approach

To make coding easier I created library fast-creator (github, npm). Main idea is to put all details about new HTML element in one object and let the library to do boring stuff.

import {create} from 'fast-creator';

let element = create({tagName:'p', className:'sample-class', text:'First paragraph'});
document.querySelector('.container').append(element);

Code is shorter, and also you don’t have any problems with escaping strings if you want to use variables.

Let’s see bigger example. Code and equivalent HTML:

import {create} from 'fast-creator';

create({
    tagName: 'a',
    href: '/',
    title: 'some link',
    data: {
        a: 1,
        b: 2
    },
    classList: ['link', 'sample'],
    children: [{
        tagName: 'span',
        text: 'Link'
    }]
})
<a href="/" title="some link" data-a="1" data-b="2" class="link sample"><span>Link</span></a>

Type of tag is provided by tagName (default is div). Content could be set in 3 ways: text (which is transferred to textContent), html (to innerHTML) or children (which is an array that is executed recursively).

All other properties of object are translated to attributes (like in example href and title). Exception of this rule is class, because it is keyword in ES6, so there are properties className (string) and classList (array of strings). Second exception is data – you can put there attributes like to .dataset property of HTML elements.

Emmet

There is a plugin to code editors called Emmet. It converts css selectors for HTML. It inspired me to make code even shorter:

import {create} from 'fast-creator';

create('section.first#main')
<section class="first" id="main"></section>

Of course this not always will be helpful, especially if you need to read data from external variables, so you can combine this to methods

import {create} from 'fast-creator';

create('article', {
    className: 'main',
    children: ['p.first', 'p.last']
})
<article class="main"><p class="first"></p><p class="last"></p></article>

Links

[en] HTML vs XHTML – what is the difference

Polish version

Lot’s of people use HTML, but not many really understand it. If you don’t know what’s the difference between <br> and <br/> this article is for you.

What was before World Wide Web?

SGML (Standard Generalized Markup Language) is format for writing text documents with additional informations (tags). In 1986 it became ISO standard. SGML document look’s something like this:

<tag1>
    Some Text
    <tag2 attribute otherattribute="value">
</tag1>

Standard defines syntax, and how to parse it. SGML parser know, that there is tag with name tag1 and it has 2 child nodes: text and another tag.

But it doesn’t define what tag1 means (semantics). It’s general purpose language, it’s base for more specific applications like

HTML

Published in 1991, HTML defines for example that <a> is a link, and href attribute contains url.

But excluding HTML, SGML wasn’t so popular. That’s why not many people bother to even remember this name. But I think, that it is important to know the difference between a syntax and a semantics.

XML and XHTML

In 1998 was completed new standard: Extensible Markup Language (XML). It is successor of SGML: it carries only about syntax of document.

In 2000 W3C (organization, that makes web standard) published XHTML 1.0. It was HTML 4.01 witch syntax changed for XML – XHTML document is 100% valid XML document.

What is the difference between HTML 4.01 AND XHTML 1.0?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 <head>
   <title>XHTML 1.0 Example</title>
 </head>
 <body>
   <p>
     This is an example
     <br/>
     of XHTML
   </p>
   <div id="empty"/>
 </body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 strictl//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
 <head>
   <title>XHTML 1.0 Example</title>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 </head>
 <body>
   <p>
     This is an example
     <br>
     of XHTML
   </p>
   <div id="empty"></div>
 </body>
</html>

It looks similar, that’s why many people don’t see differences on first sight.

First big change is that XML don’t tolerate syntax errors. In case of error SGML would to try parse something, but XML should return error.

Every XHTML document should have XML declaration, that provides version of XML and encoding.

XML has namespaces, so you can combine many different format in one document. For example you can write XHTML inside SVG or RSS files.

Self closing tags

HTML provides mechanism for automated closing tags. For example <br> is self closing – it cannot have any content. Another example: <p> cannot have another <p> inside, so when you write

<p>first
<p>second
<p>last</p>

parser knows, that opening new <p> should automatically close previous. But as you see, it requires, that parser know individual behaviour of each tag. In XHTML you must close all tags manually, so every XML parser should parse a document correctly without any knowledge about this tags. If something isn’t closed, you will get an error.

But to have more readable code, in XML you have short syntax <br/> which is equal <br></br>. But it is important to know, that in HTML this / is ignored (as i said before, HTML tries to ignore syntax errors) and don’t do anythink.

If you write:

<body>
  <div/>
  <p>Some text</p>
</body>

if it is inside XHTML document, browser will parse as

<body>
  <div></div>
  <p>Some text</p>
</body>

but inside HTML document it will be

<body>
  <div>
    <p>Some text</p>
  </div>
</body>

Abandoned XHTML 2.0

At the beginning XHTML 1.0 and 1.1 has 2 big problems. First: it wasn’t fully supported by Internet Explorer untill version 9 (released in 2011, 11 years after XHTML was standarized). And remember, that evet then users didn’t updated theis browsers too quicly. So if you wanted to write XHTML, you still needed to serve it as HTML, so browser will parse it as HTML, so you don’t have any advantages of using XHTML.

Second problem was, that programmers didn’t like that idea, that in case of any syntax error whole webpage/application will stop working, and user will see big error message.

W3C proposed XHTML 2.0, which was designed to break backwards compatibility. This idea didn’t meet with approval of web developers, so in 2006 project was abandoned. But it isn’t the end of XHTML.

What is now – HTML5

After abandoning XHTML 2.0 W3C created new standard: HTML5. One of the main assumptions was that HTML and XHTML will be developed together as part of the same standard. You can choose your syntax, but everything else will be identical. After parsing code by browser it will be threaded identically.

W3C decided also, that HTML won’t be fully compatible with SGML specification, because no one really cares. They also introduced using MathML (still not supported by Chrome 😡) or SVG tags inside HTML file.

It’s important to know, that even if you don’t write namespaces in HTML, browser will add it automatically while parsing. You can test it by simple JS code:

var div = document.createElement('div');
div.innerHTML = '<p></p><svg></svg>';
console.log(div.children[0].namespaceURI);// -> "http://www.w3.org/1999/xhtml"
console.log(div.children[1].namespaceURI);// -> "http://www.w3.org/2000/svg"

It is important to know, that if you want to add svg elements to html by JS, you need to add namespaces manually, otherwise browser will not treat is as SVG, but rather like unknown HTML element.

var badSvg=document.createElement("svg");
console.log(badSvg.namespaceURI);// -> "http://www.w3.org/1999/xhtml"
var goodSvg=document.createElementNS("http://www.w3.org/2000/svg","svg");
console.log(goodSvg.namespaceURI);// -> "http://www.w3.org/2000/svg"

[en] How to send images in emails correctly

Polish version

Have you ever opened mail and noticed, that text is shown correctly, but images are not loaded? And your mail client gives you message: that images were blocked, and you need to click to open it.

This problem is common. It is so common, that it’s hard to find message with images, that loads correctly (unless you mark sender e-mail as trusted). It is so common, that many people I talked about it don’t notice it anymore, and other thinks, that the only solution is to avoid using images.

But reason why and solution is very simple.

Reason

Emails are sent as HTML. So many people treats it as a normal webpage – but they aren’t.

In normal webpage if you want to add image, you puts link to it in <img> tag. And for web browser it doesn’t matter, if it is on the same server or not. So in emails the easiest solution is to upload image to any webserver and put full url inside <img> tag inside email.

But this behavior is great opportunity for spammers. If spammer sends spam, it would like to know if it was readed. Then he know to which email is worth sending more spam. So he could add to each message <img> with unique url, but all pointing to his server. When someone opens mail, also opens image – which means connecting to his server. That’s why mail programs blocks images.

Solution

To send email with images you need to add these as attachments. It solves problem, because image will be sended with email, without any need to ask other server.

Adding attachment, you can specify ContentID (cid). it will be use as url inside mail’s html.

<img src="cid:your_content_id" alt="">

Also don’t forget to set this attachment as inline – so it won’t show your receiver on attachment’s list.

You also could use data: url with base64 encoding, but this isn’t supported in all mail programs, especially in Microsoft Outlook. As I said earlier, email is not a webpage and you can use only small part of browser’s capabilities if you want to be sure, that everyone will reads your message correctly.

[en] Javascript tricks #1 – extendings prototypes

Polish version

Javascripts gives us lots of methods to perform operations on arrays in functional style, such as filter, map, reduce etc.

const input=[
    {name: "John", points: 5},
    {name: "Bob", points: 0},
    {name: "Alice", points: 4}];
console.log(input.filter(x=>x.points>0).map(x=>x.name));
// => ["John", "Alice"]

But capabilities of this built-in methods are not so powerful like for example in C# and .Net.

There are libraries designed for this purpose. For example Lodash has a lot of functions:

var _ = require('lodash');

const input=[
    {name: "John", points: 5},
    {name: "Bob", points: 0},
    {name: "Alice", points: 4}];
console.log(_.map(_.filter(input, x=>x.points>0),x=>x.name));
// => ["John", "Alice"]

As you see, this method are not invoked on arras but gets arrays as a parameter. If you want to chain methods (like in example, filter and there map) code starts to be less readable – name of method map is on beginning of line, but it’s method – on end.

Extensions

In C# there is something called ‘extension method’. This is method, that is added to class outside it.

public static class A{
    public static string MyMethod(this List<string> a){
        return "Hello, world!";
    }
}

//...

var animals = new List<string>{"cat", "dog", "lion"};
Console.WriteLine(animals.MyMethod());

You can do very similar think in JS. Javascript uses prototype-based inheritance, so all arrays (not every array-like object is array) inherit from Array.prototype. It is object built-in browser, but you can add to it properties and methods like to any other objects.

const animals = ["cat", "dog", "lion"];
Array.prototype.myMethod=function(){return "Hello, world!";}
console.log(animals.myMethod());// => "Hello, world!"

Now many experienced JS developers probably treats me like heretic. It is because main difference between this and C# extension method is that in C# extension methods exist in some namespace and it is visible only after importing this namespace. If you edit prototype in JS, you do it globally (not only for current scope, but for all arrays). It is called prototype pollution.

So be very careful with it. If you have project written by more than you – please inform other programmers what you doing. And I advise against doing this in libraries.

What methods you can add?

I will show you some examples of useful methods you can add. If you want, you can download npm library I created (but I encourage you to write yourself)

npm i prototype-extensions
# OR
yarn add prototype-extensions

sum

First of methods simply returns one number, that is sum of all items.

const array=[10, 2, 5, 0.5];
console.log(array.sum());// => 17.5

Sometimes we don’t have plain numbers, but complex objects. That is why a good idea it pass as argument function, that will extract plain number for us.

const work=[
{worket: 'Alice', workedHours:8, pricePerHour:20},
{worket: 'Bob', workedHours:10, pricePerHour:15},
{worket: 'John', workedHours:2, pricePerHour:30},
];
const totalCost = work.sum(x=>x.workedHours * pricePerHour);
console.log(totalCost);// => 370

Implementation

if (!Array.prototype.sum) {
    Array.prototype.sum = function (fun = x => x) {
        return this.reduce((sum, item) => sum + Number(fun(item)), 0);
    }
}

First if is to ensure, that we don’t override any already existing method.

At second line we create new function and assign to prototype of arrays. As parameter we take other function, that we will execute on each array of item. Default value of this parameter is function, that do nothing. If this syntax is unclear for you, here is other version that do the same

 Array.prototype.sum = function (fun) {
    if(!fun){
        fun = function(input){
            return input;
        }
    }

sortBy

It is very common think to sort. But in built-in js method require function that compare 2 objects and return if first is bigger, smaller or equal. It will be much more convenient to just sort by value (or multiple values)

const people=[
    {name:'Anna', age:18},
    {name:'Bob', age:25},
    {name:'John', age:17},
];
people.sortBy(x=>x.age);
console.log(people);// => [
                    // =>     {name:'John', age:17},
                    // =>     {name:'Anna', age:18},
                    // =>     {name:'Bob', age:25},
                    // => ];

Implementation

if (!Array.prototype.sortBy) {
    Array.prototype.sortBy = function (...args) {
        let orders = args.map(x => typeof x == 'function' ? x : y => y[x]);
        let compareFunction = (a, b) => {
            for (let order of orders) {
                let valueA = order(a);
                let valueB = order(b);
                if (valueA > valueB)
                    return 1;
                else if (valueA < valueB)
                    return -1;
            }
            return 0;
        };
        return this.sort(compareFunction);
    }
}

I assumed, that you could want to order by many values (if some values were equal sort by next). That’s why I used …args notation (it creates an array of function’s arguments) and used for..of loop.

I also assumed, that you could as argument put not only method, but also string with name of property (that is why I put map function)

min & max

How to find biggest or lowest element of array? You could sort it, and then get first/last element, but this solution has one problem – performance. it’s much much quicker to make method special for finding one minimum/maximum element.

const array1 = [5,10,2.2,-30];
console.log(array1.min()); // => -30
console.log(array1.max()); // => 10

But in objective world, it’s rare to have arrays of plain numbers.

const people=[
    {name:'Anna', age:18},
    {name:'Bob', age:25},
    {name:'John', age:17},
];
console.log(people.min(x=>x.age));// => {name:'John', age:17}

Implementation

if (!Array.prototype.max) {
    Array.prototype.max = function (fun = x => x) {
        let value = null;
        let object = null;
        for (let item of this) {
            const itemValue = fun(item);
            if (typeof itemValue === 'number' && !isNaN(itemValue) && (value == null || itemValue > value)) {
                value = itemValue;
                object = item;
            }
        }
        return object;
    }
}

groupBy

Sometimes you want to group some objects by common property:

const people=[
    {name:'Alice', type:'teacher'},
    {name:'Bob', type:'student'},
    {name:'John', type:'student'}
];
const grouped = people.groupBy(x => x.type);
console.log(grouped); // => Map(2){
                      // =>  "teacher" => [{name:'Alice', type:'teacher'}],
                      // =>  "student" => [{name:'Bob', type:'student'}, {name:'John', type:'student'}]
                      // => }

You can ask, why I return Map instead of simple Object? It’s because in Map key could be everything, not only strings and symbols, so this gives us more flexibility.

Implementation

if (!Array.prototype.groupBy) {
    Array.prototype.groupBy = function (fun = x => x) {
        const ret = new Map();
        for (const value of this) {
            const key = fun(value);
            if (ret.has(key))
                ret.get(key).push(value);
            else
                ret.set(key, [value]);
        }
        return ret;
    }
}

Future

In ECMAScript Next specification there is proposed bind operator :: ( https://github.com/tc39/proposal-bind-operator) which would be better solution that extending prototypes. But it is on stage 0, which means it isn’t sure that it will be added to JavaScript specification, and even if, it would take lots of time until browsers will implement this.

Read more:

[en] Promises in Vue – how to do api requests correctly

Polish version

On this article I assume, that you have knowlege about promises in JS. If not, read MDN article.

Look at this vue component and try to find bug in it:

<template>
    <div>
        <button @click="load(1)" :class="{active:active===1}">Show first article</button>
        <button @click="load(2)" :class="{active:active===2}">Show second article</button>
        <p v-if="loader">Loading...</p>
        <p v-else>{{content}}</p>
    </div>
</template>
<script>
export default {
    data(){
        return {content:null, active:null, loader:false}
    },
    methods:{
        load(id){
            this.active=id;
            this.loader=true;
            fetch(`/article/${id}`)
                .then(response=>response.json())
                .then(json=>{
                    this.content=json;
                    this.loader=false;
                });
        }
    }
};
</script>
<style>
    button.active{
        color:red;
    }
</style>

It is simple component, that has 2 buttons. After clicking on button it loads content from rest api and adds class active so you can see which article is opened. It even has message ‘Loading…’ until content was loaded. It is so simple, what could be wrong here?

But what will it do, when you try click both buttons quickly? Probably nothing, because you probably testing it on localhost, so api responds faster that you click. And even if it is slower (or you simulate slow network in dev tools) probably nothing happens.

It is because server responses in the same order that you clicked. But it is possible, that processing of first request will take more time, that the second. Then your content variable don’t match active variable, so for user content of article don’t match selected button.

You can think, so if works correctly most of time, that it is not worth to carry. But in realiy this is the worst kind of bug: user/customer says, taht sometimes your softwarre is buggy, but when you tries, it works complettly fine. But customer don’t stop complaining.

My method how to reproduce such bug is to add random sleep to all requests on server, so all responses will be received in random order.

How to fix it

There are many ways to fix it. The simplest could be, to disable buttons when loader is true. But this isn’t user-friendly and for me it is hiding bug, not fixing.

Second idea is to test if this request is still valid

        load(id){
            this.active=id;
            this.loader=true;
            fetch(`/article/${id}`)
                .then(response=>response.json())
                .then(json=>{
                    if(this.active!=id) return;//id changed, so ignore
                    this.content=json;
                    this.loader=false;
                });
        }

In this example we tested if id was changed, because we assume that if we ask api multiple times for the same id we get the same response. If we can’t assume that, use Symbol.

        load(id){
            const loadSymbol = Symbol();
            this.loadSymbol = loadSymbol;
            this.active=id;
            this.loader=true;
            fetch(`/article/${id}`)
                .then(response=>response.json())
                .then(json=>{
                    if(this.loadSymbol != loadSymbol) return;//loadSymbol changed, so ignore
                    this.content=json;
                    this.loader=false;
                });
        }

Promise Status

Let’s look at this class:

import {Enum} from 'enumify-fork';

export default class PromiseStatus {
    constructor(promise = null) {
        this.promise = promise;
    }

    set promise(promise) {
        this.data = null;
        this.error = null;
        this.status = PromiseStatus.Status.noPromise;
        this._promise = null;
        if (promise) {
            this._promise = promise;
            this.status = PromiseStatus.Status.pending;
            promise.then(data => {
                if (this._promise === promise) {
                    this.data = data;
                    this.status = PromiseStatus.Status.resolved;
                }
            }, error => {
                if (this._promise === promise) {
                    this.error = error;
                    this.status = PromiseStatus.Status.resolved;
                }
            })
        }
    }

    get promise() {
        return this._promise;
    }
}

PromiseStatus.Status = class extends Enum {
};
PromiseStatus.Status.initEnum(['noPromise', 'pending', 'resolved', 'rejected']);

You provide promise to it, and it gives you property status, which informs you if promise is pending (data are still loading), resolved (data loaded successfully) of rejected (some error). data and error contains variables provided by resolve and reject respectively.

But what is the difference between this and standard .then().catch()? Answer is, that you can use this properties directly in vue template (for example in v-if) or computed properties, and your html will be rerendered automatically.

You can download this class from npm/yarn. Link to github repo: https://github.com/matrix0123456789/reactive-promise-status

yarn add reactive-promise-status
OR
npm install reactive-promise-status

How to use it?

<template>
    <div>
        <button @click="load(1)" :class="{active:active===1}">Show first article</button>
        <button @click="load(2)" :class="{active:active===2}">Show second article</button>
        <p v-if="content.status === Status.pending">Loading...</p>
        <p v-else-if="content.status === Status.resolved">{{content.data}}</p>
        <p v-else-if="content.status === Status.rejected">Error while loading article</p>
    </div>
</template>
<script>
import PromiseStatus from 'reactive-promise-status';

export default {
    data(){
        return {content:new PromiseStatus(), active:null, Status:PromiseStatus.Status}
    },
    methods:{
        load(id){
            this.active=id;
            this.content.promise = fetch(`/article/${id}`).then(response=>response.json());
        }
    }
};
</script>
<style>
    button.active{
        color:red;
    }
</style>

Note, that I created one object of type PromiseStatus, and in load method I changed its property promise. That is because if you set content as null and try to check content.state you will get exception. That’s why there is 4th status noPromise

[en] Backdrop-filter – biggest new css feature of the year

In 2007 Microsoft released Windows Vista, with it’s new GUI style called Aero Glass. The biggest graphical feature of this was transparent background of window with blurred everything below. It was 12 years ago, and i still think, blurred background looks great.

But creating this effect in webpage wasn’t easy. There was css property filter, but it applies at whole element, and don’t touch what is below. Backdrop-filter can do exactly the same effects, but for everything below our object. Let’s see this difference on screenshots:

filter: blur(10px);
https://codepen.io/MateuszKrawczyk/pen/zYOBdpw
backdrop-filter: blur(10px);
https://codepen.io/MateuszKrawczyk/pen/OJLXjzG

But not only blur. You can use this for all filter functions:

  • blur
  • brightness
  • contrast
  • grayscale
  • hue-rotate
  • invert
  • opacity
  • saturate
  • sepia

This feature was earlier in MS Edge and Safari, but now it is also in Chrome 76. Unfortunately, we’re still waiting for firefox to implement this, and implementation in Chrome is sometimes buggy.

Read more: