JSON from api to html

I am pulling json from an API but its format is not familiar to me.

It looks like this:

{"ok": true, "database": "boe_spending", "query_name": null, "rows": [["CITIBANK NA", 99237716.31], ["MARYLAND STATE RETIREMENT & PENSION SYSTEM", 16438857.25], ["DALY COMPUTERS INC", 9314951.79]], "truncated": false, "columns": ["payee_name_refined", "total"], "query": {"sql": "select payee_name_refined, sum(amount) as totalrnfrom vendors rnwhere agency_name = 'ALLEGANY COUNTY PUBLIC SCHOOLS'rngroup by 1rnorder by 2 descrnlimit 10", "params": {}}, "error": null, "private": false, "allow_execute_sql": true, "query_ms": 7.000529003562406}

I want to display the data in “rows” in HTML using javascript.

I am used to seeing JSON formatted like this (and I would know how to print it in my HTML):

[
    {
        "payee_name_refined": "CITIBANK NA",
        "sum": "99237716.31"
    },
    {
        "payee_name_refined": "MARYLAND STATE RETIREMENT & PENSION SYSTEM",
        "sum": "16438857.25"
    },
    {
        "payee_name_refined": "DALY COMPUTERS INC",
        "sum": "9314951.79"
    }
]

But I don’t know what to do with the data I get from the API.

Ultimately, I’d like to print the following in HTML:

CITIBANK NA, $99,237,716.31

MARYLAND STATE RETIREMENT & PENSION SYSTEM, $16,438,857.25

DALY COMPUTERS INC, $9,314,951.79

How can I use the provided JSON data to accomplish this?

Thanks for any help

Unique by Most Recent Date

I have a list of objects that I need to filter, for example:

[
   {
      "name":"Aaron",
      "status":"Pending",
      "createdDate":"1-1-2000"
   },
   {
      "name":"Bob",
      "status":"Approved",
      "createdDate":"1-2-2000"
   },
   {
      "name":"Aaron",
      "status":"Rejected",
      "createdDate":"1-3-2000"
   }
]

My intention is to get an array unique by name but only by most recent date, so Aarons’s “Pending” object is not included since it was created before the “Rejected” object was created.

[
   {
      "name":"Bob",
      "status":"Approved",
      "createdDate":"1-2-2000"
   },
   {
      "name":"Aaron",
      "status":"Rejected",
      "createdDate":"1-3-2000"
   }
]

I have the idea that I can extract all of the objects into their own arrays by name, then grab the latest one from each and add them to a final array, but seems like there is a cleaner way to do this.

“Uncaught TypeError: LRU is not a constructor” when trying to connect to a MySQL server via Sequelize

I’m trying to make a web application based on boardgame.io that is just their Tic-Tac-Toe tutorial game, but the results of each match get saved to a MySQL database. In its current state, my code just tries to connect to the database, the result of which should be displayed into the browser’s console.

import { Client } from 'boardgame.io/client';
import { TicTacToe } from './Game';

class TicTacToeClient {
  constructor(rootElement) {
    this.client = Client({ game: TicTacToe });
    this.client.start();
    this.rootElement = rootElement;
    this.createBoard();
    this.attachListeners();
    this.client.subscribe(state => this.update(state));
    const { Sequelize, DataTypes } = require("sequelize");
    const sequelize = new Sequelize(
      'tictactoetest',
      'xxxx',
      'xxxx',
       {
         host: 'localhost',
         dialect: 'mysql',
         dialectModule: require('mysql2')
       }
     );
     
     sequelize.authenticate().then(() => 
     {
         console.log('Connection has been established successfully.');
      }).catch((error) => {
         console.error('Unable to connect to the database: ', error);
      });
      const Record = sequelize.define("record", 
      {
          log: 
          {
            type: DataTypes.STRING,
            allowNull: false
          },
          winner: 
          {
            type: DataTypes.STRING,
            allowNull: false
          }
      }, {
          tableName: 'record'
      });
  
      sequelize.sync().then(() => {
          console.log('Record table created successfully!');
       }).catch((error) => {
          console.error('Unable to create table : ', error);
       });
  }

  createBoard() 
  {
    //Irrelevant
  }

  attachListeners() 
  {
    //Irrelevant
  }

  update(state) 
  {
    //Irrelevant
  }
}

const appElement = document.getElementById('app');
const app = new TicTacToeClient(appElement);

The game itself works properly, but instead of the confirmation of success/failure, I get “Uncaught TypeError: LRU is not a constructor”. I have tried installing all the LRU libraries I could with NPM, nothing helps. I have successfully ran the same DB connection code in a separate file using “node”, so I have no idea where the issue could be.

I want to click on text and display pdf in a modal

Currently I show the name of pdf documents in text and when clicked it calls a controller and then displays the PDF on the screen.
I would like to click but instead of opening another screen the pdf file I would like a modal to open with the pdf.

I wanted to know what I can change in my code to do it, I leave below the view and controller that I use.

This is my view where I show the name of the document on the screen and when I click I send as a parameter an ID of the document that I want to show on the screen.

<a href="@Url.Action("GetPDF", "Home", new { Model.Id })">
 Document Name: @Model.documentType 
</a>

The controller receives the file ID and calls via a function get the file information from the database, get the byte of the file and convert it to PDF.

  public async Task<ActionResult> GetPDF(Guid id)
        {

            var vm = new ViewModels.Home.AttachmentViewModel();
            var result = vm.GetServiceAttachment(id));

            //Function to get the file information from DB .

            
            byte[] file;
            foreach (var attachment in result)
            {
              
                  file = attachment.File;

                  byte[] byteArray = file;


               return new FileContentResult(byteArray, "application/pdf");
            }
            return null;
    }

Canvas not drawing all images only on certain mobile devices

I’m having a problem with the canvas not drawing all images (only some are drawn) on specific devices.
To be exact Mobile Chrome (Samsung), I have not met this issue on any other device so far.

  const drawSymbol = (
    ctx: CanvasRenderingContext2D,
    symbol: CardSymbol,
    image: HTMLImageElement,
  ) => {
    window.requestAnimationFrame(() => {
      ctx.drawImage(
        image,
        symbol.x,
        symbol.y,
        symbol.width,
        symbol.height,
      );
    });
  };

  useEffect(() => {
    const canvas = canvasRef.current;
    if (canvas) {
      const ctx = canvas.getContext('2d');
      if (ctx) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        for (const symbol of card) {
          const image = images[symbol.image.id];
          if (image.loadedImg) {
            drawSymbol(ctx, symbol, image.loadedImg);
          } else {
            const img = new Image();
            img.onload = () => {
              image.loadedImg = img; // Cache loaded image
              drawSymbol(ctx, symbol, img);
            };
            img.src = image.src;
          }
        }
      }
    }
  }, [card]);

Some images seem to draw and some simply don’t. I’ve noticed that sometimes a portion of the images draw and then get removed and a different portion is drawn, but I cannot confirm if this actually happens as it’s hard to spot (milliseconds).
Does anyone have an idea why could this be happening?

Do you think that a single window.requestAnimationFrame for all images could solve the issue?

Swiperjs Sync the slide changes with a custom progress bar

So I’m attempting to make a custom progress bar that splits into multiple bars depending on the number of slides and progresses through each synced with the duration of the slide speed and slide duration.

Issue: While the bar does progress, the timing slowly goes off until it’s entirely out of sync with the slide changes. I know it is likely to do with the calculation for the progress duration, but I’m not sure how I could calculate this differently to keep it in sync.

JS

// homepage carousel
let autoPlayDelay = 1500;


const mySwiper = new Swiper('.vertical-swiper', {
  slidesPerView: 1,
  spaceBetween: 0,
  mousewheel: false,
  autoplay: {
    delay: autoPlayDelay
  },
  keyboard: true,
  loop: false,
  direction: 'vertical',
  speed: 1500,
  height: "465",
  navigation: {
    nextEl: '.swiper-btn-next',
    prevEl: '.swiper-btn-prev',
  },
});



let progress = document.querySelector('.swiper-progress-bar .progress');
const progressSections = document.querySelector('.swiper-progress-bar .progress-sections');

let slidersCount = mySwiper.params.loop ? mySwiper.slides.length - 2 : mySwiper.slides.length;
let widthParts = 100 / slidersCount;

function initProgressBar() {
  let calcProgress = (slidersCount - 1) * (autoPlayDelay + mySwiper.params.speed);
  calcProgress += autoPlayDelay;
  progress.style.width = '0%';
  progress.classList.remove('stopped');
  progress.animate([{
    width: '0%'
  }, {
    width: '100%'
  }], calcProgress, 'linear');
}

initProgressBar();

for (let i = 0; i < slidersCount; i++) {
  const span = document.createElement('span');
  progressSections.appendChild(span);
}

// Cache DOM queries
const activeHeader = document.querySelector('.header-text');
const activeEyebrow = document.querySelector('.eyebrow-text');

function updateSlide(index) {
  const slide = mySwiper.slides[index];
  const collectionsEyebrow = slide.querySelector('.slide__eyebrow');
  const collectionsHeader = slide.querySelector('.slide__heading');

  if (activeHeader && activeEyebrow && collectionsEyebrow && collectionsHeader) {
    // Slide up
    activeHeader.classList.add('is--move');
    activeEyebrow.classList.add('is--move');

    // Replace text
    setTimeout(() => {
      activeHeader.textContent = collectionsHeader.textContent;
      activeEyebrow.textContent = collectionsEyebrow.textContent;
    }, 300);

    // Slide down
    setTimeout(() => {
      activeHeader.classList.remove('is--move');
      activeEyebrow.classList.remove('is--move');
    }, 400);
  }
}

window.addEventListener('load', function() {
  // Call update header & eyebrow on page load
  const activeIndex = mySwiper.activeIndex;
  updateSlide(activeIndex);
});

// Call updateSlide function on slide change
mySwiper.on('slideChange', function() {
  const activeIndex = mySwiper.activeIndex;
  updateSlide(activeIndex);


  // update slidersCount and widthParts
  slidersCount = mySwiper.params.loop ? mySwiper.slides.length - 2 : mySwiper.slides.length;
  widthParts = 100 / slidersCount;


  let progress = document.querySelector('.swiper-progress-bar .progress');

  // Calculate progress bar width based on current slide index and autoplay delay
  const slideDelay = mySwiper.params.autoplay.delay;
  const progressWidth = (activeIndex + 1) * widthParts;
  const progressTime = (activeIndex + 1) * slideDelay;

  if ((this.progress === -0 || (this.progress === 1 && this.params.loop)) && !progress.parentElement.classList.contains('stopped')) {
    progress.style.width = '0';
    if (this.activeIndex === 0) {
      initProgressBar();
    }
  }

  /*   if (progress.parentElement.classList.contains('stopped')) {
      progress.animate(
        [
          { width: progress.style.width },
          { width: progressWidth + '%' }
        ],
        {
          duration: progressTime,
          easing: 'linear'
        }
      );
    } */

  if (progress.parentElement.classList.contains('stopped')) {
    const progressWidth = Math.round(widthParts * (mySwiper.activeIndex + 1));
    progress.animate({
        width: progressWidth + '%'
      },
      mySwiper.params.speed,
      'linear'
    );
  }

});

mySwiper.on('touchMove', function() {
  const progress = document.querySelector('.swiper-progress-bar .progress');
  progress.style.animationPlayState = 'paused';
  progress.parentElement.classList.add('stopped');
});


mySwiper.on('beforeSlideChangeStart', function() {
  const slide = this.el.querySelector('.swiper-slide');
  const slideImg = slide.querySelector('.img-container img');

  const setClasses = !slide.classList.contains('swiper-slide-active');
  setClass(slideImg, 'swiper-slide-active', 'remove');

  if (setClasses) {
    slide.classList.toggle('swiper-slide-active');
    this.el.querySelector('.swiper-slide').classList.toggle('expand-img');
  }
});

function setClass(el, className, fnName) {
  el.classList[fnName](className);
}

Example: https://jsfiddle.net/Fitzlegit/5Lo8vuxk/87/

Need help running a loop through an array (object)

How do I run a simple loop through an object array that will check for similarities of a previously exctracted value from a form. I am doing a project in which I am setting up a pizzeria. The user will input desired size of pizza and toppings in a form. I will then extract the values for total.

This is the JavaScript code I used to extract the values from the form:

let form=document.querySelector("form");
form.addEventListener("submit",(event)=>{
event.preventDefault();
// run an array through the checkbox
let topping=[];
document.querySelectorAll('[type="checkbox"]').forEach(item=>{
if (item.checked=== true)
{
topping.push(item.value);
}})


//to extract the value of the text field:
let fullname=document.querySelector("#fullname").value;
let address=document.querySelector("#address").value;
let pies=document.querySelector("#pies").value;
let pizzasize=document.querySelector('input[name="size"]:checked').value;

How do I copy AND shrink a canvas onto another?

I have two canvases, one big & one small. I want the small one to mirror the entire big one, but shrunken to fit. I can only get it to mirror the small corner instead of the entire thing. The big canvas will eventually allow drawing and the small will mirror it on change, but for a basic example, see below or this codepen https://codepen.io/b3aver/pen/abRZLKa.

<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript">
    var bigCanvas = document.getElementById("bigCanvas")
    var bigContext = bigCanvas.getContext("2d");
    bigContext.fillStyle="red";
    bigContext.fillRect(0, 0, bigCanvas.height, bigCanvas.width);
    bigContext.fillStyle="blue";
    bigContext.fillRect(bigCanvas.height/3, bigCanvas.height/3, bigCanvas.height/3, bigCanvas.width/3);
    bigContext.fillStyle="white";
    bigContext.fillRect(7,7,7,7);

    var smallCanvas = document.getElementById("smallCanvas");
    var smallContext = smallCanvas.getContext("2d");

    function dupe(){
        smallContext.drawImage(bigCanvas,0,0)
    }
</script>
</head>
<body>
    <canvas id="bigCanvas" height="280" width="280"></canvas>
    <canvas id="smallCanvas" height="28" width="28"></canvas>
    <button id="duplciateBtn" onclick="dupe()">Duplicate</button>
</body>
</html>

I’ve played around with the context scale (both big & small) but still can’t get it to cooperate. The closest I’ve gotten is changing the big context scale to (0.1,0.1), drawing on the big canvas & then it shrinks it into the corner. But I want the big canvas to stay big.

3 canvases showing the issue

The left is the big canvas, the top right is what I want, and the bottom right is what I get.

How to add buttons in Angular mat-table?

I’ve sucessfully used Angular mat-table to display data from database:

enter image description here

<table mat-table [dataSource]="UserDataSourceFilters" class="mat-elevation-z1 mt-5">
            <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
                <th mat-header-cell *matHeaderCellDef>{{ getUserColumnDisplayName(column) }}</th>
                <td mat-cell *matCellDef="let emp">{{ emp[column] }}</td>
            </ng-container>
          
            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
            <tr mat-row *matRowDef="let emprow; columns: displayedColumns" (click)="onRowExchangeClicked(emprow)"
                [ngClass]="{ 'clicked-row': true  }"></tr>
        </table>

        <mat-paginator [length]="100" [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100, 200]"
            aria-label="Select page">
        </mat-paginator>

Now I want to add another column, which contains buttons. So in component.ts, I add a new column called actions:

displayedColumns: string[] = ['firstName', 'lastName', 'email', ..., 'type','actions'];

and in my html i added this container:

<ng-container matColumnDef="actions">
                <mat-header-cell *matHeaderCellDef>actions</mat-header-cell>
                <mat-cell *matCellDef="let row">
                <button mat-button>Edit</button>
                </mat-cell>
            </ng-container>

But when i run the project, I got this error:

enter image description here

How do I load a youtube video page, without reloading the whole page?

I’m making a Chrome extension and I’m trying to add functionality of adding my own youtube video suggestion panels to youtube pages, so clickable elements on youtube which take user to a videopage.
Behaviour should be exactly same as if clicking on the videos on youtube: because it’s an SPA, the page is not refreshed, but videopage replaces a part of the DOM.

First thing I tried was doing
window.location.href = "https://www.youtube.com/watch?v=m-ioG4KEVyc", but this is too naive and the whole page gets reloaded(duh).

How would one go about making youtube load the video page from a link without reloading the whole page when I don’t have access to the underlying angular app?

Firebase Functions zwraca błąd “Error: Unexpected end of form at Multipart._final”

I started using Firebase Functions and ran into a problem. Namely, when I created my API (running locally), deployed to Firebase Functions using firebase deploy --only functions and called from my frontend – in the function logs an error is displayed:

Error: Unexpected end of form
at Multipart._final (/workspace/node_modules/busboy/lib/types/multipart.js:588:17)
at callFinal (node:internal/streams/writable:696:27)
at prefinish (node:internal/streams/writable:725:7)
at finishMaybe (node:internal/streams/writable:735:5)
at Multipart.Writable.end (node:internal/streams/writable:633:5)
at onend (node:internal/streams/readable:693:10)
at processTicksAndRejections (node:internal/process/task_queues:78:11)

My goal is to receive the file in the API and process it using the easy-template-x bibiotech. When I used multer for this, the problem was the same

index.js

const functions = require('firebase-functions');
const routes = require('./src/routes/routes');
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());

app.use('/', routes);

app.listen(3009, () => {
    console.log('Listening on 3001...');
});

exports.app = functions.https.onRequest(app);

routes.js

const checkErrors = require('../controllers/checkErrors');
const express = require('express');
const router = express.Router();

router.post('/checkErrors', checkErrors);
module.exports = router;

And checkErrors.js

const {TemplateHandler} = require('easy-template-x');
const handler = new TemplateHandler();
const busboy = require('busboy');

const checkErrors = async (req, res) => {
    const bb = busboy({headers: req.headers});
    let templateBuffer = null;
    let jsonData = '';

    bb.on('file', (fieldname, file, filename, encoding, mimetype) => {
        file.on('data', (data) => {
            templateBuffer = data;
        });
    });

    bb.on('field', (fieldname, val) => {
        jsonData += val;
    });

    bb.on('finish', async () => {
        jsonData = JSON.parse(jsonData);
        console.log(jsonData);
        const templateTags = await handler.parseTags(templateBuffer);
        const templateTagsNames = templateTags.map(({name}) => name);

        //Znajdź brakujące wartości w Excel i je zidentyfikuj
        const missingValues = [];
        jsonData
            .filter((row) => {
                return !templateTagsNames.every((name) => Object.keys(row).includes(name));
            })
            .forEach((row) => {
                templateTagsNames.forEach((templateName) => {
                    if (!row.hasOwnProperty(templateName)) {
                        missingValues.push({fieldName: templateName, rowNum: row.rowNum + 1});
                    }
                });
            });

        res.json({
            errors: missingValues,
        });
    });

    return req.pipe(bb);
};

module.exports = checkErrors;

Controlling page breaks when creating and printing canvas using html2canvas

I have a series of blocks that, in order for it to be presentable, I convert it to a canvas using html2canvas() and then print the canvas using jQuery.printThis()

The html structure is like:

<div id="container">
    <div class="block">bla bla bla -- long content</div>
    <div class="block">bla bla bla -- long content</div>
    <div class="block">bla bla bla -- long content</div>
    <div class="block">bla bla bla -- long content</div>
    ....
</div>

The code for printing is:

html2canvas(document.getElementById('container')).then(function (canvas) {
    jQuery('<img>').attr("src", canvas.toDataURL('image/png')).printThis();
});

The problems is that, when there are more blocks than fit inside a page, and the blocks are several lines, the page break is in the middle of a block.

If I add the css:

@media print {
    .basket-product-row {
        page-break-inside: avoid;
    }
}

and print the div directly without html2canvas() using just

jQuery('#container').printThis();

then the pages are divided correctly.

How do I still use html2canvas() and control the page breaks?

popup window’s X and Y axis cannot mount to my page elemets

Apologize in advance as I’m a beginner on JS page developing. Now I got an original code from my team’s project. In the JSP page I got a link element:

<jhx:link id="ctryLink" url="javascript:displayDivSelect('selectOrigCtryDiv', ctryLink');">

When click the link, it will run the following function:

displayDivSelect = function (divId, linkId, fromOtherCg) {
   // retrieve the cache which map div id to popup window object
   var winCache = arguments.callee.winCache;
   if (!winCache) {
      winCache = {};
      arguments.callee.winCache = winCache;
   }
   // retrieve or create a popup window object
   var win = winCache[divId];
   if (!win) {
      win = new PopupWindow(divId);
      win.autoHide(); 
      win.setSize(15, 20);
      if (fromOtherCg) {
         win.offsetX = 0;
         win.offsetY = 15;
      } else {
         win.offsetX = -350;
         win.offsetY = -150;
      }
      winCache[divId] = win;
   }
   // show or hide div
   if (linkId) {
      win.showPopup(linkId);                         
      // set a background frame for given div to cover drop down list
      var div = document.getElementById(divId);
      var frame = document.getElementById("popupWindowFrame"); //using iframe work for old IE version
      frame.style.top = div.offsetTop;
      frame.style.left = div.offsetLeft; 
      frame.style.height = div.offsetHeight;
      frame.style.width = div.offsetWidth;
      frame.style.visibility = div.style.visibility;
      frame.style.display = div.style.display;
   } else {
      win.hidePopup();               
   }
};

And the showPopup function is:


function showPopup(anchorname)  {
        this.getXYposition(anchorname);
        this.x += this.offsetX;
    this.y += this.offsetY;
    if (this.divName != null) {
        // Show the DIV object
        if (this.use_gebi) {
            document.getElementById(this.divName).style.left = this.x + "px";
            document.getElementById(this.divName).style.top = this.y + "px";
            document.getElementById(this.divName).style.visibility = "visible";
            }
            /* other codes*/
}

My target is to make sure every time i click the link then a dropdown list will popup just under middle the link label,

so the code was trying to calculate the link element’s position so it can set some offsetX, Y and let the dropdown mount to the link label’s position and popup in the expected position.

Now i got the problem: when viewing the webpage in 100%, the dropdown position seems ok.
Then i close the dropdown, zoom in the webpage to 120% (or bigger, to 80% or smaller), click the link again, then the dropdown’s X,Y position will change and fly to somewhere else.

Tried a lot of method and no idea how & why, thanks for your time and help if you have any idea!

get root cause
get updated code

Cannot convert a local variable into a global one in jquery [duplicate]

I’m trying to set up a date range picker for a project I’m working on with some others. I’ve been able to get the input of the user and store it in a variable, but only locally within its function. Nothing I try can get the variable into a global scope where it can be used more effectively.

Here’s the code I’ve been using. It was to my understanding that declaring the variables globally and assigning their values within the function without the var keyword would set the variable as global rather than local, which it does do in regular javascript, but not in any of my jquery. Any input on what I’m doing wrong would be appreciated.

$(function() {
    var startTime
    var endTime
    $('input[name="datetimes"]').daterangepicker({
        timePicker: true,
        startDate: moment().startOf('hour'),
        endDate: moment().startOf('hour').add(32, 'hour'),
        locale: {
        format: 'hh:mm A'
        }
    });
    $('#daterange').on('apply.daterangepicker', function(ev, picker) {
        startTime = (picker.startDate.format('YYYY-MM-DD h:mm A'));
        endTime = (picker.endDate.format('YYYY-MM-DD h:mm A'));
        console.log(startTime)
        console.log(endTime)
      });
    console.log(startTime)
    console.log(endTime)
});