Reputation: 1
I'm coding a few JavaScript classes for my school project and need to make some circuit breaker components. I'm following the standard for importing and exporting JavaScript classes, but when I test the code using XAMPP and the website being built for these JavaScript classes, I'm getting this error "CircuitBreaker.js:12 Uncaught ReferenceError: Cannot access 'Component' before initialization at CircuitBreaker.js:12:37"
Here are the Classes Connected to this Component.
Component.js
import {Drag_Event, Zoom_Event} from "./CADDIEngine.js";
export class Component {
constructor(name, color="black", iconPath=null) {
// Functionality
this.children = [];
this.current_rating = 0 // component current rating
this.errors = [];
this.frequency = 0; // if Component has a frequency rating it should be 60hz
this.id = 0; // RBDC team will implement a UUID system later
this.icon_path = " "; // this should be a hard coded path using in the
// child class contructor
this.name = name;
this.parent = null; // start the parent as null
this.pass_up_map = {}; // Used for passing information up & down the tree
this.personal_current_draw = 1; // This will not be used for most components
this.phase = 0; // 1 = single-phase, 3 = three-phase, 0 = N/A
this.sccr = 0; // "short circuit current rating"
this.type_array = []; // list of function types component fulfils
this.volt_rating = { //Component voltage rating range
min: 0,
max: 0
};
this.waveForm = 0; // AC or DC (1 = AC, 2 = DC, 0 = N/A)
// Attributes for the GUI interface.
// These keep track of coordinate information
// The RBDC team should be the only people using
// or modifying these variables
// Coordinate and location attributes
this.absX = 200;
this.absY = 200;
this.relativeX = this.absX;
this.relativeY = this.absY;
this.offsetX = 0; // offset based on user position
this.offsetY = 0; // offset based on user position
// Location attributes for the middle
this.absMiddleX = this.absX + (this.width / 2);
this.absMiddleY = this.absY + (this.height / 2);
this.relativeMiddleX = this.relativeX + (this.width / 2);
this.relativeMiddleY = this.relativeY + (this.height / 2);
// Configures image
if (iconPath == null){
iconPath = "../assets/component_icons/icon_missing.svg";
}
this.hasIcon = false;
this.img;
if (iconPath != null){
this.hasIcon = true;
this.img = new Image();
this.img.src = iconPath;
}
// Misc attributes
this.width = 80;
this.height = 80;
this.stacking_height = this.height * 1.5; // Defines how much space this components wants between it and its children
this.color = color;
this.canvasContext;
this.selected = false;
this.engine;
// Call the first update
this._update_middle_coords();
}
drag(deltaX, deltaY){
this.relativeX += deltaX;
this.relativeY += deltaY;
this._update_middle_coords();
}
set_coords(newX=this.absX, newY=this.absY){
// // Calculate how far off the relative Coordinates are so we can account for them
// let relativeOffsetX = this.absX - this.relativeX;
// let relativeOffsetY = this.absY - this.relativeY;
let relativeOffsetX = this.relativeX - this.absX;
let relativeOffsetY = this.relativeY - this.absY;
// Update the absolute coords
this.absX = newX;
this.absY = newY;
// Update relative coords with new abs coords and relativeOffset
this.relativeX = this.absX + relativeOffsetX;
this.relativeY = this.absY + relativeOffsetY;
// Reset relativeX, relativeY, then apply all the events from engine
// this.absX = newX;
// this.absY = newY;
// this.relativeX = this.absX;
// this.relativeY = this.absY;
// if (this.engine != null){
// // Apply all the apst movement events
// console.log("Applying everything to " , this.name);
// console.log(this.engine);
// for (let movement of this.engine.movement_record){
// if (movement instanceof Drag_Event){
// // this.drag(movement.totalMoveX, movement.totalMoveY);
// } else if (movement instanceof Zoom_Event){
// this.change_zoom(movement.curMouseX, movement.curMouseY, movement.scaleDelta, movement.scale);
// }
// }
// }
// Make middle coords update
this._update_middle_coords();
}
update_tree(){
// Finds the top most parent
if (this.parent == null){
// this is the parent. Start recursing all the way down.
this._update_recursive_down();
} else {
// this is not the grandparent.
this.parent.update_tree();
}
this.organize_children();
}
click(){
console.log("" , this.name, " Component click");
if (this.selected){
this.selected = false;
} else {
this.selected = true;
}
}
deselect(clientX, clientY){
/*
Deselects the Component. This primarily
acts as an interface for child classes.
*/
this.selected = false;
}
_update_recursive_down(){
// this.total_current_draw = this.personal_current_draw;
// Gets pass_up_map
this.pass_up_map['total_current_draw'] = this.personal_current_draw;
this.pass_up_map['widest_root'] = 0;
this.pass_up_map['longest_root'] = 0;
// Null map to hold data when looping
let this_child_map = {};
for (let child of this.children) {
// Send update down & get updated result
this_child_map = child._update_recursive_down();
// Updates total current draw
this.pass_up_map['total_current_draw'] += this_child_map['total_current_draw'];
// Updates the widest root
this.pass_up_map['widest_root'] += (this_child_map['widest_root'] - 1) <= 0 ? 0 : this_child_map['widest_root'] - 1; // ternary makes sure it isn't below 0
this.pass_up_map['widest_root'] += 1; // increment for this child
// Updates the deepest root
if (this_child_map['longest_root'] + 1 > this.pass_up_map['longest_root']){
this.pass_up_map['longest_root'] = this_child_map['longest_root'] + 1;
}
}
// Add self to the longest_root value
// this.pass_up_map['longest_root']++;
this.update_self();
// return this.total_current_draw;
return this.pass_up_map;
}
organize_children(){
let thisMaxRoot = this.pass_up_map['widest_root'];
// Verifies that the max root is not 0
// This can happen to components without descendants
// since those components interpret no descendants as
// 0 wide
if (thisMaxRoot < 1){
thisMaxRoot = 1;
}
// Variables that control positioning of component children
let childWidth = 100;
let childGap = 70;
let totalChildWidth = childWidth + childGap + 100;
let leftOffset = (childWidth * thisMaxRoot) / 2;
// Variables for the loop
let thisChildIndex = 0;
let childMaxRoot;
let childAbsX;
// Organizes the children
if (this.children.length == 1){
// There shouldn't be any offset if there's only one child.
// Thus, this is a special case for that
let thisChild = this.children[0];
// Calculates the offset to make sure it is centered on x axis
thisChild.set_coords(this.absX, this.absY + this.stacking_height);
thisChild.organize_children();
} else if (this.children.length > 1) {
// Since there is more than one child we need to do this loop
for (var child of this.children){
// Gets the wideness of this child
childMaxRoot = child.pass_up_map['widest_root'];
// Calculates the new absolute coordinates and sets them
childAbsX = this.absX - leftOffset + (thisChildIndex * totalChildWidth);
child.set_coords(childAbsX, this.absY + this.stacking_height);
// Update the index in regards to the total length of this child
thisChildIndex += (childMaxRoot > 0) ? childMaxRoot : 1;
// Recurse
child.organize_children();
}
}
}
change_zoom(mouseX, mouseY, scaleDelta, scale){
this.offsetX -= (this.relativeMiddleX - mouseX) * scaleDelta ;
this.offsetY -= (this.relativeMiddleY - mouseY) * scaleDelta ;
// this.engine.scale = scale;
this._update_middle_coords();
}
_update_middle_coords(){
this.absMiddleX = this.absX + (this.width / 2);
this.absMiddleY = this.absY + (this.height / 2);
// Make sure we aren't multiplying by undefined. If engine isn't
// set yet then just use 1 as our multiplyer
let this_scale;
if (typeof this.engine != 'undefined') {
this_scale = this.engine.scale;
} else {
this_scale = 1;
}
this.relativeMiddleX = this.relativeX + (this.width / 2) * this_scale;
this.relativeMiddleY = this.relativeY + (this.height / 2) * this_scale;
}
draw(canvasContext, scale){
let thisFrameX = this.relativeX + this.offsetX;
let thisFrameY = this.relativeY + this.offsetY;
let thisFrameMidX = this.relativeMiddleX + this.offsetX;
let thisFrameMidY = this.relativeMiddleY + this.offsetY;
let thisFrameWidth = this.width;
let thisFrameHeight = this.height;
// Always restart the path before drawing
canvasContext.beginPath();
if (this.hasIcon){
canvasContext.drawImage(this.img, thisFrameX, thisFrameY, thisFrameWidth * scale, thisFrameHeight * scale);
} else {
// set color
canvasContext.fillStyle = this.color;
// Draw the rectangle, as well as a red dot to indicate the center
canvasContext.fillRect(thisFrameX, thisFrameY, thisFrameWidth * scale, thisFrameHeight * scale);
}
if (this.selected){
canvasContext.strokeStyle = "white";
canvasContext.strokeRect(thisFrameX, thisFrameY, thisFrameWidth * scale, thisFrameHeight * scale);
}
canvasContext.arc(thisFrameMidX, thisFrameMidY, 1, 0, 2 * Math.PI, false);
canvasContext.fillStyle = "red";
canvasContext.fill();
canvasContext.fillStyle = "black";
// Draws line to the parent
if (this.parent != null){
// Update parents middle coords
this.parent._update_middle_coords();
canvasContext.strokeStyle = "black";
canvasContext.lineWidth = 2;
canvasContext.beginPath();
canvasContext.moveTo(this.relativeMiddleX + this.offsetX, this.relativeY + this.offsetY);
canvasContext.lineTo(this.parent.relativeMiddleX + this.parent.offsetX, this.parent.relativeY + (this.parent.height * this.parent.engine.scale) + this.parent.offsetY);
canvasContext.stroke();
}
}
update_self() {
// must be implemented by child classes
// throw new Error("update_self() must be implemented by child classes");
}
update_server() {
// to be implemented by RBDC
// This will send updated data back to the server for storage
return false;
}
add_child(newComponent, perpetuate=true) {
// Adds a child to the component
// This will be used by the frontend to connect components together
this.children.push(newComponent);
if (perpetuate){
newComponent.set_parent(this, false);
}
// Make sure everything updates to prevent visual bugs
this.update_tree();
this.organize_children();
}
set_parent(newComponent, perpetuate=true) {
// Adds a parent to the component
// This will be used by the frontend to connect components together
this.parent = newComponent
if (perpetuate){
newComponent.add_child(this, false);
}
// Make sure everything updates to prevent visual bugs
this.update_tree();
this.organize_children();
}
get_data(){
// Get ID of all children
let childIDArr = [];
for (let child in this.children){
childIDArr.push(child.id);
}
// Get the ID of parent, or use null if this is a top parent
let parentId = null;
if (this.parent != null){
parentId = this.parent.id;
}
return {
id: this.id,
errors: this.errors,
children: childIDArr,
parent: parentId,
personal_current: this.personal_current_draw,
total_current: this.total_current_draw
}
}
get_errors() {
return this.errors;
}
get_total_current_draw() {
return this.total_current_draw;
}
get_personal_current_draw() {
return this.personal_current_draw;
}
get_children() {
return this.children;
}
get_parent() {
return this.parent;
}
}
CircuitBreaker.js
import { Component } from "./Component.js";
export class CircuitBreaker extends Component {
constructor (children, current_rating, errors, id, icon_path, name, parent, pass_up_map,
phase, sccr, type_array, waveform, volt_rating) {
//this.CircuitBreaker = new Component();
// passing in parent class
super(children, current_rating, errors, id, icon_path, name, parent, pass_up_map,
phase, sccr, type_array, waveform, volt_rating);
// constructing Circuit Breaker specific properties
this.name = "Circuit Breaker";
this.triptype = "";
this.protection_multiplier = 0.0;
}
InstantMCCB.js
import { CircuitBreaker } from "./CircuitBreaker.js";
export class InstantMCCB extends CircuitBreaker {
constructor (children, current_rating, errors, id, icon_path, name, parent, pass_up_map,
phase, sccr, type_array, waveform, volt_rating) {
// passing in parent class
super(children, current_rating, errors, id, icon_path, name, parent, pass_up_map,
phase, sccr, type_array, waveform, volt_rating);
// constructing Instant MCCB Circuit Breaker specific properties
this.name = "InstantMCCB";
this.triptype = "InstantMCCB";
this.protection_multiplier = 8.0;
}
// Methods
// validates the UL 508A rules for Instant MCCB Circuit Breakers
update_self() {
i = 0;
while (this.children[i] != 'null') {
i++;
if (this.children[i] == 'null') {
fulloadamps = this.children[i].Load.getFullLoadAmps();
}
}
if (fulloadamps < (current_rating * 0.8)) {
this.errors = "Full Load Current of Load is to low";
} else if ( fullloadamps < (this.volt_rating['max'] * this.protection_multiplier)) {
this.errors = "% Branch Circuit Protection Multiplier is to low"
} else {
return true;
}
}
// creates a JSON array for the interfaces of the UI and the database.
get_data() {
JSON_InstantMCCB = JSON.stringify(this)
return JSON_InstantMCCB;
}
// takes in a JSON array to set the Instant MCCB Circuit Breaker attributes
set_data() {
return 0;
}
}
Obviously The Code isnt finished for most of these classes, but I am unable to even start bug testing the code since I am unable to initlaize these functions even though I can initilaze Add_Component.js and Component.js which are using the same important and export code.
I'm currently Using CADDIEEngine to add the Components to the GUI another class member is building for the project, and I am unable to get the website to add any of the other Components built besides Add_Component and Component.
CADDIEEngine.js
import { Add_Component } from "./Add_Component.js";
import { Component } from "./Component.js";
import { CircuitBreaker } from "./CircuitBreaker.js";
import { InstantMCCB } from "./InstantMCCB.js";
import { InverseMCCB } from "./InverseMCCB.js";
import { MPCB } from "./MPCB.js";
export class CADDIEngine {
// CAD Drafting Interface Engine (CADDIE)
// CAD Design and Display Interface ENgine
constructor (targetFPS) {
// Set up canvas
this.canvas = document.querySelector('.test-canvas');
this.c = this.canvas.getContext('2d');
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
// Set up mouse tracking attributes
this.middleClickPressed = false;
this.curMouseX = 0;
this.curMouseY = 0;
this.lastMouseX = 0;
this.lastMouseY = 0;
this.mouseDX = 0;
this.mouseDY = 0;
// Performance attributes
this.rollingFPS = 0;
this.fps_target = targetFPS;
this.fps = 0;
// Zooming attributes
this.scale = 1;
this.zoomOffsetX = 1;
this.zoomOffsetY = 1;
this.mouseLastZoomX = 0;
this.mouseLastZoomY = 0;
this.pauseForScroll = false;
// Miscellenious attributes
this.components = [];
this.pushed_buttons = {};
this.movement_record = [];
this.supported_components = { // List of supported components
"Add Button": Add_Component,
"Generic Component": Component,
"Instant MCCB": InstantMCCB,
"Inverse MCCB": InverseMCCB,
"MPCB": MPCB,
// "Ad Button": Add_Component, // extra bogus components to demo the interface
// "Geeric Componnt": Component,
// "Add utton": Add_Component,
// "Generic Coponent": Component,
// "Add Butto": Add_Component,
// "Generic Cmponent": Component,
// "Add utton": Add_Component,
// "Generic Cmponent": Component,
// "Ad Button": Add_Component,
// "Generic Coponent": Component,
// "Add Buon": Add_Component,
// "Genericomponent": Component,
};
I've tried Commenting out all the code currently in the classes besides the constructor and super functions, making all the exports a default export, and tried initializing the Component class before the CircuitBreaker class is initialized with a
let Component = new Component("CircuitBreaker");
or
const Component = new Component("CircuitBreaker");
I'm not sure what exactly is causing the unexplained reference error where Component is not intialized before CircuitBreaker that is not an issue with the Component and Add_Component classes.
Upvotes: 0
Views: 76