{"id":63485,"date":"2026-02-17T19:56:14","date_gmt":"2026-02-17T16:56:14","guid":{"rendered":"https:\/\/www.qu.edu.sa\/?page_id=63485"},"modified":"2026-03-19T19:33:35","modified_gmt":"2026-03-19T16:33:35","slug":"cards","status":"publish","type":"page","link":"https:\/\/www.qu.edu.sa\/en\/cards\/","title":{"rendered":"Greeting card"},"content":{"rendered":"<style>\n            .qu-card-v2-font-preload { position:absolute; visibility:hidden; pointer-events:none; opacity:0; white-space:nowrap; }\n            .qu-card-v2-wrap { max-width:720px; margin:20px auto; text-align:center; border:1px solid #eee; border-radius:14px; padding:14px; background:#fff; }\n            .qu-card-v2-field { display:flex; flex-direction:column; gap:6px; text-align:right; margin:0 auto 12px; max-width:520px; }\n            .qu-card-v2-field label { font-weight:700; font-size:14px; }\n            .qu-card-v2-field input { width:100%; padding:12px; font-size:18px; border:1px solid #ddd; border-radius:10px; text-align:center; box-sizing:border-box; }\n            .qu-card-v2-note { font-size:12px; color:#666; margin-top:8px; text-align:center; line-height: 1.4; }\n            .qu-card-v2-btns { display:flex; gap:12px; justify-content:center; margin:10px 0; flex-wrap:wrap; }\n            .qu-card-v2-download { border:none; padding:12px 26px; font-size:18px; border-radius:12px; cursor:pointer; background:#1B8354; color:#fff; font-weight: bold; transition: 0.3s; }\n            .qu-card-v2-download:active { transform: scale(0.98); }\n            .qu-card-v2-wrap img, .qu-card-v2-wrap canvas { width:100%; max-width:100%; height:auto; display:block; margin-top:14px; border-radius:12px; border:1px solid #eee; }\n            .qu-card-v2-wrap canvas { display:none; }\n            \/* \u0625\u062e\u0641\u0627\u0621 \u0627\u0644\u0635\u0648\u0631\u0629 \u0627\u0644\u0623\u0635\u0644\u064a\u0629 \u0639\u0646\u062f \u0627\u0644\u0643\u062a\u0627\u0628\u0629 \u0644\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u0646\u062a\u064a\u062c\u0629 \u0641\u0642\u0637 *\/\n            .is-generated .qu-card-v2-output { border: 2px solid #1B8354; }\n        <\/style>\n\n        <script>\n            class QuCardGeneratorV2 {\n                constructor(config) {\n                    this.config = config;\n                    this.wrap = document.getElementById(config.uid);\n                    this.textEl = this.wrap.querySelector('.qu-card-v2-input');\n                    this.outputEl = this.wrap.querySelector('.qu-card-v2-output');\n                    this.canvas = this.wrap.querySelector('.qu-card-v2-canvas');\n                    this.downloadBtn = this.wrap.querySelector('.qu-card-v2-download');\n                    this.ctx = this.canvas.getContext('2d');\n                    this.isBusy = false;\n                    this.templateImage = new Image();\n                    this.templateImage.crossOrigin = 'anonymous';\n                    this.templateImage.src = this.config.imageUrl;\n                    this.bindEvents();\n                }\n\n                isIOS() {\n                    return \/iPad|iPhone|iPod\/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);\n                }\n\n                async draw() {\n                    const text = (this.textEl.value || '').trim();\n                    if (!text) return false;\n\n                    try {\n                        if (document.fonts) await document.fonts.load(`${this.config.fontSize}px \"${this.config.fontFamily}\"`);\n                        \n                        this.canvas.width = this.templateImage.naturalWidth;\n                        this.canvas.height = this.templateImage.naturalHeight;\n                        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n                        this.ctx.drawImage(this.templateImage, 0, 0);\n\n                        const boxY = this.canvas.height - this.config.boxYFromBottom;\n                        const boxW = this.canvas.width - this.config.boxWOffset;\n                        const centerX = this.config.boxX + (boxW \/ 2);\n                        const centerY = boxY + (this.config.boxH \/ 2);\n\n                        this.ctx.fillStyle = this.config.textColor;\n                        this.ctx.textAlign = 'center';\n                        this.ctx.textBaseline = 'middle';\n                        try { this.ctx.direction = 'rtl'; } catch(e) {}\n                        this.ctx.font = `${this.config.fontSize}px \"${this.config.fontFamily}\", Arial`;\n\n                        let y = centerY + this.config.textOffsetY;\n                        if (this.isIOS()) y += this.config.iosTextOffsetY;\n\n                        this.ctx.fillText(text.slice(0, this.config.maxChars), centerX, y);\n                        \n                        \/\/ \u062a\u062d\u062f\u064a\u062b \u0627\u0644\u0635\u0648\u0631\u0629 \u0627\u0644\u0645\u0639\u0631\u0648\u0636\u0629 \u0644\u0644\u0645\u0633\u062a\u062e\u062f\u0645 (\u0645\u0647\u0645 \u062c\u062f\u0627\u064b \u0644\u0644\u0640 iPhone)\n                        this.outputEl.src = this.canvas.toDataURL('image\/png');\n                        this.wrap.classList.add('is-generated');\n                        return true;\n                    } catch (e) {\n                        console.error(e);\n                        return false;\n                    }\n                }\n\n                async handleDownload() {\n                    const ok = await this.draw();\n                    if (!ok) return;\n\n                    \/\/ \u062a\u062d\u0648\u064a\u0644 \u0627\u0644\u0643\u0627\u0646\u0641\u0627\u0633 \u0625\u0644\u0649 Blob \u0648\u0647\u0648 \u0627\u0644\u0645\u0633\u0627\u0631 \u0627\u0644\u0623\u0643\u062b\u0631 \u0623\u0645\u0627\u0646\u0627\u064b \u0641\u064a \u0633\u0641\u0627\u0631\u064a\n                    this.canvas.toBlob((blob) => {\n                        const url = URL.createObjectURL(blob);\n                        \n                        if (this.isIOS()) {\n                            \/\/ \u0641\u064a \u0627\u0644\u0622\u064a\u0641\u0648\u0646\u060c \u0646\u0641\u062a\u062d \u0627\u0644\u0635\u0648\u0631\u0629 \u0641\u064a \u062a\u0628\u0648\u064a\u0628 \u062c\u062f\u064a\u062f \u0623\u0648 \u0646\u0648\u062c\u0647 \u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645 \u0644\u062d\u0641\u0638 \u0627\u0644\u0645\u0639\u0627\u064a\u0646\u0629\n                            window.open(url, '_blank');\n                            alert('\u062a\u0645 \u062a\u062c\u0647\u064a\u0632 \u0627\u0644\u0635\u0648\u0631\u0629. \u0627\u0636\u063a\u0637 \u0645\u0637\u0648\u0644\u0627\u064b \u0639\u0644\u064a\u0647\u0627 \u0648\u0627\u062e\u062a\u0631 \"\u062d\u0641\u0638 \u0641\u064a \u0627\u0644\u0635\u0648\u0631\".');\n                        } else {\n                            const link = document.createElement('a');\n                            link.href = url;\n                            link.download = this.config.downloadName;\n                            document.body.appendChild(link);\n                            link.click();\n                            document.body.removeChild(link);\n                        }\n                        \n                        setTimeout(() => URL.revokeObjectURL(url), 2000);\n                    }, 'image\/png');\n                }\n\n                bindEvents() {\n                    this.downloadBtn.addEventListener('click', async () => {\n                        if (this.isBusy) return;\n                        this.isBusy = true;\n                        this.downloadBtn.textContent = '\u062c\u0627\u0631\u064a \u0627\u0644\u0645\u0639\u0627\u0644\u062c\u0629...';\n                        await this.handleDownload();\n                        this.downloadBtn.textContent = this.config.download_btn_text || '\u062a\u062d\u0645\u064a\u0644';\n                        this.isBusy = false;\n                    });\n                }\n            }\n        <\/script>\n        \n    <style>\n        @font-face {\n            font-family: 'FrutigerArabic';\n            src: url('\/wp-content\/uploads\/qu_fonts_logo\/Frutiger3.ttf') format('truetype');\n            font-display: swap;\n        }\n    <\/style>\n\n    <div class=\"qu-card-v2-wrap\" id=\"qu_card_v2_wrap_1\">\n        <div class=\"qu-card-v2-field\">\n            <label>Name (will appear inside the card)<\/label>\n            <input type=\"text\" class=\"qu-card-v2-input\" value=\"\" placeholder=\"\" autocomplete=\"off\">\n            <div class=\"qu-card-v2-note\">On some iPhones, the image may open in a new tab, then can be saved from sharing or long press.<\/div>\n        <\/div>\n\n        <div class=\"qu-card-v2-btns\">\n            <button type=\"button\" class=\"qu-card-v2-download\">Download<\/button>\n        <\/div>\n\n        <img decoding=\"async\" class=\"qu-card-v2-output\" src=\"\/wp-content\/uploads\/2026\/03\/qu_eid_1447_v2.jpg\" alt=\"Preview\">\n        <canvas class=\"qu-card-v2-canvas\"><\/canvas>\n    <\/div>\n\n    <script>\n        (function(){\n            const init = () => {\n                if (typeof QuCardGeneratorV2 !== 'undefined') {\n                    new QuCardGeneratorV2({\"uid\":\"qu_card_v2_wrap_1\",\"imageUrl\":\"\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/qu_eid_1447_v2.jpg\",\"fontFamily\":\"FrutigerArabic\",\"fontSize\":40,\"textColor\":\"#ffffff\",\"maxChars\":60,\"boxX\":95,\"boxYFromBottom\":328,\"boxWOffset\":190,\"boxH\":150,\"textOffsetY\":0,\"iosTextOffsetY\":85,\"downloadName\":\"qu_card.png\"});\n                }\n            };\n            if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);\n            else init();\n        })();\n    <\/script>\n\n    \n\n\n\n<p><\/p>","protected":false},"excerpt":{"rendered":"","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"departments-pages-type":[239],"class_list":["post-63485","page","type-page","status-publish","hentry","departments-pages-type-static-content"],"_links":{"self":[{"href":"https:\/\/www.qu.edu.sa\/en\/wp-json\/wp\/v2\/pages\/63485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.qu.edu.sa\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.qu.edu.sa\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.qu.edu.sa\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.qu.edu.sa\/en\/wp-json\/wp\/v2\/comments?post=63485"}],"version-history":[{"count":44,"href":"https:\/\/www.qu.edu.sa\/en\/wp-json\/wp\/v2\/pages\/63485\/revisions"}],"predecessor-version":[{"id":68978,"href":"https:\/\/www.qu.edu.sa\/en\/wp-json\/wp\/v2\/pages\/63485\/revisions\/68978"}],"wp:attachment":[{"href":"https:\/\/www.qu.edu.sa\/en\/wp-json\/wp\/v2\/media?parent=63485"}],"wp:term":[{"taxonomy":"departments-pages-type","embeddable":true,"href":"https:\/\/www.qu.edu.sa\/en\/wp-json\/wp\/v2\/departments-pages-type?post=63485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}