Categories
JavaScript Tips

JavaScript Tips — Errors, Auto-Resizing Text Area, and More

Like any kind of apps, there are difficult issues to solve when we write JavaScript apps.

In this article, we’ll look at some solutions to common JavaScript problems.

Replace All Commas in a String

We can replace all commas in a string with the replace method.

For instance, we can write:

const str = 'foo,bar,baz';
const newStr = str.replace(/,/g, '-');

Then newStr is “foo-bar-baz” .

Good Way to Extend Error in JavaScript?

We can extend the Error class with the extends keyword.

For instance, we can write:

class SpecialError extends Error {
  constructor(message) {
    super(message);
    this.name = 'special error';
  }
}

We created a SpecialError class which inherits from the Error class.

We can set our own name to distinguish it from the Error instance.

Convert String with Commas to Array

We can convert strings with commas to an array with the split method.

For instance, we can write;

const string = "1,2,3";
const array = string.split(",");
console.log(array);

We have a string that we call split on with a comma to split the string into an array.

Add or Update a Query String Parameter

To add or update a query string parameter, we can create a URLSearchParams instance with the query string.

Then we can call set on it with the key and value to set the parameter.

For instance, we can write:

const searchParams = new URLSearchParams(window.location.search)
searchParams.set("foo", "baz");
const newURL = `${window.location.pathname}?${searchParams.toString()}`;
history.pushState(null, '', newURL);

We get the query string in the browser search bar with window.location.search .

Then we call set with the key and value of it.

Next, we get the query string by calling toString on the URLSearchParams instance.

And we combine the pathname and query string together.

Then we call pushState to with the new URL to reload the page with the new query string.

Open a URL in a New Window Rather than a Tab

To always open a URL in a new window rather than a tab, we can pass in a 3rd argument to window.open with the width and height of the window.

For instance, we can write:

window.open(url, '_blank', "height=200,width=200");

The 3rd argument has the specifications of the window.

Check if a Variable is a Number

We can check if a variable is a number by using the isNaN and isFinite functions.

For instance, we can write:

!isNaN(parseFloat(num)) && isFinite(num);

We use parseFloat to try to parse num to a float.

Then we can check the returned value with isNaN .

We also pass num to isFinite to check that.

If both expressions are true then we know we got a finite number.

Creating a Text Area with Auto-Resize

To create a text area with auto-resize, we can listen to the input event.

Then we can set the height of the text area in the input event listener to the scrollHeight plus 12 pixels.

scrollHeight gets the full height of the text.

To do that we can write:

<textarea></textarea>

to create the text area.

Then we can write:

function resizeTextarea(ev) {
  this.style.height = 'auto';
  this.style.height = `${this.scrollHeight}px`;
}
const textArea = document.querySelector('textarea');
textArea.addEventListener('keyup', resizeTextarea);

'auto' resets the height to the original.

Then we set the height to the scrollheight to make it the height of the text.

Why Shouldn’t we use document.write?

We shouldn’t use document.write to render HTML on the screen.

It doesn’t work with XHTML.

It’s run after the page finishes loading and overwrites the page.

Also, it runs where it’s encountered.

It’s doesn’t write content like we do with DOM manipulating and can easily create bugs since we’re writing string’s content onto a page.

Therefore, we shouldn’t use document.write to write content onto the screen.

Check if the URL has a Given String

We can use the indexOf method on window.location.href to check if a URL contains a given string.

For instance, we can write:

window.location.href.indexOf("foo") > -1

to check if 'foo' is in the current page’s URL.

If the returned value is -1, that means it’s not in the URL.

Otherwise, it’s in the URL.

Conclusion

We can use the URLSearchParams constructor to parse and manipulate query strings.

window.open can open a new window.

The Error constructor can be extended with a child class.

Categories
JavaScript Tips

JavaScript Tips — bind and apply, Loops, and Nested Properties

Like any kind of apps, there are difficult issues to solve when we write JavaScript apps.

In this article, we’ll look at some solutions to common JavaScript problems.

JavaScript for…in vs for

for-in and for loops are different.

for-in is exclusively used for looping through the properties of an object.

For instance, we can write:

for (const key in obj){
  //...
}

key is the property name of an object.

A for loop can be used for anything.

For instance, we can write:

for (let i = 0; i < a.length; i++){
  //...
}

We loop through an array a with the loop.

But we can do anything else with it.

Use of .apply() with the ‘new’ Operator

We can use apply with any function.

To use them together, we create a new constructor with the bind and apply method together.

For instance, we can write:

function newCall(Cls, ...args) {
  return new (Function.prototype.bind.apply(Cls, args));
}

We created the newCall constructor get the class, we want to call apply with.

Then we get the args .

bind returns a new constructor function that calls apply with the Cls constructor function with the arguments args that we want.

Then we can use the constructor by writing:

const s = newCall(Foo, a, b, c);

We pass the Foo constructor into newCall with arguments a , b , and c .

Then we get a Foo instance created with those arguments.

Use of <script type = “text/template”> … </script>

A script tag with type text/template is used for some libraries as templates.

For instance, jQuery can get the template from this script tag.

If we have:

<script id="hello" type="text/template">
  hello world
</script>
<script>
  console.log($('#hello').html());
</script>

Then jQuery gets the script tag with ID hello and return the HTML content from it by calling html .

So we get 'hello world' logged in the console log.

Get All Properties Values of a JavaScript Object without Knowing the Keys

We can get all property values of a JavaScript object without knowing the keys in a few ways.

One way is to use the for-in loop:

for(var key in obj) {
  const value = obj[key];
  //...
}

We can also use the Object.key method to get an array of all the property keys.

So we can write:

const keys = Object.keys(obj);

for (const key of keys) {
  const val = obj[key];
}

We use the for-of loop to loop through the array of keys returned from Object.keys .

Object.values returns all the values from an array.

So we can loop through the values without getting the keys:

const values = Object.values(obj);

for (const val of values) {
  //...
}

Accessing Nested JavaScript Objects and Arrays by String Path

There are a few ways to get the value of a nested property in an object.

One way is to write a function from scratch:

const resolve(path, obj = {}, separator = '.') {
  const properties = Array.isArray(path) ? path : path.split(separator);
  return properties.reduce((prev, curr) => prev && prev[curr], obj)
}

We created the resolve method to get the property of each level.

The property path is split by the separator.

Then we go through all the properties to get to the nested property’s value with reduce .

Then we can call it by writing:

resolve("style.width", document.body)

to get an object’s properties.

If there’s an array, we write:

resolve("part.0.size", obj)

where 0 is an index of an array.

To make our lives easier, we can use the Lodash get method.

Then we can write:

_.get(object, 'a[0].b.c');

to get the property by the path.

Response to Preflight Request doesn’t Pass Access Control Check Error

This error means that the options request that’s made before the actual request failed.

To fix this issue, we can turn off CORS.

Also, we can use a proxy like Nginx to handle the options request.

We can also enable CORS properly by making sure the options request responds with a successful response.

Conclusion

The for-in loop is different from a for loop.

To make sure that cross-domain requests succeed, we should make sure that we should configure our server properly.

There are some ways to access the nested path of an object.

We can use bind and apply together.

Categories
JavaScript Tips

JavaScript Tips — Arrow Keys, Array Checks, and More

As with many kinds of apps, there are difficult issues to solve when we write apps for JavaScript. In this article, we’ll look at some solutions to common JavaScript problems.

Check if Arrow Keys are Pressed

We can check if an arrow key is pressed with the which property of the event object.

To do that, we can write:

document.onkeydown = (e) => {  
  switch(e.which) {  
    case 37:   
      break;  
    case 38:  
      break;  
    case 39:  
      break;  
    case 40:  
      break;  
    default:   
      return;   
  }  
  e.preventDefault();  
};

We watch the key down event by setting an event handler to the onkeydown method of document .

Then inside the function, we get the which property to check the key code.

37 is the left key.

38 is the up key.

39 is the right key.

40 is the down key.

We also have to call preventDefault() to prevent the default action, which is scrolling and moving the cursor.

Check if an Element Exists in the Visible DOM

We can check if an element exists by selecting it in the DOM.

If it’s visible then the element will be returned.

To do that, we can use document.getElementById to get an element by ID.

document.querySelector gets an element by any selector.

document.querySelectorAll gets a group of elements by any selector.

documebt.getElementsByClassName gets a group of elements by class name.

document.getElementsByName gets a group of elements by their name attribute value.

The ones that return groups have a length property, so we can use that to check if there is anything.

For instance, we can write:

const foo = document.querySelector('#foo');

to get an element with the ID foo if it’s visible.

Converting a JavaScript Object to an Array

We can convert a JavaScript object to an array with the Object.keys and map methods.

For instance, we can write:

const obj = { 1: 'foo', 2: 'bar' };  
const arr = Object.keys(obj).map((key) => obj[key]);

We call the Object.keys to get the keys. Then we return the value in the map callback.

Also, we can use the Object.values method to get the values as an array:

const arr = Object.values(obj);

Underscore and Lodash also have the values method:

const arr = _.values(obj);

Contains Case Insensitive

We can check if a substring is in a string in a case-insensitive way by using the toLowerCase and indexOf methods.

For example, we can write:

if (str.toLowerCase().indexOf("foo") === -1) {  
  //...  
}

We can also use regex to do the check:

if (!/Foo/i.test(str)) {  
  //...  
}

i means case insensitive.

We can replace the indexOf method with the includes method:

if (str.toLowerCase().includes("foo")) {  
  //...  
}

or:

if (str.toLowerCase().includes("foo".toLowerCase())) {  
  //...  
}

How to Append Data to div

To append data to a div, we can append it using the innerHTML property.

For instance, we can write:

const div = document.getElementById('div');  
div.innerHTML += 'more data';

We get the div and append more data toinnerHTML .

We can also create a text node and call appendChild to append it to the div:

const div = document.getElementById("div");  
const content = document.createTextNode("more stuff");  
div.appendChild(content);

Get the Rendered Height of an Element

We can get the height of an element with the clientHeight property.

It’s the total of the height of the element, padding, and height of the horizontal scrollbar if it exists.

Then we can write:

document.getElementById('div').clientHeight;

There’s also the offsetHeight property.

It includes the CSS height, borders, padding, and horizontal scrollbar if it exists.

For example, we write:

document.getElementById('div').offsetHeight;

Check if an Array Contains any Element of Another Array

To check if an array has an element of another array, we can use the some and includes methods.

For example, we can write:

const hasElement = arr1.some(r => arr2.includes(r))

We use the some method to check if any element in arr1 meets the condition returned in the callback.

arr2.includes(r) checks if an item in arr2 is included in arr1 .

Conclusion

We can check if an array has an entry of another array with the some and includes methods. We can check if arrow keys are pressed by checking a few key codes. Also, we can use a few methods to convert an object to an array.

Categories
JavaScript Tips

Useful JavaScript Tips — Semicolons, Dates, and Logging Objects

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some tips we should follow to write JavaScript code faster and better.

Semicolon

Semicolons can be automatically inserted in JavaScript.

It inserts semicolons on the next line after code that breaks the current one.

Also, when the next line starts with a } , a semicolon is inserted.

When the end of the source code file is reached, then the semicolon is added.

Semicolons are also inserted after the break keyword.

It’s also added after the throw and continue keywords.

If we don’t add it ourselves, then the interpreter will insert it for us.

Manipulating Dates Easily with Moment.js

To make date manipulating easier, we can use moment.js

We can install it by adding a script tag or installing the package.

We can write:

<script src="https://unpkg.com/moment" />

or:

npm install moment

If we use the package, we can write:

import moment from 'moment'

To get the current date and time, we can write:

const date = moment();

To parse a date, we can write:

const date = moment(string);

It takes various formatting codes. They are:

  • YYYY — 4 digits year
  • YY — 2 digits year
  • M — 2 digits month number without the 0
  • MM — 2 digits month number
  • MMM — 3 letters month name
  • MMMM — full month name
  • dddd — full day name
  • gggg — 4 digits week year
  • gg — 2 digits week year
  • w — week of the year without leading zero
  • ww — week of the year with leading zero
  • e — day of week that starts with 0
  • D — 2 digits day number without the leading 0
  • DD — 2 digits day number
  • Do — day number with ordinal
  • T — start of the time part
  • HH — 2 digit hours from 0 to 23
  • H — 2 digit hours from 0 to 23 without the leading 0
  • kk — 2 digit hours from 1 to 24
  • k — 2 digit hours from 1 to 24 without leading 0
  • a/A — am or pm
  • hh — 2 digit hours (12 hours time)
  • mm — 2 digit minutes
  • ss — 2 digits seconds
  • s — 2 digits seconds without leading 0
  • S — 1 digit milliseconds
  • SS — 2 digit milliseconds
  • SSS — 3 digits milliseconds
  • Z — timezone
  • x — UNIX timestamp in milliseconds

For instance, we can format date by writing:

moment().format("YYYY-MM-DD")

Moment.js comes with a few constants.

They are the following:

  • moment.HTML5_FMT.DATETIME_LOCAL — ‘YYYY-MM-DDTHH:mm’
  • moment.HTML5_FMT.DATETIME_LOCAL_SECONDS — ‘YYYY-MM-DDTHH:mm:ss’
  • moment.HTML5_FMT.DATETIME_LOCAL_MS — ‘YYYY-MM-DDTHH:mm:ss.SSS’
  • moment.HTML5_FMT.DATE — ‘YYYY-MM-DD’
  • moment.HTML5_FMT.TIME — ‘HH:mm’
  • moment.HTML5_FMT.TIME_SECONDS — ‘HH:mm:ss’
  • moment.HTML5_FMT.TIME_MS — ‘HH:mm:ss.SSS’
  • moment.HTML5_FMT.WEEK — ‘YYYY-[W]WW’
  • moment.HTML5_FMT.MONTH — ‘YYYY-MM’

We can validate a date with the isValid method.

For instance, we can write:

moment('2020-13-32').isValid()

which returns false , or:

moment('2020-01-23').isValid()

which returns true .

Get the Relative Time String

We can use the fromNow method to get the relative from the current date and time.

For instance, we can write:

moment("2020-11-23").fromNow()

and get ‘in 6 months’ .

We can pass true to fromNow , then it shows the difference without reference to the future or past.

So if we write:

moment("2020-11-23").fromNow(true)

Then we get ‘6 months’ .

Manipulating Dates

We can use the Moment.js add and subtract methods to add or subtract amounts from a date.

For instance, we can write:

moment('2020-11-23').add(1, 'days');  
moment('2020-11-23').subtract(1, 'days');

The 2nd argument can have the following values:

  • years
  • quarters
  • months
  • weeks
  • days
  • hours
  • minutes
  • seconds
  • milliseconds

Inspect a JavaScript Object

There are various ways to inspect objects in JavaScript.

We can use the console.log method to log an expression and get its return value.

For instance, we can write:

console.log(dog)

There’s also the console.dir method to let us inspect any object.

For instance, we can write:

console.dir(dog)

JSON.stringify is another way to let us inspect an object.

It’ll return a string.

For instance, given that we have:

const dog = {  
  color: 'white',  
  breed: 'poodle'  
}

we can write:

console.log(JSON.stringify(dog))

which creates an unprettified string.

Then we get:

{"color":"white","breed":"poodle"}

logged.

To pretty-print the string, we can pass in 2 more arguments.

We write:

console.log(JSON.stringify(dog, null, 2))

and we get:

{  
  "color": "white",  
  "breed": "poodle"  
}

Conclusion

Moment.js makes date manipulating easier than with the Date constructor.

We can inspect expression values with console and JSON.stringify.

Categories
JavaScript Tips

JavaScript Tips — Wait for All Promises, Heights, Dates, and More

Like any kind of apps, there are difficult issues to solve when we write JavaScript apps.

In this article, we’ll look at some solutions to common JavaScript problems.

Skip Over an Element in .map()

We can skip over an element in map by using filter to filter out the entries we don’t want first.

For instance, we can write:

const sources = images.filter((img) => {
  return img.src.split('.').pop() !== "json"
})
.map(img => img.src);

Now we only map the items that doesn’t end with 'json' .

Interpolate Variables in Strings in JavaScript

We can use template strings to interpolate variables in strings.

For example, we can write:

const a = 5;
const b = 1;
console.log(`sum is ${a + b}.`);

We interpolated the result of a + b into our string in the last line.

The Optimum Way to Compare Strings in JavaScript?

To compare 2 strings in JavaScript, we can use the localeCompare method.

For instance, we can write:

strA.localeCompare(strB)

This lets us compare strings in a locale-sensitive manner.

Wait Until All Promises Complete Even if Some Rejected

To wait for promises to complete, we can use the Promise.allSettled method.

It’ll complete even though some may be rejected.

For instance, we can write:

Promise.allSettled([promise1, promise2])
.then(([result1, result2]) => {
  // ...
});

We pass in an array of promises.

Then we call then and we get all the results in an array.

Each result object has the status and reason or value properties.

status is the promise’s status. If it’s fulfilled, status will be 'fulfilled' . Otherwise, it’ll be 'rejected' .

value is the resolved value.

reason is the error for rejection.

For loop for HTMLCollection elements

To loop through a HTMLCollection object, we can use the for-of loop to do it.

For instance, we can write:

const els = document.getElementsByClassName("foo");
for (const item of els) {
  console.log(item.id);
}

We get all the items with class name foo .

Then we use the for-of loop to loop through them.

To convert it to an array, we can use the Array.from or the spread operator:

const arr = Array.from(document.getElementsByClassName("foo"));

or:

const arr = [...document.getElementsByClassName("foo")];

Now we can use array methods on it.

Get the Number of Days Between Two Date Strings

We can get the number of days between 2 days by parsing the dates and then get their difference.

Assuming that our dates are in MM/DD/YYYY format, we can write:

const parseDate = (str) => {
  const [month, day, year] = str.split('/');
  return new Date(year, month-1, day);
}

const dateDiff = (first, second) => {
  return Math.round((second - first)/(1000 * 60 * 60 * 24));
}

We split the str date string.

Then we pass the split items into the Date constructor as arguments.

year has the year, month has the month, but we’ve to subtract it by 1 since JavaScript constructor assumes that 0 is January, 1 is February, etc.

day is the day of the month.

In dateDiff , we get the difference by subtraction the second by the first .

They’re both Date instances.

Then we divide by the number of milliseconds in a day.

Then we can write:

const diff = dateDiff(parseDate('2/1/2000'), parseDate('3/2/2000'));

to use it.

Use a Variable for a Key in a JavaScript Object Literal

We can use a variable for a key in JavaScript object literals.

For instance, we can write:

const prop = "foo",
const obj = { [prop]: 10 };

We just pass in prop into the brackets, then the key would be foo .

Get the Rendered Height of an Element

We can use the clientHeight , offsetHeight , and scrollHeight to get the rendered height of an element.

For example, we can write:

const height = document.querySelector('div').clientHeight;

or:

const height = document.querySelector('div').offsetHeight;

or:

const height = document.querySelector('div').scrollHeight;

clientHeight includes the height and vertical padding.

offsetHeight includes the height, vertical padding, and vertical borders.

scrollHeight includes the height of the contained document, vertical padding, and vertical borders.

Conclusion

We can use filter with map to map selected entries of arrays.

There are a few ways to get the height of elements.

We can get the number of days between 2 dates by create date objects then subtracting them and dividing them by the number of milliseconds in a day.

Promise.allSettled lets us wait for all promises to finish regardless of their status.