Using PDF-Lib to create a document and print without saving the document locally

Within my web application, I am attempting to create a PDF document (which I am doing successfully) and then print it.

Most of the solutions I have found said that you will have to do it server-side probably with some PHP, which would be fine. but If I did that, I would have no clue how to do this.

The application is only really used by one machine and it is not distributed on the web so it is locally hosted only so no need for another end-user computer.


Application Goal / Expected result

I would like the application to:

  • Generate a PDF based on the user’s input (DONE AND WORKS)
  • Use the PDF and PRINT straight away

So it appears I would have a few viable options…

  • PDF-Lib client-side only (possible client-side DB?)
  • PDF-Lib client-side and a server-side link using PHP?
  • Fully server-side
  • A base 64 link?

I have tried locally saving it to the machine and using the file but it will not allow me, unfortunately 🙁

HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Get Your Certificate for The Event</title>
    <link rel="stylesheet" href="style.css">
    <link rel="favicon" href="favicon.ico">
</head>

<body>
    <header>
        <img src="FR_Logo.png" alt="FRSystems Logo" width="500" height="250" />
        <h4>Get your certificate of your laps</h4>

    </header>
    <main>

        <label for="name">Type Your Name</label>
        <input required type="text" name="Name" autocomplete="name" placeholder="" id="name" minlength="1"
               maxlength="16">
        <Button id="submitBtn">Get Certificate</Button>


    </main>

    <script src="https://unpkg.com/pdf-lib/dist/pdf-lib.js"></script>
    <script src="https://unpkg.com/pdf-lib/dist/pdf-lib.min.js"></script>
    <iframe id="iframe"></iframe>

    <script src="./FileSaver.js"></script>
    <script src="https://unpkg.com/@pdf-lib/[email protected]"></script>
    <script src="./index.js"></script>
</body>

</html>

Index.JS

const userName = document.getElementById("name");
const submitBtn = document.getElementById("submitBtn");

const { PDFDocument, rgb, degrees, StandardFonts } = PDFLib;


const capitalize = (str, lower = false) =>
  (lower ? str.toLowerCase() : str).replace(/(?:^|s|["'([{])+S/g, (match) =>
    match.toUpperCase()
  );

submitBtn.addEventListener("click", () => {
  const val = capitalize(userName.value);

  //check if the text is empty or not
  if (val.trim() !== "" && userName.checkValidity()) {
    console.log(val);
    createPdf(val);
  } else {
    userName.reportValidity();
  }
});

function print() {
    var frame = document.getElementById('frame');
    frame.contentWindow.focus();
    frame.contentWindow.print();
};


function readURL(input) {
    console.log("GOT HERE");
//    if (input.files && input.files[0]) {
    console.log("GOT HERE 2");
    var reader = new FileReader();

    reader.onload = function (e) {
        console.log(e.target.result);
//            $('#pdfResult')
//                .attr('src', e.target.result);
    };
    reader.readAsDataURL(input.files[0]);
    console.log(reader.readAsDataURL(input.files[0]));

//    }
};

async function createPdf(val) {
    const pdfDoc = await PDFDocument.create();
    const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman);

    const page = pdfDoc.addPage();
    const { width, height } = page.getSize();
    page.setSize(841.89, 595.28)
    // midpoint x = 420.945, y= 297.64

    console.log(page.getSize(),width,height)
    const fontSize = 30
    var textWidth = timesRomanFont.widthOfTextAtSize(val, fontSize);
    console.log(timesRomanFont.widthOfTextAtSize(val, fontSize))
    var textHeight = timesRomanFont.heightAtSize(fontSize);
    var nameY = ((page.getHeight() / 2) + 50) - (textHeight / 2);
    var centerY = page.getHeight() / 2 - textHeight / 2;
    var centerX = page.getWidth() / 2 - textWidth / 2;

    page.drawText(val, {
        x: centerX,
        y: nameY,
        size: fontSize,
        font: timesRomanFont,
        color: rgb(0, 0, 0),
    });

    var score = "32"; // Would be taken from the database (Select query) using ID/ChipNumber
    var scoreString = "who completed " + score + " laps";
    var bottomText = "< EVENT NAME > on < LONG DATE >";
    var supportingText = "< Support Text >"

    var textWidthScoreString = timesRomanFont.widthOfTextAtSize(scoreString, fontSize);
    console.log(timesRomanFont.widthOfTextAtSize(scoreString, fontSize));
    var scoreY = ((page.getHeight() / 2) + 0) - (textHeight / 2);
    var scoreX = page.getWidth() / 2 - textWidthScoreString / 2;

    var bottomTextWidthString = timesRomanFont.widthOfTextAtSize(bottomText, fontSize);
    var bottomTextY = ((page.getHeight() / 2) - 50) - (textHeight / 2);
    var bottomTextX = page.getWidth() / 2 - bottomTextWidthString / 2;


    var supportingTextWidthString = timesRomanFont.widthOfTextAtSize(supportingText, fontSize);
    var supportingTextY = ((page.getHeight() / 2) - 100) - (textHeight / 2);
    var supportingTextX = page.getWidth() / 2 - supportingTextWidthString / 2;


    page.drawText(scoreString, {
        x: scoreX,
        y: scoreY,
        size: fontSize,
        font: timesRomanFont,
        color: rgb(0, 0, 0),
    });

    page.drawText(bottomText, {
        x: bottomTextX,
        y: bottomTextY,
        size: fontSize,
        font: timesRomanFont,
        color: rgb(0, 0, 0),
    });

    page.drawText(supportingText, {
        x: supportingTextX,
        y: supportingTextY,
        size: fontSize,
        font: timesRomanFont,
        color: rgb(0, 0, 0),
    });


    const pdfBytes = await pdfDoc.save();

    console.log(pdfBytes);
    console.log(pdfDoc)

    // Create a new file
    // This uses File Saver to save the files, i used this to temp save whilst i moved around the text
    var file = new File(
        [pdfBytes],
        "test-Certificate.pdf",
        {
            type: "application/pdf;charset=utf-8",
        }
    );
    console.log(file);





//    var iframe = document.getElementById('iframe');
//    iframe.src = file;
//    iframe.contentWindow.focus();
//    iframe.contentWindow.print();
//    readURL(file);
//    saveAs(file);
    console.log(saveAs(file));

};

Download string data as file based on the file type (text/Json)

I am trying to downloading a string data as file such as text, and json files based on the fileType we are passing as parameter. I have tried below code.

function downloadString(text, fileType, fileName) {
  var blob = new Blob([text], { type: fileType });

  var a = document.createElement('a');
  a.download = fileName;
  a.href = URL.createObjectURL(blob);
  a.dataset.downloadurl = [fileType, a.download, a.href].join(':');
  a.style.display = "none";
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  setTimeout(function() { URL.revokeObjectURL(a.href); }, 1500);
}

Downloading is working. But it always download txt file even if we pass json filetype.
Can anyone help this?

From .map get product ID and search from another json text with same id and replace it to name

I need advice.
via .map I get the product id (item.id), and from another JSON text I would need it to find in it the number of that id and take the same id found product_name and rewrite the product id to that product_name from the second JSON text.

https://justpaste.it/4cik4

{ subCategoryList && (
                
                    subCategoryList.map(function(item, id) {
                        return(
                          <tr key={id}>
                            <td>{item.subproduct_name}</td>
                            <td>{item.products_id}</td> <--- HERE
                            <td>{item.product_url_header}</td>
                            <td className='action'> <i class='bx bx-pencil hover' onClick={()=>editSubcategoryRecord(item.id, item.products_id, item.subproduct_name, item.product_url_header)}></i> <i class='bx bx-trash-alt hover' onClick={()=>deleteSubCategory(item.id)}></i> </td>
                          </tr>
                    )}.bind(this))

                  )
                }

Cannot read properties of null (reading ‘style’) at X [duplicate]

Similar to what I did in other parts of the document and worked, I was trying to hide the delete button if an user isn’t logged in or in other profile. However, I get this message “Uncaught (in promise) TypeError: Cannot read properties of null (reading ‘style’)
at showEditDelete”, pointing to the delete deleteBtn.display.style

async function showEditDelete() {
let deleteBtn = document.getElementById("delete-col");
let currentProfileId = await usersAPI_auto.getById(userId);
let loggedUserId = sessionManager.getLoggedUser().userId;
if (sessionManager.isLogged()){
    if (loggedUserId != currentProfileId){
        deleteBtn.style.display = "none"
    }
} else {
    deleteBtn.style.display = "none";  
}

}

Set CSS definition on an Angular Directive that applies to its children

Im trying to implement a responsive table directive in my angular app, which sets the min and max width and font-size of the columns in a MatTable.

These values are based on the parent containers width, and the number of columns.

The directive gets the column definitions as an input array of strings.(eg.[“ordernum”,”ordername”,”timestamp”])

Currently the code looks like this:


@Input('ResponsiveTable') columns: string[] = [];
...
constructor(
    private el: ElementRef,
    private host: MatTable<any>,
    private breakpointObserver: BreakpointObserver
  ) {}
....

 ngOnInit(): void {
    //set table style props
    this.el.nativeElement.style.minWidth =
      minCellWidth * this.columns.length + 'px';
    this.el.nativeElement.style.width = tableWidth + '%';

    // //subscriptions
    this.subscriptions.push(
      this.host.contentChanged.subscribe(() =>
        setTimeout(() => this.initStyle())
      )
    );
  }

  
...
  initStyle() {
    //get tableSize
    const parentWidth = this.el.nativeElement.parentNode.clientWidth;
    this.maxColumnWidth =
      parentWidth / this.columns.length > minCellWidth
        ? parentWidth / this.columns.length
        : minCellWidth;

    //set the headers, and maxWidth
    this.el.nativeElement.querySelectorAll('th').forEach((header: any) => {
      header.style.maxWidth = this.maxColumnWidth + 'px';
      header.style.fontSize = `calc(8px + 0.25vw + 0.5vw / ${this.columns.length})`;
      header.style.padding = '6px';
    });

    //set the table cells and maxWidth
    this.el.nativeElement.querySelectorAll('td').forEach((cell: any) => {
      cell.style.maxWidth = this.maxColumnWidth + 'px';
      cell.style.fontSize = `calc(8px + 0.25vw + 0.5vw / ${this.columns.length})`;
    });

    this.initBreakpointObserver();

    this.tableWidth = this.el.nativeElement.width;
  }

I think this is not efficient, because every time a content change happens, I have to query all the cells and headers, to set their max and min width.

It would be nice to add some CSS to the parent element, that selects all its children mat-cells and mat-headers, and set their size. Sadly I cant use a classic CSS class beacause the size value is based on the number of table columns.

Is there a way to progmatically add a CSS class that selects all the children cells and applies the style to them, even if a new row is added?

Or what could be a better solution?

New array with non-repeating values [duplicate]

I need to create a findUnique() function that creates a new array with non-repeating values.

This is how it should be:

console.log([10, 5, 6, 10, 6, 7, 2].findUnique()) // [5, 7, 2]

My try:

Array.prototype.findUnique = function() {
    let arr = this;
    let newarr = arr.filter((v, i, a) => {
       return a.indexOf(v) === i
    })
    return newarr
}

But it returns:

[10, 5, 6, 7, 2]

How can I make it return only non-repeated values?

Prime React Country & City Dropdown

I want to create dropdown fields containing countries and cities using PrimeReact. I want to provide this with json file. After the country is selected, I want the cities to be listed accordingly. I couldn’t find any examples. How can I achieve this?

"data" :[
    {
      "code2": "AF",
      "code3": "AFG",
      "name": "Afghanistan",
      "capital": "Kabul",
      "region": "Asia",
      "subregion": "Southern Asia",
      "states": [
        {
          "code": "BDS",
          "name": "Badakhshān",
          "subdivision": null
        },

Quero criar uma única array com os objetos que vem de uma requisição [closed]

Eu consigo obter alguns objeto em uma requisição porem gostaria de colocar todos esses objetos em uma única array. Quando crio uma array e coloco todos os objeto parece q são criada uma array para cada objeto é estranho e isso buga a minha mente.

const veiculos = dados => {

    var dev = []

    let fetchPro = fetch(`${baseUrl}/api/devices/${dados.deviceId}`, {
        headers: {
            cookie: cookie
        },
    }).then(reponse => reponse.json())
    .then(reponse => {
        dados.Prefixo = reponse.name;
        dev.push(dados)
    })

    Promise.resolve(fetchPro)
    .then(() => log.log(dev))

}

Obtenho esse resultado….

enter image description here

Eu so queria colocar os objetos dentro de uma única array por por exemplo

enter image description here

how to setState for an array of fulfilled promises

In my react app, I am retrieving some data from firebase , but when I try to store the items in my state it stores only the first item of the fulfilled promises ,

const HomePage = (props) => {
  const [events ,setEvents] = React.useState([])
const fetchGames=async()=>{
    const DB =await db.collection('game').get()

    DB.docs.forEach(item=>{
      setEvents([...events,item.data()])
      console.log(item.data()); // Here shows all the items that stored in my firebase collection
     })
    }
    
    useEffect(()=>
    {
      fetchGames()
    }, [])
return(
<div>
{
     events.map((event)=>
        (
          <div>
            {event.home_color}
          </div>

        )
        )
    }
</div>
)

Eventually the events state will display only one item , unlike in the console log which displayed all the items , how to fix this?

drop down values are not reflecting until we remove focus from drop down after selection

here getDAtes and isChecked are boolean values and we fetch startDate from grid and caluclate starttime according to it. there are time values in allTimes array

//index.js

{field: 'starttime', headername: 'starttime', renderCell: (params) => (
  <Dropdown value={(getDates && isChecked) ? getStartTime(params.row.startDate) : 
   getDropDownStartTime(params)}
     options={[...allTimes]}
     onChange={(event) => {
       params.row[STARTTIME] = event.target.value;
       handleGridUpdate(params.row, STARTTIME);
     }}
  />
}

//handlegridupdate

handleGridUpdate = useCallback((row,type) => {
  const item = info[row.id] ? Object.assign({}, info[row.id]) : {};
  if(type === STARTTIME){
    item.starttime = row.starttime;
  }
info[row.id]=item;
dispatch(setInfo(info));
}, [dispatch, info]);

Angular ng303 problem but i cant do anything about that

this is my html

  <div class="mb-3">
    <label for="filterText" class="form-label">Ürün ara</label>
    <input type="text"   class="form-control" id="filterText" 
    placeholder="arama ifadesi giriniz">
  </div>
 
  
  <h4 style="text-align: left">Müşteriler</h4>
  <table class="table">
    <thead class="table-light">
      <tr>
        <td scope="col">Id</td>
        <td scope="col">İsim</td>
        <td scope="col">Email</td>
        <td scope="col">Soyisim</td>
       
    </thead>
    <tbody>
      <tr *ngFor="let users of users">
          <td>{{users.Id}}</td>
      </tr>
  </tbody>
  
  

this is my .ts

import { Component, OnInit } from "@angular/core";
 import { Users } from "src/app/models/Users";
import { AuthService } from "src/app/services/auth.service";
 

 

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.css'],
})
export class UsersComponent implements OnInit {
  user: Users   ;
  users : Users[] = []
  dataLoaded = false;
  filterText="";

  constructor(private authservice: AuthService
   ) {}

    ngOnInit(): void {
  this.getusers()
  }


  getusers() {
    this.authservice.getusers().subscribe(response=>{
      this.user = response.data
      console.log(this.users)
      this.dataLoaded = true;
    })   
  }

  getById(Id:number) {
    this.authservice.getById(Id).subscribe(response=>{
      this.user= response.data
      this.dataLoaded = true;
    })   
  }
  
  
 






}

this is error when i start the browser i see what should i do

NG0303: Can’t bind to ‘ngForOf’ since it isn’t a known property of ‘tr’. core.mjs:10178
Angular 3
UsersComponent_Template users.component.html:21
Angular 22
RxJS 6
Angular 8
emit
checkStable
onHasTask
hasTask
_updateTaskCount
_updateTaskCount
runTask
drainMicroTaskQueue

idea for designing a maze pattern

I’m in the process of writing path finding for Maze. I got this image while googling, which seems perfect for maze background. Any suggestions, How can I design this image using HTML, CSS and javascript.

should i use flex or grid or a simple table will do?

enter image description here

Attribute name to variavel javascript

I’m developing a dynamic page with javascript.

I’m not that advanced with the language, I’m trying to collect the name of the classes defined in the div through the html object variable,

so far I created a loop to repeat the structure created dynamically, assign a class: object to define as a class name for each block created through the objects variable

however I would like to use the name of each class summarized as a variable or if there is a way in which I could simply call the block and dynamically create html structure within it without the others clone the same.

// objs 
const html = [
    {
        id: 0,
        class: 'hero',
        titulo: "Teste",
    },
    {
        id: 1,
        class: 'section_1',
        titulo: "Teste 2",
    },
];

// main code
let section = document.createElement("section");
let el_page = document.getElementById("main");

const global = app => {

    const main = document.getElementById("main");
    const div = document.createElement("div");

    // get names and set div all class name
    for (let i = 0; i < html.length; i++) {
        div.setAttribute("class", app.class);
    }
    //creat el div
    main.append(div);
}

html.forEach(app => global(app));
    <main id="main">
teste
    </main>