The JavaScript progress bar fails to function properly when implemented with object-oriented JavaScript programming

I am currently attempting to refactor this demonstration in an object-oriented manner, following the example found at: https://www.w3schools.com/howto/howto_js_progressbar.asp Here is my code:

document.getElementById("barButton").addEventListener("click", callMove);

function callMove(){
var bar1 = new ProgressBar();
bar1.move();
}

function ProgressBar() {
this.elem = document.getElementById("myBar"),
this.width = 1;
}

ProgressBar.prototype = {
constructor: ProgressBar,
move: function() {
this.id = setInterval(this.frame, 300);
},
frame: function() {

if(this.width >= 100) {
clearInterval(this.id);
}
else {
this.width++;
if(this.width >= 50) {
return;
}
this.elem.style.width = this.width + '%';
}
},
}
#myProgress {
  width: 100%;
  background-color: grey;
}

#myBar {
  width: 1%;
  height: 30px;
  background-color: black;
}
<html>

<head>
<title>
This is a OO progress bar test.
</title>
<link rel="stylesheet" href="testOOProgressBar.css">
</head>

<body>
<div id="myProgress">
<div id="myBar"></div>
</div>
<br>
<button id="barButton">Click Me</button> 
<script src="testOOProgressBar.js"></script>
</body>

</html>

However, when I click the button, the progress bar does not advance as expected; instead, I encounter

Uncaught TypeError: Cannot read property 'style' of undefined at frame
in the console. What could be the issue here? It appears that this.width is not being passed from ProgressBar() to its prototype.

Answer №1

Your issue arises from attempting to access something like this:

undefined.style

Upon examining the code, it becomes evident that the error is originating from the Progressbar.frame function, specifically involving the use of .style on one line.

To understand further, look at what precedes it: this.elem... which equates to undefined!

The primary concern lies in:

setInterval assigns this to the global object when executing the specified function.

This can be prevented by using .bind():

document.getElementById("barButton").addEventListener("click", callMove);

function callMove() {
  var bar1 = new ProgressBar();
  bar1.move();
}

function ProgressBar() {
  this.elem = document.getElementById("myBar"),
    this.width = 1;
}

ProgressBar.prototype = {
  constructor: ProgressBar,
  move: function() {
    this.id = setInterval(this.frame.bind(this), 300);
  },
  frame: function() {
    if (this.width >= 100) {
      clearInterval(this.id);
    } else {
      this.width++;
      if (this.width >= 50) {
        return;
      }
      this.elem.style.width = this.width + '%';
    }
  },
}
#myProgress {
  width: 100%;
  background-color: grey;
}

#myBar {
  width: 1%;
  height: 30px;
  background-color: black;
}
<html>

<head>
  <title>
    This is a OO progress bar test.
  </title>
  <link rel="stylesheet" href="testOOProgressBar.css">
</head>

<body>
  <div id="myProgress">
    <div id="myBar"></div>
  </div>
  <br>
  <button id="barButton">Click Me</button>
  <script src="testOOProgressBar.js"></script>
</body>

</html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In React js, I wanted to display the animation specifically on the "add to bag" button for the added item

When I click the "add to bag" button, all other buttons also display the animation. How can I make sure that only the clicked button shows the animation? Any suggestions? <Table responsive> <thead> <tr> ...

:hover functionality can only be activated within the Inspector

The element top_fixed_right:hover on my homepage is functioning perfectly. However, on a different page, the same div only responds to the :hover state when forced using Chrome's developer tools. Normal mouse hovering does not trigger it. I tried op ...

Randomized Image Generator Array with Descriptive Captions

I am currently designing a unique image generator with additional fields or captions that will be displayed on the page. To achieve this, I believe the best approach is to create an array of objects. However, my knowledge of objects and classes is a bit ou ...

What is the best way to implement a calendar view for selecting time periods on an HTML page?

Is there a way to implement a calendar view when clicking on the input box within an HTML page? I am looking to create a function where users can select a time period to generate a file. How can this be accomplished? If possible, could you share some samp ...

Issue with source file detection in RequireJS and Karma

Having trouble testing my Angular scripts with Karma and RequireJS, as I keep encountering this error: Error in Firefox 28.0.0 (Mac OS X 10.9): 'There is no timestamp for /base/app/public/js/test/unit/controllersSpec.js!' Warning [web-server]: ...

Error message: Failure to define class methods when exporting the class from a file

In my project, I have defined a class called BinarySearchTree in a file named a.js. This class has been exported and then imported into another file where it is used as the parent class for a different class called Traversal. However, I encountered an issu ...

Struggle with comparing strings in different cases

When utilizing the "WithText" function within a Testcafe script, it appears to be case-sensitive. How can I modify it to be case-insensitive? For example, allowing both "Myname" and "myname" for a user input. It's problematic when a script fails due t ...

Sending data to a Sheetlabs API using Axios

I'm currently collaborating with a service called Sheetlabs to transform a Google Sheet into a full-fledged API. Unfortunately, I'm struggling to find useful resources online apart from the Sheetlabs documentation, as it appears to be a relativel ...

Is it possible to move the res.send() outside of the function in node.js?

I currently have the following code: var server = http.createServer(function(req,res){ res.writeHead(200,{'Content-Type': 'text/html; charset=utf-8'}); var oo = require('/test.js'); oo(connection, function (e, res ...

When trying to convert to JSON in node, the process fails. However, the data can still be

I am currently working on converting an array to JSON in order to send it to a client. The data I see in the console is as follows: [ NL: [ true, true, true, true, true, true, true, true, true, true, true, true ], ...

HTML Brickwork Picture Arrangement

I recently integrated this code into a WordPress theme and encountered an issue where the new images are displaying vertically instead of horizontally. I am seeking assistance in aligning the new images to appear on the green line instead of the red line a ...

Top-notch loading icon using jquery

Recently, I embarked on the journey of learning Javascript and jQuery simultaneously, and to my surprise, it feels quite manageable. As I delve deeper into creating functions, I am currently working on displaying a loading image. While I initially used on ...

Tips for accurately placing the iOS audio player in the footer section

In my web page, I have created a simple footer that shows the currently playing track title and includes an HTML audio player. The layout looks great on desktop browsers and Android devices, but on iOS, the player is positioned far below the footer. To ad ...

Progressive Web App with Vue.js and WordPress Rest API integration

When creating an ecommerce website using Wordpress, I utilized Python for scraping data from other websites to compare prices and bulk upload products through a CSV file. My next goal is to learn Vue and transform the website into a PWA as it will be esse ...

Problem uploading images to server and database

I'm currently experiencing difficulties with photo uploads on my website. The issue arises at the $fileName = basename($_FILES["file"]["name"]); line where I receive the error message "Please select a file to upload". There seems to be no database in ...

Adjust text at multiple positions using Javascript

I am working on parsing a complex query and developing a tool using the following sample: var str =" SELECT 'Capital Return' AS Portfolio_Classification , '(Gross)' AS Portfolio_Type , '0.21%& ...

Minify and group options available for asset managers specifically designed for traditional HTML websites

My primary focus is on working with the CakePHP framework and utilizing a fantastic plugin that minifies and groups selected assets into a single file, reducing the number of HTTP requests needed for the entire site. Currently, I am collaborating with des ...

Challenges with variable scopes and passing variables in Ionic 2 (Typescript)

In my Ionic 2 TypeScript file, I am facing an issue with setting the value of a variable from another method. When I close the modal, I get undefined as the value. I'm encountering difficulty in setting the value for coord. export class RegisterMapP ...

Tips for creating a stylish, blurred, and centered box for a login form on a full-size background that is also responsive

I attempted to create a login form on an HTML page using Angular, featuring a full-size background image that is centered. The form itself is contained within a div with a blurred background, also centered both horizontally and vertically within the browse ...

Jquery's LOAD function can be used as an effective alternative to or substitute for I

My current setup involves using jQuery to load user messages every second, but I am looking for a solution that mimics the behavior of <iframe>, <object>, or <embed> tags. <script> setInterval( function() { $('#chat').loa ...