Categories
JavaScript JavaScript Basics

Using the JavaScript Number Object

The Number JavaScript object is a wrapper object that lets us work with numbers by providing us with various constants and methods. A primitive number can be created by the Number() function. A JavaScript number is a double-precision 64-bit binary format IEEE 754 value.


Creating a Number Object

We create a Number object using the Number function by writing the following code:

new Number('123');   
const a = new Number('123');  
const b = Number('123');

The main purpose of the Number function is to create a number from a string. The Number constructor used with the new operator is for creating a Number object, which is of type “object” instead of “number.” A number primitive isn’t an instance of Number. The data type for a primitive number value is a number. The type with the typeof operator and the constructor that it’s constructed from with the instanceof operator, are as in the following code:

console.log(typeof new Number('123'));  
console.log(new Number('123') instanceof Number);

We get “object” and true respectively when we run the two lines of code above. On the other hand, if we write this code instead:

console.log(typeof Number('123'));  
console.log(Number('123') instanceof Number);

We get number and false respectively.

The primary uses of the Number object are for checking if an object can be converted to a number. If a non-number is passed into the Number function, we get NaN returned. If the Number is used without the new operator in a non-constructor context, it’s handy to use for type conversion.

The Number object has the following properties:

  • Number.EPSILON: the smallest interval between two representable numbers.
  • Number.MAX_SAFE_INTEGER: the maximum safe integer in JavaScript, 2⁵³ minus 1.
  • Number.MAX_VALUE: the largest positive representable number (1.7976931348623157e+308).
  • Number.MIN_SAFE_INTEGER: the minimum safe integer in JavaScript, -2⁵³ minus 1.
  • Number.MIN_VALUE: the smallest positive representable number; the positive number closest to zero without actually being zero.
  • Number.NaN: the "not a number" value.
  • Number.NEGATIVE_INFINITY: value representing negative infinity.
  • Number.POSITIVE_INFINITY: value representing infinity.

Static Methods

The Number object has a few static methods.

Number.isNaN()

Determines whether the passed value is NaN. Returns true if a variable’s value is NaN. For example, we can use it to determine if an object is a number with the following code:

console.log(Number.isNaN(+'abc')); // true  
console.log(Number.isNaN(+'123')); // false

The first line logs true because when 'abc' is converted to a number with the unary + operator, we get NaN. On the other hand, the second line logs false because when '123' is converted to a number with a + operator, we get 123, which is a number, so the second line logs false.

Number.isFinite()

Determines whether the passed value is a finite number. Returns true if a number is finite and false otherwise. For example, we can use it to determine if an object is a number with the following code:

console.log(Number.isFinite(Infinity)); // false  
console.log(Number.isFinite(123)); // true

We get false for the first line because Infinity isn’t a finite number, but the second line logs true because 123 is a finite number.

Number.isInteger()

Determines whether the passed value is an integer. Returns true if the number is an integer and false otherwise. For example, we can use this method as in the following code:

console.log(Number.isInteger(123)); // true  
console.log(Number.isInteger(123.45)); // false

The first line logs true because 123 is an integer, but the second line logs false because it’s not an integer. If the argument passed is not of the number type then it will return false. For example, Number.isInteger('10'); will return false.

Number.isSafeInteger()

Determines whether an integer passed in the argument is within the range of a safe integer, i.e. if the number is between -2⁵³ minus 1 and 2⁵³ minus 1. For example, if we have:

console.log(Number.isSafeInteger(Math.pow(2, 53) - 1)); // true  
console.log(Number.isSafeInteger(Math.pow(2, 53))); // false

The first line logs true because Math.pow(2, 53) — 1 is within the safe range, but the second line logs false because Math.pow(2, 53) is not in the safe range.

Number.parseFloat()

The parseFloat method converts a string that’s passed into the argument and returns a number that’s parsed from the string as a floating-point number. If it can’t be parsed, then NaN is returned. For example, if we have:

console.log(Number.parseFloat('123.45'));  
console.log(Number.parseFloat('123'));  
console.log(Number.parseFloat('abc'));

We get 123.45 from the first line, 123 from the second line, and NaN from the third line.

Number.parseInt()

The parseInt method converts a string that’s passed into the argument and returns a number that’s parsed from the string as a whole number. If the first character of the string can’t be parsed, and the radix is smaller than 11, then NaN is returned. For example, if we have:

console.log(Number.parseFloat('123.45'));  
console.log(Number.parseFloat('123'));  
console.log(Number.parseFloat('abc'));

Then we get 123 from the first line and second line, and NaN from the third line.

It also takes a radix as the second argument, which is the base of the mathematical numeral systems. If the string starts with 0x then the radix will be set to 16. If the string starts with anything else, then the radix will be set to 10.

To convert a hexadecimal string into a number, we can write something like the following:

console.log(Number.parseInt('0x1'));

We get 1 when the last line is run. To convert a binary string to decimal, we can write something like:

console.log(Number.parseInt('0111', 2));

The line above will log 7, which is the decimal equivalent of the binary number 0111.


<img class="do t u hm ak" src="https://miro.medium.com/max/8000/0*azxvdPlJ5DchQYGA" width="4000" height="2423" role="presentation"/>

Photo by Andrew Buchanan on Unsplash

Instance Methods

All Number instances inherit from Number.prototype, which provides the object with a few instance methods. The instance methods for Number follow.

Number.toExponential()

The toExponential method returns a string representing the number in exponential notation. It takes an optional that specifies the number of fractional digits to include. For example, we can write:

(123).toExponential(1);

Then we get 1.2e+2.

Number.toFixed()

The toFixed method returns a string representing the number in fixed-point notation. It takes an optional that specifies the number of fractional digits to include after the decimal point. For example, we can write:

console.log((123).toFixed(1));

And we get 123.0.

Number.toLocaleString()

This method returns a string with a language-sensitive representation of the number. It overrides the Object.prototype.toLocaleString() method. The first argument is the locales argument, which takes one locale string or an array of locale strings. This is an optional argument. It takes a BCP 47 language tag with the optional Unicode extension key nu to specify the numbering system for formatting the number. Possible values for nu include: "arab", "arabext", "bali", "beng", "deva", "fullwide", "gujr", "guru", "hanidec", "khmr", "knda", "laoo", "latn", "limb", "mlym", "mong", "mymr", "orya", "tamldec", "telu", "thai", "tibt". The instance of the object created by the constructor has the format method return a string with the formatted number.

The second argument accepts an object with a few properties: localeMatcher, style, unitDisplay, currency, useGrouping, minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, minimumSignificantDigits, and maximumSignificantDigits.

The localeMatcher option specifies the locale-matching algorithm to use. The possible values are lookup and best fit. The lookup algorithm searches for the locale until it finds the one that fits the character set of the strings that are being compared. best fit finds the locale that is at least as, but possibly more-suited than the lookup algorithm.

Style

The style option specifies the formatting style to use. Possible values for the style option include decimal, currency, percent, and unit. decimal is the default option and it’s used for plain number formatting, currency is for currency formatting, percent is for percent formatting, and unit is for unit formatting.

Possible values for thecurrency property are ISO 4217 currency codes, such as USD for the U.S. dollar and EUR for Euro. There’s no default value. If the style property is set to currency then the currency property must be provided. The currencyDisplay property sets how the currency is displayed in currency formatting. Possible values are symbol for adding localized currency symbols and is the default value, code is for adding the ISO currency code, name to use a localized currency name such as “dollar.” useGrouping option is for setting the grouping separator to use for numbers. It’s a boolean value.

minimumIntegerDigits, minimumFractionDigits, and maximumFractionDigits are considered one group of options. minimumIntegerDigits specifies the minimum number of integer digits to use, ranging from 1 to 21, with 1 being the default option. minimumFractionDigits is the minimum number of fraction digits to use, ranging from 0 to 20. The default is 0 for plain number and percent formatting. The default for currency formatting is specified by the ISO 4217 currency code list, and 2 if it’s not specified in the list. maximumFractionDigits is the maximum number of fraction digits to use, with possible values ranging from 0 to 20. The default for plain numbers is the maximum between minimumFractionDigits and 3. The default for currency formatting is the maximum between minimumFractionDigits and the number of fractional unit digits provided by the ISO 4217 currency code list, or 2 if the list doesn’t provide that information. The default for percent formatting is the maximum between minimumFractionDigits and 0.

minimumSignificantDigits and maximumSignificantDigits are considered as another group of options. If at least one of the options in this group is defined, then the first group is ignored. minimumSignificantDigits is the minimum number of significant digits to use, with possible values ranging from 1 to 21 with the default being 1. maximumSignificantDigits is the maximum number of significant digits to use, with possible values ranging from 1 to 21, with the default being 21.

For example, we can use this method in the following examples:

const number = 123.45;console.log(number.toLocaleString('fr', {  
  style: 'currency',  
  currency: 'EUR'  
}));

console.log(number.toLocaleString('zh-Hant-CN-u-nu-hanidec', {  
  style: 'currency',  
  currency: 'JPY'  
}))

console.log(number.toLocaleString('en-IN', {  
  maximumSignificantDigits: 3  
}));

The first console.log statement will log 123,45 €, the second console.log will log ¥一二三, and the third console.log will get 123.

Number.toPrecision()

The toPrecision method returns a string representing the number to a specified precision in fixed-point or exponential notation. It takes an argument that optionally lets us specify the base between 1 and 100. If it’s not specified then all digits after the decimal point will be returned. For example, we can use it as in the following code:

const numObj = 5.12345;console.log(numObj.toPrecision());  
console.log(numObj.toPrecision(100));  
console.log(numObj.toPrecision(5));  
console.log(numObj.toPrecision(2));  
console.log(numObj.toPrecision(1));

We get the following logged for each line:

5.123455.1234500000000000596855898038484156131744384765625000000000000000000000000000000000000000000000000005.12355.15

Number.toString()

The toString method returns a string representing the specified object in the specified radix, or base of the number. It overrides the Object.prototype.toString() method. The radix is an optional argument that lets us specify the base between 2 and 36. The default radix is 10. If the number is negative the sign is preserved. If it’s not a whole number, then a dot sign will be used to separate the decimal places. For example, we can write:

const count = 10;  
  
console.log(count.toString());    // '10'  
console.log((15).toString());     // '15'  
console.log((15.2).toString());   // '15.2'

It also works for non-decimal numbers. For example, we can write:

console.log((-0b0111).toString(10)); // '-7'

It’s handy for converting numbers of different bases to other numbers.

Number.valueOf()

The valueOf method returns the primitive value of the specified object. It overrides the Object.prototype.valueOf() method. For example, if we have a Number object constructed with the new operator, we can write:

const numObj = new Number('10');  
const numPrim = numObj.valueOf();  
console.log(numPrim);  
console.log(typeof numPrim);

We get the following logged when the code above is run:

10  
number

Converting Other Objects to Numbers

With the Number function, we can convert Date objects and null to numbers. For example, for Date objects, we can write:

const d = new Date(2019, 0, 1, 0, 0, 0);  
console.log(Number(d));

We get 1546329600000, which is the UNIX timestamp for January 1, 2019. The null object will be converted to 0, so if we write:

console.log(Number(null));

We get 0.


Conclusion

The Number JavaScript object is a wrapper object that lets us work with numbers by providing us with various constants and methods. A primitive number can be created by the Number() function. It has a number of useful static and instance methods for checking numbers and converting between strings and numbers and vice versa. The toString method is also handy for converting numbers to different bases.

Categories
JavaScript JavaScript Basics

Cloning Arrays in JavaScript

There are a few ways to clone an array in JavaScript,

Object.assign

Object.assign allows us to make a shallow copy of any kind of object including arrays.

For example:

const a = [1,2,3];
const b = Object.assign([], a); // [1,2,3]

Array.slice

The Array.slice function returns a copy of the original array.

For example:

const a = [1,2,3];
const b = a.slice(0); // [1,2,3]

Array.from

The Array.slice function returns a copy of the original array. It takes array like objects like Set and it also takes an array as an argument.

const a = [1,2,3];
const b = Array.from(a); // [1,2,3]

Spread Operator

The fastest way to copy an array, which is available with ES6 or later, is the spread operator.

const a = [1,2,3];
const b = [...a]; // [1,2,3]

JSON.parse and JSON.stringify

This allows for deep copy of an array and only works if the objects in the array are plain objects. It can be used like this:

const a = [1,2,3];
const b = JSON.parse(JSON.stringify(a)); // [1,2,3]

Categories
CSS

Simple Introduction to CSS Grid

CSS grid lets us create layouts with CSS easily.

It’s also good for creating responsive layouts because we can group different items together.

In this article, we’ll look at how to define a grid layout also make it responsive.

Defining a Grid Layout

We can define a grid layout with some HTML and CSS.

If we want to define 4 div’s with one header, one left and right div with an empty space in between it, and one footer, we can do it as follows.

First, we add the HTML:

<div class='container'>  
  <div class='item-a'>  
    A  
  </div>  
  <div class='item-b'>  
    B  
  </div>  
  <div class='item-c'>  
    C  
  </div>  
  <div class='item-d'>  
    D  
  </div>  
</div>

Then we add the CSS:

.item-a {  
  grid-area: header;  
  background-color: lightyellow;  
}

.item-b {  
  grid-area: main;  
  background-color: lightgreen;  
}

.item-c {  
  grid-area: sidebar;  
  background-color: lightblue;  
}

.item-d {  
  grid-area: footer;  
  background-color: pink;  
}

.container {  
  display: grid;  
  grid-template-columns: 24vw 25vw 25vw 24vw;  
  grid-template-rows: auto;  
  grid-template-areas:  
    "header header header header"  
    "main main . sidebar"  
    "footer footer footer footer";  
}

Then we get the following:

The CSS has the following parts.

First, we look at the container class. This is the most important part of the grid.

We have display: grid; which designates that the div with the container class has a grid layout.

Then we define the grid columns with the grid-template-columns , which we set the value to 24vw 25vw 25vw 24vw .

This means we have 4 columns with the leftmost and rightmost columns having 24vw and the one in between having 25vw .

Then we have grid-template-rows: auto; . We leave it as auto since we aren’t concerned with the height of the rows.

To define how the grid is shared between the components inside the div with the container class, we write:

grid-template-areas:  
    "header header header header"  
    "main main . sidebar"  
    "footer footer footer footer";

We have the first row all fille with the header area in the first row.

Then in the new row, we have the main area fill the 2 leftmost columns. A dot for an empty space, and the sidebar area for the rightmost column.

In the bottom row, we have the footer area fill the whole row.

Then we can designate the areas with the item classes as follows:

.item-a {  
  grid-area: header;  
  background-color: lightyellow;  
}

.item-b {  
  grid-area: main;  
  background-color: lightgreen;  
}

.item-c {  
  grid-area: sidebar;  
  background-color: lightblue;  
}

.item-d {  
  grid-area: footer;  
  background-color: pink;  
}

In the code above, we designated whatever having the item-a class as the header with the grid-area and set the background color.

This means that whatever has the class item-a will be the header that fills the top row.

Then we do the same with the other 3 classes, so whatever has the class item-b will fill the leftmost 2 columns in the second row. The element with the class item-c fills the rightmost column of the second row. The element with the class item-d fills all of the bottom rows.

This is how we define a layout with a grid.

Responsive Layout

We can define a responsive layout with CSS selectors and adding a new layout for narrow screens.

We can define a narrow screen layout that only shows the header, main and footer areas as follows:

.item-a {  
  grid-area: header;  
  background-color: lightyellow;  
}

.item-b {  
  grid-area: main;  
  background-color: lightgreen;  
}

.item-c {  
  grid-area: sidebar;  
  background-color: lightblue;  
}

.item-d {  
  grid-area: footer;  
  background-color: pink;  
}

.container {  
  display: grid;  
  grid-template-rows: auto;  
}

@media only screen and (min-width: 751px) {  
  .container {  
    grid-template-columns: 24vw 25vw 25vw 24vw;  
    grid-template-areas:  
      "header header header header"  
      "main main . sidebar"  
      "footer footer footer footer";  
  }  
}

@media only screen and (max-width: 750px) {  
  .item-c {  
    display: none;  
  }

  .container {  
    grid-template-columns: 90vw;  
    grid-template-rows: auto;  
    grid-template-areas:  
      "header"  
      "main"  
      "footer";  
  }  
}

All we did is hide anything with class item-c when the screen width is 750px or less. Otherwise, we keep the same layout as before.

Otherwise, we just move the code around a bit to prevent duplication.

Then when our screen is narrow, we get

Conclusion

Using the CSS grid, making layouts is easier than ever.

First, we set the container div to display: grid to make it a container for a grid.

We then can define layouts with the grid-template-columns to define the columns, grid-template-rows to define the rows. This will form a grid.

Then we set the grid-template-areas attribute to define our layout one row at a time.

We can extend this to be responsive by using CSS media queries and then defining alternative layouts for different screen sizes.

Categories
JavaScript Vue

Generate Static Websites with Nuxt

Static websites are getting popular again nowadays. Informational and brochure sites no longer need to use content management systems like WordPress to be updated dynamically.

With static site generators, you can get your content from dynamic sources like headless CMS’s, APIs, and also from files like Markdown files.

Nuxt is a great static site generator based on Vue.js that is easy to use to build static websites. With Nuxt, all we have to do to build static websites from dynamic content is that we create the templates for showing the content dynamically from the dynamic sources like APIs and Markdown files. Then in the Nuxt configuration file, we define the routes statically so that it can go through the same routes to generate the content into static files.

In this article, we will build a news website using Nuxt and will use the News API, located at https://newsapi.org/, for the content. You have to know Vue.js before you can build a website using Nuxt since Nuxt is a framework based on Vue.js.

To start, first we register for an API key at the News API website. It is free if we only want the headlines. We start building the website by using the Nuxt CLI. We run the create-nuxt-app command by typing in:

npx create-nuxt-app news-website

This will create the initial project files in the news-website folder. When the wizard is run, we select none for server side frameworks, none for UI framework, none for test framework, Universal for the Nuxt mode, and choose to include Axios, linting and prettifying choices are up to you.

Next we need to install some packages. We need the @nuxtjs/dotenv package for reading the environment variables locally and the country-list library for getting a list of countries in our website. To install them we run:

npm i @nuxtjs/dotenv country-list

Now we can start building our website. In the default.vue file, we replace the existing code with:

<template>  
  <div>  
    <nav class="navbar navbar-expand-lg navbar-light bg-light">  
      <nuxt-link class="navbar-brand" to="/">News Website</nuxt-link>  
      <button  
        class="navbar-toggler"  
        type="button"  
        data-toggle="collapse"  
        data-target="#navbarSupportedContent"  
        aria-controls="navbarSupportedContent"  
        aria-expanded="false"  
        aria-label="Toggle navigation"  
      >  
        <span class="navbar-toggler-icon"></span>  
      </button> <div class="collapse navbar-collapse" id="navbarSupportedContent">  
        <ul class="navbar-nav mr-auto">  
          <li class="nav-item active">  
            <nuxt-link class="nav-link" to="/">Home</nuxt-link>  
          </li>  
          <li class="nav-item dropdown">  
            <a  
              class="nav-link dropdown-toggle"  
              href="#"  
              id="navbarDropdown"  
              role="button"  
              data-toggle="dropdown"  
              aria-haspopup="true"  
              aria-expanded="false"  
            >Headliny by Country</a>  
            <div class="dropdown-menu" aria-labelledby="navbarDropdown">  
              <nuxt-link  
                class="dropdown-item"  
                :to="`/headlines/${c.code}`"  
                v-for="(c, i) of countries"  
                :key="i"  
              >{{c.name}}</nuxt-link>  
            </div>  
          </li>  
        </ul>  
      </div>  
    </nav>  
    <nuxt />  
  </div>  
</template>

<script>  
import { requestsMixin } from "~/mixins/requestsMixin";  
const { getData } = require("country-list");

export default {  
  mixins: [requestsMixin],  
  data() {  
    return {  
      countries: getData()  
    };  
  }  
};  
</script>

<style>  
.bg-light {  
  background-color: lightcoral !important;  
}  
</style>

This is the file for defining the layout of our website. We added the Bootstrap navigation bar here. The bar has links for the home page and a drop-down for the list of countries. The nuxt-link components are all links to pages for getting the headlines for the country when the static files are generated. The countries are obtained from the country-list package in the script section by calling the getData function. In the style section, we changed the background color of our navigation bar by overriding the default color of the .bg-light class. The nuxt component in the bottom of the template section is where our content will be displayed.

Next we create amixins folder and create a file called requestsMixin.js file. In there, we add:

const APIURL = "https://newsapi.org/v2";  
const axios = require("axios");

export const requestsMixin = {  
  methods: {  
    getHeadlines(country) {  
      return axios.get(  
        `${APIURL}/top-headlines?country=${country}&apiKey=${process.env.VUE_APP_APIKEY}`  
      );  
    }, 

    getEverything(keyword) {  
      return axios.get(  
        `${APIURL}/everything?q=${keyword}&apiKey=${process.env.VUE_APP_APIKEY}`  
      );  
    }  
  }  
};

This file has the code to get the headlines by country and keyword from the News API.

Then in the pages folder, we create the headlines folder and in the headlines folder, create a _countryCode.vue file. In the file, we add:

<template>  
  <div class="container">  
    <h1 class="text-center">Headlines in {{getCountryName()}}</h1>  
    <div v-if="headlines.length > 0">  
      <div class="card" v-for="(h, i) of headlines" :key="i">  
        <div class="card-body">  
          <h5 class="card-title">{{h.title}}</h5>  
          <p class="card-text">{{h.content}}</p>  
          <button class="btn btn-primary" :href="h.url" target="_blank" variant="primary">Read</button>  
        </div>  
        <img :src="h.urlToImage" class="card-img-bottom" />  
      </div>  
    </div>  
    <div v-else>  
      <h2 class="text-center">No headlines found.</h2>  
    </div>  
  </div>  
</template><script>  
import { requestsMixin } from "~/mixins/requestsMixin";  
const { getData } = require("country-list");

export default {  
  mixins: [requestsMixin],  
  data() {  
    return {  
      headlines: [],  
      countries: getData()  
    };  
  },  
  beforeMount() {  
    this.getHeadlinesByCountry();  
  },  
  methods: {  
    async getHeadlinesByCountry() {  
      this.country = this.$route.params.countryCode;  
      const { data } = await this.getHeadlines(this.country);  
      this.headlines = data.articles;  
    }, 

    getCountryName() {  
      const country = this.countries.find(  
        c => c.code == this.$route.params.countryCode  
      );  
      return country ? country.name : "";  
    }  
  }  
};  
</script>

In the file, we accept the route parameter countryCode and from there, we call the this.getHeadlines function from the requestsMixin that we made earlier and included in this component to get the headlines from the News API. Then the results are displayed in Bootstrap cards in the template section. In the template, we get the country name by finding it from the country-list data. We display a message if there are no headlines found. In general, if we want to make a page that accepts URL parameters, we have to make a file with an underscore as the first character and the variable name of the URL parameter that we want. So _countryCode.vue will let us get the countryCode parameter by using this.$route.params.countryCode in this example.

Next in index.vue in the pages folder, we replace the exist code with:

<template>  
  <div class="container">  
    <h1 class="text-center">Home</h1>  
    <div class="card" v-for="(h, i) of headlines" :key="i">  
      <div class="card-body">  
        <h5 class="card-title">{{h.title}}</h5>  
        <p class="card-text">{{h.content}}</p>  
        <button class="btn btn-primary" :href="h.url" target="_blank" variant="primary">Read</button>  
      </div>  
      <img :src="h.urlToImage" class="card-img-bottom" />  
    </div>  
  </div>  
</template>

<script>  
import { requestsMixin } from "~/mixins/requestsMixin";  
const { getData } = require("country-list");

export default {  
  mixins: [requestsMixin],  
  data() {  
    return {  
      headlines: []  
    };  
  },  
  beforeMount() {  
    this.getHeadlinesByCountry();  
  },  
  methods: {  
    async getHeadlinesByCountry() {  
      const { data } = await this.getHeadlines("us");  
      this.headlines = data.articles;  
    }  
  }  
};  
</script>

<style>  
</style>

This lets us display the headlines for the US in the home page. It works similarly to the _countryCode.vue page except that we only get the US headlines instead of accepting a URL parameter to get headlines from different countries depending on the URL.

Next we create an create-env.js in the project’s root folder and add the following:

const fs = require('fs')  
fs.writeFileSync('./.env', `API_KEY=${process.env.API_KEY}`)

This allows us to deploy to Netlify because we need to create the .env file on the fly there from the entered environment variables. Also, we create the .env file manually and put the API_KEY as the key and the News API API key as the value.

Next in nuxt.config.js , we replace the existing code with:

require("dotenv").config();  
const { getData } = require("country-list");

export default {  
  mode: "universal",  
  /*  
   ** Headers of the page  
   */  
  head: {  
    title: "News Website",  
    meta: [  
      { charset: "utf-8" },  
      { name: "viewport", content: "width=device-width, initial-scale=1" },  
      {  
        hid: "description",  
        name: "description",  
        content: process.env.npm_package_description || ""  
      }  
    ],  
    link: [  
      { rel: "icon", type: "image/x-icon", href: "/favicon.ico" },  
      {  
        rel: "stylesheet",  
        href:  
         "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"  
      }  
    ],  
    script: [  
      { src: "https://code.jquery.com/jquery-3.3.1.slim.min.js" },  
      {  
        src:  
          "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"  
      },  
      {  
        src:  
          "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"  
      }  
    ]  
  },  
  /*  
   ** Customize the progress-bar color  
   */  
  loading: { color: "#fff" },  
  /*  
   ** Global CSS  
   */  
  css: [],  
  /*  
   ** Plugins to load before mounting the App  
   */  
  plugins: [],  
  /*  
   ** Nuxt.js dev-modules  
   */  
  buildModules: [],  
  /*  
   ** Nuxt.js modules  
   */  
  modules: [  
    // Doc: https://axios.nuxtjs.org/usage    
    "@nuxtjs/axios",  
    "@nuxtjs/dotenv"  
  ],  
  /*  
   ** Axios module configuration  
   ** See https://axios.nuxtjs.org/options
   */  
  axios: {},  
  /*  
   ** Build configuration  
   */  
  build: {  
    /*  
     ** You can extend webpack config here  
     */  
    extend(config, ctx) {}  
  },  
  env: {  
    apiKey: process.env.API_KEY || ""  
  },  
  router: {  
    routes: [  
      {  
        name: "index",  
        path: "/",  
        component: "pages/index.vue"  
      },  
      {  
        name: "headlines-id",  
        path: "/headlines/:countryCode?",  
        component: "pages/headlines/_countryCode.vue"  
      }  
    ]  
  },  
  generate: {  
    routes() {  
      return getData().map(d => `headlines/${d.code}`);  
    }  
  }  
};

In the head object, we changed the title so that we display the title we want instead of the default title. In the link section, we add the Bootstrap CSS, and in the script section, we add the Bootstrap JavaScript files and jQuery, which is a dependency of Bootstrap. Since we want to build a static site, we cannot use BootstrapVue because it is dynamic. We do not want any dynamic JavaScript in the generated output, so we have to use plain Bootstrap. In the modules section, we added ”@nuxtjs/dotenv” to read the environment variables from the .env file that we created into our Nuxt app. We also added require(“dotenv”).config(); so that we get the process.env.API_KEY which can be added to this configuration file. We have to do this so that we don’t have to check in our .env file. In the env section, we have the apiKey: process.env.API_KEY || “”, which is what we get by reading the API KEY in the .env file with dotenv.

In the router section, we define the dynamic routes so that they can be viewed when users click on links with the given URLs or click on a link with such URLs. Nuxt also uses these routes to generate static files. In the generate section, we define the routes that Nuxt will traverse to generate the static files for the static website. In this case, the array of routes consist of routes for the headlines page that we created earlier. It will loop through them to get the data for them, then render them and generate the file from the rendered results. The folder structure will correspond to the routes. So since our path is /headlines/:countryCode , the generated artifact will have the headlines folder along withe all the country code as names of subfolders, and inside each folder there will be a index.html with the rendered content.

Now we are ready to deploy our website to Netlify. Create a Netlify account by going to https://www.netlify.com/. The free plan will work for our needs. Then commit your code to a Git repository hosted on GitHub, Gitlab or Bitbucket. Then when you log in to Netlify, click on New site from Git. From there, you can add your Git repository that’s hosted in one of those services. Then when you’re asked to enter the Build Command, enter node ./create-env.js && npm run generate, and the Publish directory would be dist .

After that, enter the API Key in the .env file into the Environment variables section of the website settings, which you can go to by clicking on the Environment link on the Build & deploy menu. Enter API_KEY as the key and your News API API key as the value. Then click the save button.

Once you commit and push everything in a Git repository hosted by GitHub, Gitlab or Bitbucket, Netlify will build and deploy automatically.

Categories
JavaScript JavaScript Basics

How to Check if a Variable is a Number

We can check if a variable is a number in multiple ways.

isNaN

We can check by calling isNaN with the variable as the argument. It also detects if a string’s content is a number. For example:

isNaN(1) // false  
isNaN('1') // false  
isNaN('abc') // true

Note: isNaN(null) is true .

typeof Operator

We can use the typeof operator before a variable to check if it’s a number, like so:

typeof 1 == 'number' // true  
typeof '1' == 'number' // false