Skip to content

Commit 0f3ba20

Browse files
author
Vinod Gaur JD
committed
certificate page
1 parent 049a159 commit 0f3ba20

File tree

2 files changed

+504
-230
lines changed
  • jobsdoor360-website/src/main/ejs/main-files/myaccount/certificate
  • myaccount/certificate

2 files changed

+504
-230
lines changed
Lines changed: 161 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,166 @@
1-
<!doctype html>
2-
<html>
3-
<head>
4-
<meta charset="utf-8" />
5-
<title>Certificate</title>
6-
<style>
7-
body { font-family: Arial, sans-serif; padding: 20px; }
8-
#pdfContent {
9-
width: 800px; /* set a fixed width for consistent rendering */
10-
background: white;
11-
padding: 24px;
12-
border: 1px solid #ddd;
13-
box-shadow: 0 0 6px rgba(0,0,0,0.04);
14-
}
15-
.section { margin-bottom: 18px; }
16-
.btn { display:inline-block; padding:10px 14px; background:#007bff; color:#fff; border-radius:6px; text-decoration:none; cursor:pointer; }
17-
</style>
18-
</head>
19-
<body>
20-
21-
<h2>Demo: Generate multi-page PDF on client-side</h2>
22-
23-
<div id="pdfContent">
24-
<h1>Demo document</h1>
25-
<p class="section">This is some sample content to show client-side PDF generation. Add your dynamic HTML here before generating the PDF.</p>
26-
27-
<!-- Generate long content for testing multi-page behavior -->
28-
<div id="long">
29-
<script>
30-
// create a lot of text to force multi-page
31-
let html = "";
32-
for (let i=1; i<=60; i++) {
33-
html += `<h3>Heading ${i}</h3><p>This is paragraph ${i}. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam.</p>`;
34-
}
35-
document.write(html);
36-
</script>
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Certificate</title>
5+
<meta
6+
name="description"
7+
content="Certificate by JobsDoor360: Learn Full Stack, Java, and Web Development. Advance Your Career with Industry Professionals. Gain In-Demand Skills for Software Jobs. Practice Interviews and Perfect Your CV"
8+
/>
9+
<link rel="stylesheet" href="style.css" />
10+
<!--<link rel="stylesheet" href="/staticfiles/mainfiles/myaccount/certificate/style.css" />-->
11+
<link
12+
href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"
13+
rel="stylesheet"
14+
/>
15+
<%- include('../../../partials/head.ejs') %>
16+
</head>
17+
18+
<body>
19+
<%- include('../../../partials/navbar.ejs') %>
20+
21+
<button id="btn" class="btn">Download Certificate</button>
22+
<br>
23+
24+
<div id="pdfContent">
25+
<div id="certificate" role="document" aria-label="Certificate of Completion">
26+
<div class="badge">DSA QUIZ</div>
27+
28+
<div class="title">
29+
<h1>Certificate of Completion</h1>
30+
<p>This certificate is proudly presented to</p>
31+
</div>
32+
33+
<div class="content">
34+
<div class="recipient" id="cert-name">[Participant Name]</div>
35+
<div class="desc" id="cert-desc">
36+
For successfully passing the <strong>Data Structures & Algorithms (DSA)</strong> quiz with outstanding performance.
37+
</div>
38+
39+
<div class="meta" aria-hidden="false">
40+
<div class="box">
41+
<label>Score</label>
42+
<div class="value" id="cert-score">95%</div>
43+
</div>
44+
45+
<div class="box">
46+
<label>Quiz</label>
47+
<div class="value" id="cert-quiz">DSA Fundamentals — Quiz #3</div>
48+
</div>
49+
50+
<div class="box">
51+
<label>Date</label>
52+
<div class="value" id="cert-date">Nov 20, 2025</div>
53+
</div>
54+
55+
<div class="box">
56+
<label>Duration</label>
57+
<div class="value" id="cert-duration">30 minutes</div>
58+
</div>
59+
</div>
60+
61+
<div class="footer">
62+
<div class="issuer">
63+
<img src="https://via.placeholder.com/56x56.png?text=Logo" alt="Issuer logo" />
64+
<div class="info">
65+
<div class="org">Jobsdoor360 Academy</div>
66+
<div class="small">Verified by the DSA assessment team</div>
67+
</div>
68+
</div>
69+
70+
<div class="signatures" aria-hidden="true">
71+
<div class="sign">
72+
<div class="line"></div>
73+
<div class="name">Shivpriya Gaur</div>
74+
<div class="role">Course Lead</div>
75+
</div>
76+
77+
<div class="sign">
78+
<div class="line"></div>
79+
<div class="name">Vinod Gaur</div>
80+
<div class="role">Head — Assessments</div>
81+
</div>
82+
</div>
83+
</div>
84+
</div>
85+
</div>
3786
</div>
38-
</div>
39-
40-
<br>
41-
<button id="btn" class="btn">Generate & Download PDF</button>
42-
43-
<%- include('../../../partials/footer.ejs') %>
44-
45-
<!-- libs -->
46-
<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
47-
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
48-
49-
<script>
50-
async function getData() {
51-
const params = new URLSearchParams(window.location.search);
52-
let data = await decryptData(params.get('data'));
53-
return JSON.parse(data);
54-
}
55-
56-
getData().then(data => {
57-
let name = getLoggedInUserName();
58-
59-
console.log(data, name);
60-
});
6187

88+
<%- include('../../../partials/footer.ejs') %>
6289

63-
document.getElementById('btn').addEventListener('click', async () => {
64-
const { jsPDF } = window.jspdf;
65-
66-
const element = document.getElementById('pdfContent');
67-
68-
// Ensure element is fully visible/rendered
69-
element.style.background = 'white';
70-
71-
// 1) Render element to canvas with html2canvas
72-
const canvas = await html2canvas(element, {
73-
scale: 2, // increase for better quality
74-
useCORS: true, // allow cross-origin images if served with CORS
75-
allowTaint: false,
76-
logging: false
90+
<!-- libs -->
91+
<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
92+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
93+
94+
<script>
95+
async function getData() {
96+
const params = new URLSearchParams(window.location.search);
97+
let data = await decryptData(params.get('data'));
98+
return JSON.parse(data);
99+
}
100+
101+
getData().then(data => {
102+
let name = getLoggedInUserName();
103+
104+
console.log(data, name);
105+
});
106+
107+
108+
document.getElementById('btn').addEventListener('click', async () => {
109+
const { jsPDF } = window.jspdf;
110+
111+
const element = document.getElementById('pdfContent');
112+
113+
// Ensure element is fully visible/rendered
114+
element.style.background = 'white';
115+
116+
// 1) Render element to canvas with html2canvas
117+
const canvas = await html2canvas(element, {
118+
scale: 2, // increase for better quality
119+
useCORS: true, // allow cross-origin images if served with CORS
120+
allowTaint: false,
121+
logging: false
122+
});
123+
124+
// 2) Prepare jsPDF A4
125+
const pdf = new jsPDF('p', 'mm', 'a4');
126+
const pdfWidthMM = pdf.internal.pageSize.getWidth();
127+
const pdfHeightMM = pdf.internal.pageSize.getHeight();
128+
129+
// Convert canvas size into PDF units
130+
const imgWidthPx = canvas.width;
131+
const imgHeightPx = canvas.height;
132+
const pxPerMm = imgWidthPx / pdfWidthMM; // number of canvas px per mm of PDF width
133+
const pageHeightPx = Math.floor(pdfHeightMM * pxPerMm); // page height in canvas px
134+
135+
// 3) Slice the canvas into page-sized chunks
136+
let y = 0;
137+
while (y < imgHeightPx) {
138+
const canvasSlice = document.createElement('canvas');
139+
canvasSlice.width = imgWidthPx;
140+
// sliceHeightPx: remaining or pageHeightPx
141+
const sliceHeightPx = Math.min(pageHeightPx, imgHeightPx - y);
142+
canvasSlice.height = sliceHeightPx;
143+
144+
const ctx = canvasSlice.getContext('2d');
145+
// draw the slice from the original canvas into the temp canvas
146+
ctx.drawImage(canvas, 0, y, imgWidthPx, sliceHeightPx, 0, 0, imgWidthPx, sliceHeightPx);
147+
148+
// convert slice to image data
149+
const imgData = canvasSlice.toDataURL('image/png');
150+
151+
// compute slice height in mm for jsPDF
152+
const sliceHeightMM = sliceHeightPx / pxPerMm;
153+
154+
// Add image to PDF — full width, computed height
155+
pdf.addImage(imgData, 'PNG', 0, 0, pdfWidthMM, sliceHeightMM, undefined, 'FAST');
156+
157+
y += sliceHeightPx;
158+
if (y < imgHeightPx) pdf.addPage();
159+
}
160+
161+
// 4) Save the PDF
162+
pdf.save('generated_document.pdf');
77163
});
78-
79-
// 2) Prepare jsPDF A4
80-
const pdf = new jsPDF('p', 'mm', 'a4');
81-
const pdfWidthMM = pdf.internal.pageSize.getWidth();
82-
const pdfHeightMM = pdf.internal.pageSize.getHeight();
83-
84-
// Convert canvas size into PDF units
85-
const imgWidthPx = canvas.width;
86-
const imgHeightPx = canvas.height;
87-
const pxPerMm = imgWidthPx / pdfWidthMM; // number of canvas px per mm of PDF width
88-
const pageHeightPx = Math.floor(pdfHeightMM * pxPerMm); // page height in canvas px
89-
90-
// 3) Slice the canvas into page-sized chunks
91-
let y = 0;
92-
while (y < imgHeightPx) {
93-
const canvasSlice = document.createElement('canvas');
94-
canvasSlice.width = imgWidthPx;
95-
// sliceHeightPx: remaining or pageHeightPx
96-
const sliceHeightPx = Math.min(pageHeightPx, imgHeightPx - y);
97-
canvasSlice.height = sliceHeightPx;
98-
99-
const ctx = canvasSlice.getContext('2d');
100-
// draw the slice from the original canvas into the temp canvas
101-
ctx.drawImage(canvas, 0, y, imgWidthPx, sliceHeightPx, 0, 0, imgWidthPx, sliceHeightPx);
102-
103-
// convert slice to image data
104-
const imgData = canvasSlice.toDataURL('image/png');
105-
106-
// compute slice height in mm for jsPDF
107-
const sliceHeightMM = sliceHeightPx / pxPerMm;
108-
109-
// Add image to PDF — full width, computed height
110-
pdf.addImage(imgData, 'PNG', 0, 0, pdfWidthMM, sliceHeightMM, undefined, 'FAST');
111-
112-
y += sliceHeightPx;
113-
if (y < imgHeightPx) pdf.addPage();
114-
}
115-
116-
// 4) Save the PDF
117-
pdf.save('generated_document.pdf');
118-
});
119-
</script>
120-
</body>
164+
</script>
165+
</body>
121166
</html>

0 commit comments

Comments
 (0)