ESLint Globals configuration for testing in general?

I’m using a testing library that allows suite to be used, and if I add Jest like this to the ESLint globals configuration in eslint.config.js it works for the test global, but not for suite.

import eslint from "@eslint/js";
import globals from "globals";

export default [
    // apply recommended rules to JS files
    
    {
        languageOptions: {
            globals: {
                ...globals.browser,
                ...globals.jest
            }
        }
    },
    {

        files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
        rules: eslint.configs.recommended.rules
    },
    {
        ignores: ["rollup.config.js", "web-test-runner.config.js", "src/index.bundle.js"]
    }
]

Is there are generic global for ESLint that we can use that will cover most of the generic testing globals?

This is the linting error:

/Users/oleersoy/Temp/Remove/fs-javascript-starter/src/hello-world.component.spec.js
  4:1  error  'suite' is not defined  no-undef

✖ 1 problem (1 error, 0 warnings)

Mapbox Feature Mismatch Between Map and Rendered Features Query

I am getting strange behavior with Mapbox 3 when I click on the map. It seems like the features arbitrarily correspond (or don’t) with the location of the map click. In the example below, I am clicking in empty space and getting back 3 features:

Map click event where no features should be captured

In the second image I am displaying the coordinates of the features selected and they are not very close (when compared to the scale at zoom level 16) to the point clicked. The point clicked is the second command shown:

Queried features vs Map Click Point @ Zoom Level 16

If I then query the features that are returned in Postgres to see the actual locations being selected, I get even another representation of the data:

Representation of mapped data from database

To put it simply, something is not right here, and I am not sure why the click event would return data that is not in the same location, or in some cases even close. While in others it returns the feature displayed on the map correctly. Any guidance or starting steps to break this problem down would be most appreciated.

How do you change a Node of a LinkedList to null in Javascript [duplicate]

So I was trying to solve a problem “delete the middle of a LinkedList” and here’s how I did.

But this works for all cases except when the slow points to the end of the List because apparently slow=null doesn’t affect the List.

    let slow = head;
    let fast = head;

    while(fast && fast.next!== null){
        slow = slow.next;
        fast = fast.next.next;
    }

    if(slow.next){
        slow.val = slow.next.val;
        slow.next = slow.next.next;
    }else{
        slow = null;
    }
    return head;
};

This appeared strange to me. So I created a Linked List and I find it’s the same case. Notice below that I change b to null. However, the original list remains unaffected. Shouldn’t c start pointing to null?

Question: Why is modifying b doesn’t affect the original list and how can I resolve this?

function ListNode(val, next) {
     this.val = (val===undefined ? 0 : val)
     this.next = (next===undefined ? null : next)
}

let a = new ListNode(1);
let b = new ListNode(2, a);
let c = new ListNode(3, b);

console.log("before", c);
b= null;
console.log(b);
console.log("after", c);

Getting a nested for loop to run synchonously with timeouts inside the inner loop

Expected behavior:

  1. Typewriter animation is on
  2. The nested forEach loop prints one letter at a time, 1 second apart
  3. Then the citation is added
  4. Then the typewriter animation is removed

Current behavior:

  1. Typewriter animation is on
  2. Code hits the inner forEach loop once and waits for the timeout
  3. Outer loops moves on to add the citation
  4. Outside the outer loop, the animation stops
  5. The content for the inner loop gets added all at once

jsfiddle

It seems like the inner loop is happening async, though I’m not sure why. I’ve tried using setTimeout and setInterval like this but it still runs async

let letters = c.value.split('')
let i = 0;
let interval = setInterval( ()=> {
     p.innerHTML += letters[i]
     i++
     if(i === letters.length) clearInterval(interval)
}, 100);

I’ve also tried sleep(1000) without then() and that prints the citation after the string, but the string still appears all at once

JS Regex MatchAll with combination of Comma & Semicolon

I’m having a requirement of js regex should return the object from String.

String: 'A: 100 - 200, B: Test & Test2, Tes3, C: 40, D: 11 22, E: E 444,55E'

Output:

{
A: '100 - 200',
B: 'Test & Test2, Tes3',
C: '40',
D: '11 22',
E: 'E 444,55E'
}

I tried with following regex.

const regexp = /([^:]+): ?([^,]*),? ?/g;

But the output was not correct. Value for E is wrong.

{A: '100 - 200', B: 'Test & Test2', Tes3C: '40', D: '11 22', E: 'E 444'} 

I want to build a website like eTinyurl.com, can anybody tell how does eTinyurl.com work? [closed]

I am a non IT background person, but have some some basic knowledger of PHP, CSS, Javascript. I want to build a website like etinyurl.com.

So please share the details about it, How can I build a website like etinyurl.com in PHP.

I tried to make it but it had lot of bugs, it is not working for all URLs, and second, when I try URL expanding, then I am not getting any idea about that.

Can you reference a variable dynamically using JavaScript for Playwright [duplicate]

I have a JSON file that I’m reading data from for a Playwright test as below:

async answerMyDetails(){
    const testDataFile = './myJsonFile.json'
    let data = await fs.readFile(testDataFile)
    let testData = await JSON.parse(data)

    await this.page.locator(`div:has(> label:has-text("Some Text")) input`).fill(`${testData.myDetailsPageQuestions.vehicleReg.answer_fullUkLicence_carInsurance}`)
}

I’d like to change this so that the _fullUkLicence_carInsurance part of the property that’s being read from the JSON file is not hard coded and can be determined at the time the function is called, e.g. something like:

(answerSet == fullUkLicence_carInsurance)

async answerMyDetails(answerSet){
    const testDataFile = './myJsonFile.json'
    let data = await fs.readFile(testDataFile)
    let testData = await JSON.parse(data)

    await this.page.locator(`div:has(> label:has-text("Some Text")) input`).fill(`${testData.myDetailsPageQuestions.vehicleReg.answer_{answerSet}}`)
}

Can’t access json in JavaScript [duplicate]

I’m trying to access below the top-level of a JavaScript decoded JSON object but I can’t for some reason

> attacks // This was me 

> Promise {<fulfilled>: {…}}
   [[Prototype]]: Promise
   [[PromiseState]]: "fulfilled"
   [[PromiseResult]]: Object
     data: Array(595)
     [0 … 99]
     [100 … 199]
     [200 … 299]
     [300 … 399]
     [400 … 499]
     [500 … 594]
     length: 595
     [[Prototype]]: Array(0)
   [[Prototype]]: Object

> attacks.data.length // This was also me

> Uncaught TypeError: Cannot read properties of undefined (reading 'length')
    at <anonymous>:1:14

As you can see, I’m able to grab the top level of the array and it shows me the data inside but I can’t actually access it in variable form.

I’m not sure what to do.

How to calculate correct position of a element when dragged using translate with scale applied in javascript

I am working on the following Drag and Drop library as a side project. I am using transform translate to make a element draggable. I store the initial client.x and client.y and calculate the translate value by subtracting the current client.x and client.y when the mouse move. In simple terms I record the initial click coords(x,y) and when I subtract the current coords(x,y) on mouse move it will give me the distance by which mouse has moved from the initial position which I then apply to the element using translate.

It works as expected. I have even implemented cursor offset which also works but the only thing I am not able to figure out is how to adjust the position if scale property is applied to the element. When the element scale is changed from 1 to any other value the size and position of the element will change which is messing up my current calculation.

I have created a simple diagram which you can see here. I’m also sharing the screenshot bellow.

diagram for drag and drop element

You might need to understand the flow of the program so below is a simple explanation

  • when a element is made draggable a pointer down event is attached to trigger dragStart.
  • dragStart creates the default drag preview, sets the initial position and cursor offset
  • when the element is dragged #translateDragPreview method is called to set the position of the element.

The position of the element is handle by these two following methods

  #translateDragPreview(x?: number, y?: number) {
    if (this.#draggedPreview.element === null) return;
    const cords = {
      x: x ?? this.#internalState.activeCords.x,
      y: y ?? this.#internalState.activeCords.y,
    };

    const initialX = this.#initialPosition.x / this.#draggedPreview.scale;
    const initialY = this.#initialPosition.y / this.#draggedPreview.scale;

    this.#draggedPreview.element.style.transform = `translate(
    ${cords.x - initialX}px, 
    ${cords.y - initialY}px) 
    scale(${this.#draggedPreview.scale})`;
  }
  #setCursorOffset(
    dragElement: HTMLElement,
    event: PointerEvent,
    offset: BaseDraggableType["modifiers"]["cursor"]["offset"],
  ) {
    const cursorOffset = offset;
    const rect = dragElement.getBoundingClientRect();
    const { scale } = this.#draggedPreview;

    const clickX = this.#internalState.initialCords.x - rect.left;
    const clickY = this.#internalState.initialCords.y - rect.top;

    const adjustRect: (value: number) => number = (value) => value + (value - value / scale);
    const adjustedRect = {
      left: rect.left / scale,
      right: adjustRect(rect.right),
      top: adjustRect(rect.top),
      bottom: adjustRect(rect.bottom),
      width: adjustRect(rect.width),
      height: adjustRect(rect.height),
    };

    const presetOffset = {
      "top-left": {
        x: adjustedRect.left - cursorOffset.x,
        y: adjustedRect.top - cursorOffset.y,
      },
      "top-right": {
        x: adjustedRect.right + cursorOffset.x,
        y: adjustedRect.top - cursorOffset.y,
      },
      "bottom-left": {
        x: adjustedRect.left - cursorOffset.x,
        y: adjustedRect.bottom + cursorOffset.y,
      },
      "bottom-right": {
        x: adjustedRect.right + cursorOffset.x,
        y: adjustedRect.bottom + cursorOffset.y,
      },
      center: {
        x: adjustedRect.left + adjustedRect.width / 2 + cursorOffset.x - 4,
        y: adjustedRect.top + adjustedRect.height / 2 + cursorOffset.y - 2,
      },
      auto: {
        x: adjustedRect.left + clickX + cursorOffset.x,
        y: adjustedRect.top + clickY + cursorOffset.y,
      },
    };

    this.#initialPosition = presetOffset[cursorOffset.preset];
  }

Some more information

  • this.#internalState.activeCords stores the current client.x and client.y
  • this.#internalState.initialCords.x stores the initial click coordinate (x,y)
  • this.#initialPosition stores the intialPosition with offset applied. I also tried to adjust the scale but it is not working if scale value is more or less then 1

Here is a code sandbox link with setup. please check the index.html and main.ts file . In the main.ts file you fill see dragOptions with scale option set to 1 if you will change it to any other value the element position will not be set properly.
You can also change the preset to any of the following

  • preset: “top-left” | “top-right” | “bottom-left” | “bottom-right” | “center” | “auto”;

if you don’t want to go through all the code, you can just help me formulate how to calculate a elements correct position when it is dragged using translate and adjusted for scale value. When scale is applied the size and position is change and how to adjust for that I need a formula for that.

I have also created a simple demo in codepen. Please have a look. it is the same approach I have used in my library.

Please let me know if any further information is required I’m happy to help.

Explain why the order of operations is different between jQuery 2.2.4 and jQuery 3.7.1

Given three files:

  1. view.html:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Boilerplate HTML Page</title>
        <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
        <script src="helper.js" defer></script> <!-- Include helper.js -->
    </head>
    <body>
        <header>
            <h1>Welcome to My Page</h1>
        </header>
        <main>
            <p>This is a simple boilerplate HTML page.</p>
        </main>
        <footer>
            <p>&copy; 2024 Your Name</p>
        </footer>
    </body>
    </html>
  1. helper.js:
    // document.addEventListener("DOMContentLoaded", function() {
    $(document).ready(function () {
        var initPicker = function () {
            console.log("helper");
        };

        var init = function () {
            $.getScript("picker.js")
                .done(function () {
                    initPicker();
                })
                .fail(function (ex) {
                    console.error("Failed to load the picker script.");
                });
        };

        init();
    });
  1. picker.js:
    var cp = cp || {};

    // document.addEventListener("DOMContentLoaded", function() {
    $(document).ready(function () {
        cp.picker = (function($) {
            console.log("picker");
        })($);
    });

Fire this up with node or whatever you use, and open js console logs and refresh the page.You will see that “picker” is logged first, and “helper” second. This is the desired case for me.

However, if you change jquery from 2.2.4 to 3.7.1 (and no other changes), then you will see “helper” logged first and “picker” logged second.

Furthermore, replacing the two calls to $(document).ready with vanilla javascript’s document.addEventListener(“DOMContentLoaded”), will result in only “helper” getting logged and “picker” is not logged at all.

I’ve tried a number of different things such as using promises, changing defer and async values, etc. Nothing seems to work unless:

  1. You change jquery version back to 2.2.4
  2. You actually import before within the view.html header.
  3. You remove the $(document).ready that wraps the “picker.js” file.

Unfortunately, in my particular case none of those three options are viable. I need to understand exactly what is going on here so that I can decide on a course of action or find another solution. I am struggling to find answers on the interwebs.

I need to find out how to update this in such a way that both “picker.js” and “helper.js” are loaded after the DOM is ready, and “picker.js” loads before “helper.js”, with minimal changes – and not one of the three listed options above.

BIRT Page break using script

I am using BIRT 4.0 I have a table with 2 columns. I would like to do a page break if column A = ‘TEXT’. What script format do I need and where do I insert it ?
The table is populated via an Oracle SQL select statement.
I have not done scripting in the past so I’m not sure what to try or where to start.

p5.js: Clip not working for a specific shape

I’m trying to apply an invert clip to a shape, but it isn’t work for this specific clip shape.
It works if the clip is not inverted, and it works with other clips, such as ellipses, simple shapes and shapes with bezier curves.

Here is the code:

    function setup() {
        createCanvas(400, 400);
        background(200);

        push();
        translate(-130,50);
  
        beginClip({ invert: true });
        beginShape();
        vertex(332.83,125.59);
        bezierVertex(308.92, 125.59, 303.01, 143.18, 303.01, 153.9);
        vertex(364.44, 153.9);
        bezierVertex(364.44, 143.45, 358.67, 125.59, 332.83, 125.59);
        endShape(CLOSE);
        endClip();
  
        beginShape();
        vertex(397.15, 174.93);
        vertex(303.42, 174.93);
        bezierVertex(304.66, 187.99, 317.71, 194.58, 339.15, 194.58);
        bezierVertex(371.31, 194.58, 394.26, 186.33, 395.5, 185.92);
        vertex(395.5, 212.86);
        bezierVertex(394.54, 213.27, 376.81, 221.79, 337.23, 221.79);
        bezierVertex(289.95, 221.79, 267.96, 199.66, 267.96, 162.42);
        bezierVertex(267.96, 125.18, 292.42, 100.85, 332.56, 100.85);
        bezierVertex(379.15, 100.85, 397.43, 132.32, 397.43, 165.17);
        bezierVertex(397.43, 168.61, 397.43, 172.18, 397.16, 174.93);
        endShape(CLOSE);
  
        pop();  
    }

Can you help me?

Thank you.

How to apply a fill color to a text object in Illustrator?

I try to recolor text object. The color PANTONE 185 C is present in the swatches and if object type is CompoundPathItem then it works. But when a text object selected then it lost a color (that is, it turns into an object without fill).

var doc = app.activeDocument;
var swatches = doc.swatches;

if (doc.selection.length > 0) {
    var targetItem = doc.selection[0];

    if (targetItem.typename == "PathItem" || targetItem.typename == "CompoundPathItem") {
        var colorFound = false;

        for (var i = 0; i < swatches.length; i++) {
            if (swatches[i].name == "PANTONE 185 C") {
                alert("PANTONE 185 C");
                targetItem.fillColor = swatches[i].color;
                colorFound = true;
                break;
            }
        }

        if (!colorFound) {
            alert("PANTONE 185 C not found in Swatches");
        }
    } else {
      
      alert("apply fill color");
      var textRange = targetItem.textRange;
      applyFillColor(textRange, swatches[i].color);
      
    }
    
} else {
    alert("select an object");
}

function applyFillColor(textRange, color) {
    for (var i = 0; i < textRange.characters.length; i++) {
        textRange.characters[i].fillColor = color;
    }
}

Augmenting filepath with two drop down selections using Javascript, causing reload of a PDF viewer

I am trying to work out what is wrong with my current code. My objective is to have two dropdown selections, each augmenting the year and month, respectively, of the filepath given to a PDF Loader. The PDF loader should refresh upon selection change. I’m very new to Javascript, but can work through problems (if slowly), and would like some help pointing to what is wrong and what some solutions might be to the holes in my code.

Currently, I have the two dropdown selections, and they should augment the URL scheme fed into the PDF loader, however, it’s just not working, so I must be missing something obvious.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>dhleader.org</title>
    </head>
    <body>

    <select name="Year" id="yearDropdown">
        <option value="">Please Select a Year</option>
        <hr />
        <optgroup label="'60s">
            <option value="1962">1962</option>
            <option value="1963">1963</option>
            <option value="1964">1964</option>
            <option value="1965">1965</option>
            <option value="1966">1966</option>
            <option value="1967">1967</option>
            <option value="1968">1968</option>
            <option value="1969">1969</option>
        </optgroup>
        <hr />
        <optgroup label="'70s">
            <option value="1970">1970</option>
            <option value="1971">1971</option>
            <option value="1972">1972</option>
    </select>

    <select name="Month" id="monthDropdown">
        <option value="">Please Select a Month</option>
        <option value="January">January</option>
        <option value="February">February</option>
        <option value="March">March</option>
        <option value="April">April</option>
        <option value="May">May</option>
        <option value="June">June</option>
        <option value="July">July</option>
        <option value="August">August</option>
        <option value="September">September</option>
        <option value="October">October</option>
        <option value="November">November</option>
        <option value="December">December</option>
    </select>

    <br /><br /><br />

    <div id="pspdfkit" style="width: 100%; height: 100vh; max-width: 1920px;"></div>
    <script src="https://cdn.cloud.pspdfkit.com/[email protected]/pspdfkit.js"></script>
    <script>

        let currentDocumentUrl = "https://www.dhleader.org/1967_April_DearbornHeightsLeader.pdf"; // Default PDF

        function loadPdf(url) {
            if (PSPDFKit !== undefined && typeof PSPDFKit === "object") {
                PSPDFKit.load({
                    container: "#pspdfkit",
                    document: url,
                    // licenseKey: "YOUR_LICENSE_KEY_GOES_HERE",
                });
            } else {
                console.error("PSPDFKit library not found");
            }
        }

        document.addEventListener("DOMContentLoaded", () => {
            loadPdf(currentDocumentUrl); // Load the default PDF

            const yearDropdown = document.getElementById("yearDropdown");
            const monthDropdown = document.getElementById("monthDropdown");

            function updatePdf() {
                const year = yearDropdown.value;
                const month = monthDropdown.value;
                currentDocumentUrl = `https://www.dhleader.org/${year}_${month}_DearbornHeightsLeader.pdf`; // Construct new URL
                loadPdf(currentDocumentUrl); // Load the new PDF
            }

            yearDropdown.addEventListener("Change", updatePdf); // Update on year change
            monthDropdown.addEventListener("Change", updatePdf); // Update on month change
        });


    </script>
    </body>
</html>

The PDF files used in this example code are quite hefty currently at around 500mb to 1.5gb each, so apologies for that. The site is live at www.dhleader.org, if not yet functional.

Addendum: What online resources might be wise for me to check? Unfortunately, though I’ve advanced pretty well in Python, I don’t know where to start with getting a good sense of the fundamentals in Javascript.

Reload pagination function to use updated variable when variable is updated

I am trying to update the pagination of of Javascript object whenever the variable with that object is filtered.

Ex: 5 page pagination becomes 2 pages when click button to filter the array to only show objects that have a certain category.

I’m currently passing the master array to the pagination via a testToShow variable and the testToShow is updated onClick to filter the array based on category names.

My issue:
The testToShow variable updates to a new value whenever the testToShow variable is filtered onClick but the showPage pagination function does not update based on the new array value.
Currently it just redirects to page one but is still based on the original variable value.

HTML:

<button role="tab" aria-selected="true" class="btn-secondary btn-filter" onclick="filterTests('PZ')">Personalization</button>

<div class="pagination">
                                    <div id="ux-results" class="tableList accordion-group">
                                    </div>
                                    <div class="pagination-block pagination flex">
                                        <span class="pageButton material-icons" id="button_prev">
                                            keyboard_arrow_left
                                        </span>
                                        <span id="page_number" class="outline-none"></span>
                                        <span class="pageButton material-icons" id="button_next">
                                            keyboard_arrow_right
                                        </span>
                                    </div>
                                  </div>
                                </div>

Example of Javascript Object:

const uxTests = [
    {
       category: "Ecomm", 
       projectName: "Project Name 1",
       date: "TBD", 
       details: "Objective: TBD",
       resultsLink: "https://www.google.com",
       isStillTesting: true,
   },
   {
       category: "PZ", 
       projectName: "Project Name 2",
       date: "TBD", 
       details: "Objective: TBD",
       resultsLink: "https://www.google.com",
       isStillTesting: true,
   },
 ]

Update variable:

let testToShow = uxTests;

function filterTests(category) {
    let testToShow = uxTests.filter(test => test.category.includes(category.toString()));

    showPage();
}

Pagination function:

function showPage() {
        "use strict";        
    
        function Pagination() {
    
          const prevButton = document.getElementById('button_prev');
          const nextButton = document.getElementById('button_next');
          const clickPageNumber = document.querySelectorAll('.clickPageNumber');
          
          let current_page = 1;
          let records_per_page = 5;
          
          this.init = function() {
              changePage(1);
              pageNumbers();
              selectedPage();
              clickPage();
              addEventListeners();
         }
          
          let addEventListeners = function() {
              prevButton.addEventListener('click', prevPage);
              nextButton.addEventListener('click', nextPage);   
          }
                
          let selectedPage = function() {
              let page_number = document.getElementById('page_number').getElementsByClassName('clickPageNumber'); 
              for (let i = 0; i < page_number.length; i++) {
                  if (i == current_page - 1) {
                      page_number[i].style.fontWeight = "bold";
                  } 
                  else {
                      page_number[i].style.fontWeight = "normal";
                  }
              }   
          }  
          
          let checkButtonStatus = function() {
            current_page == 1 ? prevButton.classList.add("deactivate")  : prevButton.classList.remove("deactivate");
            current_page == numPages() ? nextButton.classList.add("deactivate") : nextButton.classList.remove("deactivate");
          }
    
          let changePage = function(page) {
              const results = document.getElementById('ux-results');
    
              if (page < 1) {
                  page = 1;
              } 
              if (page > (numPages() -1)) {
                  page = numPages();
              }
           
              results.innerHTML = "";
    
              for(var i = (page -1) * records_per_page; i < (page * records_per_page) && i < testToShow.length; i++) {
                  results.innerHTML += `
                    <div class="accordion-item ${testToShow[i].category.toLowerCase()}">
                        <button class="accordion-btn" aria-expanded="false">
                            <div class="flex">
                                <span class="dot ${testToShow[i].isStillTesting ? 'testing' : ''}"></span>
                                <div class="title">
                                    ${testToShow[i].projectName}
                                </div>
                            </div>
                            <i class="material-icons">expand_more</i>
                        </button>
                        <div class="accordion-content">
                            <div class="accordion-content-body">
                                <div class="flex">
                                    <div>
                                        <div class="test-date">${testToShow[i].date}</div>
                                        <p>
                                            ${testToShow[i].details}
                                        </p>
                                    </div>
                                    <a href="${testToShow[i].resultsLink}">View Full Results</a>
                                </div>
                            </div>
                        </div>
                    </div>
                  `;
              }
              checkButtonStatus();
              selectedPage();
              accordion();
          }
    
          let prevPage = function() {
              if(current_page > 1) {
                  current_page--;
                  changePage(current_page);
              }
          }
    
          let nextPage = function() {
              if(current_page < numPages()) {
                  current_page++;
                  changePage(current_page);
              } 
          }
    
          let clickPage = function() {
              document.addEventListener('click', function(e) {
    
                  if(e.target.nodeName == "SPAN" && e.target.classList.contains("clickPageNumber")) {
                    console.log("clicked page");
    
                      current_page = e.target.textContent;
                      changePage(current_page);
                  }
              });
          }
    
          let pageNumbers = function() {
              let pageNumber = document.getElementById('page_number');
                  pageNumber.innerHTML = "";
    
              for(let i = 1; i < numPages() + 1; i++) {
                  pageNumber.innerHTML += "<span class='clickPageNumber'>" + i + "</span>";
              }
          }
    
          let numPages = function() {
              return Math.ceil(testToShow.length / records_per_page);  
          }
       }
      let pagination = new Pagination();
      pagination.init();

}

window.onload = showPage();