Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.

Script HTML Generator URL Undangan Digital: Solusi Modern untuk Acara Anda

Pernahkah Anda merasa kerepotan saat membuat undangan digital untuk acara spesial seperti pernikahan, ulang tahun, atau gathering? Mengedit URL satu per satu untuk setiap tamu dan menulis pesan undangan secara manual bisa memakan waktu berjam-jam. Tapi, bagaimana jika ada cara untuk mengotomatiskan semua itu? Generator URL Undangan Digital hadir sebagai solusi cerdas yang akan mengubah cara Anda mengelola undangan acara!

Mengapa Memilih Generator URL Undangan Digital?

Bayangkan Anda bisa membuat ratusan undangan personal dalam hitungan menit. Dengan alat ini, Anda dapat:

  • Menghemat Waktu: Buat URL undangan personal untuk setiap tamu hanya dengan memasukkan daftar nama.
  • Personalisasi Pesan: Tambahkan pesan undangan dinamis dengan nama tamu dan URL khusus dalam satu klik.
  • Fitur Praktis: Salin pesan undangan individual atau semua sekaligus, dan ekspor ke file CSV untuk distribusi mudah.
  • Desain Responsif: Antarmuka yang ramah pengguna, cocok untuk diakses dari ponsel, tablet, atau komputer.
  • Gratis dan Mudah: Tidak perlu keahlian teknis, siapa pun bisa menggunakannya!

Alat ini dirancang untuk memudahkan Anda mengundang tamu dengan cara yang modern, efisien, dan profesional. Baik untuk acara kecil maupun besar, Generator URL Undangan Digital adalah asisten setia Anda.

Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.

Cara Kerja Generator URL Undangan Digital

Menggunakan alat ini sangat sederhana:

  1. Masukkan Base URL: Salin URL dasar undangan Anda, misalnya https://undangan-digital.space/dedi-puput/?u=.
  2. Tulis Template Pesan: Buat pesan undangan dengan placeholder {name} untuk nama tamu dan {url} untuk link undangan, seperti: “Halo {name}, kami undang Anda ke pernikahan kami! Klik: {url}”.
  3. Masukkan Daftar Nama: Ketik nama tamu, satu per baris (contoh: Pendi, Budi, Ani).
  4. Generate dan Bagikan:
    • Klik “Generate URL” untuk melihat pesan undangan personal untuk setiap tamu.
    • Gunakan tombol “Salin Pesan” untuk menyalin pesan individual, atau “Salin Semua Pesan” untuk menyalin semua sekaligus.
    • Ekspor ke file CSV untuk mengimpor ke aplikasi seperti Excel atau platform pengiriman pesan.

Fitur Unggulan

  • Salin Mudah: Salin pesan undangan satu per satu atau semua sekaligus dengan notifikasi sukses.
  • Ekspor ke CSV: Simpan daftar nama, URL, dan pesan undangan dalam format CSV yang kompatibel dengan Excel.
  • Template Pesan Dinamis: Personalisasi pesan dengan nama tamu dan URL secara otomatis.
  • Error Handling: Notifikasi yang jelas jika ada kesalahan input, dengan saran untuk memperbaikinya.
  • Desain Profesional: Antarmuka modern yang responsif, memastikan pengalaman pengguna yang mulus di semua perangkat.

Cocok untuk Siapa?

  • Penyelenggara Acara: Untuk pernikahan, ulang tahun, atau acara korporat.
  • Bisnis Undangan Digital: Tingkatkan efisiensi layanan Anda dengan otomatisasi.
  • Individu: Siapa pun yang ingin membuat undangan dengan cepat tanpa repot.

Mulai Sekarang!

Tidak perlu lagi mengedit URL atau menulis pesan satu per satu. Dengan Generator URL Undangan Digital, Anda bisa fokus pada hal yang lebih penting—mempersiapkan acara terbaik Anda. Coba alat ini sekarang dan rasakan kemudahan mengundang tamu dengan gaya modern!

Unduh kode sumbernya di bawah ini dan jalankan melalui server web (misalnya, menggunakan python -m http.server 8000 atau hosting di Netlify). Bagikan undangan Anda dengan cepat dan profesional!

Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.

<script type="text/javascript">
        var gk_isXlsx = false;
        var gk_xlsxFileLookup = {};
        var gk_fileData = {};
        function filledCell(cell) {
          return cell !== '' && cell != null;
        }
        function loadFileData(filename) {
        if (gk_isXlsx && gk_xlsxFileLookup[filename]) {
            try {
                var workbook = XLSX.read(gk_fileData[filename], { type: 'base64' });
                var firstSheetName = workbook.SheetNames[0];
                var worksheet = workbook.Sheets[firstSheetName];

                // Convert sheet to JSON to filter blank rows
                var jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, blankrows: false, defval: '' });
                // Filter out blank rows (rows where all cells are empty, null, or undefined)
                var filteredData = jsonData.filter(row => row.some(filledCell));

                // Heuristic to find the header row by ignoring rows with fewer filled cells than the next row
                var headerRowIndex = filteredData.findIndex((row, index) =>
                  row.filter(filledCell).length >= filteredData[index + 1]?.filter(filledCell).length
                );
                // Fallback
                if (headerRowIndex === -1 || headerRowIndex > 25) {
                  headerRowIndex = 0;
                }

                // Convert filtered JSON back to CSV
                var csv = XLSX.utils.aoa_to_sheet(filteredData.slice(headerRowIndex)); // Create a new sheet from filtered array of arrays
                csv = XLSX.utils.sheet_to_csv(csv, { header: 1 });
                return csv;
            } catch (e) {
                console.error(e);
                return "";
            }
        }
        return gk_fileData[filename] || "";
        }
        </script><!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Generator URL Undangan Digital</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        #output {
            max-height: 400px;
            overflow-y: auto;
        }
        .copy-btn:hover .tooltip, .copy-all-btn:hover .tooltip {
            visibility: visible;
            opacity: 1;
        }
        .url-item {
            transition: background-color 0.2s;
        }
        .url-item:hover {
            background-color: #f1f5f9;
        }
        #errorNotification {
            transition: opacity 0.5s;
        }
    </style>
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center p-4">
    <div class="bg-white rounded-lg shadow-xl p-6 w-full max-w-3xl">
        <h1 class="text-3xl font-bold text-center text-gray-800 mb-6">Generator URL Undangan Digital</h1>
        
        <!-- Error Notification -->
        <div id="errorNotification" class="hidden bg-red-100 text-red-700 p-3 rounded-lg mb-4"></div>

        <!-- Input Base URL -->
        <div class="mb-6">
            <label for="baseURL" class="block text-sm font-medium text-gray-700 mb-2">Base URL Undangan</label>
            <input type="url" id="baseURL" class="block w-full p-3 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500 transition" placeholder="Contoh: https://undangan-digital.space/dedi-puput/?u=" value="https://undangan-digital.space/dedi-puput/?u=">
            <p id="urlError" class="text-red-500 text-sm mt-2 hidden">Masukkan URL yang valid (contoh: https://undangan-digital.space/dedi-puput/?u=)</p>
        </div>

        <!-- Input Message Template -->
        <div class="mb-6">
            <label for="messageTemplate" class="block text-sm font-medium text-gray-700 mb-2">Template Pesan Undangan</label>
            <textarea id="messageTemplate" class="block w-full p-3 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500 transition" rows="4" placeholder="Contoh: Halo {name}, kami mengundang Anda ke acara kami! Klik link berikut: {url}"></textarea>
            <p class="text-sm text-gray-500 mt-2">Gunakan {name} untuk nama tamu dan {url} untuk link undangan.</p>
        </div>

        <!-- Input Name List -->
        <div class="mb-6">
            <label for="nameList" class="block text-sm font-medium text-gray-700 mb-2">Daftar Nama (satu nama per baris)</label>
            <textarea id="nameList" class="block w-full p-3 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500 transition" rows="6" placeholder="Masukkan nama, contoh:&#10;Pendi&#10;Budi&#10;Ani"></textarea>
            <p id="nameError" class="text-red-500 text-sm mt-2 hidden">Masukkan minimal satu nama yang valid!</p>
        </div>

        <!-- Buttons -->
        <div class="flex flex-col sm:flex-row gap-4 mb-6">
            <button onclick="generateInvitationURLs()" class="w-full bg-indigo-600 text-white p-3 rounded-lg hover:bg-indigo-700 transition font-semibold">Generate URL</button>
            <button onclick="copyAllURLs()" class="copy-all-btn w-full bg-gray-600 text-white p-3 rounded-lg hover:bg-gray-700 transition font-semibold relative">
                Salin Semua Pesan
                <span class="tooltip absolute invisible opacity-0 bg-gray-800 text-white text-xs rounded py-1 px-2 -top-10 left-1/2 transform -translate-x-1/2 transition-opacity">Semua pesan disalin!</span>
            </button>
            <button onclick="exportToCSV()" class="w-full bg-green-600 text-white p-3 rounded-lg hover:bg-green-700 transition font-semibold">Ekspor ke CSV</button>
        </div>

        <!-- Output -->
        <div class="mb-4">
            <h2 class="text-lg font-semibold text-gray-800 mb-3">Hasil Pesan Undangan:</h2>
            <div id="output" class="bg-gray-50 p-4 border border-gray-200 rounded-lg"></div>
        </div>
    </div>

    <script>
        // Fungsi untuk menampilkan notifikasi error
        function showError(message) {
            const errorNotification = document.getElementById("errorNotification");
            errorNotification.textContent = message;
            errorNotification.classList.remove("hidden");
            setTimeout(() => {
                errorNotification.classList.add("opacity-0");
                setTimeout(() => errorNotification.classList.add("hidden"), 500);
                errorNotification.classList.remove("opacity-0");
            }, 5000);
        }

        // Fallback untuk menyalin teks jika Clipboard API tidak tersedia
        function fallbackCopyText(text) {
            const textArea = document.createElement("textarea");
            textArea.value = text;
            document.body.appendChild(textArea);
            textArea.select();
            try {
                document.execCommand("copy");
                return true;
            } catch (err) {
                return false;
            } finally {
                document.body.removeChild(textArea);
            }
        }

        // Fungsi global untuk menghasilkan URL dan pesan undangan
        window.generateInvitationURLs = function(baseURL = null, names = null, messageTemplate = null) {
            const baseURLInput = baseURL || document.getElementById("baseURL").value.trim();
            const nameListInput = names || document.getElementById("nameList").value.trim();
            const messageTemplateInput = messageTemplate || document.getElementById("messageTemplate").value.trim() || "Halo {name}, kami mengundang Anda ke acara kami! Klik link berikut: {url}";
            const outputDiv = document.getElementById("output");
            const urlError = document.getElementById("urlError");
            const nameError = document.getElementById("nameError");

            // Reset error messages and output
            urlError.classList.add("hidden");
            nameError.classList.add("hidden");
            outputDiv.innerHTML = "";

            // Validasi URL
            let validBaseURL = baseURLInput;
            if (!validBaseURL.endsWith("?u=") && !validBaseURL.endsWith("&u=")) {
                validBaseURL = baseURLInput.endsWith("/") ? `${baseURLInput}u=` : `${baseURLInput}/?u=`;
            }
            try {
                new URL(validBaseURL);
            } catch {
                urlError.classList.remove("hidden");
                return [];
            }

            // Validasi daftar nama
            const nameList = nameListInput.split("\n").map(name => name.trim()).filter(name => name);
            if (nameList.length === 0) {
                nameError.classList.remove("hidden");
                return [];
            }

            // Generate URLs dan pesan
            const results = nameList.map((name, index) => {
                const encodedName = encodeURIComponent(name);
                const url = `${validBaseURL}${encodedName}`;
                const message = messageTemplateInput.replace(/{name}/g, name).replace(/{url}/g, url);
                return { id: index, name, url, message };
            });

            // Tampilkan hasil dengan tombol salin per pesan
            outputDiv.innerHTML = results.map(item => `
                <div class="url-item flex flex-col p-2 border-b border-gray-200">
                    <div class="flex items-center justify-between">
                        <span class="text-sm text-gray-700 font-semibold">${item.name}</span>
                        <button onclick="copySingleMessage('${item.message.replace(/'/g, "\\'")}', this)" class="copy-btn bg-blue-500 text-white px-3 py-1 rounded-md hover:bg-blue-600 transition text-sm relative">
                            Salin Pesan
                            <span class="tooltip absolute invisible opacity-0 bg-gray-800 text-white text-xs rounded py-1 px-2 -top-8 right-0 transition-opacity">Pesan disalin!</span>
                        </button>
                    </div>
                    <span class="text-sm text-gray-600 mt-1">${item.message}</span>
                </div>
            `).join("");

            return results.map(item => item.message);
        };

        // Fungsi untuk menyalin satu pesan
        function copySingleMessage(message, button) {
            try {
                navigator.clipboard.writeText(message).then(() => {
                    const tooltip = button.querySelector(".tooltip");
                    tooltip.classList.remove("invisible");
                    tooltip.classList.add("opacity-100");
                    setTimeout(() => {
                        tooltip.classList.remove("opacity-100");
                        tooltip.classList.add("invisible");
                    }, 1500);
                }).catch(() => {
                    if (fallbackCopyText(message)) {
                        const tooltip = button.querySelector(".tooltip");
                        tooltip.classList.remove("invisible");
                        tooltip.classList.add("opacity-100");
                        setTimeout(() => {
                            tooltip.classList.remove("opacity-100");
                            tooltip.classList.add("invisible");
                        }, 1500);
                    } else {
                        showError("Gagal menyalin pesan. Coba jalankan aplikasi melalui server web (bukan file lokal) atau salin manual.");
                    }
                });
            } catch (err) {
                if (fallbackCopyText(message)) {
                    const tooltip = button.querySelector(".tooltip");
                    tooltip.classList.remove("invisible");
                    tooltip.classList.add("opacity-100");
                    setTimeout(() => {
                        tooltip.classList.remove("opacity-100");
                        tooltip.classList.add("invisible");
                    }, 1500);
                } else {
                    showError("Gagal menyalin pesan. Clipboard API tidak didukung. Coba jalankan di HTTPS atau server lokal.");
                }
            }
        }

        // Fungsi untuk menyalin semua pesan
        function copyAllURLs() {
            const messages = Array.from(document.querySelectorAll(".url-item .text-sm.text-gray-600")).map(span => span.textContent).join("\n\n");
            if (messages) {
                try {
                    navigator.clipboard.writeText(messages).then(() => {
                        const tooltip = document.querySelector(".copy-all-btn .tooltip");
                        tooltip.classList.remove("invisible");
                        tooltip.classList.add("opacity-100");
                        setTimeout(() => {
                            tooltip.classList.remove("opacity-100");
                            tooltip.classList.add("invisible");
                        }, 1500);
                    }).catch(() => {
                        if (fallbackCopyText(messages)) {
                            const tooltip = document.querySelector(".copy-all-btn .tooltip");
                            tooltip.classList.remove("invisible");
                            tooltip.classList.add("opacity-100");
                            setTimeout(() => {
                                tooltip.classList.remove("opacity-100");
                                tooltip.classList.add("invisible");
                            }, 1500);
                        } else {
                            showError("Gagal menyalin pesan. Coba jalankan aplikasi melalui server web (bukan file lokal) atau salin manual.");
                        }
                    });
                } catch (err) {
                    if (fallbackCopyText(messages)) {
                        const tooltip = document.querySelector(".copy-all-btn .tooltip");
                        tooltip.classList.remove("invisible");
                        tooltip.classList.add("opacity-100");
                        setTimeout(() => {
                            tooltip.classList.remove("opacity-100");
                            tooltip.classList.add("invisible");
                        }, 1500);
                    } else {
                        showError("Gagal menyalin pesan. Clipboard API tidak didukung. Coba jalankan di HTTPS atau server lokal.");
                    }
                }
            }
        }

        // Fungsi untuk ekspor ke CSV
        function exportToCSV() {
            const baseURL = document.getElementById("baseURL").value.trim();
            const nameList = document.getElementById("nameList").value.trim().split("\n").map(name => name.trim()).filter(name => name);
            const messageTemplate = document.getElementById("messageTemplate").value.trim() || "Halo {name}, kami mengundang Anda ke acara kami! Klik link berikut: {url}";
            if (!nameList.length) {
                showError("Masukkan minimal satu nama untuk mengekspor ke CSV.");
                return;
            }

            let validBaseURL = baseURL;
            if (!validBaseURL.endsWith("?u=") && !validBaseURL.endsWith("&u=")) {
                validBaseURL = baseURL.endsWith("/") ? `${baseURL}u=` : `${baseURL}/?u=`;
            }

            const csvContent = [
                "Name,URL,Message",
                ...nameList.map(name => {
                    const encodedName = encodeURIComponent(name);
                    const url = `${validBaseURL}${encodedName}`;
                    const message = messageTemplate.replace(/{name}/g, name).replace(/{url}/g, url);
                    return `"${name.replace(/"/g, '""')}","${url}","${message.replace(/"/g, '""')}"`;
                })
            ].join("\n");

            const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
            const url = URL.createObjectURL(blob);
            const a = document.createElement("a");
            a.href = url;
            a.download = "undangan_urls.csv";
            a.click();
            URL.revokeObjectURL(url);
        }
    </script>
</body>
</html>

Catatan: Untuk memastikan fitur salin berfungsi, jalankan aplikasi melalui server web (http:// atau https://), bukan langsung dari file lokal (file://).

Iklan
Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.

Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.

Beri komentar

Kamu yakin ingin keluar?

Ya, Keluar
Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.
Lelah dengan iklan? Hanya dengan IDR 833 / hari, buka konten eksklusif dan nikmati pengalaman tanpa iklan. Selengkapnya.
Kami harap dukungan Anda via iklan ini membantu kami terus menyajikan konten bermanfaat.
Tunggu hingga iklan selesai untuk menyalin atau mendownload kode.
Situs ini menggunakan cookie untuk memberikan pengalaman menjelajah yang lebih baik. Dengan menggunakan situs web ini, Anda menyetujui penggunaan cookie kami.