Categories
JavaScript Answers

How to Get the Browser’s Scrollbar Sizes with JavaScript?

Sometimes, we want to get the scrollbar size of an element with JavaScript.

In this article, we’ll look at how to get the size of the scrollbar that’s part of a scrollable element with JavaScript.

Use the getBoundingClientRect Method and the scrollHeight Property

We can get the element’s scrollbar size with the getBoundingClientRect method and the scrollHeight property of an element.

To do this, we subtract the height property value retuned by getBoundingClientRect method by the scrollHeight property’s value to get the width of the horizontal scrollbar.

For instance, if we have:

<div id="app" style='width: 100px; overflow-x: scroll'></div>

Then we can add elements to the div and get the horizontal scrollbar height by writing:

const app = document.querySelector('#app')
for (let i = 0; i < 100; i++) {
  const span = document.createElement('span')
  span.textContent = i
  app.appendChild(span)
}

const getScrollbarHeight = (el) =>{
  return el.getBoundingClientRect().height - el.scrollHeight;
};
console.log(getScrollbarHeight(app))

We get the div with querySelector .

Then we add some spans into the div.

The div has width set and overflow-x set to scroll.

This means the div should have a horizontal scrollbar.

Next, we create the getScrollbarHeight function that subtracts the height from getBoundingClientRect by the scrollHeight , which gives us the height of the horizontal scrollbar.

Then we log the scrollbar height with console log.

Likewise, we can get the scrollbar width with:

<div id="app" style='height: 100px; overflow-y: scroll'></div>

and:

const app = document.querySelector('#app')
for (let i = 0; i < 100; i++) {
  const p = document.createElement('p')
  p.textContent = i
  app.appendChild(p)
}

const getScrollbarHeight = (el) =>{
  return el.getBoundingClientRect().width - el.scrollWidth;
};
console.log(getScrollbarHeight(app))

We add p elements into a div that’s scrollable vertically.

Instead of subtracting the heights, we subtract the widths.

And we should get the scrollbar width from the console log.

Conclusion

We can get the scrollbar width and height by calling the getBoundingClientRect method and the scroll width or height and getting the difference between the 2.

Categories
JavaScript Answers

How to Add a Widget that we can Zoom In and Out on a Web Page When We Spin the Mouse Wheel Like on Google Maps with JavaScript?

Sometimes, we want to create a widget on a web page where we can zoom in and out on something as we can do on Google Maps.

In this article, we’ll look at how to create a widget that we can zoom in and out with the mouse wheel as we can do on Google Maps.

Draw the Image We can Zoom In and Out on the Canvas

We can draw the image we want to be able to zoom in and out on the canvas.

Then we can listen to the wheel event and transform the canvas image when we move the mouse wheel to let us zoom the image in and out.

For instance, we can write the following HTML:

<canvas id="canvas" width="600" height="200"></canvas>

Then we can write the following JavaScript code to draw the image on the canvas and zoom the image in and out as we move the mouse wheel:

const zoomIntensity = 0.2;

const canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
const width = 600;
const height = 200;

let scale = 1;
let originx = 0;
let originy = 0;
let visibleWidth = width;
let visibleHeight = height;

const draw = () => {
  context.fillStyle = "white";
  context.fillRect(originx, originy, width / scale, height / scale);
  context.fillStyle = "black";
  context.fillRect(50, 50, 100, 100);
  window.requestAnimationFrame(draw);
}
draw();

canvas.onwheel = (event) => {
  event.preventDefault();
  const mousex = event.clientX - canvas.offsetLeft;
  const mousey = event.clientY - canvas.offsetTop;
  const wheel = event.deltaY < 0 ? 1 : -1;
  const zoom = Math.exp(wheel * zoomIntensity);
  context.translate(originx, originy);
  originx -= mousex / (scale * zoom) - mousex / scale;
  originy -= mousey / (scale * zoom) - mousey / scale;
  context.scale(zoom, zoom);
  context.translate(-originx, -originy);
  scale *= zoom;
  visibleWidth = width / scale;
  visibleHeight = height / scale;
}

We have the draw function that clears the screen to white with the first and 2nd lines.

Then we call fillStyle and fillRect to draw a black square.

And then we call window.requestAnimationFrame to redraw the canvas.

Once we defined the draw function, we call it to start the initial draw.

Next, we set the canvas.onwheel property to a function that zoom the image in and out when we move the mouse wheel.

In the function, we first call event.preventDefault() to stop the default behavior when the mouse wheel moves.

Then we get the mouse offset with:

const mousex = event.clientX - canvas.offsetLeft;
const mousey = event.clientY - canvas.offsetTop;

Next, we write the following to normalize mouse movement to avoid unusual jumps:

const wheel = event.deltaY < 0 ? 1 : -1;

Then we get the zoom factor with:

const zoom = Math.exp(wheel * zoomIntensity);

And then we translate the visible origin so that it’s at the context’s origin with:

context.translate(originx, originy);

Then we compute the new origin after the zoom is done with:

originx -= mousex/(scale*zoom) - mousex/scale;
originy -= mousey/(scale*zoom) - mousey/scale;

Next, we call context.scale(zoom, zoom) to scale the image around the origin.

And then we translate the image to offset the visible origin so that it’s at the proper position after zoom:

context.translate(-originx, -originy);

And finally, we update the dimensions after zoom with:

scale *= zoom;
visibleWidth = width / scale;
visibleHeight = height / scale;

Now when we move the mouse wheel, the black square should zoom in and out.

Conclusion

We can add a widget with an image that we can zoom in and out by drawing an image on the canvas and translating and scaling the image when we move the mouse wheel.

Categories
JavaScript Answers

How to Extract the Base URL from a String in JavaScript?

Sometimes, we want to extract the base URL from a string with JavaScript.

In this article, we’ll look at ways to extract the base URL from a string with JavaScript.

Create an Anchor Element and Get the Base URL Parts From the Created Element

We can create an anchor element and get the base URL parts from the created element.

For instance, we can write:

const a = document.createElement("a");
a.href = "http://www.example.com/article/2020/09/14/this-is-an-article/";
const baseUrl = `${a.protocol}//${a.hostname}`
console.log(baseUrl)

We create the a element with document.createElement .

Then we set the href of it to the URL we want to extract the base URL from.

Then we can get the baseURL by combining the protocol and hostname properties.

As a result, we see that baseURL is ‘http://www.example.com’ .

Create a URL Object and Get the Base URL Parts From the Created Element

Another way to get the base URL from a URL is to create an URL instance and extract the base URL parts from the object.

For instance, we can write:

const url = new URL("http://www.example.com/article/2020/09/14/this-is-an-article/")
const baseUrl = `${url.protocol}//${url.hostname}`
console.log(baseUrl)

We pass in the full URL as an argument of the URL constructor.

Then we can get the base URL by combining the protocol and hostname as we did before.

And so baseURL should be the same as the previous example.

Conclusion

We can extract the base URL from a string with JavaScript by creating an anchor element or using the URL constructor.

Categories
JavaScript Answers

How to Output Numbers With Leading Zeros in JavaScript?

Sometimes, we want to output numbers with leading zeroes in our JavaScript programs.

In this article, we’ll look at how to create numbers with leading zeroes with JavaScript.

String.prototype.padStart

The JavaScript string’s padStart method lets us add characters we want to a string until it reaches a given length.

For instance, we can write:

const padded = (123).toString().padStart(5, '0')
console.log(padded)

We call toString on the number to convert it to a string.

Then we call padStart with 5 to pad the string to length 5.

And we pass in '0' to pad the number with leading 0’s.

Therefore, padded is '00123' .

Write Our Own Code

We can also write our own code to pad a number string with leading zeroes.

For instance, we can write:

const zeroPad = (num, places) => {
  const numZeroes = places - num.toString().length + 1;
  if (numZeroes > 0) {
    return Array(+numZeroes).join("0") + num;
  }
  return num
}

console.log(zeroPad(5, 2))
console.log(zeroPad(5, 4))
console.log(zeroPad(5, 6))

We create the zeroPad function that takes the num and places parameters.

num has the number we want to pad with leading zeroes.

places is the number of decimal places that we want to pad to.

In the function, we compute the numZeroes variable, which is the number of leading zeroes we want to add to make the string the length set by places .

We compute that by substracting places with num.toString().length plus 1.

This subtracts the final number of places with the length of the number string plus 1.

We add 1 so that we create the correct sized array since we want to add zeroes in between the array entries with join .

Then if numZeroes is bigger than 0, we return a string with leading zeroes by creating an array, then calling join with 0 to create the zero string, and then concatenating that with the num value.

Otherwise, we return num itself.

So the console log should log:

05
0005
000005

Conclusion

We can pad our JavaScript nuinmber strings with leading zeroes with the padStart method or write our own code to do so.

Categories
JavaScript Answers

How to Let Users Download JavaScript Array Data as a CSV on Client-Side?

Sometimes, we may want to let users download a nested array with data as a CSV text file.

In this article, we’ll look at how to let users download a JavaScript array’s data as a CSV on the client-side.

Using the window.open Method

We can use the window.open method to open a URL encoded string to let users download that to their computer.

For instance, we can write:

const rows = [
  ["name1", "new york", "abc"],
  ["name2", "san francisco", "def"]
];

let csvContent = "data:text/csv;charset=utf-8,";

for (const rowArray of rows) {
  const row = rowArray.join(",");
  csvContent += `${row}rn`;
}
const encodedUri = encodeURI(csvContent);
window.open(encodedUri);

We have the rows nested array that we want to convert to a CSV string and let users download it.

To do the conversion, we first define the beginning of the csvContent string which specifies the MIME type and the character set.

Then we loop through the rows entries, join each row’s entries and append them to the csvContent string with newline characters.

Then we call encodeURI with the csvContent string to encode it to a URL encoded string.

And finally, we can download the string as a file with window.open .

We can also shorten the for-of with the map method:

const rows = [
  ["name1", "new york", "abc"],
  ["name2", "san francisco", "def"]
];

const csvContent = `data:text/csv;charset=utf-8,${rows
  .map((e) => e.join(","))
  .join("n")}`;

const encodedUri = encodeURI(csvContent);
window.open(encodedUri);

We just call map on rows to map each row to a comma-separated string with join .

Then we call join on the mapped strings.

Download the file this way doesn’t let us set the file name.

To let us set the file name, we can create an invisible link and click on it programmatically.

To do that, we weiter:

const rows = [
  ["name1", "new york", "abc"],
  ["name2", "san francisco", "def"]
];
const csvContent = `data:text/csv;charset=utf-8,${rows
  .map((e) => e.join(","))
  .join("n")}`;
const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "data.csv");
document.body.appendChild(link);
link.click()

We call createElement to create an a element.

Then we set the href to the encodedUri .

And then we set the download attribute to the file name with setAttribute .

Next, we call appendChild with the link to attach it to the body.

And then we call click on it to click it to start the download.

Save the Data as a Blob

We can save the data as a blob by rewriting the example above.

For instance, we can write:

const rows = [
  ["name1", "new york", "abc"],
  ["name2", "san francisco", "def"]
];
const csvContent = rows
  .map((e) => e.join(","))
  .join("n");
const blob = new Blob([csvContent], {
  type: 'text/csv;charset=utf-8;'
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("download", "data.csv");
document.body.appendChild(link);
link.click()
URL.revokeObjectURL(link.href)

We have the csvContent string that only has the CSV string content.

Then we create a blob from it with the Blob constructor.

In the 2nd argument of it, we set the type to the data type of the blob.

Next, we call URL.createObjectURL to create an encoded URL that we can download.

And we create the link element the same way as before, but with url created from URL.createObjectURL instead.

Also, we’ve to call URL.revokeObjectURL to free up resources after the download is done.

Conclusion

We can let generate CSVs from nested arrays on client-side and let users download them with some JavaScript code.