-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Preview Button * Add preview Icon * Add preview button and block * Add js script for controling preview * Update preview.js * Add base data to preview * Add preview - name - url - photo - description - email * Update preview.png * Add Links to preview * Add links to preview * Add default preview * Add animation * Move preview.js to index.js * Update Icon * Add Preview for theme * Themes Load images * js preview in new html window independent * default theme * Rename css * Final preview Feature * Add meta data * Make preview only for devices min-width: 1000px * Update index.php * Update .gitignore
- Loading branch information
Showing
4 changed files
with
219 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
/dist/ | ||
/dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
:root{ | ||
--buttonSize: 70px; | ||
--buttonOffset: 10px; | ||
--buttonRadius: 10px; | ||
--previewWidth: 30vw; | ||
--previewHeight: 100vh; | ||
--previewXOffset: 0; | ||
--previewYOffset: 0; | ||
--animationDuration: 500ms; | ||
} | ||
#previewButton { | ||
position: fixed; | ||
width: var(--buttonSize); | ||
height: var(--buttonSize); | ||
bottom: var(--buttonOffset); | ||
right: var(--buttonOffset); | ||
border-radius: var(--buttonRadius); | ||
z-index: 2; | ||
} | ||
|
||
#previewButton > *{ | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
||
#previewBlock{ | ||
position: fixed; | ||
top: var(--previewYOffset); | ||
right: var(--previewXOffset); | ||
width: var(--previewWidth); | ||
height: var(--previewHeight); | ||
z-index: 1; | ||
transition: var(--animationDuration); | ||
right: -100%; | ||
} | ||
|
||
@media screen and (max-width: 1000px){ | ||
#previewButton{ | ||
display: none; | ||
} | ||
#previewBlock{ | ||
display: none; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
const localStorageIgnore = ["photo"]; | ||
const themeUrl = "https://cdn.jsdelivr.net/npm/[email protected]"; | ||
|
||
// Elements | ||
const addCustomLinkButton = document.querySelector("a.btn"); | ||
|
@@ -218,3 +219,152 @@ checkbox_preview.addEventListener("change", () => { | |
checkbox_zip.addEventListener("change", () => { | ||
checkbox_preview.disabled = checkbox_zip.checked; | ||
}); | ||
|
||
/*****************************************************/ | ||
/***************** Real Time Preview *****************/ | ||
/*****************************************************/ | ||
|
||
// Get Window Elements | ||
var previewButton = document.getElementById('previewButton'); | ||
var previewBlock = document.getElementById('previewBlock'); | ||
var additionalLinkButton = document.getElementById("additionalLink"); | ||
var formData = document.getElementById('form'); | ||
var theme = document.getElementById('theme'); | ||
|
||
// Real time variables | ||
var preview = false; | ||
var photo = ""; | ||
var linkCount = Number(additionalLinkButton.getAttribute("data-index")); | ||
const styleElement = document.createElement('style'); | ||
|
||
// Preview Button functionality | ||
previewButton.addEventListener('click', () => { | ||
preview = !preview; | ||
if (preview) { | ||
// previewBlock.style.display = 'block'; | ||
previewBlock.style.right = '0'; | ||
previewButton.style.filter = 'invert(1)'; | ||
UpdatePreview(); | ||
} else { | ||
// previewBlock.style.display = 'none'; | ||
previewBlock.style.right = '-100%'; | ||
previewButton.style.filter = 'invert(0)'; | ||
} | ||
}); | ||
|
||
// Update Preview Photo On Input | ||
formData['photo'].addEventListener('input', (e) => { | ||
var photoData = e.target.files[0]; | ||
if(photoData) { | ||
const reader = new FileReader(); | ||
reader.onload = (e) => { | ||
photo = e.target.result; | ||
UpdatePreview(); | ||
} | ||
reader.readAsDataURL(photoData); | ||
} | ||
}); | ||
|
||
// Add Listner for additionalLinkButton and for form data | ||
additionalLinkButton.addEventListener('click', () => { | ||
linkCount++; | ||
var linkId = `links[${linkCount}]`; | ||
document.getElementById(linkId + "[url]").addEventListener('input', UpdatePreview); | ||
document.getElementById(linkId + "[name]").addEventListener('input', UpdatePreview); | ||
document.getElementById(linkId + "[icon]").addEventListener('input', UpdatePreview); | ||
}); | ||
|
||
// Update Prview Function | ||
function UpdatePreview() { | ||
var name = formData['name'].value; | ||
var mainUrl= formData['url'].value; | ||
var description = formData['description'].value; | ||
var email = formData['email'].value; | ||
var links = ""; | ||
var photoCode = ""; | ||
var themePath = ""; | ||
|
||
// Links | ||
for (var i = 0; i < linkCount; i++) { | ||
var linkId = `links[${i}]`; | ||
var linkUrl = document.getElementById(linkId + "[url]").value; | ||
var linkName = document.getElementById(linkId + "[name]").value; | ||
var linkIcon = document.getElementById(linkId + "[icon]").value; | ||
|
||
if(linkUrl !== ""){ | ||
if(linkIcon !== ""){ | ||
links += | ||
`<a class="link" href="${linkUrl}" target="_blank"> | ||
<ion-icon name="${linkIcon}"></ion-icon> | ||
${linkName} </a>`; | ||
} | ||
else{ | ||
links += | ||
`<a class="link" href="${linkUrl}" target="_blank"> | ||
${linkName} </a>`; | ||
} | ||
} | ||
} | ||
|
||
// Check if data is added | ||
if(photo !== '') photoCode = `<img id="userPhoto" src="${photo}" alt="User Photo"></img>`; | ||
if(name !== '') name = `<a href="${mainUrl}"><h1 id="userName">${name}</h1></a>`; | ||
if(description !== '') description =`<p id="description">${description}</p>`; | ||
if(email !== '') email = `<a class="link" href="mailto:${email}" target="_blank"><ion-icon name="mail"></ion-icon> Email</a>`; | ||
|
||
// Add path to files | ||
if(theme.value !== "") | ||
{ | ||
let jsonString = theme.value.match(/{.*}/)[0]; | ||
var json = JSON.parse(jsonString); | ||
themePath = "themes/" + json.id; | ||
} | ||
else themePath = "themes/darkmode"; | ||
|
||
// Add Style | ||
var themeStylePath = themeUrl + "/" + themePath+ "/" + "style.css"; | ||
|
||
// Add JS | ||
var themeJSPath = themeUrl + "/" + themePath+ "/" + "index.js"; | ||
|
||
// Update Preview | ||
var previewHTMLCode = | ||
`<html> | ||
<head> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<meta charset="UTF-8"> | ||
<link rel="stylesheet" href="${themeStylePath}"> | ||
</head> | ||
<body> | ||
${photoCode} | ||
${name} | ||
${description} | ||
<div id="links"> | ||
${links} | ||
${email} | ||
</div> | ||
</body> | ||
<script src="${themeJSPath}"></script> | ||
<script type="module" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ionicons/ionicons.esm.js"></script> | ||
<script nomodule src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ionicons/ionicons.js"></script> | ||
</html>`; | ||
|
||
var blob = new Blob([previewHTMLCode], { type: 'text/html' }); | ||
var url = URL.createObjectURL(blob); | ||
previewBlock.innerHTML = `<object style="width: 100%; height: 100%;" type='text/html' data='${url}'></object>`; | ||
}; | ||
|
||
// Add Listner for all links on file Load | ||
for (var i = 0; i < linkCount; i++) { | ||
var linkId = `links[${i}]`; | ||
document.getElementById(linkId + "[url]").addEventListener('input', UpdatePreview); | ||
document.getElementById(linkId + "[name]").addEventListener('input', UpdatePreview); | ||
document.getElementById(linkId + "[icon]").addEventListener('input', UpdatePreview); | ||
} | ||
|
||
// Add Listner for all forms inputs on file Load | ||
formData['name'].addEventListener('input', UpdatePreview); | ||
formData['url'].addEventListener('input', UpdatePreview); | ||
formData['description'].addEventListener('input', UpdatePreview); | ||
formData['email'].addEventListener('input', UpdatePreview); | ||
theme.addEventListener('input', UpdatePreview); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,7 +43,24 @@ | |
<head> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
|
||
<meta name="description" content="Create your own LinkFree and have all your links in one place"> | ||
<meta name="author" content="Chris K. Thomas"> | ||
<meta name="keywords" content="linkfree, linktree, link in bio, link in bio alternative, linkfree generator, linktree generator, link in bio generator"> | ||
<meta property="og:title" content="LinkFree Generator"> | ||
<meta property="og:description" content="Create your own LinkFree and have all your links in one place"> | ||
<meta property="og:url" content="https://chriskthomas.github.io/linkfree-generator/"> | ||
<meta property="og:image" content="https://lh3.googleusercontent.com/p/AF1QipMjTWdGPL1Ch8Q0poYcH5vhl_tvqF-1o1_4slJD=s680-w680-h510"> | ||
<meta property="og:type" content="website"> | ||
<meta property="og:site_name" content="LinkFree Generator"> | ||
<meta property="og:locale" content="en_US"> | ||
<meta name="twitter:card" content="summary_large_image"> | ||
<meta name="twitter:title" content="LinkFree Generator"> | ||
<meta name="twitter:description" content="Create your own LinkFree and have all your links in one place"> | ||
<meta name="twitter:image" content="https://lh3.googleusercontent.com/p/AF1QipMjTWdGPL1Ch8Q0poYcH5vhl_tvqF-1o1_4slJD=s680-w680-h510"> | ||
|
||
<title>LinkFree Generator</title> | ||
<link rel="stylesheet" href="index.css"> | ||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> | ||
</head> | ||
|
||
|
@@ -53,7 +70,7 @@ | |
<p> | ||
Fill out this form to generate your own single page website. All fields are optional except for your name. So, don't worry if you don't have all these accounts. The output will be a single <code>index.html</code> file that you can upload to any static hosting provider such as GitHub Pages, Cloudflare Pages, Vercel, Netlify, or DigitalOcean Apps. | ||
</p> | ||
<form class="mb-3" action="api.php" method="post" enctype="multipart/form-data" accept-charset="utf-8"> | ||
<form id="form" class="mb-3" action="api.php" method="post" enctype="multipart/form-data" accept-charset="utf-8"> | ||
<div class="mb-3"> | ||
<label for="name" class="form-label">Name</label> | ||
<input type="text" id="name" name="name" class="form-control" placeholder="Chris K. Thomas" required> | ||
|
@@ -102,7 +119,7 @@ | |
</div> | ||
<?php } ?> | ||
<?php if ($num_clinks < 50) { ?> | ||
<a class="btn btn-secondary mb-2" data-index="<?= ($lastsite_index + $num_clinks) ?>" role="button">+ Add Additional Link</a> | ||
<a id="additionalLink" class="btn btn-secondary mb-2" data-index="<?= ($lastsite_index + $num_clinks) ?>" role="button">+ Add Additional Link</a> | ||
<?php } ?> | ||
<div class="mb-3"> | ||
<div class="form-text"> | ||
|
@@ -154,7 +171,11 @@ | |
|
||
</div> | ||
</footer> | ||
|
||
<button id="previewButton"><ion-icon name="eye"></ion-icon></button> | ||
<div id="previewBlock"></div> | ||
<script src="./index.js"></script> | ||
</body> | ||
|
||
<script type="module" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ionicons/ionicons.esm.js"></script> | ||
</body> | ||
</html> |