|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>File Upload</title> |
|
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css"> |
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script> |
|
|
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> |
|
<script src="https://unpkg.com/@vkontakte/vk-bridge/dist/browser.min.js"></script> |
|
<script type="text/javascript" src="https://vk.com/js/api/openapi.js?169"></script> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
<title>GrapesJS Project</title> |
|
<link href="https://unpkg.com/grapesjs/dist/css/grapes.min.css" rel="stylesheet" /> |
|
<link href="index.css" rel="stylesheet" /> |
|
|
|
|
|
<script src="https://unpkg.com/grapesjs"></script> |
|
|
|
<script src="https://unpkg.com/grapesjs-blocks-basic"></script> |
|
<script src="https://unpkg.com/grapesjs-component-countdown"></script> |
|
<script src="https://unpkg.com/grapesjs-parser-postcss"></script> |
|
<script src="https://unpkg.com/grapesjs-component-code-editor/dist/grapesjs-component-code-editor.min.css"></script> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script src="https://unpkg.com/grapesjs-component-code-editor"></script> |
|
<script src="https://unpkg.com/grapesjs-templates"></script> |
|
<link href="https://unpkg.com/grapesjs-rte-extensions/dist/grapesjs-rte-extensions.min.css" rel="stylesheet" /> |
|
<script src="https://unpkg.com/grapesjs-rte-extensions"></script> |
|
<script src="https://unpkg.com/grapesjs-user-blocks"></script> |
|
|
|
|
|
|
|
|
|
|
|
<style> |
|
h1 { |
|
background-color: #4CAF50; |
|
color: white; |
|
padding: 20px; |
|
margin: 0; |
|
border-bottom: 2px solid #388E3C; |
|
} |
|
button[type="submit"] { |
|
color: white; |
|
background-color: #4CAF50; |
|
border: none; |
|
cursor: pointer; |
|
padding: 10px 20px; |
|
font-size: 16px; |
|
border-radius: 5px; |
|
margin-top: 20px; |
|
} |
|
button[type="submit"]:hover { |
|
background-color: #388E3C; |
|
} |
|
#imageUrl { |
|
margin-top: 20px; |
|
font-size: 16px; |
|
color: #333; |
|
cursor: pointer; |
|
text-decoration: underline; |
|
} |
|
#progressBarContainer { |
|
width: 80%; |
|
margin: 20px auto; |
|
background-color: #ddd; |
|
border-radius: 13px; |
|
padding: 3px; |
|
} |
|
#progressBar { |
|
width: 0%; |
|
height: 20px; |
|
background-color: #4CAF50; |
|
border-radius: 10px; |
|
text-align: center; |
|
line-height: 20px; |
|
color: white; |
|
} |
|
</style> |
|
|
|
|
|
|
|
<style> |
|
body { |
|
background-color: green; |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
color: #ffffff; |
|
height: 100vh; |
|
} |
|
#floating-element nav ul li a { |
|
color: #fff; |
|
} |
|
.responsive-image-container { |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
width: 100%; |
|
height: auto; |
|
} |
|
.responsive-image { |
|
max-width: 100%; |
|
height: auto; |
|
object-fit: cover; |
|
} |
|
.centered-text { |
|
text-align: center; |
|
} |
|
.gjs-one-bg { |
|
background-color: green !important; |
|
} |
|
.countdown-timer { |
|
text-align: center; |
|
font-size: 24px; |
|
color: #333; |
|
} |
|
@media (max-width: 768px) { |
|
.responsive-image-container { |
|
flex-direction: column; |
|
} |
|
.responsive-image { |
|
width: 100%; |
|
margin-bottom: 20px; |
|
} |
|
} |
|
|
|
.modal_1 { |
|
display: none; |
|
position: fixed; |
|
z-index: 10; |
|
padding-top: 100px; |
|
left: 0; |
|
top: 0; |
|
width: 100%; |
|
height: 100%; |
|
overflow: auto; |
|
background-color: rgb(0,0,0); |
|
background-color: rgba(0,0,0,0.4); |
|
} |
|
|
|
.modal-content_1 { |
|
position: relative; |
|
background-color: #fefefe; |
|
margin: auto; |
|
padding: 0; |
|
border: 1px solid #888; |
|
width: 60%; |
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); |
|
-webkit-animation-name: animatetop_1; |
|
-webkit-animation-duration: 0.4s; |
|
animation-name: animatetop_1; |
|
animation-duration: 0.4s |
|
} |
|
|
|
@-webkit-keyframes animatetop_1 { |
|
from {top:-300px; opacity:0} |
|
to {top:0; opacity:1} |
|
} |
|
@keyframes animatetop_1 { |
|
from {top:-300px; opacity:0} |
|
to {top:0; opacity:1} |
|
} |
|
|
|
.close_1 { |
|
color: white; |
|
float: right; |
|
font-size: 28px; |
|
font-weight: bold; |
|
} |
|
.close_1:hover, |
|
.close_1:focus { |
|
color: #000; |
|
text-decoration: none; |
|
cursor: pointer; |
|
} |
|
.modal-header_1 { |
|
padding: 2px 16px; |
|
background-color: green; |
|
color: white; |
|
} |
|
.modal-body_1 {padding: 2px 16px;} |
|
.modal-footer_1 { |
|
padding: 2px 16px; |
|
background-color: green; |
|
color: white; |
|
} |
|
#gjs { |
|
position: absolute; |
|
left: 0; |
|
transition: left 0.3s ease; |
|
} |
|
#toggleAppBtn { |
|
z-index: 1000; |
|
} |
|
</style> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</head> |
|
<body> |
|
<script> |
|
vkBridge.send('VKWebAppInit'); |
|
</script> |
|
|
|
|
|
|
|
|
|
<button id="toggleAppBtn" style="position: absolute; top: 10px; left: 10px;">Показать/Скрыть приложение</button> |
|
|
|
<button id="myBtn" style="position: absolute; top: 30px; right: 10px;">Открыть модальное</button> |
|
|
|
<button id="testBtn" style="position: absolute; top: 70px; right: 32px;">Тестовая кнопка</button> |
|
<div id="gjs" style="height: 90vh;"></div> |
|
|
|
<div id="myModal_1" class="modal_1"> |
|
|
|
<div class="modal-content_1"> |
|
<div class="modal-header_1"> |
|
<span class="close_1">×</span> |
|
<h2>HTMLешка</h2> |
|
</div> |
|
<div class="modal-body_1"> |
|
<p>Некоторый текст в модальном теле</p> |
|
|
|
|
|
<div id="progressBarContainer"> |
|
<div id="progressBar">0%</div> |
|
</div> |
|
<div id="imageUrl" onclick="copyToClipboard(this)">Кликните после загрузки, для получения ссылки на страницу.</div> |
|
<form id="uploadForm" enctype="multipart/form-data" method="post" action="/up_page"> |
|
<input type="file" name="file" accept=".html"> |
|
<input type="text" name="filename" placeholder="имя файла(маршрут)"> |
|
<button type="submit">Загрузить</button> |
|
</form> |
|
|
|
|
|
<br><br><br> |
|
</div> |
|
<div class="modal-footer_1"> |
|
<h3>Добавление HTML файла с пользовательским маршрутом.</h3> |
|
</div> |
|
</div> |
|
</div> |
|
<script> |
|
|
|
const editor = grapesjs.init({ |
|
container: "#gjs", |
|
fromElement: true, |
|
height: "100vh", |
|
storageManager: { |
|
type: 'local', |
|
autosave: true, |
|
autoload: true, |
|
stepsBeforeSave: 1, |
|
}, |
|
plugins: [ |
|
"gjs-blocks-basic", |
|
"grapesjs-component-countdown", |
|
"grapesjs-component-code-editor", |
|
"grapesjs-templates", |
|
"grapesjs-rte-extensions", |
|
"grapesjs-user-blocks" |
|
], |
|
pluginsOpts: { |
|
"gjs-blocks-basic": { |
|
blocks: ['column1', 'column2', 'column3', 'column3-7', 'text', 'quote', 'social'], |
|
blocksBasicOpts: { |
|
flexGrid: true, |
|
stylePrefix: 'gjs-', |
|
columns: 12, |
|
rowHeight: 75, |
|
addBasicStyle: true |
|
} |
|
}, |
|
"grapesjs-component-code-editor": { |
|
panelId: 'views-container', |
|
appendTo: '.gjs-pn-views-container', |
|
openState: { pn: '35%', cv: '65%' }, |
|
closedState: { pn: '15%', cv: '85%' }, |
|
codeViewOptions: {}, |
|
preserveWidth: false, |
|
clearData: false, |
|
editJs: true, |
|
cleanCssBtn: true, |
|
htmlBtnText: 'Применить', |
|
cssBtnText: 'Применить', |
|
cleanCssBtnText: 'Удалить' |
|
}, |
|
"grapesjs-templates": { |
|
|
|
}, |
|
"grapesjs-rte-extensions": { |
|
base: { |
|
bold: true, |
|
italic: true, |
|
underline: true, |
|
strikethrough: true, |
|
link: true, |
|
}, |
|
fonts: { |
|
fontColor: true, |
|
hilite: true, |
|
}, |
|
format: { |
|
heading1: true, |
|
heading2: true, |
|
heading3: true, |
|
paragraph: true, |
|
clearFormatting: true, |
|
}, |
|
align: true, |
|
darkColorPicker: true, |
|
maxWidth: '600px' |
|
}, |
|
"grapesjs-user-blocks": { |
|
|
|
} |
|
}, |
|
}); |
|
|
|
</script> |
|
|
|
|
|
<script type="text/javascript" src="https://huggingface.co/spaces/DMTuit/psy_vk/resolve/main/js/rus/rus.js"></script> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script> |
|
|
|
editor.BlockManager.add('custom-player', { |
|
label: 'Custom Player', |
|
content: `<div id="player" style="width: 480px; height: 270px; border: 3px solid black; margin: auto; position: fixed; top: 0; left: 0; right: 0;"></div>`, |
|
attributes: { |
|
class: 'fa fa-play' |
|
} |
|
}); |
|
|
|
editor.CssComposer.addRules(` |
|
#player { |
|
width: 480px; |
|
height: 270px; |
|
border: 3px solid black; |
|
margin: 0 auto; |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
right: 0; |
|
display: block; |
|
} |
|
`); |
|
|
|
|
|
|
|
|
|
|
|
|
|
</script> |
|
|
|
<script> |
|
|
|
|
|
|
|
editor.BlockManager.add('custom-iframe', { |
|
label: 'Custom Iframe', |
|
content: `<iframe id="custom-iframe" frameborder="0" width="480" height="405" src="https://rutube.ru/play/embed/538dc9cc0b952dd52f47e28df7df5e81/" allow="clipboard-write; autoplay" webkitallowfullscreen mozallowfullscreen allowfullscreen style="position: relative; top: 0; margin: 0 auto; display: block;"></iframe>`, |
|
attributes: { |
|
class: 'fa fa-video-camera' |
|
} |
|
}); |
|
editor.CssComposer.addRules(` |
|
#custom-iframe { |
|
width: 480px; |
|
height: 405px; |
|
border: none; |
|
margin: 0 auto; |
|
position: relative; |
|
top: 0; |
|
display: block; |
|
} |
|
`); |
|
|
|
|
|
|
|
|
|
</script> |
|
|
|
<script> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const pn = editor.Panels; |
|
const panelViews = pn.addPanel({ |
|
id: "views", |
|
}); |
|
panelViews.get("buttons").add([ |
|
{ |
|
attributes: { |
|
title: editor.I18n.t('panels.buttons.open-code'), |
|
}, |
|
className: "fa fa-file-code-o", |
|
command: "open-code", |
|
editJs: true, |
|
togglable: false, |
|
id: "open-code", |
|
}, |
|
]); |
|
|
|
editor.Commands.add('gjs-open-import-webpage', { |
|
run(editor, sender) { |
|
sender && sender.set('active', 0); |
|
const modal = editor.Modal; |
|
const container = document.createElement('div'); |
|
const importLabel = document.createElement('div'); |
|
importLabel.innerHTML = editor.I18n.t('commands.gjs-open-import-webpage.label'); |
|
const importInput = document.createElement('textarea'); |
|
importInput.style.width = '100%'; |
|
importInput.style.height = '200px'; |
|
importInput.placeholder = 'HTML/CSS code...'; |
|
const importButton = document.createElement('button'); |
|
importButton.innerHTML = editor.I18n.t('panels.buttons.gjs-open-import-webpage'); |
|
importButton.onclick = () => { |
|
const code = importInput.value; |
|
try { |
|
const parser = new DOMParser(); |
|
const doc = parser.parseFromString(code, 'text/html'); |
|
const html = doc.body.innerHTML; |
|
const css = Array.from(doc.querySelectorAll('style')).map(style => style.innerHTML).join('\n'); |
|
if (html) { |
|
editor.setComponents(html); |
|
editor.setStyle(css); |
|
modal.close(); |
|
} |
|
} catch (error) { |
|
console.error('Error parsing HTML/CSS:', error); |
|
} |
|
}; |
|
container.appendChild(importLabel); |
|
container.appendChild(importInput); |
|
container.appendChild(importButton); |
|
modal.setTitle(editor.I18n.t('commands.gjs-open-import-webpage.title')); |
|
modal.setContent(container); |
|
modal.open(); |
|
} |
|
}); |
|
|
|
pn.addButton('options', { |
|
id: 'gjs-open-import-webpage', |
|
className: 'fa fa-download', |
|
command: 'gjs-open-import-webpage', |
|
attributes: { |
|
title: editor.I18n.t('panels.buttons.gjs-open-import-webpage'), |
|
'data-tooltip-pos': 'bottom', |
|
}, |
|
}); |
|
|
|
pn.addButton('options', { |
|
id: 'undo', |
|
className: 'fa fa-undo', |
|
command: function() { editor.runCommand('core:undo') }, |
|
attributes: { |
|
title: 'Undo', |
|
'data-tooltip-pos': 'bottom', |
|
}, |
|
}); |
|
pn.addButton('options', { |
|
id: 'redo', |
|
className: 'fa fa-repeat', |
|
command: function() { editor.runCommand('core:redo') }, |
|
attributes: { |
|
title: 'Redo', |
|
'data-tooltip-pos': 'bottom', |
|
}, |
|
}); |
|
|
|
pn.addButton('options', { |
|
id: 'clear-canvas', |
|
className: 'fa fa-trash', |
|
command: 'core:canvas-clear', |
|
attributes: { |
|
title: 'Очистить холст', |
|
'data-tooltip-pos': 'bottom', |
|
}, |
|
}); |
|
</script> |
|
|
|
<script> |
|
|
|
var modal_1 = document.getElementById("myModal_1"); |
|
|
|
|
|
var btn_1 = document.getElementById("myBtn"); |
|
|
|
|
|
var span_1 = document.getElementsByClassName("close_1")[0]; |
|
|
|
|
|
btn_1.onclick = function() { |
|
modal_1.style.display = "block"; |
|
} |
|
|
|
|
|
span_1.onclick = function() { |
|
modal_1.style.display = "none"; |
|
} |
|
|
|
|
|
window.onclick = function(event) { |
|
if (event.target == modal_1) { |
|
modal_1.style.display = "none"; |
|
} |
|
} |
|
</script> |
|
|
|
<script> |
|
document.addEventListener('DOMContentLoaded', () => { |
|
console.log('DOMContentLoaded выполнен'); |
|
|
|
|
|
document.getElementById('testBtn').addEventListener('click', function() { |
|
console.log('Тестовая кнопка работает!'); |
|
|
|
|
|
const editor = grapesjs.editors[0]; |
|
const htmlContent = editor.getHtml(); |
|
const cssContent = editor.getCss(); |
|
|
|
|
|
const fullHtmlContent = ` |
|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Скачанная HTML-страница</title> |
|
<style>${cssContent}</style> |
|
</head> |
|
<body> |
|
${htmlContent} |
|
</body> |
|
</html> |
|
`; |
|
|
|
|
|
const blob = new Blob([fullHtmlContent], { type: 'text/html' }); |
|
const link = document.createElement('a'); |
|
link.href = URL.createObjectURL(blob); |
|
link.download = 'downloaded_page.html'; |
|
document.body.appendChild(link); |
|
link.click(); |
|
document.body.removeChild(link); |
|
}); |
|
}); |
|
</script> |
|
|
|
<script> |
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
|
document.getElementById('toggleAppBtn').addEventListener('click', function() { |
|
const app = document.getElementById('gjs'); |
|
if (app.style.left === '0px' || app.style.left === '') { |
|
app.style.left = '-15%'; |
|
} else { |
|
app.style.left = '0'; |
|
} |
|
}); |
|
}); |
|
</script> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script> |
|
document.getElementById('uploadForm').addEventListener('submit', function(event) { |
|
event.preventDefault(); |
|
var formData = new FormData(this); |
|
var request = new XMLHttpRequest(); |
|
request.open('POST', '/up_page'); |
|
request.upload.addEventListener('progress', function(event) { |
|
if (event.lengthComputable) { |
|
var percentComplete = (event.loaded / event.total) * 100; |
|
document.getElementById('progressBar').style.width = percentComplete + '%'; |
|
document.getElementById('progressBar').innerText = Math.round(percentComplete) + '%'; |
|
} |
|
}, false); |
|
request.addEventListener('load', function(event) { |
|
var response = event.target.responseText; |
|
if (event.target.status === 200) { |
|
var fullUrl = response.split('saved to ')[1]; |
|
document.getElementById('imageUrl').innerText = 'Click to copy URL'; |
|
document.getElementById('imageUrl').setAttribute('data-url', fullUrl); |
|
Toastify({ |
|
text: "File uploaded successfully", |
|
duration: 3000, |
|
gravity: "top", |
|
position: "center", |
|
backgroundColor: "#4CAF50", |
|
}).showToast(); |
|
} else if (event.target.status === 409) { |
|
Toastify({ |
|
text: "File with this name already exists", |
|
duration: 3000, |
|
gravity: "top", |
|
position: "center", |
|
backgroundColor: "#FF5733", |
|
}).showToast(); |
|
} |
|
document.getElementById('progressBar').style.width = '0%'; |
|
document.getElementById('progressBar').innerText = '0%'; |
|
}, false); |
|
request.send(formData); |
|
}); |
|
|
|
function copyToClipboard(element) { |
|
var tempInput = document.createElement("input"); |
|
tempInput.value = element.getAttribute('data-url'); |
|
document.body.appendChild(tempInput); |
|
tempInput.select(); |
|
document.execCommand("copy"); |
|
document.body.removeChild(tempInput); |
|
Toastify({ |
|
text: "URL copied to clipboard", |
|
duration: 3000, |
|
gravity: "top", |
|
position: "center", |
|
backgroundColor: "#4CAF50", |
|
}).showToast(); |
|
} |
|
</script> |
|
</body> |
|
</html> |