Categories
JavaScript Answers

How to Specify a Suggested Filename When Using a Link to Download Data?

Sometimes, we may have links in our webpage to let us download files when clicking a link.

We may want to specify a filename for the file that’s downloaded.

In this article, we’ll look at how to set a suggested filename when we add a link to let users download files.

Setting the Download Attribute

We can set the download attribute of the a element to let us set the filename of the file downloaded.

For instance, we can write:

<a download='sample.gif' href='data:image/gif;base64,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'>
  download file
</a>

We set the href to a base64 URL.

And we set the download attribute to sample.gif .

Then our file would be named sample.gif when we download it.

We can also do the same thing with JavaScript.

To do this we write:

const saveContent = (fileContents, fileName) => {
  const link = document.createElement('a');
  link.download = fileName;
  link.href = fileContents;
  link.click();
}

const fileContents = 'data:image/gif;base64,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'

saveContent(fileContents, 'sample.gif')

We create the saveContent function which creates an a element with document.createElement .

Then we set the download property to set the value of the download attribute.

Then we set the href property to set the href attribute of the a element.

Finally, we call click on the a element to start the download.

This works if we use base64 URLs but not when we download from a URL with a file name at the end.

So if we set href to something like https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf, then the downloaded file will always be named dummy.pdf.

Conclusion

We can set the file name of the file downloaded with the download attribute.

Categories
JavaScript Answers

How to Format a Date as an ISO-8601 String with Moment.js?

Sometimes, we may want to format a date into the IS0–8601 standard format.

In this article, we’ll look at how to format a date into an ISO-8601 string with moment.js.

The toISOString Method

Moment.js comes with the toISOString method to let us format dates to ISO-8601 format.

For instance, we can write:

console.log(moment(new Date(2021, 1, 1)).toISOString())

Then we get:

'2021-02-01T08:00:00.000Z'

as a result.

The format Method

The format method also lets us format a date to an ISO-8601 date string.

For instance, we can write:

import moment from "moment";
console.log(moment(new Date(2021, 1, 1)).format());

Then we get the same result as before.

Timezone Support

We can use the Moment Timezone library to add support for time zones.

Then we can set the time zone in our app and then use the toISOString method to convert the moment object to an ISO-8601 string.

For instance, we can write:

const moment = require("moment-timezone");
moment().tz("America/Los Angeles");
console.log(moment(new Date(2021, 1, 1)).toISOString(true));

Then the console log logs:

'2021-02-01T00:00:00.000-08:00'

as a result.

Parsing ISO-8601 Dates

We can parse ISO-8601 dates with moment.js

For instance, we can write:

import moment from "moment";
console.log(moment("2021-01-01", moment.ISO_8601));

We pass in a date string in ISO-8601 format.

And we pass in the moment.ISO_8601 constant to let moment know that the date string in the first argument is an ISO-8601 date.

Conclusion

We can create and parse ISO-8601 date strings with moment.js in our JavaScript code.

Categories
JavaScript Answers

What is JSON Equivalent of XQuery/XPath?

If we’re manipulating XML, we can use the XQuery or XPath query languages to find the elements we want in the XML code.

In JSON, there’s no such query language built-in natively in any runtime environment, but there’re many libraries that let us do the same thing.

In this article, we’ll look at the equivalents of XQuery or XPath with JSON.

JSPath

One library that we can use to query JSON objects is the JSPath library.

To use it, we can run:

npm i jspath

to install it.

Then we can use it to query JSON by writing:

import JSPath from "jspath";

const results = JSPath.apply(
  '.automobiles{.maker === "Honda" && .year > 2009}.model',
  {
    automobiles: [
      { maker: "Nissan", model: "Teana", year: 2000 },
      { maker: "Honda", model: "Jazz", year: 2023 },
      { maker: "Honda", model: "Civic", year: 2007 },
      { maker: "Toyota", model: "Yaris", year: 2008 },
      { maker: "Honda", model: "Accord", year: 2011 }
    ],
    motorcycles: [{ maker: "Honda", model: "ST1300", year: 2012 }]
  }
);

console.log(results);

We call JSPath.apply to query the object we have in the 2nd argument.

The first argument is a string with the query.

We search for items in the automobiles array with maker equals 'Honda' and year bigger than 2009.

And we get the model property of each object.

Therefore, result is:

["Jazz", "Accord"]

It also supports wildcard queries with * .

For instance, we can write:

import JSPath from "jspath";

const results = JSPath.apply(
  '.automobiles{.maker === "Honda" && .year > 2009}.*',
  {
    automobiles: [
      { maker: "Nissan", model: "Teana", year: 2000 },
      { maker: "Honda", model: "Jazz", year: 2023 },
      { maker: "Honda", model: "Civic", year: 2007 },
      { maker: "Toyota", model: "Yaris", year: 2008 },
      { maker: "Honda", model: "Accord", year: 2011 }
    ],
    motorcycles: [{ maker: "Honda", model: "ST1300", year: 2012 }]
  }
);

console.log(results);

Then result is:

["Honda", "Jazz", 2023, "Honda", "Accord", 2011]

We get all the property values of matched result objects with the * operator.

JSONPath

Another library that we can use to query JSON objects is to use the JSONPath library.

To install it, we run:

npm i jsonpath

Then we can use it by writing:

const jp = require("jsonpath");
const persons = [
  { name: "James", age: 36 },
  { name: "Mary", age: 34 },
  { name: "Jane", age: 35 },
  { name: "Bob", age: 28 }
];

const names = jp.query(persons, "$..name");
console.log(names);

We call jp.query to get the name property from each entry of the persons array with the “$..name” query.

$ means the root object.

.. means we find the properties recursively.

Therefore, we have:

["James", "Mary", "Jane", "Bob"]

as a result of names .

We can also query for objects that meets a given condition by writing:

const jp = require("jsonpath");
const obj = {
  persons: [
    { name: "James", age: 36 },
    { name: "Mary", age: 34 },
    { name: "Jane", age: 35 },
    { name: "Bob", age: 28 }
  ]
};

const names = jp.query(obj, "$..persons[?(@.age>30)]");
console.log(names);

We call jp.query to find objects in the persons array property with age bigger than 30.

So we get:

[
  {
    "name": "James",
    "age": 36
  },
  {
    "name": "Mary",
    "age": 34
  },
  {
    "name": "Jane",
    "age": 35
  }
]

as the value of names .

Conclusion

We can use the JSPath and JSONPath libraries to query for items in JavaScript objects.

Categories
JavaScript Answers

How to Check if a String is a Date String with JavaScript?

Using the Date.parse() Method

One way to check if a string is date string with JavaScript is to use the Date.parse method.

To do this, we write:

console.log(Date.parse('2020-01-01'))
console.log(Date.parse('abc'))

Date.parse returns a timestamp in milliseconds if the string is a valid date.

Otherwise, it returns NaN .

So the first console log will log 1577836800000 and the 2nd one will log NaN .

Using moment.js

Another way to check if a date is a valid date is to use moment.js’ isValid method.

For instance, we can write:

console.log(moment("06/22/2015", "MM/DD/YYYY", true).isValid())

and we see true logged since ”06/22/2015" can be parsed into a date.

Using the Date Constructor

We can also check if a date is a valid date with the Date constructor.

If we pass in a string that isn’t a valid date string, it’ll return 'Invalid Date' .

So we can check for that to see if it’s a date.

In addition, we can parse the date string into a timestamp and check if it returns NaN with the isNaN function.

Therefore, having both checks together lets us check if a string is a date string reliably.

For instance, we can write:

const isDate = (date) => {
  return (new Date(date) !== "Invalid Date") && !isNaN(new Date(date));
}

console.log(isDate('2020-01-01'))
console.log(isDate('abc'))

We create the isDate function to add both checks.

The date parameter is a string to check.

So we get true and false from the console logs respectively.

Conclusion

We can check if a string is a date string with JavaScript by using native date methods or moment.js.

Categories
JavaScript Answers

How to Set a DOM element as the First Child?

Sometimes, we may want to set a DOM element as the first child element.

In this article, we’ll look at ways to set a DOM element as the first child.

Using the prepend Method

In modern browsers, an HTML element object comes with the prepend method to let us prepend an element as the first child.

For instance, if we have the following HTML:

<div>  
  <p>  
    bar  
  </p>  
  <p>  
    baz  
  </p>  
</div>

Then we can write the following JavaScript to prepend an element as the first child of the div:

const div = document.querySelector('div')  
const newChild = document.createElement('p')  
newChild.textContent = 'foo'  
div.prepend(newChild)

We get the div with the document.querySelector method.

Then we call document.createElement to create an element.

Next, we set the textContent property to add some content to the p element we created.

And then we call div.prepend to prepend newChild as the first child of the div.

There’s also the append method to append an element as the last child of a parent element.

Using the insertAdjacentElement Method

We can also use the insertAdjacentElement method to insert an element as the first child of an element.

For instance, if we have the same HTML:

<div>  
  <p>  
    bar  
  </p>  
  <p>  
    baz  
  </p>  
</div>

Then we can write:

const div = document.querySelector('div')  
const newChild = document.createElement('p')  
newChild.textContent = 'foo'  
div.insertAdjacentElement('afterbegin', newChild)

to call insertAdjacentElement with 'afterbegin' and the newChild to prepend newChild as the first child element of the div.

Other possible values for the first argument of insertAdjacentElement is:

  • beforebegin: before the element itself.
  • beforeend: just inside the element, after its last child.
  • afterend: after the element itself.

Using the insertBefore Method

Another method we can use to prepend an element as the first child is to use the insertBefore method.

For instance, we can write:

const div = document.querySelector('div')  
const newChild = document.createElement('p')  
newChild.textContent = 'foo'  
if (div.firstChild) {  
  div.insertBefore(newChild, div.firstChild);  
} else {  
  div.appendChild(childNode);  
}

given the same HTML we have in the previous examples to prepend newChild as the first child of the div.

We check if there’s a firstChild element attached to the div.

If there is, then we call insertBefore to insert newChild before the firstChild of the div.

Otherwise, we just call appendChild to append newChild as a child element.

Conclusion

We can use various HTML element methods to prepend an element as the first child of a parent element.