Tuesday, January 7, 2020

Implement TabPages in Vanilla JS and CSS

Today, as the lunch break challenge I decided to create Tabs in Vanilla JS and that's what I made:

About

In descriptive writing, the author does not just tell the reader what was seen, felt, tested, smelled, or heard. Rather, the author describes something from their own experience and, through careful choice of words and phrasing, makes it seem real. Descriptive writing is vivid, colorful, and detailed.

Good descriptive writing creates an impression in the reader's mind of an event, a place, a person, or a thing. The writing will be such that it will set a mood or describe something in such detail that if the reader saw it, they would recognize it.

To be concrete, descriptive writing has to offer specifics the reader can envision. Rather than "Her eyes were the color of blue rocks" (Light blue? Dark blue? Marble? Slate?), try instead, "Her eyes sparkled like sapphires in the dark."

Details

To be evocative, descriptive writing has to unite the concrete image with phrasing that evokes the impression the writer wants the reader to have. Consider "her eyes shone like sapphires, warming my night" versus "the woman's eyes had a light like sapphires, bright and hard." Each phrase uses the same concrete image, then employs evocative language to create different impressions.

To be plausible, the descriptive writer has to constrain the concrete, evocative image to suit the reader's knowledge and attention span. "Her eyes were brighter than the sapphires in the armrests of the Tipu Sultan's golden throne, yet sharper than the tulwars of his cruelest executioners" will have the reader checking their phone halfway through. "Her eyes were sapphires, bright and hard" creates the same effect in a fraction of the reading time. As always in the craft of writing: when in doubt, write less.

n this excerpt from Jamaica Inn by Daphne du Maurier, notice the writer's choice of adjectives, adverbs, and verbs. Granite. Mizzling. Du Maurier's choice of words allows the reader to almost feel the weather occurring on the page.

Contacts

First name:

Last name:

A paragraph without a header.


The HTML is the following:

Tuesday, December 24, 2019

Swagger UI for ExpressJS

Swagger is a tool that allows to describe a service API. One of the reasons for that is creation of documentation for all API functions so make it easy to examine and navigate through. Even further, swagger allows to call the API functions in a simple manner like let's say Postman does. So working with ExpressJS I just discovered the swagger-ui-express library that gives us opportunity to build the swagger UI in literaly few steps. So I created the simplest possible example (Github Link) that will be be taken to pieces below step-by-step.

As usually, we start with installing the package npm install -s swagger-ui-express.

Now let's create a simple ExpressJS HTTP server with several CRUD functions.

const express = require('express');
const app = express();

const uuidv4 = require('uuid/v4');

//stores the books collection
let _books = [];

app.route('/api/book')
    .get(function (req, res) {
        res.json(_books.filter(b => b.id == req.query.id));
    })
    .put(function (req, res) {
        let book = JSON.parse(JSON.stringify(req.query));
        book.id = uuidv4();
        _books.push(book);
        res.json(book);
    })
    .delete(function (req, res) {
        _books = _books.filter(b => b.id != req.query.id);
        res.json(_books);
    })

app.get('/api/books', function (req, res) {
    res.json(_books);
});


// start the server in the port 3000
app.listen(3000, function () {
    console.log('Start app listening on port 3000.');
});

The service exposes functions allow to get/add/delete records (books) and retrieve all the books as well.

Next step is to display that API on UI.

Tuesday, December 3, 2019

Update styles in bulk via JavaScript

Updating an element style using javascript is pretty easy: document.getElementById(id).style.property = new style. But what if we have hundreds/thousands/.. elements to be updated? Calling the property setter above will force page re-rendering every time, so it would take considerable time. That's where bulk update is really helpful. Instead of applying styles after every change we can compose the css sheet with all the styles collected together and appy it at once.

Tuesday, October 29, 2019

Array.prototype.forEach() function does not await..

Recently I discovered that Array.prototype.forEach() function is not suitable for 'awaitable' functions. Let's have a look at an example.

const getAsyncData = (n) => {
   return new Promise((resolve, reject) => {
      setTimeout(() => resolve(n), 500)
   })
};

const arr = [1,2,3,4,5];

//forEach example
(async () => {
   let total = 0;
   arr.forEach(async n => {
      let res = await getAsyncData(n);
      console.log(res);
      total += res;
   });
  
   console.log('total = ' + total);
})();

I expected that forEach will await for every call of the getAsyncData() function so that to calculate total correctly, but surprisingly the result was different.

total = 0
1
2
3
4
5

Obviously, forEach ignores await keyword and quits immediately so total is not calculated.

Sunday, September 15, 2019

React create-react-app edit WebPack DevServer settings (adding SSL certificate options)

I have a React application that has been created with the create-react-app tool and I needed to change WebPack DevServer settings. Three the most popular suggestions I found on the internet were:
  • npm run eject
  • fork the react-scripts and make necessary changes
  • use a library like react-app-rewired
Unfortunately, all of them have various drawbacks (I will not discuss them here) and require too much effort. So finally, I found the simplest possible solution. The config file is here
'./node_modules/react-scripts/config/webpackDevServer.config.js'. Just edit the file here and that's it! For example, my task was to add an SSL certificate (.pfx). So for that I had to do 3 simple steps:
  1. Create a new folder security on the root app level and put the certificate file into it.
  2. Add the string HTTPS=true to the .env file. If you don't have the file, just create it on the root app level.
  3. Add the two options to the config file
Well, if you have another password for your certificate, update the pfxPassphrase field. If you have a different certificate type, the fields must be different. Reference to the official WebPack DevServer documentation, there is the entire option list https://webpack.js.org/configuration/dev-server/

But this solution has one drawback - the changes above are not saved when we delete node_modules folder and install everything from scratch with npm install.
I have found the simple fix for that - to make a script that overrides the config file when necessary.
  1. Create a new folder config on the root app level and copy the updated webpackDevServer.config.js file into it.
  2. Create a new script postInstall.js on the root app level and insert the following code inside it:
    const fs = require('fs');
    
    fs.copyFile(
        './config/webpackDevServer.config.js',
        './node_modules/react-scripts/config/webpackDevServer.config.js',
        err => {
            if (err) {
                console.error('Cannot copy webpackDevServer.config');
                console.error(err);
                throw err;
            }
    
            console.log('webpackDevServer.config is copied');
        }
    );
    
  3. Add the following line into the package.json file, scripts section: "post-install": "node ./postInstall.js"

So now, after npm install just run another command npm run post-install and that's it - your webpackDevServer.config file has been copied from the /config folder to the destination. Have a nice day!

Monday, July 8, 2019

jQuery autocomplete table

Jquery allows us to build really beautiful autocomplete box. For example, my task recently was to create a table-view autocomplete. That's what I made:



You can try it on JSFiddler:
https://jsfiddle.net/AndrewBuntsev/8jbqyrv4/

Thursday, June 20, 2019

Array.prototype.map(parseInt) tricky question

When I ran the following JS
['1', '7', '11'].map(parseInt);
I surprisingly saw the result [1, NaN, 3] instead of [1, 7, 11]. But if we try parseFloat
['1', '7', '11'].map(parseFloat);
the result is correct [1, 7, 11]
If we try the extended form of parseInt
['1', '7', '11'].map(i => parseInt(i));
we get the proper outcome as well.

So why is it so messy with the short parseInt?