{"id":443,"date":"2026-07-24T02:38:03","date_gmt":"2026-07-24T02:38:03","guid":{"rendered":"https:\/\/opart.unhas.ac.id\/?p=443"},"modified":"2026-08-01T02:43:19","modified_gmt":"2026-08-01T02:43:19","slug":"doc-barcode","status":"publish","type":"post","link":"https:\/\/opart.unhas.ac.id\/?p=443","title":{"rendered":"Doc. Barcode"},"content":{"rendered":"\n<link href=\"https:\/\/cdn.jsdelivr.net\/npm\/bootstrap@5.3.3\/dist\/css\/bootstrap.min.css\" rel=\"stylesheet\">\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/qrcodejs\/1.0.0\/qrcode.min.js\"><\/script>\n<script src=\"https:\/\/unpkg.com\/pdf-lib\/dist\/pdf-lib.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/pdf.js\/2.16.105\/pdf.min.js\"><\/script>\n\n<style>\n.opart-qr-page{\n    background:linear-gradient(135deg,#eef6ff,#ffffff);\n    font-family:\"Segoe UI\", Arial, sans-serif;\n    color:#1b2a3a;\n    padding:35px 15px;\n}\n\n.opart-wrapper{\n    max-width:950px;\n    margin:0 auto;\n}\n\n.opart-card{\n    background:#ffffff;\n    border:1px solid #d9e9ff;\n    border-radius:24px;\n    box-shadow:0 12px 30px rgba(0,64,128,0.10);\n    overflow:hidden;\n}\n\n.opart-header{\n    background:linear-gradient(135deg,#062a63,#0c62b7,#1496e1);\n    color:white;\n    padding:32px 28px;\n}\n\n.opart-title{\n    font-size:32px;\n    font-weight:800;\n    margin:0;\n}\n\n.opart-subtitle{\n    margin-top:8px;\n    font-size:16px;\n    opacity:.9;\n}\n\n.opart-body{\n    padding:30px;\n}\n\n.section-box{\n    background:linear-gradient(145deg,#ffffff,#f5faff);\n    border:1px solid #dcecff;\n    border-radius:18px;\n    padding:24px;\n    margin-bottom:25px;\n}\n\n.section-title{\n    font-size:20px;\n    font-weight:700;\n    color:#0a2a66;\n    margin-bottom:18px;\n}\n\n.form-label{\n    font-weight:600;\n    color:#0a2a66;\n}\n\n.form-control,\n.form-select{\n    border-radius:12px;\n    border:1px solid #c8dff5;\n    padding:11px 14px;\n}\n\n.form-control:focus,\n.form-select:focus{\n    border-color:#1496e1;\n    box-shadow:0 0 0 .2rem rgba(20,150,225,.15);\n}\n\n.btn-opart{\n    background:linear-gradient(135deg,#0a4fa3,#1496e1);\n    color:#ffffff;\n    border:none;\n    border-radius:14px;\n    padding:12px 18px;\n    font-weight:700;\n    box-shadow:0 8px 18px rgba(20,150,225,0.22);\n}\n\n.btn-opart:hover{\n    background:linear-gradient(135deg,#083f84,#0f7dcc);\n    color:#ffffff;\n}\n\n.btn-download{\n    background:linear-gradient(135deg,#007f5f,#00b894);\n    color:#ffffff;\n    border:none;\n    border-radius:14px;\n    padding:13px 18px;\n    font-weight:700;\n    box-shadow:0 8px 18px rgba(0,184,148,0.22);\n}\n\n.btn-download:hover{\n    background:linear-gradient(135deg,#00684f,#00a383);\n    color:#ffffff;\n}\n\n#qrcode{\n    display:flex;\n    justify-content:center;\n    align-items:center;\n    min-height:180px;\n    background:#f8fbff;\n    border:1px dashed #b9d8f5;\n    border-radius:16px;\n    padding:18px;\n}\n\n#qrcode canvas{\n    max-width:170px;\n    max-height:170px;\n    border-radius:10px;\n    border:1px solid #d9e9ff;\n    box-shadow:0 8px 20px rgba(0,64,128,0.10);\n}\n\n#pdfArea{\n    position:relative;\n    border:1px solid #c8dff5;\n    border-radius:18px;\n    margin-top:20px;\n    overflow:auto;\n    background:#f8fbff;\n    min-height:260px;\n    display:flex;\n    justify-content:center;\n    align-items:flex-start;\n    padding:15px;\n}\n\n#pdfPreview{\n    display:block;\n    max-width:100%;\n    height:auto;\n    border-radius:10px;\n    box-shadow:0 8px 20px rgba(0,0,0,0.10);\n}\n\n#qrOverlay{\n    position:absolute;\n    cursor:move;\n    display:none;\n    border-radius:8px;\n    box-shadow:0 6px 15px rgba(0,0,0,0.18);\n    z-index:10;\n}\n\n.info-note{\n    font-size:14px;\n    color:#5d6d7e;\n    margin-top:10px;\n}\n\n.step-badge{\n    display:inline-flex;\n    align-items:center;\n    justify-content:center;\n    width:30px;\n    height:30px;\n    background:#0a4fa3;\n    color:white;\n    border-radius:50%;\n    font-weight:700;\n    margin-right:8px;\n}\n\n.footer-note{\n    text-align:center;\n    color:#607080;\n    font-size:14px;\n    margin-top:18px;\n}\n\n@media(max-width:768px){\n    .opart-title{\n        font-size:25px;\n    }\n\n    .opart-body{\n        padding:20px;\n    }\n}\n<\/style>\n\n<div class=\"opart-qr-page\">\n    <div class=\"opart-wrapper\">\n        <div class=\"opart-card\">\n\n            <div class=\"opart-header\">\n                <h1 class=\"opart-title\">Opart barcode document<\/h1>\n                <div class=\"opart-subtitle\">\n                    Generate QR code with selected journal logo and embed it into PDF documents.\n                <\/div>\n            <\/div>\n\n            <div class=\"opart-body\">\n\n                <div class=\"section-box\">\n                    <h2 class=\"section-title\">\n                        <span class=\"step-badge\">1<\/span>Select Logo &#038; Generate QR\n                    <\/h2>\n\n                    <label class=\"form-label\">Select Logo<\/label>\n                    <select id=\"logoSelect\" class=\"form-select mb-3\">\n                        <option value=\"\">&#8212; Select Logo &#8212;<\/option>\n                        <option value=\"zonalaut\">Zona Laut<\/option>\n                        <option value=\"maritimepark\">Maritime Park<\/option>\n                        <option value=\"sensistek\">Sensistek<\/option>\n                    <\/select>\n\n                    <label class=\"form-label\">QR Content<\/label>\n                    <input type=\"text\" id=\"qrdata\" class=\"form-control mb-3\"\n                           placeholder=\"Enter URL, DOI, or text\">\n\n                    <button class=\"btn btn-opart w-100 mb-3\" onclick=\"generateQR()\">\n                        Generate QR\n                    <\/button>\n\n                    <div id=\"qrcode\">\n                        <span style=\"color:#8aa0b5;\">QR preview will appear here<\/span>\n                    <\/div>\n\n                    <div class=\"info-note\">\n                        Select a journal logo and enter the QR content. The selected logo will be placed automatically at the center of the QR code.\n                    <\/div>\n                <\/div>\n\n                <div class=\"section-box\">\n                    <h2 class=\"section-title\">\n                        <span class=\"step-badge\">2<\/span>Embed QR into PDF\n                    <\/h2>\n\n                    <label class=\"form-label\">Upload PDF<\/label>\n                    <input type=\"file\" id=\"pdfInput\" class=\"form-control mb-3\" accept=\"application\/pdf\">\n\n                    <div class=\"info-note\">\n                        After uploading the PDF, drag the QR code to the desired position on the first page.\n                    <\/div>\n\n                    <div id=\"pdfArea\">\n                        <canvas id=\"pdfPreview\"><\/canvas>\n                        <img id=\"qrOverlay\">\n                    <\/div>\n\n                    <button class=\"btn btn-download w-100 mt-3\" onclick=\"embedQRtoPDF()\">\n                        Download Final PDF\n                    <\/button>\n                <\/div>\n\n                <div class=\"footer-note\">\n                    Offshore and Subsea Production Research Laboratory \u2014 Hasanuddin University\n                <\/div>\n\n            <\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n<script>\npdfjsLib.GlobalWorkerOptions.workerSrc =\n\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/pdf.js\/2.16.105\/pdf.worker.min.js\";\n\nlet uploadedLogo = null;\nlet finalCanvas = null;\n\nlet qrRX = 0.1;\nlet qrRY = 0.3;\n\nlet dragging = false;\n\nconst presetLogos = {\n    zonalaut: \"https:\/\/opart.unhas.ac.id\/wp-content\/uploads\/2026\/07\/Logo-Zonalaut.png\",\n    maritimepark: \"https:\/\/opart.unhas.ac.id\/wp-content\/uploads\/2026\/07\/Logo-Maritimepark-150x150.png\",\n    sensistek: \"https:\/\/opart.unhas.ac.id\/wp-content\/uploads\/2026\/07\/Logo-Sensistek.png\"\n};\n\ndocument.getElementById(\"logoSelect\").addEventListener(\"change\", function(){\n    const selectedLogo = this.value;\n    uploadedLogo = selectedLogo ? presetLogos[selectedLogo] : null;\n});\n\nfunction generateQR(){\n    const qrdata = document.getElementById(\"qrdata\");\n    const qrcode = document.getElementById(\"qrcode\");\n\n    if(!uploadedLogo){\n        alert(\"Please select a logo first.\");\n        return;\n    }\n\n    if(!qrdata.value){\n        alert(\"Please enter QR content.\");\n        return;\n    }\n\n    qrcode.innerHTML = \"\";\n\n    new QRCode(qrcode,{\n        text: qrdata.value,\n        width: 350,\n        height: 350,\n        correctLevel: QRCode.CorrectLevel.H\n    });\n\n    const t = setInterval(()=>{\n        const img = qrcode.querySelector(\"img\");\n        const canvas = qrcode.querySelector(\"canvas\");\n\n        if(img && img.complete){\n            clearInterval(t);\n            drawQRImageToCanvas(img);\n        }\n\n        if(canvas){\n            clearInterval(t);\n            drawQRCanvasToCanvas(canvas);\n        }\n    },50);\n}\n\nfunction drawQRImageToCanvas(img){\n    const s = 350;\n    const c = document.createElement(\"canvas\");\n    c.width = c.height = s;\n    const ctx = c.getContext(\"2d\");\n\n    ctx.drawImage(img,0,0,s,s);\n    drawLogoOnQR(c);\n}\n\nfunction drawQRCanvasToCanvas(sourceCanvas){\n    const s = 350;\n    const c = document.createElement(\"canvas\");\n    c.width = c.height = s;\n    const ctx = c.getContext(\"2d\");\n\n    ctx.drawImage(sourceCanvas,0,0,s,s);\n    drawLogoOnQR(c);\n}\n\nfunction drawLogoOnQR(c){\n    const qrcode = document.getElementById(\"qrcode\");\n    const ctx = c.getContext(\"2d\");\n    const s = c.width;\n\n    const logo = new Image();\n    logo.crossOrigin = \"anonymous\";\n    logo.src = uploadedLogo;\n\n    logo.onload = ()=>{\n        const logoRatio = 0.23;\n        const padding = 10;\n\n        const logoSize = s * logoRatio;\n        const boxSize = logoSize + padding * 2;\n\n        const x = (s - boxSize) \/ 2;\n        const y = (s - boxSize) \/ 2;\n\n        ctx.fillStyle = \"white\";\n        ctx.fillRect(x, y, boxSize, boxSize);\n\n        ctx.drawImage(\n            logo,\n            (s - logoSize) \/ 2,\n            (s - logoSize) \/ 2,\n            logoSize,\n            logoSize\n        );\n\n        finalCanvas = c;\n        qrcode.innerHTML=\"\";\n        qrcode.appendChild(c);\n    };\n\n    logo.onerror = ()=>{\n        alert(\"Logo could not be loaded. Please check the logo URL.\");\n    };\n}\n\ndocument.getElementById(\"pdfInput\").onchange = async e=>{\n    if(!finalCanvas){\n        alert(\"Generate QR first.\");\n        return;\n    }\n\n    const file = e.target.files[0];\n    if(!file) return;\n\n    const buf = await file.arrayBuffer();\n    const pdf = await pdfjsLib.getDocument({data:buf}).promise;\n    const page = await pdf.getPage(1);\n\n    const viewport = page.getViewport({scale:1.25});\n    const cv = document.getElementById(\"pdfPreview\");\n    const ctx = cv.getContext(\"2d\");\n\n    cv.width  = viewport.width;\n    cv.height = viewport.height;\n\n    await page.render({canvasContext:ctx,viewport}).promise;\n\n    const qrOverlay = document.getElementById(\"qrOverlay\");\n    qrOverlay.src = finalCanvas.toDataURL(\"image\/png\");\n    qrOverlay.style.display=\"block\";\n\n    updateOverlaySize();\n    placeOverlay();\n};\n\nfunction updateOverlaySize(){\n    const pdfPreview = document.getElementById(\"pdfPreview\");\n    const qrOverlay = document.getElementById(\"qrOverlay\");\n\n    const rect = pdfPreview.getBoundingClientRect();\n    const availableHeight = rect.height * (1 - qrRY) - 30;\n    const size = Math.min(availableHeight * 0.75, 90);\n\n    qrOverlay.style.width = size + \"px\";\n    qrOverlay.style.height = size + \"px\";\n}\n\nfunction placeOverlay(){\n    const pdfPreview = document.getElementById(\"pdfPreview\");\n    const qrOverlay = document.getElementById(\"qrOverlay\");\n\n    const x = pdfPreview.offsetLeft + (qrRX * pdfPreview.clientWidth);\n    const y = pdfPreview.offsetTop + (qrRY * pdfPreview.clientHeight);\n\n    qrOverlay.style.left = x + \"px\";\n    qrOverlay.style.top = y + \"px\";\n}\n\ndocument.getElementById(\"qrOverlay\").onmousedown = ()=> dragging=true;\ndocument.onmouseup = ()=> dragging=false;\n\ndocument.onmousemove = e=>{\n    if(!dragging) return;\n\n    const pdfPreview = document.getElementById(\"pdfPreview\");\n    const qrOverlay = document.getElementById(\"qrOverlay\");\n\n    const rect = pdfPreview.getBoundingClientRect();\n\n    let x = e.clientX - rect.left - qrOverlay.offsetWidth \/ 2;\n    let y = e.clientY - rect.top - qrOverlay.offsetHeight \/ 2;\n\n    if(x < 0) x = 0;\n    if(y < 0) y = 0;\n\n    if(x > rect.width - qrOverlay.offsetWidth) {\n        x = rect.width - qrOverlay.offsetWidth;\n    }\n\n    if(y > rect.height - qrOverlay.offsetHeight) {\n        y = rect.height - qrOverlay.offsetHeight;\n    }\n\n    qrRX = x \/ rect.width;\n    qrRY = y \/ rect.height;\n\n    updateOverlaySize();\n    placeOverlay();\n};\n\nasync function embedQRtoPDF(){\n    if(!finalCanvas){\n        alert(\"Generate QR first.\");\n        return;\n    }\n\n    const pdfInput = document.getElementById(\"pdfInput\");\n\n    if(!pdfInput.files[0]){\n        alert(\"Upload PDF first.\");\n        return;\n    }\n\n    const file = pdfInput.files[0];\n    const buf = await file.arrayBuffer();\n\n    const pdf = await PDFLib.PDFDocument.load(buf);\n    const img = await pdf.embedPng(finalCanvas.toDataURL(\"image\/png\"));\n\n    const page = pdf.getPages()[0];\n    const {width:pw, height:ph} = page.getSize();\n\n    const availableHeight = ph * (1 - qrRY) - 30;\n    const qrSize = Math.min(availableHeight * 0.75, 90);\n\n    page.drawImage(img,{\n        x: qrRX * pw,\n        y: ph - (qrRY * ph) - qrSize,\n        width: qrSize,\n        height: qrSize\n    });\n\n    const out = await pdf.save();\n    const a = document.createElement(\"a\");\n    a.href = URL.createObjectURL(new Blob([out],{type:\"application\/pdf\"}));\n    a.download = \"PDF_with_QR_Logo.pdf\";\n    a.click();\n}\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>Opart barcode document Generate QR code with selected journal logo and embed it into PDF documents. 1Select Logo &#038; Generate QR Select Logo &#8212; Select Logo &#8212;Zona LautMaritime ParkSensistek QR Content Generate QR QR preview will appear here Select a journal logo and enter the QR content. The selected logo will be placed automatically at &hellip; <\/p>\n","protected":false},"author":2,"featured_media":456,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-443","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-apps"],"_links":{"self":[{"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=\/wp\/v2\/posts\/443","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=443"}],"version-history":[{"count":6,"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=\/wp\/v2\/posts\/443\/revisions"}],"predecessor-version":[{"id":455,"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=\/wp\/v2\/posts\/443\/revisions\/455"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=\/wp\/v2\/media\/456"}],"wp:attachment":[{"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opart.unhas.ac.id\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}