psy_vk / pages.html
DmitrMakeev's picture
Update pages.html
3f35659 verified
raw
history blame
28.7 kB
<!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 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>
for (n=0; n<100; n++) {
document.write('<script src="https://unpkg.com/grapesjs"></script\>');
document.write('<script src="https://unpkg.com/grapesjs-blocks-basic"></script\>');
document.write(' <script src="https://unpkg.com/grapesjs-component-countdown"></script\>');
// obr.js обрабатывает переменную,
// разные значения которой записаны в файлах 0.js ... 99.js
}
</script>
<script>
for (s=0; s<100; s++) {
document.write('<script src="https://unpkg.com/grapesjs-parser-postcss"></script\>');
document.write('<script src="https://unpkg.com/grapesjs-component-code-editor/dist/grapesjs-component-code-editor.min.css"></script\>');
// obr.js обрабатывает переменную,
// разные значения которой записаны в файлах 0.js ... 99.js
}
</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>
<!-- The Modal -->
<div id="myModal_1" class="modal_1">
<!-- Модальное содержание -->
<div class="modal-content_1">
<div class="modal-header_1">
<span class="close_1">&times;</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>
// Инициализация GrapesJS редактора
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
}
},
"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-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": {
// Настройки для grapesjs-user-blocks
}
},
});
// Добавление русского языка
editor.I18n.addMessages({
ru: {
styleManager: {
sectors: {
'general': 'Общие',
'dimension': 'Размер',
'typography': 'Типографика',
'decorations': 'Оформление',
'extra': 'Ещё больше',
'flex': 'Flex',
},
properties: {
'background-repeat': 'Повторение',
'background-position': 'Позиция',
'width': 'Ширина',
'height': 'Высота',
'max-width': 'Макс. ширина',
'min-height': 'Мин. высота',
'margin': 'Отступ',
'padding': 'Внутр.отступ',
'font-family': 'Шрифт',
'font-size': 'Размер шрифта',
'font-weight': 'Толщина шрифта',
'color': 'Цвет текста',
'text-align': 'Вырав. текста',
'text-decoration': 'Оформ. текста',
'text-shadow': 'Текст. тень',
'opacity': 'Прозрачность',
'border-radius': 'Радиус скруг.',
'border': 'Граница',
'box-shadow': 'Тень блока',
'background': 'Фон',
}
},
blockManager: {
labels: {
'responsive-image': 'Адаптивное изображение',
'centered-text': 'Центрированный текст',
}
},
panels: {
buttons: {
'open-code': 'Открыть код',
'gjs-open-import-webpage': 'Импортировать',
}
},
commands: {
'gjs-open-import-webpage': {
title: 'Импортировать шаблон',
label: '<div style="margin-bottom: 10px; font-size: 13px;">Вставьте здесь ваш HTML/CSS и нажмите Импортировать</div>',
}
}
}
});
// Установка русского языка по умолчанию
editor.I18n.setLocale('ru');
// Удаление ненужных блоков
const unwantedBlocks = ['video', 'link', 'image'];
unwantedBlocks.forEach(blockId => {
editor.BlockManager.remove(blockId);
});
// Добавление блока адаптивной картинки
editor.BlockManager.add('responsive-image', {
label: editor.I18n.t('blockManager.labels.responsive-image'),
content: {
type: 'image',
style: {
display: 'block',
margin: 'auto',
maxWidth: '100%',
height: 'auto',
objectFit: 'cover'
},
attributes: {
alt: 'Responsive Image'
}
},
attributes: {
class: 'fa fa-image'
}
});
// Добавление блока центрированного текста
editor.BlockManager.add('centered-text', {
label: editor.I18n.t('blockManager.labels.centered-text'),
content: {
type: 'text',
style: {
textAlign: 'center'
},
content: 'Centered Text'
},
attributes: {
class: 'fa fa-align-center'
}
});
</script>
<script>
// Создаем блок формы
editor.Blocks.add('custom-form', {
label: 'Custom Form',
content: `
<div class="form-container container">
<form id="contactForm">
<div class="form-group title-field">
<h4>КЛУБ-ПРАКТИК. 255 техник для психолога - 2024</h4>
</div>
<div class="form-group name-field">
<label for="name">Имя</label>
<input type="text" id="name" required>
</div>
<div class="form-group email-field">
<label for="email">Почта</label>
<input type="email" id="email" required>
</div>
<div class="form-group phone-field">
<label for="phone">Телефон</label>
<input type="tel" id="phone" required>
</div>
<div class="form-group options-field">
<label for="options">Выберите тариф</label>
<select id="options" required>
<option value="" disabled selected>Тариф</option>
<option>БИЗНЕС - 69 970р.</option>
<option>PREMIUM - 89 970р.</option>
<option>VIP - 149 990р.</option>
</select>
</div>
<div class="form-check newsletter-field">
<input type="checkbox" id="newsletter" required>
<label for="newsletter">Согласие на email рассылку</label>
</div>
<div class="form-group privacy-policy-link">
<a href="#" id="privacyPolicyLink">Политика конфиденциальности</a>
</div>
<div class="form-group submit-button">
<button type="submit" class="btn-primary">ПЕРЕЙТИ К ОПЛАТЕ</button>
</div>
</form>
</div>
`,
});
// Добавляем возможность настройки каждого элемента формы
editor.DomComponents.addType('form-input', {
model: {
defaults: {
script: function() {
console.log('Form input initialized with placeholder: ', this.getAttribute('placeholder'));
},
traits: [
{
type: 'text',
name: 'id',
label: 'Id',
changeProp: true,
},
{
type: 'text',
name: 'placeholder',
label: 'Placeholder',
changeProp: true,
},
{
type: 'checkbox',
name: 'required',
label: 'Required',
changeProp: true,
},
{
type: 'text',
name: 'class',
label: 'CSS Class',
changeProp: true,
},
],
},
'script-props': ['id', 'placeholder', 'required', 'class'],
},
});
editor.DomComponents.addType('form-select', {
model: {
defaults: {
script: function() {
console.log('Form select initialized with options: ', this.options);
},
traits: [
{
type: 'text',
name: 'id',
label: 'Id',
changeProp: true,
},
{
type: 'text',
name: 'options',
label: 'Options',
changeProp: true,
},
{
type: 'checkbox',
name: 'required',
label: 'Required',
changeProp: true,
},
{
type: 'text',
name: 'class',
label: 'CSS Class',
changeProp: true,
},
],
},
'script-props': ['id', 'options', 'required', 'class'],
},
});
editor.DomComponents.addType('form-checkbox', {
model: {
defaults: {
script: function() {
console.log('Form checkbox initialized. Required: ', this.getAttribute('required'));
},
traits: [
{
type: 'text',
name: 'id',
label: 'Id',
changeProp: true,
},
{
type: 'checkbox',
name: 'required',
label: 'Required',
changeProp: true,
},
{
type: 'text',
name: 'class',
label: 'CSS Class',
changeProp: true,
},
],
},
'script-props': ['id', 'required', 'class'],
},
});
editor.DomComponents.addType('form-button', {
model: {
defaults: {
script: function(props) {
console.log('Form button initialized with text: ', props.text);
console.log('AVP: ', props.avp);
console.log('GRUPS: ', props.grups);
console.log('REDIRECT: ', props.redirect);
// Пример использования переменной redirect для перенаправления пользователя при отправке формы
this.addEventListener('click', function(event) {
event.preventDefault();
if (props.redirect) {
window.location.href = props.redirect;
}
});
},
traits: [
{
type: 'text',
name: 'id',
label: 'Id',
changeProp: true,
},
{
type: 'text',
name: 'text',
label: 'Button Text',
changeProp: true,
},
{
type: 'text',
name: 'avp',
label: 'AVP',
changeProp: true,
},
{
type: 'text',
name: 'grups',
label: 'GRUPS',
changeProp: true,
},
{
type: 'text',
name: 'redirect',
label: 'Redirect',
changeProp: true,
},
{
type: 'text',
name: 'class',
label: 'CSS Class',
changeProp: true,
},
],
},
'script-props': ['id', 'text', 'avp', 'grups', 'redirect', 'class'],
},
});
// Добавляем возможность настройки ссылки "Политика конфиденциальности"
editor.DomComponents.addType('privacy-policy-link', {
model: {
defaults: {
script: function(props) {
const link = this;
link.href = props.href || '#';
link.target = props.newWindow ? '_blank' : '_self';
console.log('Privacy policy link initialized with href: ', props.href);
},
traits: [
{
type: 'text',
name: 'id',
label: 'Id',
changeProp: true,
},
{
type: 'text',
name: 'href',
label: 'Link URL',
changeProp: true,
},
{
type: 'checkbox',
name: 'newWindow',
label: 'Open in new window',
changeProp: true,
},
{
type: 'text',
name: 'class',
label: 'CSS Class',
changeProp: true,
},
],
},
'script-props': ['id', 'href', 'newWindow', 'class'],
},
});
// Добавление кнопки для открытия редактора кода
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",
},
]);
// Добавление команды для импорта HTML и CSS
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>
// Get the modal
var modal_1 = document.getElementById("myModal_1");
// Get the button that opens the modal
var btn_1 = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span_1 = document.getElementsByClassName("close_1")[0];
// When the user clicks the button, open the modal
btn_1.onclick = function() {
modal_1.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span_1.onclick = function() {
modal_1.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
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('Тестовая кнопка работает!');
// Получаем HTML-код из GrapesJS
const editor = grapesjs.editors[0]; // Предполагается, что у вас есть только один редактор
const htmlContent = editor.getHtml();
const cssContent = editor.getCss();
// Генерация HTML-контента
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>