Initial commit

This commit is contained in:
2025-07-27 18:47:50 +03:00
parent ae1ed5b41b
commit d127006d9d
196 changed files with 72333 additions and 0 deletions

90
main_plugin/auth/auth.css Normal file
View File

@@ -0,0 +1,90 @@
/* авторизация */
#authorizationButton {
width: 26px;
height: 26px;
position: relative;
cursor: pointer;
user-select: none;
float: right;
margin-left: 5px;
}
#authorizationButton:hover {
background-image: url(../../img/pict/g_iconslyb.svg);
}
#loginButton {
margin: 0px 3px;
}
/* окно авторизации */
#authorizationDiv {
font-size: 0.85em;
display: inline-block;
position: fixed;
user-select: none;
background-color: rgba(255, 255, 255, 0.92);
width: 370px;
border-radius: 5px;
height: 230px;
box-shadow: 0px 0px 5px #777;
color: #000000;
text-shadow: none;
z-index: 100;
min-height: fit-content;
}
#authorizationDiv input, #authorizationDiv textarea, #authorizationDiv select, #authorizationDiv button {
font-size: 0.85em;
}
.authorizationDivTop {
text-align: center;
border: none;
border-bottom: inherit;
padding: 5px;
background-color: rgba(255, 255, 255, 0.6);
}
.authorizationDivCloseFun {
background-image: url(../../img/pict/b_iconslyb.svg);
float: right;
width: 22px;
height: 22px;
background-position: -159px -120px;
cursor: pointer;
}
.authorizationDivMainDiv {
display: flex;
align-items: center;
height: 200px;
justify-content: center;
flex-direction: column;
padding: 10px 0px;
}
.formRow {
display: flex;
justify-content: center;
width: -webkit-fill-available;
margin: 5px 45px;
}
.formRow label {
margin-right: 10px;
white-space: nowrap;
}
.formRow input {
flex: 1;
min-width: 0;
}
#BackArrow {
background-position: -77px -37px;
background-image: url(../../img/pict/b_iconslyb.svg);
width: 26px;
height: 26px;
position: absolute;
left: 0px;
top: 33px;
}
#BackArrow:hover {
background-image: url(../../img/pict/g_iconslyb.svg);
cursor: pointer;
}

131
main_plugin/auth/auth.js Normal file
View File

@@ -0,0 +1,131 @@
addEventListener("load", function() {
movementMenu("authorizationDiv");
/* создание кнопки авторизации */
authorizationButtonId = document.getElementById("authorizationButton");
handleJsonRpcRequest('authorizationInformation', {}, 1).then(data => {
authorizationDivId = document.getElementById("authorizationDiv");
if (data.login == "true") {
authorizationButtonId.style.background = "url(../../img/pict/mc_iconslyb.svg) -1038px 1px";
document.documentElement.style.setProperty('--autButBackX', '-1038');
document.documentElement.style.setProperty('--autButBackY', '1');
authorizationButtonId.onclick = function() {
createAjaxRequest({ handleRequestAction: 'API', logoff: 'Выйти' }, function(response) {
location.reload();
});
};
} else if (data.login == "false") {
authorizationButtonId.style.background = "url(../../img/pict/mc_iconslyb.svg) -756px 1px";
document.documentElement.style.setProperty('--autButBackX', '-756');
document.documentElement.style.setProperty('--autButBackY', '1');
authorizationButtonId.onclick = function() {
const el = authorizationDivId;
if (el.style.visibility === "visible") {
el.style.visibility = "hidden";
} else {
el.style.visibility = "visible";
el.style.top = "20%";
el.style.left = "50%";
el.style.transform = "translate(-50%, -20%)";
}
};
}
});
});
function authorizationDivCloseFun() {
document.getElementById("authorizationDiv").style.visibility = "hidden";
}
function loginButtonFunCreate() {
document.querySelector(".authorizationDivMainDiv").innerHTML = `
<div id="BackArrow" onClick="mainButtonFunCreate()"></div>
<div class="formRow">
<label>{{login_label}}:</label>
<input type="text" id="loginInput" name="login">
</div>
<div class="formRow">
<label>{{password_label}}:</label>
<input type="password" id="passInput" name="pass" autocomplete="">
</div>
<div class="formRow">
<button type="button" id="loginButton" onClick="loginButtonFun()">{{login}}</button>
</div>
`;
}
function loginButtonFun() {
var login = document.getElementById("loginInput").value;
var pass = document.getElementById("passInput").value;
createAjaxRequest({ handleRequestAction: 'API', login: login, pass: pass, log: "Войти" }, function(response) {
if (response.status == "true") {
handleJsonRpcRequest('authorizationInformation', {}, 1).then(data => {
location.reload();
});
} else {
messageFunction("{{incorrect_login_password}}");
}
});
}
function registrationButtonFunCreate() {
document.querySelector(".authorizationDivMainDiv").innerHTML = `
<div id="BackArrow" onClick="mainButtonFunCreate()"></div>
<div class="formRow">
<label>{{login_label}}:</label>
<input type="text" id="loginInput" name="login">
</div>
<div class="formRow">
<label>{{password_label}}:</label>
<input type="text" id="passInput" name="pass">
</div>
<div class="formRow">
<label>{{repeat_password_label}}:</label>
<input type="text" id="passСheckInput" name="pass">
</div>
<div class="formRow">
<label>{{email_label}}:</label>
<input id="emailInput">
</div>
<div class="formRow">
<button type="button" id="loginButton" onClick="registrationButtonFun()">{{register}}</button>
</div>
`;
}
function registrationButtonFun() {
var login = document.getElementById("loginInput").value;
var pass = document.getElementById("passInput").value;
var passСheck = document.getElementById("passСheckInput").value;
var email = document.getElementById("emailInput").value;
if (login.trim() == "" || pass.trim() == "" || passСheck.trim() == "" || email.trim() == "" ) {
messageFunction("{{fill_all_fields}}");
return;
}
if (pass != passСheck) {
messageFunction("{{passwords_do_not_match}}");
return;
}
handleJsonRpcRequest('registrationRequest', { login, pass, email }, 1).then(response => {
if (response.status == true) {
messageFunction("{{account_creation_request_sent}}");
} else if (response.status == "name coincidence") {
messageFunction("{{user_exists}}");
} else if (response.status == "error while creating") {
messageFunction("{{account_creation_error}}");
} else if (response.status == "incorrect mail") {
messageFunction("{{incorrect_email}}");
} else {
messageFunction("{{account_creation_request_error}}");
}
});
}
function mainButtonFunCreate() {
document.querySelector(".authorizationDivMainDiv").innerHTML = `
<div class="formRow">{{account_authorization}}</div>
<div class="formRow">
<button type="button" id="loginButton" onClick="loginButtonFunCreate()">{{login}}</button>
<button type="button" id="loginButton" onClick="registrationButtonFunCreate()">{{register}}</button>
</div>
`;
}

33
main_plugin/auth/auth.php Normal file
View File

@@ -0,0 +1,33 @@
<span id="authorizationButton"></span>
<div id="authorizationDiv" class="borderStyle" style="visibility: hidden; top: 20%; left: 50%; transform: translate(-50%, -20%);">
<div class="authorizationDivTop" class="borderStyle">
<span class="authorizationDivTopTitle">{{authorization}}</span>
<span class="authorizationDivCloseFun" onClick="authorizationDivCloseFun()" class="editib"></span>
</div>
<div class="authorizationDivMainDiv">
<div class="formRow">{{account_authorization}}</div>
<div class="formRow">
<button type="button" id="loginButton" onClick="loginButtonFunCreate()">{{login}}</button>
<button type="button" id="loginButton" onClick="registrationButtonFunCreate()">{{register}}</button>
</div>
</div>
</div>
<script>
window.addEventListener("load", function() {
try {
var buttonHTML = document.getElementById("authorizationButton").outerHTML;
var divHTML = document.getElementById("authorizationDiv").outerHTML;
document.getElementById("authorizationButton").remove();
document.getElementById("authorizationDiv").remove();
var container = document.getElementById("hbody");
if (!container) throw new Error("#hbody не найден для authorization");
container.insertAdjacentHTML("beforeend", buttonHTML);
container.insertAdjacentHTML("beforeend", divHTML);
} catch (e) {
console.error("Ошибка в блоке authorization:", e);
}
});
</script>

View File

@@ -0,0 +1,81 @@
<?php
/* информация об переменах */
function authorizationInformation() {
global $_SESSION;
return ['login' => $_SESSION['Login'] == 'true' ? 'true' : 'false'];
}
function registrationRequest() {
global $path, $config;
$exists = false;
$requestFile = simplexml_load_file($path . $config['usersRequest']);
foreach ($requestFile->users->user as $child) {
if ((string)$child['name'] === $_POST['login']) {
$exists = true;
break;
}
}
$usersFile = simplexml_load_file($path . $config['users']);
foreach ($usersFile->users->user as $child) {
if ((string)$child['name'] === $_POST['login']) {
$exists = true;
break;
}
}
$email = $_POST['email'];
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return ['status' => 'incorrect mail'];
}
$domain = substr(strrchr($email, "@"), 1);
if (!checkdnsrr($domain, "MX")) {
return ['status' => 'incorrect mail'];
}
if ($exists) {
return ['status' => 'name coincidence'];
}
$requestFile = simplexml_load_file($path . $config['usersRequest']);
$requestFilePath = $path . $config['usersRequest'];
$newUser = $requestFile->users->addChild('user');
$newUser->addAttribute('name', $_POST['login']);
$newUser->addAttribute('pass', $_POST['pass']);
$newUser->addAttribute('access', '');
$newUser->addAttribute('email', $_POST['email']);
$newUser->addAttribute('link', md5($_POST['login'].$_POST['pass']));
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($requestFile->asXML());
if ($dom->save($requestFilePath)) {
return registrationRequestMail();
} else {
return ['status' => 'error while creating'];
}
}
function registrationRequestMail() {
global $config;
$to = $config['emailAdmin'];
$subject = '=?UTF-8?B?'.base64_encode('Запрос на создание аккаунта на сайте ').'?='. $_SERVER['HTTP_HOST'];
$message = 'Логин: ' . $_POST['login'] . "\r\n";
$message .= 'Пароль: ' . $_POST['pass'] . "\r\n";
$message .= 'Почта: ' . $_POST['email'] . "\r\n";
$message .= 'Сайт: ' . $config['server'] . "\r\n";
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=UTF-8\r\n";
$headers .= "From: info@oblat.lv";
if (mail($to, $subject, $message, $headers)) {
return ['status' => true];
} else {
return ['status' => false, 'error' => 'Ошибка при отправке письма.'];
}
}
?>

View File

@@ -0,0 +1,8 @@
<?php
$lang = include $path . 'lang.php';
$lng = $_GET['lng'] ?? ($_SESSION['lng'] ?? 'en');
$placeholders = [];
foreach ($lang[$lng] as $key => $value) {
$placeholders['{{' . $key . '}}'] = $value;
}
echo strtr(file_get_contents($path . 'auth.js'), $placeholders);

61
main_plugin/auth/lang.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
$lang = [
'ru' => [
'authorization' => 'Авторизация',
'login_label' => 'Логин',
'password_label' => 'Пароль',
'incorrect_login_password' => 'Неверный логин или пароль!',
'repeat_password_label' => 'Повторите пароль',
'email_label' => 'Почта',
'fill_all_fields' => 'Вы должны заполнить все поля!',
'passwords_do_not_match' => 'Пароли не совпадают!',
'account_creation_request_sent' => 'Запрос на создание аккаунта отправлен!',
'user_exists' => 'Пользователь с таким логином уже существует!',
'account_creation_error' => 'Ошибка при создании аккаунта!',
'incorrect_email' => 'Вы ввели неправильную почту!',
'account_creation_request_error' => 'Ошибка при отправке запроса на создание аккаунта!',
'account_authorization' => 'Авторизация аккаунта',
'login' => 'Войти',
'register' => 'Зарегистрироваться',
'logoff' => 'Выйти',
],
'en' => [
'authorization' => 'Authorization',
'login_label' => 'Login',
'password_label' => 'Password',
'incorrect_login_password' => 'Incorrect login or password!',
'repeat_password_label' => 'Repeat password',
'email_label' => 'Email',
'fill_all_fields' => 'You must fill out all fields!',
'passwords_do_not_match' => 'Passwords do not match!',
'account_creation_request_sent' => 'Account creation request sent!',
'user_exists' => 'User with this login already exists!',
'account_creation_error' => 'Error while creating the account!',
'incorrect_email' => 'Incorrect email!',
'account_creation_request_error' => 'Error sending account creation request!',
'account_authorization' => 'Account authorization',
'login' => 'Login',
'register' => 'Register',
'logoff' => 'Log out',
],
'lv' => [
'authorization' => 'Autentifikācija',
'login_label' => 'Lietotājvārds',
'password_label' => 'Parole',
'incorrect_login_password' => 'Nepareizs lietotājvārds vai parole!',
'repeat_password_label' => 'Atkārtot paroli',
'email_label' => 'E-pasts',
'fill_all_fields' => 'Jums jāaizpilda visi lauki!',
'passwords_do_not_match' => 'Paroles nesakrīt!',
'account_creation_request_sent' => 'Pieprasījums par konta izveidi nosūtīts!',
'user_exists' => 'Lietotājs ar šo lietotājvārdu jau pastāv!',
'account_creation_error' => 'Kļūda, izveidojot kontu!',
'incorrect_email' => 'Nepareizs e-pasts!',
'account_creation_request_error' => 'Kļūda, nosūtot pieprasījumu par konta izveidi!',
'account_authorization' => 'Konta autentifikācija',
'login' => 'Ieiet',
'register' => 'Reģistrēties',
'logoff' => 'Iziet',
],
];
return $lang;

15
main_plugin/auth/plug.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
global $path, $_SESSION;
$lang = include $path . 'main_plugin/auth/lang.php';
$lng = $_SESSION['lng'] ?? 'en';
include_once $path . 'main_plugin/auth/func.auth.php';
$Html = file_get_contents($path . 'main_plugin/auth/auth.php');
foreach ($lang[$lng] as $key => $value) {
$Html = str_replace('{{' . $key . '}}', $value, $Html);
}
echo $Html;
echo '<link rel="stylesheet" href="/main_plugin/auth/auth.css">';
echo '<script type="text/javascript" src="/main_plugin/auth/lang.js.php?lng=' . $lng . '"></script>';
?>

View File

@@ -0,0 +1,781 @@
/* Главное */
.selectedColor {
background: #3a6e62;
color: #ffffff;
}
.textGrey:hover {
color: #787878;
cursor: pointer;
}
#panel {
position: absolute;
display: flex;
align-items: center;
max-width: -webkit-fill-available;
border-radius: 5px;
background: rgba(255, 255, 255, 0.8);
overflow-x: clip;
overflow-y: visible;
z-index: 100;
}
.toolbar-container {
display: flex;
align-items: center;
white-space: nowrap;
padding: 4px;
margin: 0;
flex-shrink: 0;
padding: 4px 0px;
width: 100%;
}
.arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 24px;
height: 36px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
background: rgba(255, 255, 255, 0.8);
}
#arrow-left {
left: 0;
border: none;
border-right: inherit;
}
#arrow-right {
right: 0;
border: none;
border-left: inherit;
}
/* Стили контейнера для показа увеличенных изображений */
#bas,
#C {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
visibility: hidden;
}
#bas {
z-index: 1;
background: #FFFFFF;
opacity: 0.95;
}
#view {
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
}
/* Стили контейнера, содержащего страницу */
#basis {
position: relative;
width: -webkit-fill-available;
margin: auto;
}
/* Стили таблицы, содержащей страницу */
#tab {
width: 1000px;
}
/* Стили меню */
#sect {
display: flex;
margin-bottom: 15px;
font-family: Tahoma;
font-weight: bold;
}
/* Стили пунктов меню */
.lin {
margin: 9px;
width: 180px;
height: 50px;
color: #FFFFFF;
text-align: center;
box-shadow: 5px 5px 10px #000066;
background: #660033;
line-height: 50px;
border-radius: 5px;
}
/* Стили ячейки для контента */
#main {
width: 700px;
vertical-align: top;
padding-top: 20px;
}
/* Стили ячейки для рекламы */
#rec {
width: 300px;
text-align: center;
vertical-align: top;
font-weight: bold;
color: #660033;
}
/* Стили контейнера, содержащего страницу */
#basis3 {
position: fixed;
width: -webkit-fill-available;
margin: auto;
z-index: 100;
user-select: none;
font-size: 0.97em;
}
/* Стили вкладок с настройками */
.cust {
height: auto;
padding: 8px;
position: fixed;
visibility: hidden;
z-index: 100;
background: url(../../img/img/backgr.jpg);
border-radius: 5px;
top: 30%;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
width: calc(100% - 20px);
max-width: max-content;
}
.cust2 {
height: auto;
padding: 5px;
position: absolute;
top: 236%;
width: 1118px;
border: 1px solid #000000;
visibility: hidden;
z-index: 100;
background: url(../../img/img/backgr.jpg);
border-radius: 5px;
max-width: -webkit-fill-available;
}
/* Стили кнопок (крестиков) для закрытия вкладок */
.cldiv {
margin: 2px;
cursor: pointer;
}
/* Стили вкладки с изображениями с сервера */
#p_list {
text-align: center;
}
.roster {
width: 180px;
margin: 5px;
cursor: pointer;
}
/* Стили главной панели редактора */
.toolbar-group {
position: relative;
padding: 0px 5px;
margin: 0px 2px;
display: inline-block;
}
.toolbar-group::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: -3.1px;
width: 5px;
background: linear-gradient(
to right,
#000 0px 1px,
transparent 1px 2px,
#000 2px 3px,
transparent 3px 4px,
#000 4px 5px
);
}
.toolbar-group.open {
margin-left: 7px;
}
.toolbar-group-button {
transition: transform 0.1s ease, left 0.1s ease;
}
.toolbar-group.open .toolbar-group-button {
position: absolute;
left: -9px;
transform: scale(0.6);
transform-origin: top left;
z-index: 1;
}
.toolbar-group-content {
transition: margin-left 0.1s ease;
}
.toolbar-group.open .toolbar-group-content {
margin-left: 7px;
}
#toolbar-group-button-main {
background-position: -318px -117px;
}
#toolbar-group-button-text {
background-position: -237px 1664px;
}
#toolbar-group-button-paste {
background-position: 166px 517px;
}
.align-dropdown, .align-dropdown-oneImg {
position: relative;
display: inline-block;
}
.align-dropdown-text {
position: relative;
display: inline-block;
cursor: pointer;
border: 1px solid #000000;
height: 26px;
border-radius: 5px;
vertical-align: middle;
background: #FFFFFF;
padding-right: 13px;
}
.align-dropdown-text .dropdown-arrow {
position: absolute;
right: 5px;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
}
.align-dropdown-text .current {
padding: 0 3px;
height: 28px;
line-height: 28px;
display: inline-block;
cursor: pointer;
}
.align-dropdown .current {
cursor: pointer;
}
.align-list {
list-style: none;
margin: 0;
padding: 4px 0;
position: absolute;
top: 100%;
left: -9px;
background: #fff;
border: 1px solid #000000;
display: none;
z-index: 10;
font-size: 0.95em;
}
.align-list li {
padding: 4px 8px;
cursor: pointer;
}
.align-list li:hover {
background: #eee;
}
/* Стили выпадающего списка панели */
#sel {
font-size: 1.1em;
font-family: Tahoma;
border: 1px solid #000000;
}
/* Стили кнопок навигации по этапам редактирования */
#forw,
#bac {
right: 10px;
cursor: pointer;
}
/* Стили кнопок на главной панели редактора */
.but,
.pers,
.swit,
.swit2,
.pers2,
.pers3 {
border: 1px solid #000000;
cursor: pointer;
}
.editt {
display: inline-block;
}
.editi {
border-radius: 5px;
background: #FFFFFF;
display: inline-block;
width: 26px;
height: 26px;
vertical-align: middle;
}
.edits {
border-radius: 5px;
display: inline-block;
vertical-align: middle;
}
.editib {
background-image: url(../../img/pict/b_iconslyb.svg);
}
.editimc {
background-image: url(../../img/pict/mc_iconslyb.svg);
}
.editib:hover {
background-image: url(../../img/pict/g_iconslyb.svg);
}
.editimc:hover {
background-image: url(../../img/pict/g_iconslyb.svg);
}
.editf.active {
background-image: url(../../img/pict/b_iconslyb.svg);
background-color: #e7e7e7;
}
.editf.active:hover {
background-image: url(../../img/pict/g_iconslyb.svg);
background-color: #e7e7e7;
}
#settingsMain {
background-position: -197px -597px;
}
#forma {
background-position: 45px -117px;
}
#htm {
background-position: -318px 1824px;
}
#bac {
background-position: 645px 716px;
}
#forw {
background-position: 605px 716px;
}
#img, #oneImg {
background-position: 645px 477px;
}
#hr {
background-position: 766px 676px;
}
#tabl {
background-position: 1006px 597px;
}
#link {
background-position: 245px 277px;
}
#linkdel {
background-position: 205px 277px;
}
#delin {
background-position: 205px 277px;
}
#copyr {
background-position: 445px 517px;
}
#bol {
background-position: 1006px 517px;
}
#ital {
background-position: 966px 517px;
}
#under {
background-position: 926px 517px;
}
#col {
background-position: -237px 1664px;
}
#backgr {
background-position: -278px 1664px;
}
#font {
background-position: 1046px 517px;
}
#strik {
background-position: 885px 517px;
}
#sup {
background-position: 846px 517px;
}
#sub {
background-position: 806px 517px;
}
#titleEdit {
background-position: 1045px 557px;
}
/* #pluginSave {
background-position: -479px 1665px;
}
#pluginCreateLeft {
background-position: -598px 1665px;
}
#pluginAddLeft {
background-position: -677px 1665px;
}
#pluginCreateRight {
background-position: -558px 1665px;
}
#pluginAddRight {
background-position: -638px 1665px;
}
#pluginDelete {
background-position: -518px 1665px;
}
#pluginMove {
background-position: -438px 1665px;
} */
#contentPageCreate {
background-position: 926px 676px;
}
#contentPageMove {
background-position: -1077px 1704px;
}
#contentPageSettings {
background-position: -156px 1704px;
}
#elementEdit {
background-position: 965px 557px;
}
#coup {
background-position: -357px 1662px;
}
#contentPageCreateUrlManager {
background-position: -679px 1820px;
}
.indent {
display: inline-block;
width: 5px;
}
/* картинки списков */
#equar, .align-dropdown .current.equar {
background-position: 685px 517px;
}
#equac, .align-dropdown .current.equac {
background-position: 725px 517px;
}
#equal, .align-dropdown .current.equal {
background-position: 765px 517px;
}
#equaj, .align-dropdown .current.equaj {
background-position: 645px 517px;
}
#listNone, .align-dropdown .current.listNone {
background-position: -798px 1666px;
}
#listDots, .align-dropdown .current.listDots {
background-position: 764px 437px;
}
#listNumbers, .align-dropdown .current.listNumbers {
background-position: 724px 437px;
}
#listLetters, .align-dropdown .current.listLetters {
background-position: -757px 1666px;
}
/* Стили маленьких окон на главной панели редактора */
.smbut {
position: absolute;
cursor: pointer;
visibility: hidden;
}
#ccc {
position: absolute;
opacity: 0;
left: 470px;
top: 17px;
pointer-events: none;
}
#list {
width: 100px;
height: 28px;
}
#fs {
width: 50px;
height: 28px;
}
#ff {
width: 145px;
height: 28px;
}
#mainActions {
height: 28px;
}
#pluginDropdownContent {
height: 28px;
}
#elementDropdownContent {
width: 170px;
height: 28px;
}
/* Стили контейнеров вкладок с настройками */
.deploy {
text-align: center;
line-height: 25px;
}
/* Стили textarea */
.textar {
width: 400px;
height: 70px;
font-size: 0.9em;
border: 1px solid #000000;
margin-left: 5px;
margin-right: 20px;
}
/* Стили коротких текстовых полей */
.inptx {
width: 51px;
height: 22px;
font-size: 0.9em;
border: 1px solid #000000;
margin-right: 10px;
border-radius: 5px;
}
/* Стили средних текстовых полей */
.inpmid {
width: 120px;
height: 18px;
font-size: 0.9em;
border: 1px solid #000000;
margin-right: 10px;
border-radius: 5px;
}
/* Стили длинных текстовых полей */
.inpbig {
width: 190px;
height: 18px;
font-size: 0.9em;
border: 1px solid #000000;
margin-right: 10px;
border-radius: 5px;
}
/* Стили для формы */
.inform {
display: inline-block;
margin-block-end: 0em;
}
/* Стили кнопок вставки и просмотра на вкладках с настройками */
.butin {
height: 22px;
font-size: 0.9em;
border: 1px solid #000000;
background: #FFFFFF;
cursor: pointer;
border-radius: 5px;
}
.butinAuto {
width: min-content;
height: 22px;
font-size: 0.92em;
cursor: pointer;
padding: 1px 5px 1px 5px;
cursor: pointer;
}
.butinAuto:hover {
color: #787878;
}
.buttonEditTable {
height: 22px;
font-size: 0.9em;
border: 1px solid #000000;
background: #FFFFFF;
cursor: pointer;
border-radius: 5px;
}
.buttonEditTable.active {
background-color: #e7e7e7;
}
/* Стили выпадающих списков */
.sele {
height: 22px;
font-size: 0.9em;
border: 1px solid #000000;
margin-right: 10px;
border-radius: 5px;
}
.colored {
width: 28px;
height: 22px;
cursor: pointer;
margin-right: 10px;
}
/* Стили выпадающих списков без зазора справа */
.selena {
height: 22px;
font-size: 0.9em;
border: 1px solid #000000;
margin-right: 2px;
}
/* Стили кнопок выбора цвета на вкладках с настройками */
.colored {
width: 28px;
height: 22px;
cursor: pointer;
margin-right: 10px;
}
/* Стиль кнопок зарузок изоброжений */
#selectImgForm {
width: 77px;
height: 22px;
font-size: 0.9em;
border: 1px solid #000000;
background: #FFFFFF;
cursor: pointer;
border-radius: 5px;
margin: 0px 5px 0px -15px;
}
/* Стиль окна текстового редактора */
#tex {
position: absolute;
top: 236%;
width: 1100px;
height: 380px;
border: 1px solid #000000;
padding: 10px;
font-size: 1.2em;
font-family: Tahoma;
visibility: hidden;
z-index: 6;
border-radius: 5px;
left: 0px;
}
/* Стили контейнера с кнопками для символов и самих кнопок */
#copyr_sym {
text-align: center;
}
.sym {
vertical-align: middle;
width: 25px;
height: 25px;
margin: 1px;
border: 1px solid #000000;
font-size: 1em;
font-family: Tahoma;
background: #FFFFFF;
cursor: pointer;
}
#pluginRulesButton1, #pluginRulesButton2 {
width: 1em;
display: inline-block;
}
#pluginRulesBlock1, #pluginRulesBlock2 {
width: 240px;
position: absolute;
display: inline-block;
background: #efefef;
font-size: 0.9em;
padding: 2px;
line-height: 1.6;
border-radius: 5px;
opacity: 0;
transition: max-height 0.18s ease-out, opacity 0.18s ease-out;
pointer-events: none;
}
#pluginRulesBlock1.show, #pluginRulesBlock2.show {
opacity: 1;
pointer-events: all;
}
p {
margin-block-start: 5px;
margin-block-end: 5px;
}
.pluginEditable {
outline-offset: 15px;
overflow-x: hidden;
font-family: 'Roboto', sans-serif;
}
/* поля для редактирование элементов */
#editingMenuItems {
display: inline-block;
position: fixed;
z-index: 10;
user-select: none;
background-color: rgba(255, 255, 255, 0.92);
border-radius: 5px;
font-size: 1em;
box-shadow: 0px 0px 5px #777;
padding: 5px;
visibility: hidden;
}
.editingMenuItemsElement {
padding: 2px;
cursor: pointer;
}
.editingMenuItemsElement:hover {
color: #787878;
}

2188
main_plugin/editor/editor.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,369 @@
<div style="position: absolute;">
<div id="bas"></div>
<div id="">
<img id="pict" src="../../img/img/net.jpg" alt="Фото">
</div>
</div>
<div id="basis3" style="visibility: hidden; top: 20%; left: 10px; transform: translate(0%, -20%);">
<!-- Вкладка с символами -->
<div id="copyr_d" class="cust sb borderStyle">
<div id="copyr_sym">
<input type="button" class="sym" id="s1" value="&#36;">
<input type="button" class="sym" id="s2" value="&#163;">
<input type="button" class="sym" id="s3" value="&#165;">
<input type="button" class="sym" id="s4" value="&#8364;">
<input type="button" class="sym" id="s5" value="&#8377;">
<input type="button" class="sym" id="s6" value="&#8381;">
<input type="button" class="sym" id="s7" value="&#8369;">
<input type="button" class="sym" id="s8" value="&#3647;">
<br>
<input type="button" class="sym" id="s9" value="&#177;">
<input type="button" class="sym" id="s10" value="&#215;">
<input type="button" class="sym" id="s11" value="&#247;">
<input type="button" class="sym" id="s12" value="&#8722;">
<input type="button" class="sym" id="s13" value="&#8730;">
<input type="button" class="sym" id="s14" value="&#8800;">
<input type="button" class="sym" id="s15" value="&#8804;">
<input type="button" class="sym" id="s16" value="&#8805;">
<input type="button" class="sym" id="s17" value="&#8721;">
<br>
<input type="button" class="sym" id="s26" value="&#8734;">
<input type="button" class="sym" id="s27" value="&#937;">
<input type="button" class="sym" id="s28" value="&#8486;">
<input type="button" class="sym" id="s29" value="&#945;">
<input type="button" class="sym" id="s30" value="&#946;">
<input type="button" class="sym" id="s31" value="&#8482;">
<input type="button" class="sym" id="s32" value="&#8729;">
<input type="button" class="sym" id="s33" value="&#8776;">
<br>
<input type="button" class="sym" id="s18" value="&#8592;">
<input type="button" class="sym" id="s19" value="&#8593;">
<input type="button" class="sym" id="s20" value="&#8594;">
<input type="button" class="sym" id="s21" value="&#8595;">
<input type="button" class="sym" id="s22" value="&#8598;">
<input type="button" class="sym" id="s23" value="&#8599;">
<input type="button" class="sym" id="s24" value="&#8600;">
<input type="button" class="sym" id="s25" value="&#8601;">
<br>
<input type="button" class="sym" id="s34" value="&#9632;">
<input type="button" class="sym" id="s35" value="&#9650;">
<input type="button" class="sym" id="s37" value="&#9675;">
<input type="button" class="sym" id="s38" value="&#9658;">
<input type="button" class="sym" id="s39" value="&#9660;">
<input type="button" class="sym" id="s40" value="&#9679;">
</div>
</div>
<!-- Блок настроек ссылок -->
<div id="link_d" class="cust sb borderStyle">
<div class="deploy">
{{link}}: <input id="link2" class="inpbig" style="margin-right: 0px;"> <input id="link2FromPage" onClick="linkFromPage()" type="button" value="{{select_page_from_site}}" style="margin-right: 10px;">
{{open_in_new_window}}: <select id="link3" class="sele">
<option selected value="yes">{{yes}}</option>
<option value="no">{{no}}</option>
</select><br>
</select>
{{underline}}: <select id="link5" class="sele">
<option value="yes">{{yes}}</option>
<option selected value="no">{{no}}</option>
</select>
{{color}}: <input type="color" id="link6c" class="colored" value="#0645AD" title="{{choose_color}}">
<input type="button" id="butlink" class="butin" value="{{insert}}" title="{{insert_link}}">
</div>
</div>
<!-- Окно для изменение цвета текста -->
<div id="col_d" class="cust sb borderStyle">
<div class="deploy">
{{change_text_color}}:
<input type="color" id="colColor" class="colored" alt="{{color}}" title="{{choose_color}}">
<button id="colFun_d" class="butin">{{select}}</button>
</div>
</div>
<!-- Окно для изменение цвета фона текста -->
<div id="backgr_d" class="cust sb borderStyle">
<div class="deploy">
{{change_text_background}}:
<input type="color" id="backgrColor" class="colored" alt="{{color}}" title="{{choose_color}}">
<button id="backgrFun_d" class="butin">{{select}}</button>
</div>
</div>
<!-- Окно для ввода имени плагина, для левой стороны -->
<div id="pluginCreateLeft_d" class="cust sb borderStyle">
<div class="deploy">
{{create_plugin_left}}:<br>
<label for="pluginCreateLeftName">{{enter_plugin_name}}</label>
<label id="pluginRulesButton1" class="butin">!</label>
<div id="pluginRulesBlock1">
<div>{{plugin_name_guidelines}}</div>
<hr>
<div>{{used_plugin_names}}</div>
</div>
<input type="text" id="pluginCreateLeftName" class="inpbig">
<label for="pluginCreateLeftTitle">{{enter_plugin_title}}</label>
<input type="text" id="pluginCreateLeftTitle" class="inpbig">
<button id="pluginCreateLeftFun_d" class="butin">{{add}}</button>
</div>
</div>
<!-- Список для выбора плагина, для левой стороны -->
<div id="pluginAddLeft_d" class="cust sb borderStyle">
<div class="deploy">
{{add_plugin_left}}:<br>
<label for="pluginAddLeftName">{{select_plugin}}</label>
<select id="pluginAddLeftName" class="sele"></select>
<label for="pluginAddLeftTitle">{{enter_plugin_title}}</label>
<input type="text" id="pluginAddLeftTitle" class="inpbig">
<button id="pluginAddLeftFun_d" class="butin">{{select}}</button>
</div>
</div>
<!-- Окно для ввода имени плагина, для правой стороны -->
<div id="pluginCreateRight_d" class="cust sb borderStyle">
<div class="deploy">
{{create_plugin_right}}:<br>
<label for="pluginCreateRightName">{{enter_plugin_name}}</label>
<label id="pluginRulesButton2" class="butin">!</label>
<div id="pluginRulesBlock2">
<div>{{plugin_name_guidelines}}</div>
<hr>
<div>{{used_plugin_names}}</div>
</div>
<input type="text" id="pluginCreateRightName" class="inpbig">
<label for="pluginCreateRightTitle">{{enter_plugin_title}}</label>
<input type="text" id="pluginCreateRightTitle" class="inpbig">
<button id="pluginCreateRightFun_d" class="butin">{{add}}</button>
</div>
</div>
<!-- Список для выбора плагина, для правой стороны -->
<div id="pluginAddRight_d" class="cust sb borderStyle">
<div class="deploy">
{{add_plugin_right}}:<br>
<label for="pluginAddRightName">{{select_plugin}}</label>
<select id="pluginAddRightName" class="sele"></select>
<label for="pluginAddRightTitle">{{enter_plugin_title}}</label>
<input type="text" id="pluginAddRightTitle" class="inpbig">
<button id="pluginAddRightFun_d" class="butin">{{select}}</button>
</div>
</div>
<!-- редактирования меню страницы -->
<div id="contentPageCreate_d" class="cust sb borderStyle">
<div class="deploy">
{{create_page}}:<br>
{{select_or_create_file}} <input id="contentPageCreateUrl" class="inpbig">
<div id="contentPageCreateUrlManager" class="editi editib pers" style="margin: -3px 0px 0px -16px; width: 24px; height: 20px;"></div><br>
{{menu_name}}: <input id="contentPageCreateName" class="inpbig">
{{tab_title}}: <input id="contentPageCreateTitle" class="inpbig">
{{design}}: <select id="contentPageCreateTemplate" class="sele">
<?php ?>
</select>
<br>
<button id="contentPageCreateFun_d" class="butin">{{create}}</button>
</div>
</div>
<div id="contentPageSettings_d" class="cust sb borderStyle">
<div class="deploy">
<button id="contentPageSettingsFun_d" class="butin">{{edit}}</button>
</div>
</div>
<!-- основные нрастройки страницы -->
<div id="settingsMain_d" class="cust2 sb borderStyle" style="width: 200px;">
<div class="deploy" style="text-align: left;">
<option id="save" class="butinAuto">{{save}}</option>
<option id="saveHow" class="butinAuto">{{save_as}}</option>
<option id="openPage" class="butinAuto">{{open}}</option>
<option id="newPage" class="butinAuto">{{new}}</option>
</div>
</div>
<!-- Главная панель -->
<div id="panel" class="borderStyle"><div id="arrow-left" class="arrow borderStyle">&vltri;</div><div class="toolbar-container">
<div class="toolbar-group" style="margin-left: 14px;">
<span id="toolbar-group-button-main" class="editi editib pers toolbar-group-button"></span>
<span class="toolbar-group-content">
<div id="settingsMain" class="editi editib swit"></div>
<div id="htm" onclick="showHtmlCode()" class="editi editib pers" alt="{{html_code_main_block_alt}}" title="{{html_code_main_block_title}}"></div>
<div id="bac" class="editi editib pers" alt="{{undo_action_alt}}" title="{{undo_action_title}}"></div>
<div id="forw" class="editi editib pers" alt="{{redo_action_alt}}" title="{{redo_action_title}}"></div>
</span>
</div>
<div class="toolbar-group">
<span id="toolbar-group-button-text" class="editi editib pers toolbar-group-button"></span>
<span class="toolbar-group-content">
<div class="align-dropdown-text" id="ff">
<div class="current" data-cmd="'Roboto', sans-serif">Roboto</div><span class="dropdown-arrow">▾</span>
<ul class="align-list" style="left: -1px;">
<li data-cmd="'Roboto', sans-serif"><div>Roboto</div></li>
<li data-cmd="'Open Sans', sans-serif"><div>Open Sans</div></li>
<li data-cmd="'Montserrat', sans-serif"><div>Montserrat</div></li>
<li data-cmd="'Lora', serif"><div>Lora</div></li>
<li data-cmd="'Source Sans 3', sans-serif"><div>Source Sans Pro</div></li>
<li data-cmd="'Merriweather', serif"><div>Merriweather</div></li>
<li data-cmd="'PT Serif', serif"><div>PT Serif</div></li>
<li data-cmd="'Playfair Display', serif"><div>Playfair Display</div></li>
</ul>
</div>
<div class="align-dropdown-text" id="fs">
<div class="current" data-cmd="15px">15px</div><span class="dropdown-arrow">▾</span>
<ul class="align-list" style="left: -1px;">
<li data-cmd="1px"><div>1px</div></li><li data-cmd="2px"><div>2px</div></li><li data-cmd="4px"><div>4px</div></li><li data-cmd="6px"><div>6px</div></li><li data-cmd="8px"><div>8px</div></li><li data-cmd="10px"><div>10px</div></li><li data-cmd="11px"><div>11px</div></li><li data-cmd="12px"><div>12px</div></li><li data-cmd="13px"><div>13px</div></li><li data-cmd="14px"><div>14px</div></li><li data-cmd="15px"><div>15px</div></li><li data-cmd="16px"><div>16px</div></li><li data-cmd="17px"><div>17px</div></li><li data-cmd="18px"><div>18px</div></li><li data-cmd="19px"><div>19px</div></li><li data-cmd="20px"><div>20px</div></li><li data-cmd="22px"><div>22px</div></li><li data-cmd="24px"><div>24px</div></li><li data-cmd="28px"><div>28px</div></li><li data-cmd="32px"><div>32px</div></li><li data-cmd="48px"><div>48px</div></li><li data-cmd="56px"><div>56px</div></li><li data-cmd="64px"><div>64px</div></li><li data-cmd="96px"><div>96px</div></li>
</ul>
</div>
<div id="bol" class="editi editib pers editf" alt="{{bold_alt}}" title="{{bold_title}}"></div>
<div id="ital" class="editi editib pers editf" alt="{{italic_alt}}" title="{{italic_title}}"></div>
<div id="under" class="editi editib pers editf" alt="{{underline_alt}}" title="{{underline_title}}"></div>
<div id="strik" class="editi editib pers editf" alt="{{strikethrough_alt}}" title="{{strikethrough_title}}"></div>
<div style="display: inline-block;">
<div id="col" class="editi editimc pers" alt="{{font_color_alt}}" title="{{font_color_title}}"></div>
<div id="backgr" class="editi editimc pers" alt="{{background_color_alt}}" title="{{background_color_title}}"></div>
<div class="pickr-container"></div>
</div>
<div id="sup" class="editi editib pers editf" alt="{{superscript_alt}}" title="{{superscript_title}}"></div>
<div id="sub" class="editi editib pers editf" alt="{{subscript_alt}}" title="{{subscript_title}}"></div>
<div class="align-dropdown">
<div class="current editi editib pers" style="background-position:-798px 1666px;" data-cmd="listNone"></div>
<ul class="align-list">
<li data-cmd="1"><div class="editi editib pers" id="listNone"></div></li>
<li data-cmd="2"><div class="editi editib pers" id="listDots"></div></li>
<li data-cmd="3"><div class="editi editib pers" id="listNumbers"></div></li>
<li data-cmd="4"><div class="editi editib pers" id="listLetters"></div></li>
</ul>
</div>
<div class="align-dropdown">
<div class="current editi editib pers" style="background-position: 765px 517px;" data-cmd="equal"></div>
<ul class="align-list">
<li data-cmd="equal"><div class="editi editib pers" id="equal"></div></li>
<li data-cmd="equac"><div class="editi editib pers" id="equac"></div></li>
<li data-cmd="equar"><div class="editi editib pers" id="equar"></div></li>
<li data-cmd="equaj"><div class="editi editib pers" id="equaj"></div></li>
</ul>
</div>
<div id="forma" class="editi editib pers" alt="{{remove_format_alt}}" title="{{remove_format_title}}"></div>
</span>
</div>
<div class="toolbar-group">
<span id="toolbar-group-button-paste" class="editi editib pers toolbar-group-button"></span>
<span class="toolbar-group-content">
<div id="link" class="editi editib swit" alt="{{insert_link_alt}}" title="{{insert_link_title}}"></div>
<div id="linkdel" class="editi editib pers" alt="{{remove_link_alt}}" title="{{remove_link_title}}"></div>
<div class="align-dropdown-oneImg">
<div class="current editi editib pers" id="oneImg"></div>
<ul class="align-list" style="left: -1px;">
<li data-cmd="imgLink"><div id="imgLink">{{insert_image_link}}</div></li>
<li data-cmd="imgPc"><div id="imgPc">{{insert_image_PC}}</div></li>
<li data-cmd="imgManager"><div id="imgManager">{{insert_image_manager}}</div></li>
</ul>
</div>
<div id="hr" class="editi editib pers editf"></div>
<div id="tabl" class="editi editib pers editf"></div>
<div id="copyr" class="editi editib swit"></div>
<select id="pluginDropdownContent" class="edits pers3">
<option id="pluginAddLeft" value="pluginAddLeft" class="swit">{{add_plugin_left}}</option>
<option id="pluginAddRight" value="pluginAddRight" class="swit">{{add_plugin_right}}</option>
<option id="pluginDelete" value="pluginDelete" class="editfText">{{delete_plugin}}</option>
<option id="pluginMove" value="pluginMove" class="editfText">{{move_plugin}}</option>
</select>
</span>
</div>
</div><div id="arrow-right" class="arrow borderStyle">&vrtri;</div></div>
<!-- текстовый редактор -->
<form name="dat">
<textarea id="tex" name="tex" class="sb"></textarea>
</form>
</div>
<!-- поля для редактирование элементов -->
<div id="editingMenuItems" class="borderStyle">
<div id="editingMenuItemsCopy" class="editingMenuItemsElement">{{copy}}</div>
<div id="editingMenuItemsCut" class="editingMenuItemsElement">{{cut}}</div>
<div id="editingMenuItemsPaste" class="editingMenuItemsElement">{{paste}}</div>
<hr id="editingMenuItemsHr">
<div id="elementEditPanelHr" class="elementEditPanelElement">
{{thickness_px}}: <input id="hr1Edit" class="inptx" value="1" type="number" title="{{thickness_tooltip}}"><br>
{{width_px_percent}}: <input id="hr2Edit" class="inptx" value="95%" type="text" title="{{width_tooltip}}"><br>
{{position}}: <select id="hr4Edit" class="sele" title="{{position_tooltip}}">
<option value="left_clear">{{left_clear}}</option>
<option value="right_clear">{{right_clear}}</option>
<option value="center_clear">{{center_clear}}</option>
<option selected value="left_text">{{left_text}}</option>
<option value="right_text">{{right_text}}</option>
<option value="text">{{in_text}}</option>
</select><br>
{{color}}: <input type="color" id="hr3cEdit" class="colored" title="{{choose_color}}"><br>
{{margin_top_px}}: <input id="hrMarginTopEdit" class="inptx" value="0" type="number" title="{{padding_top_tooltip}}"><br>
{{margin_right_px}}: <input id="hrMarginRightEdit" class="inptx" value="0" type="number" title="{{padding_right_tooltip}}"><br>
{{margin_bottom_px}}: <input id="hrMarginBottomEdit" class="inptx" value="0" type="number" title="{{padding_bottom_tooltip}}"><br>
{{margin_left_px}}: <input id="hrMarginLeftEdit" class="inptx" value="0" type="number" title="{{padding_left_tooltip}}"><br>
<input type="button" id="buthrEdit" class="butin" value="{{edit}}" title="{{edit_hr}}">
</div>
<div id="elementEditPanelImg" class="elementEditPanelElement">
{{image_url}}: <input id="ima1Edit" class="inpbig" title="{{url_tooltip}}"><br>
{{image_width_px}}: <input id="ima6Edit" class="inptx" placeholder="{{auto}}" value="250" type="number" title="{{width_tooltip}}"><br>
{{image_height_px}}: <input id="ima6aEdit" class="inptx" placeholder="{{auto}}" value="" type="number" title="{{height_tooltip}}"><br>
{{position}}: <select id="ima4Edit" class="sele" title="{{position_tooltip}}">
<option value="left_clear">{{left_clear}}</option>
<option value="right_clear">{{right_clear}}</option>
<option value="center_clear">{{center_clear}}</option>
<option selected value="left_text">{{left_text}}</option>
<option value="right_text">{{right_text}}</option>
<option value="text">{{in_text}}</option>
</select><br>
{{margin_top_px}}: <input id="imaMarginTopEdit" class="inptx" value="0" type="number" title="{{padding_top_tooltip}}"><br>
{{margin_right_px}}: <input id="imaMarginRightEdit" class="inptx" value="0" type="number" title="{{padding_right_tooltip}}"><br>
{{margin_bottom_px}}: <input id="imaMarginBottomEdit" class="inptx" value="0" type="number" title="{{padding_bottom_tooltip}}"><br>
{{margin_left_px}}: <input id="imaMarginLeftEdit" class="inptx" value="0" type="number" title="{{padding_left_tooltip}}"><br>
{{border_px}}: <input id="ima7Edit" class="inptx" value="0" type="number" title="{{border_tooltip}}"><br>
{{border_color}}: <input type="color" id="ima8cEdit" class="colored" title="{{choose_color}}"><br>
{{link_tooltip}}: <input id="imaLinkEdit" class="inpbig" type="url" title="{{link_tooltip}}"><br>
<input type="button" id="butimaEdit" class="butin" value="{{edit}}" title="{{edit_image}}"><br>
</div>
<div id="elementEditPanelTable" class="elementEditPanelElement">
<input type="button" class="buttonEditTable" value="{{add_row}}" id="editTableButtonAddLine" title="{{add_row_tooltip}}"><br>
<input type="button" class="buttonEditTable" value="{{delete_row}}" id="editTableButtonDeleteLine" title="{{delete_row_tooltip}}"><br>
<input type="button" class="buttonEditTable" value="{{add_column}}" id="editTableButtonAddColumn" title="{{add_column_tooltip}}"><br>
<input type="button" class="buttonEditTable" value="{{delete_column}}" id="editTableButtonDeleteColumn" title="{{delete_column_tooltip}}"><br>
{{width_px_percent}}: <input id="tab1Edit" class="inptx" value="50%" type="text" title="{{width_tooltip}}"><br>
{{position}}: <select id="tab6Edit" class="sele" title="{{position_tooltip}}">
<option value="left_clear">{{left_clear}}</option>
<option value="right_clear">{{right_clear}}</option>
<option value="center_clear">{{center_clear}}</option>
<option selected value="left_text">{{left_text}}</option>
<option value="right_text">{{right_text}}</option>
<option value="text">{{in_text}}</option>
</select><br>
{{padding_inner_px}}: <input id="tab4Edit" class="inptx" value="1" type="number" title="{{padding_inner_tooltip}}"><br>
{{margin_top_px}}: <input id="tabMarginTopEdit" class="inptx" value="0" type="number" title="{{padding_top_tooltip}}"><br>
{{margin_right_px}}: <input id="tabMarginRightEdit" class="inptx" value="0" type="number" title="{{padding_right_tooltip}}"><br>
{{margin_bottom_px}}: <input id="tabMarginBottomEdit" class="inptx" value="0" type="number" title="{{padding_bottom_tooltip}}"><br>
{{margin_left_px}}: <input id="tabMarginLeftEdit" class="inptx" value="0" type="number" title="{{padding_left_tooltip}}"><br>
{{border_px}}: <input id="tab9Edit" class="inptx" value="1" type="number" title="{{border_tooltip}}"><br>
{{border_color}}: <input type="color" id="tab10cEdit" class="colored" title="{{choose_color}}"><br>
{{background_color}}: <input type="color" id="tab11cEdit" class="colored" value="#FFFFFF" title="{{choose_color}}"><br>
<input type="button" id="butabEdit" class="butin" value="{{edit}}" title="{{edit_table}}"><br>
</div>
</div>

View File

@@ -0,0 +1,211 @@
<?php
function saveContentIdData() {
global $config, $path, $_SESSION;
$filePath = $path . $_SESSION['page_url'] . ".page.php";
$data = $_POST['saveContentIdData'] ?? '';
$file = simplexml_load_file($filePath);
$langNode = $file->content->{$_SESSION['lng']};
$file->content->{$_SESSION['lng']} = '';
$node = dom_import_simplexml($langNode);
$doc = $node->ownerDocument;
if ($node->appendChild($doc->createCDATASection("\n" . $data . "\n")) && $file->asXML($filePath)) {
return ['result' => 1];
}
return ['result' => 0];
}
function floatsBlock() {
global $config, $path, $_SESSION;
$filePath = $path . $_SESSION['page_url'] . ".page.php";
$file = simplexml_load_file($filePath);
$data = json_decode($_POST['floatsBlock'], true);
$left = $data['left'] ?? [];
$right = $data['right'] ?? [];
unset($file->lblock->block);
unset($file->rblock->block);
foreach ($left as $b) {
$n = $file->lblock->addChild('block');
$n->addAttribute('url', htmlspecialchars($b['pluginUrl'], ENT_QUOTES, 'UTF-8'));
$n->addAttribute('title', htmlspecialchars($b['title'], ENT_QUOTES, 'UTF-8'));
$n->addAttribute('tclass', htmlspecialchars($b['tclass'], ENT_QUOTES, 'UTF-8'));
$n->addAttribute('bclass', htmlspecialchars($b['bclass'], ENT_QUOTES, 'UTF-8'));
}
foreach ($right as $b) {
$n = $file->rblock->addChild('block');
$n->addAttribute('url', htmlspecialchars($b['pluginUrl'], ENT_QUOTES, 'UTF-8'));
$n->addAttribute('title', htmlspecialchars($b['title'], ENT_QUOTES, 'UTF-8'));
$n->addAttribute('tclass', htmlspecialchars($b['tclass'], ENT_QUOTES, 'UTF-8'));
$n->addAttribute('bclass', htmlspecialchars($b['bclass'], ENT_QUOTES, 'UTF-8'));
}
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($file->asXML());
return ['result' => $dom->save($filePath) ? 1 : 0];
}
function newTitle() {
global $config, $path, $_SESSION;
$title = htmlspecialchars($_POST['newTitle'] ?? '', ENT_QUOTES, 'UTF-8');
$filePath = $path . "data/filepath." . $_SESSION['lng'] . ".php";
$file = simplexml_load_file($filePath);
$p = rtrim($config['REQUEST_URI'], '.html');
$parts = explode('/', $p);
$node = $file->index;
foreach ($parts as $n) {
if ($n !== '') {
if (isset($node->$n)) {
$node = $node->$n;
} else {
return ['error' => "Node not found: $n"];
}
}
}
$node['title'] = $title;
if ($file->asXML($filePath)) {
return ['result' => 'ok'];
}
return ['error' => 'Save failed'];
}
function saveContentIdDataHow() {
global $config, $path, $_SESSION;
$_SESSION['page_url'] = $_POST['page_url'] . str_replace('.page.php', '', $_POST['nameFile']);
$filePath = $path . $_POST['page_url'] . $_POST['nameFile'];
$content = $_POST['saveContentIdData'] ?? '';
$file = simplexml_load_file($filePath);
$langNode = $file->content->{$_SESSION['lng']};
$file->content->{$_SESSION['lng']} = '';
$node = dom_import_simplexml($langNode);
$doc = $node->ownerDocument;
$node->appendChild($doc->createCDATASection("\n" . $content . "\n"));
$file->rblock = '';
$file->lblock = '';
$blocks = $_POST['floatsBlock'] ?? [];
$titles = $_POST['title'] ?? [];
$urls = $_POST['pluginUrl'] ?? [];
$tclasses = $_POST['tclass'] ?? [];
$bclasses = $_POST['bclass'] ?? [];
foreach ($blocks as $i => $blockName) {
$n = $file->$blockName->addChild('block');
$n->addAttribute('url', htmlspecialchars($urls[$i], ENT_QUOTES, 'UTF-8'));
$n->addAttribute('title', htmlspecialchars($titles[$i], ENT_QUOTES, 'UTF-8'));
$n->addAttribute('tclass', htmlspecialchars($tclasses[$i], ENT_QUOTES, 'UTF-8'));
$n->addAttribute('bclass', htmlspecialchars($bclasses[$i], ENT_QUOTES, 'UTF-8'));
}
$dom = new DOMDocument('1.0','UTF-8');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($file->asXML());
return ['result' => $dom->save($filePath) ? 1 : 0];
}
function createNewFile() {
global $config, $path, $_SESSION;
$_SESSION['page_url'] = $_POST['page_url'] . str_replace('.page.php', '', $_POST['nameFile']);
$savePath = $path . $_POST['page_url'] . $_POST['nameFile'];
$template = $path . "data/template.page.php";
$data = $_POST['saveContentIdData'] ?? '';
if (!file_exists($template)) return ['result' => 0];
if (file_put_contents($savePath, file_get_contents($template)) === false) return ['result' => 0];
$file = simplexml_load_file($savePath);
$node = $file->content->{$_SESSION['lng']};
$file->content->{$_SESSION['lng']} = '';
$dom = dom_import_simplexml($node)->ownerDocument;
dom_import_simplexml($node)->appendChild($dom->createCDATASection("\n".$data."\n"));
return ['result' => $file->asXML($savePath) ? 1 : 0];
}
function checkFileExists() {
global $path;
$f = $path . ($_POST['page_url'] ?? '') . ($_POST['nameFile'] ?? '');
return ['exists' => file_exists($f) ? 1 : 0];
}
function managerPlugin() {
$a = $_POST['action'];
$n = $_POST['pluginName'] ?? '';
$d = __DIR__ . '/../../plugin/';
switch ($a) {
case 'check':
return ['status' => (is_dir($d.$n) ? 'exists' : 'not_exists')];
case 'create':
if (!file_exists($d.$n)) {
umask(0);
mkdir($d.$n, 0777, true);
file_put_contents($d.$n.'/plug.php', "<?php\n echo '<div class=\"pluginEditable\" contenteditable=\"true\"></div>'; \n?>");
return ['status' => 'created', 'plugin' => $n];
}
return ['status' => 'already_exists'];
case 'add':
$list = array_map('basename', array_filter(glob($d.'*'), 'is_dir'));
return ['plugins' => $list];
case 'save':
$url = $_POST['pluginUrlSave'] ?? '';
$html = $_POST['pluginInnerHtml'] ?? '';
$name = basename(parse_url($url, PHP_URL_PATH));
$file = $d.$name.'/plug.php';
$res = file_put_contents($file, "<?php\n echo '<div class=\"pluginEditable\" contenteditable=\"true\">".$html."</div>';\n?>");
return ['status' => $res !== false ? 'saved' : 'error'];
}
return ['error' => 'Unknown action'];
}
function loadPlugin() {
$name = $_POST['pluginName2'] ?? '';
$dir = __DIR__ . '/../../plugin/' . $name . '/plug.php';
if (!file_exists($dir)) return ['error' => 'not_found'];
ob_start();
include($dir);
return ['html' => ob_get_clean()];
}
function uploadUserImage() {
global $config, $path, $_SESSION;
$dir = 'img/users_img/' . $_SESSION['username'] . "/";
$f = $_FILES['userImg']['name'];
$b = pathinfo($f, PATHINFO_FILENAME);
$e = pathinfo($f, PATHINFO_EXTENSION);
if (!is_dir($dir)) mkdir($dir, 0755, true);
$n = $b;
$i = 1;
while (file_exists($dir . $n . '.' . $e)) $n = $b . '_' . ++$i;
$target = $dir . $n . '.' . $e;
if (move_uploaded_file($_FILES['userImg']['tmp_name'], $target)) {
return ['path' => str_replace('\\', '/', $target)];
}
return ['error' => 'upload_failed'];
}
function nameUser() {
global $config;
return ['user' => $config['User']];
}
?>

View File

@@ -0,0 +1,8 @@
<?php
$lang = include $path . 'lang.php';
$lng = $_GET['lng'] ?? ($_SESSION['lng'] ?? 'en');
$placeholders = [];
foreach ($lang[$lng] as $key => $value) {
$placeholders['{{' . $key . '}}'] = $value;
}
echo strtr(file_get_contents($path . 'editor.js'), $placeholders);

514
main_plugin/editor/lang.php Normal file
View File

@@ -0,0 +1,514 @@
<?php
$lang = [
'ru' => [
'insert_line' => 'Вставить линию',
'thickness_px' => 'Толщина (px)',
'width_px_percent' => 'Ширина (px, %)',
'position' => 'Положение',
'left' => 'Слева',
'center' => 'По центру',
'right' => 'Справа',
'in_text' => 'В тексте',
'color' => 'Цвет',
'choose_color' => 'Нажмите, чтобы выбрать цвет',
'insert' => 'Вставить',
'insert_hr' => 'Вставить горизонтальную линию',
'insert_table' => 'Вставить таблицу',
'rows' => 'Строки',
'columns' => 'Колонки',
'padding_inner_px' => 'Внутренний отступ (px)',
'padding_outer_px' => 'Внешний отступ (px)',
'border_px' => 'Рамка (px)',
'border_color' => 'Цвет рамки',
'background_color' => 'Цвет фона',
'upload' => 'Загрузить',
'select' => 'Выбрать',
'image_url' => 'URL изображения',
'image_width_px' => 'Ширина изображения (px)',
'image_height_px' => 'Высота изображения (px)',
'margin_outer_px' => 'Внешний отступ (px)',
'link' => 'Ссылка',
'select_page_from_site' => 'Выбрать страницу с сайта',
'open_in_new_window' => 'Открывать в новом окне',
'yes' => 'Да',
'no' => 'Нет',
'underline' => 'Подчеркивание',
'insert_link' => 'Вставить ссылку',
'change_text_color' => 'Изменить цвет текста',
'change_text_background' => 'Изменить цвет фона текста',
'create_plugin_left' => 'Создать плагин слева',
'enter_plugin_name' => 'Введите имя плагина',
'plugin_name_guidelines' => 'В имени плагина только англ. буквы, цифры, пробелы, _',
'used_plugin_names' => 'Используемые имена плагинов',
'enter_plugin_title' => 'Введите заголовок плагина',
'add' => 'Добавить',
'add_plugin_left' => 'Добавить левый плагин',
'select_plugin' => 'Выберите плагин',
'create_plugin_right' => 'Создать плагин справа',
'add_plugin_right' => 'Добавить правый плагин',
'create_page' => 'Создать страницу',
'select_or_create_file' => 'Выбрать или создать файл',
'menu_name' => 'Название в меню',
'tab_title' => 'Название во вкладке',
'design' => 'Дизайн',
'create' => 'Создать',
'edit' => 'Изменить',
'save' => 'Сохранить',
'save_as' => 'Сохранить как',
'open' => 'Открыть',
'new' => 'Новый',
'html_code_main_block_alt' => 'HTML-код главного блока',
'html_code_main_block_title' => 'HTML-код главного блока',
'undo_action_alt' => 'Отменить действие',
'undo_action_title' => 'Отменить действие',
'redo_action_alt' => 'Повторить действие',
'redo_action_title' => 'Повторить действие',
'bold_alt' => 'Жирный',
'bold_title' => 'Сделать текст жирным',
'italic_alt' => 'Курсив',
'italic_title' => 'Сделать текст курсивом',
'underline_alt' => 'Подчеркнутый',
'underline_title' => 'Сделать текст подчеркнутым',
'strikethrough_alt' => 'Зачеркнутый',
'strikethrough_title' => 'Сделать текст зачеркнутым',
'font_color_alt' => 'Цвет шрифта',
'font_color_title' => 'Сделать текст другим цветом',
'background_color_alt' => 'Цвет фона',
'background_color_title' => 'Сделать фон другим цветом',
'superscript_alt' => 'Надстрочный',
'superscript_title' => 'Сделать текст надстрочным',
'subscript_alt' => 'Подстрочный',
'subscript_title' => 'Сделать текст подстрочным',
'list_none' => 'Без списка',
'align_left_alt' => 'Выравнить влево',
'align_left_title' => 'Выравнивание влево',
'align_center_alt' => 'Выравнить по центру',
'align_center_title' => 'Выравнивание по центру',
'align_right_alt' => 'Выравнить вправо',
'align_right_title' => 'Выравнивание вправо',
'align_justify_alt' => 'Выровнять по ширине',
'align_justify_title' => 'Выровнять по ширине',
'remove_format_alt' => 'Удалить форматирование',
'remove_format_title' => 'Удалить форматирование',
'insert_link_alt' => 'Вставить ссылку',
'insert_link_title' => 'Вставить ссылку',
'remove_link_alt' => 'Удалить ссылку',
'remove_link_title' => 'Удалить ссылку',
'edit_title_title' => 'Изменить заголовок',
'insert_image_link' => 'Вставить изображение по ссылке',
'insert_image_PC' => 'Загрузить изображение с компьютера',
'insert_image_manager' => 'Выбрать изображение через менеджер',
'insert_symbol' => 'Вставить символ',
'delete_plugin' => 'Удалить плагин',
'move_plugin' => 'Переместить плагин',
'copy' => 'Копировать',
'cut' => 'Вырезать',
'paste' => 'Вставить',
'auto' => 'авто',
'insert_url' => 'Вставьте URL!',
'delete_plugin_confirm' => 'Удалить плагин?',
'action_not_defined' => 'Действие не определено',
'plugin_name_empty_error' => 'Имя плагина не может быть пустым!',
'plugin_not_selected_error' => 'Плагин не выбран!',
'plugin_name_guidelines' => 'В имени плагина можно использовать только английские буквы, цифры, пробелы и подчеркивания!',
'plugin_name_exists_suffix' => ' - это имя плагина уже используется!',
'used_plugin_names' => 'Используемые имена плагина:',
'plugin_created_left_suffix' => 'создан на левую',
'plugin_added_left_suffix' => 'добавлен на левую',
'plugin_created_right_suffix' => 'создан на правую',
'plugin_added_right_suffix' => 'добавлен на правую',
'img_upload_error' => 'Ошибка при загрузке изображения!',
'rows_or_columns_not_specified' => 'Вы не указали количество строк или столбцов!',
'insert_url_or_select_image' => 'Вставьте URL или выберите изображение!',
'cursor_not_in_editable_field' => 'Курсор не в редактируемом поле!',
'cursor_or_selection_not_in_editable_field' => 'Курсор или выделение не в редактируемом поле!',
'no_text_selected' => 'Вы не выделили текст!',
'padding_top_px' => 'Отступ сверху (px)',
'padding_right_px' => 'Отступ справа (px)',
'padding_bottom_px' => 'Отступ снизу (px)',
'padding_left_px' => 'Отступ слева (px)',
'thickness_tooltip' => 'Толщина линии в пикселях',
'width_tooltip' => 'Ширина в процентах или пикселях',
'position_tooltip' => 'Позиция элемента',
'padding_top_tooltip' => 'Задайте верхний отступ в пикселях',
'padding_right_tooltip' => 'Задайте правый отступ в пикселях',
'padding_bottom_tooltip' => 'Задайте нижний отступ в пикселях',
'padding_left_tooltip' => 'Задайте левый отступ в пикселях',
'url_tooltip' => 'Введите URL изображения',
'height_tooltip' => 'Высота изображения в пикселях',
'margin_tooltip' => 'Внешний отступ в пикселях',
'border_tooltip' => 'Толщина рамки в пикселях',
'link_tooltip' => 'Ссылка при клике на изображение',
'caption' => 'Подпись к изображению',
'caption_tooltip' => 'Текст подписи под изображением',
'add_row_tooltip' => 'Добавить строку в таблицу',
'delete_row_tooltip' => 'Удалить строку из таблицы',
'add_column_tooltip' => 'Добавить столбец в таблицу',
'delete_column_tooltip' => 'Удалить столбец из таблицы',
'padding_inner_tooltip' => 'Внутренний отступ в пикселях',
'padding_outer_tooltip' => 'Внешний отступ в пикселях',
'plugin_title_empty_error' => 'Заголовок пустой!',
'open_page' => 'Откройте страницу на сайте, а не через менеджер!',
'enter_new_title' => 'Введите новый заголовок:',
'title_saved' => 'Заголовок сохранён!',
'new_file' => 'Новый файл',
'add_row' => 'Добавить строку',
'delete_row' => 'Удалить строку',
'add_column' => 'Добавить столбец',
'delete_column'=> 'Удалить столбец',
'left_clear' => 'Слева (без текста)',
'right_clear' => 'Справа (без текста)',
'center_clear'=> 'По центру (без текста)',
'left_text' => 'Слева с текстом',
'right_text' => 'Справа с текстом',
'link_tooltip' => 'Ссылка при клике на изображение',
'margin_top_px' => 'Внешний отступ сверху (px)',
'margin_right_px' => 'Внешний отступ справа (px)',
'margin_bottom_px' => 'Внешний отступ снизу (px)',
'margin_left_px' => 'Внешний отступ слева (px)',
'in_text' => 'В тексте'
],
'en' => [
'insert_line' => 'Insert line',
'thickness_px' => 'Thickness (px)',
'width_px_percent' => 'Width (px, %)',
'position' => 'Position',
'left' => 'Left',
'center' => 'Center',
'right' => 'Right',
'in_text' => 'In text',
'color' => 'Color',
'choose_color' => 'Click to choose color',
'insert' => 'Insert',
'insert_hr' => 'Insert horizontal line',
'insert_table' => 'Insert table',
'rows' => 'Rows',
'columns' => 'Columns',
'padding_inner_px' => 'Inner padding (px)',
'padding_outer_px' => 'Outer padding (px)',
'border_px' => 'Border (px)',
'border_color' => 'Border color',
'background_color' => 'Background color',
'upload' => 'Upload',
'select' => 'Select',
'image_url' => 'Image URL',
'image_width_px' => 'Image width (px)',
'image_height_px' => 'Image height (px)',
'margin_outer_px' => 'Outer margin (px)',
'link' => 'Link',
'select_page_from_site' => 'Select page from site',
'open_in_new_window' => 'Open in new window',
'yes' => 'Yes',
'no' => 'No',
'underline' => 'Underline',
'insert_link' => 'Insert link',
'change_text_color' => 'Change text color',
'change_text_background' => 'Change text background',
'create_plugin_left' => 'Create plugin left',
'enter_plugin_name' => 'Enter plugin name',
'plugin_name_guidelines' => 'Plugin name: letters, digits, spaces, underscores',
'used_plugin_names' => 'Used plugin names',
'enter_plugin_title' => 'Enter plugin title',
'add' => 'Add',
'add_plugin_left' => 'Add left plugin',
'select_plugin' => 'Select plugin',
'create_plugin_right' => 'Create plugin right',
'add_plugin_right' => 'Add right plugin',
'create_page' => 'Create page',
'select_or_create_file' => 'Select or create file',
'menu_name' => 'Menu name',
'tab_title' => 'Tab title',
'design' => 'Design',
'create' => 'Create',
'edit' => 'Edit',
'save' => 'Save',
'save_as' => 'Save as',
'open' => 'Open',
'new' => 'New',
'html_code_main_block_alt' => 'HTML code main block',
'html_code_main_block_title' => 'HTML code main block',
'undo_action_alt' => 'Undo action',
'undo_action_title' => 'Undo action',
'redo_action_alt' => 'Redo action',
'redo_action_title' => 'Redo action',
'bold_alt' => 'Bold',
'bold_title' => 'Make text bold',
'italic_alt' => 'Italic',
'italic_title' => 'Make text italic',
'underline_alt' => 'Underline',
'underline_title' => 'Underline text',
'strikethrough_alt' => 'Strikethrough',
'strikethrough_title' => 'Strikethrough text',
'font_color_alt' => 'Font color',
'font_color_title' => 'Change font color',
'background_color_alt' => 'Background color',
'background_color_title' => 'Change background color',
'superscript_alt' => 'Superscript',
'superscript_title' => 'Make text superscript',
'subscript_alt' => 'Subscript',
'subscript_title' => 'Make text subscript',
'list_none' => 'Without a list',
'align_left_alt' => 'Align left',
'align_left_title' => 'Align text left',
'align_center_alt' => 'Align center',
'align_center_title' => 'Align text center',
'align_right_alt' => 'Align right',
'align_right_title' => 'Align text right',
'align_justify_alt' => 'Justify',
'align_justify_title' => 'Justify text',
'remove_format_alt' => 'Remove format',
'remove_format_title' => 'Remove formatting',
'insert_link_alt' => 'Insert link',
'insert_link_title' => 'Insert link',
'remove_link_alt' => 'Remove link',
'remove_link_title' => 'Remove link',
'edit_title_title' => 'Edit title',
'insert_image_link' => 'Insert image by link',
'insert_image_PC' => 'Upload image from PC',
'insert_image_manager' => 'Choose image from manager',
'insert_symbol' => 'Insert symbol',
'delete_plugin' => 'Delete plugin',
'move_plugin' => 'Move plugin',
'copy' => 'Copy',
'cut' => 'Cut',
'paste' => 'Paste',
'auto' => 'auto',
'insert_url' => 'Insert URL!',
'delete_plugin_confirm' => 'Delete plugin?',
'action_not_defined' => 'Action not defined',
'plugin_name_empty_error' => 'Plugin name cannot be empty!',
'plugin_not_selected_error' => 'Plugin not selected!',
'plugin_name_guidelines' => 'Plugin name can only contain English letters, numbers, spaces, and underscores!',
'plugin_name_exists_suffix' => ' - this plugin name is already taken!',
'used_plugin_names' => 'Used plugin names:',
'plugin_created_left_suffix' => 'created on the left',
'plugin_added_left_suffix' => 'added on the left',
'plugin_created_right_suffix' => 'created on the right',
'plugin_added_right_suffix' => 'added on the right',
'img_upload_error' => 'Image upload error!',
'rows_or_columns_not_specified' => 'You didn\'t specify the number of rows or columns!',
'insert_url_or_select_image' => 'Insert URL or select an image!',
'cursor_not_in_editable_field' => 'Cursor is not in an editable field!',
'cursor_or_selection_not_in_editable_field' => 'Cursor or selection is not in an editable field!',
'no_text_selected' => 'No text selected!',
'padding_top_px' => 'Padding top (px)',
'padding_right_px' => 'Padding right (px)',
'padding_bottom_px' => 'Padding bottom (px)',
'padding_left_px' => 'Padding left (px)',
'thickness_tooltip' => 'Line thickness in pixels',
'width_tooltip' => 'Width in percent or pixels',
'position_tooltip' => 'Element position',
'padding_top_tooltip' => 'Set top padding in pixels',
'padding_right_tooltip' => 'Set right padding in pixels',
'padding_bottom_tooltip' => 'Set bottom padding in pixels',
'padding_left_tooltip' => 'Set left padding in pixels',
'url_tooltip' => 'Enter image URL',
'height_tooltip' => 'Image height in pixels',
'margin_tooltip' => 'Outer margin in pixels',
'border_tooltip' => 'Border width in pixels',
'link_tooltip' => 'Link on image click',
'caption' => 'Image caption',
'caption_tooltip' => 'Text displayed under the image',
'add_row_tooltip' => 'Add a row to the table',
'delete_row_tooltip' => 'Delete a row from the table',
'add_column_tooltip' => 'Add a column to the table',
'delete_column_tooltip' => 'Delete a column from the table',
'padding_inner_tooltip' => 'Inner padding in pixels',
'padding_outer_tooltip' => 'Outer padding in pixels',
'plugin_title_empty_error' => 'Title is empty!',
'open_page' => 'Open the page on the website, not through the manager!',
'enter_new_title' => 'Enter a new title:',
'title_saved' => 'Title saved!',
'new_file' => 'Jauns fails',
'add_row' => 'Add row',
'delete_row' => 'Delete row',
'add_column' => 'Add column',
'delete_column'=> 'Delete column',
'left_clear' => 'Left (no text)',
'right_clear' => 'Right (no text)',
'center_clear'=> 'Center (no text)',
'left_text' => 'Left with text',
'link_tooltip' => 'Link on image click',
'margin_top_px' => 'Margin top (px)',
'margin_right_px' => 'Margin right (px)',
'margin_bottom_px' => 'Margin bottom (px)',
'margin_left_px' => 'Margin left (px)',
'right_text' => 'Right with text'
],
'lv' => [
'insert_line' => 'Ievietot līniju',
'thickness_px' => 'Biezums (px)',
'width_px_percent' => 'Platums (px, %)',
'position' => 'Novietojums',
'left' => 'Pa kreisi',
'center' => 'Centrā',
'right' => 'Pa labi',
'in_text' => 'Tekstā',
'color' => 'Krāsa',
'choose_color' => 'Klikšķiniet, lai izvēlētos krāsu',
'insert' => 'Ievietot',
'insert_hr' => 'Ievietot horizontālu līniju',
'insert_table' => 'Ievietot tabulu',
'rows' => 'Rindas',
'columns' => 'Kolonnas',
'padding_inner_px' => 'Iekšējais atkāpums (px)',
'padding_outer_px' => 'Ārējais atkāpums (px)',
'border_px' => 'Rāmja biezums (px)',
'border_color' => 'Rāmja krāsa',
'background_color' => 'Fona krāsa',
'upload' => 'Augšupielādēt',
'select' => 'Izvēlēties',
'image_url' => 'Attēla URL',
'image_width_px' => 'Attēla platums (px)',
'image_height_px' => 'Attēla augstums (px)',
'margin_outer_px' => 'Ārējais atkāpums (px)',
'link' => 'Saite',
'select_page_from_site' => 'Izvēlēties lapu no vietnes',
'open_in_new_window' => 'Atvērt jaunā logā',
'yes' => 'Jā',
'no' => 'Nē',
'underline' => 'Pasvītrojums',
'insert_link' => 'Ievietot saiti',
'change_text_color' => 'Mainīt teksta krāsu',
'change_text_background' => 'Mainīt teksta fona krāsu',
'create_plugin_left' => 'Izveidot spraudni pa kreisi',
'enter_plugin_name' => 'Ievadiet spraudņa nosaukumu',
'plugin_name_guidelines' => 'Nosaukumā tikai angļu burtu, ciparu, atstarpju un apakšsvītru',
'used_plugin_names' => 'Izmantotie spraudņu nosaukumi',
'enter_plugin_title' => 'Ievadiet spraudņa virsrakstu',
'add' => 'Pievienot',
'add_plugin_left' => 'Pievienot kreiso spraudni',
'select_plugin' => 'Izvēlēties spraudni',
'create_plugin_right' => 'Izveidot spraudni pa labi',
'add_plugin_right' => 'Pievienot labo spraudni',
'create_page' => 'Izveidot lapu',
'select_or_create_file' => 'Izvēlēties vai izveidot failu',
'menu_name' => 'Nosaukums izvēlnē',
'tab_title' => 'Cilnes virsraksts',
'design' => 'Dizains',
'create' => 'Izveidot',
'edit' => 'Rediģēt',
'save' => 'Saglabāt',
'save_as' => 'Saglabāt kā',
'open' => 'Atvērt',
'new' => 'Jauns',
'html_code_main_block_alt' => 'Galvenā bloka HTML kods',
'html_code_main_block_title' => 'Galvenā bloka HTML kods',
'undo_action_alt' => 'Atcelt darbību',
'undo_action_title' => 'Atcelt darbību',
'redo_action_alt' => 'Atkārtot darbību',
'redo_action_title' => 'Atkārtot darbību',
'bold_alt' => 'Treknraksts',
'bold_title' => 'Padarīt tekstu treknu',
'italic_alt' => 'Kursīvs',
'italic_title' => 'Padarīt tekstu kursīvu',
'underline_alt' => 'Pasvītrot',
'underline_title' => 'Pasvītrot tekstu',
'strikethrough_alt' => 'Pārvilkt',
'strikethrough_title' => 'Pārvilkt tekstu',
'font_color_alt' => 'Fonta krāsa',
'font_color_title' => 'Mainīt fonta krāsu',
'background_color_alt' => 'Fona krāsa',
'background_color_title' => 'Mainīt fona krāsu',
'superscript_alt' => 'Augšraksts',
'superscript_title' => 'Padarīt tekstu augšrakstu',
'subscript_alt' => 'Apakšraksts',
'subscript_title' => 'Padarīt tekstu apakšrakstu',
'list_none' => 'Bez saraksta',
'align_left_alt' => 'Līdzināt pa kreisi',
'align_left_title' => 'Līdzināt pa kreisi',
'align_center_alt' => 'Centrēt',
'align_center_title' => 'Centrēt tekstu',
'align_right_alt' => 'Līdzināt pa labi',
'align_right_title' => 'Līdzināt pa labi',
'align_justify_alt' => 'Izlīdzināt',
'align_justify_title' => 'Izlīdzināt tekstu',
'remove_format_alt' => 'Noņemt formatējumu',
'remove_format_title' => 'Noņemt formatējumu',
'insert_link_alt' => 'Ievietot saiti',
'insert_link_title' => 'Ievietot saiti',
'remove_link_alt' => 'Noņemt saiti',
'remove_link_title' => 'Noņemt saiti',
'edit_title_title' => 'Rediģēt virsrakstu',
'insert_image_link' => 'Ievietot attēlu pēc saites',
'insert_image_PC' => 'Augšupielādēt attēlu no datora',
'insert_image_manager' => 'Izvēlēties attēlu no pārvaldnieka',
'insert_symbol' => 'Ievietot simbolu',
'delete_plugin' => 'Dzēst spraudni',
'move_plugin' => 'Pārvietot spraudni',
'copy' => 'Kopēt',
'cut' => 'Izgriezt',
'paste' => 'Ielīmēt',
'auto' => 'auto',
'insert_url' => 'Ievietojiet URL!',
'delete_plugin_confirm' => 'Vai dzēst spraudni?',
'action_not_defined' => 'Darbība nav definēta',
'plugin_name_empty_error' => 'Spraudņa nosaukums nedrīkst būt tukšs!',
'plugin_not_selected_error' => 'Spraudnis nav izvēlēts!',
'plugin_name_guidelines' => 'Spraudņa nosaukumā var izmantot tikai angļu alfabēta burtus, ciparus, atstarpes un zemsvītras līnijas!',
'plugin_name_exists_suffix' => ' - šis spraudņa nosaukums jau ir izmantots!',
'used_plugin_names' => 'Izmantotie spraudņu nosaukumi:',
'plugin_created_left_suffix' => 'izveidots kreisajā pusē',
'plugin_added_left_suffix' => 'pievienots kreisajā pusē',
'plugin_created_right_suffix' => 'izveidots labajā pusē',
'plugin_added_right_suffix' => 'pievienots labajā pusē',
'img_upload_error' => 'Attēla augšupielādes kļūda!',
'rows_or_columns_not_specified' => 'Jūs neesat norādījis rindu vai kolonnu skaitu!',
'insert_url_or_select_image' => 'Ievietojiet URL vai izvēlieties attēlu!',
'cursor_not_in_editable_field' => 'Kursors nav rediģējamā laukā!',
'cursor_or_selection_not_in_editable_field' => 'Kursors vai atlase nav rediģējamā laukā!',
'no_text_selected' => 'Nav izvēlēts teksts!',
'padding_top_px' => 'Augšējais polsterējums (px)',
'padding_right_px' => 'Labais polsterējums (px)',
'padding_bottom_px' => 'Apakšējais polsterējums (px)',
'padding_left_px' => 'Kreisais polsterējums (px)',
'thickness_tooltip' => 'Līnijas biezums pikseļos',
'width_tooltip' => 'Platums procentos vai pikseļos',
'position_tooltip' => 'Elementa pozīcija',
'padding_top_tooltip' => 'Iestatiet augšējo polsterējumu pikseļos',
'padding_right_tooltip' => 'Iestatiet labo polsterējumu pikseļos',
'padding_bottom_tooltip' => 'Iestatiet apakšējo polsterējumu pikseļos',
'padding_left_tooltip' => 'Iestatiet kreiso polsterējumu pikseļos',
'url_tooltip' => 'Ievadiet attēla URL',
'height_tooltip' => 'Attēla augstums pikseļos',
'margin_tooltip' => 'Ārējais attālums pikseļos',
'border_tooltip' => 'Rāmja platums pikseļos',
'link_tooltip' => 'Saite, kad klikšķina uz attēla',
'caption' => 'Attēla paraksts',
'caption_tooltip' => 'Teksts zem attēla',
'add_row_tooltip' => 'Pievienot rindu tabulai',
'delete_row_tooltip' => 'Dzēst rindu no tabulas',
'add_column_tooltip' => 'Pievienot kolonnu tabulai',
'delete_column_tooltip' => 'Dzēst kolonnu no tabulas',
'padding_inner_tooltip' => 'Iekšējais polsterējums pikseļos',
'padding_outer_tooltip' => 'Ārējais polsterējums pikseļos',
'plugin_title_empty_error' => 'Virsraksts ir tukšs!',
'open_page' => 'Atveriet lapu vietnē, nevis caur pārvaldnieku!',
'enter_new_title' => 'Ievadiet jauno virsrakstu:',
'title_saved' => 'Virsraksts saglabāts!',
'new_file' => 'Jauns fails',
'add_row' => 'Pievienot rindu',
'delete_row' => 'Dzēst rindu',
'add_column' => 'Pievienot kolonnu',
'delete_column'=> 'Dzēst kolonnu',
'left_clear' => 'Pa kreisi (bez teksta)',
'right_clear' => 'Pa labi (bez teksta)',
'center_clear'=> 'Centrēti (bez teksta)',
'left_text' => 'Pa kreisi ar tekstu',
'right_text' => 'Pa labi ar tekstu',
'link_tooltip' => 'Saite kad klikšķina uz attēla',
'margin_top_px' => 'Ārējais attālums augšā (px)',
'margin_right_px' => 'Ārējais attālums pa labi (px)',
'margin_bottom_px' => 'Ārējais attālums apakšā (px)',
'margin_left_px' => 'Ārējais attālums pa kreisi (px)',
'in_text' => 'Tekstā'
],
];
return $lang;

View File

@@ -0,0 +1,18 @@
<?php
global $path, $_SESSION, $configAdmins;
$lang = include $path . 'main_plugin/editor/lang.php';
$lng = $_SESSION['lng'] ?? 'en';
if (in_array($_SESSION['username'], $configAdmins, true)) {
include_once $path . 'main_plugin/editor/func.editor.php';
$Html = file_get_contents($path . 'main_plugin/editor/editor.php');
foreach ($lang[$lng] as $key => $value) {
$Html = str_replace('{{' . $key . '}}', $value, $Html);
}
echo $Html;
echo '<link rel="stylesheet" href="/main_plugin/editor/editor.css">';
echo '<script type="text/javascript" src="/main_plugin/editor/lang.js.php?lng=' . $lng . '"></script>';
}
?>

View File

@@ -0,0 +1,180 @@
<?php
#функция нахождения всех файлов в папке
function managerPathFolder($params) {
global $config, $path, $_SESSION;
$lang = include $path . 'main_plugin/manager/lang.php';
$dirParam = $params['managerPathFolder'] ?? '';
$directory = realpath($path . ($dirParam ?: ''));
if ($directory && is_dir($directory)) {
$files = scandir($directory);
$data = [];
foreach ($files as $file) {
if ($file === '.' || $file === '..') continue;
$filePath = $directory . '/' . $file;
if (is_dir($filePath)) {
$name = $file;
$type = $lang[$_SESSION['lng']]['folder'];
$items = array_diff(scandir($filePath), ['.','..']);
$size = count($items);
} else {
$extension = pathinfo($file, PATHINFO_EXTENSION);
$name = $extension ? $file : pathinfo($file, PATHINFO_FILENAME);
$type = $lang[$_SESSION['lng']]['file'];
$size = filesize($filePath);
}
$data[] = [
'name' => $name,
'path' => ($dirParam ?: '') . "/" . $file,
'type' => $type,
'size' => $size,
'creationTime' => date('Y-m-d H:i:s', filemtime($filePath)),
];
}
array_unshift($data, ['rootFolder' => basename($path)]);
return ['items' => $data];
}
return ['error' => "Invalid path: {$dirParam}"];
}
// проверка на существование папки в буфере
function checkFolderForFile($params) {
global $_SESSION;
$exists = !empty($_SESSION['managerClipboardFile']['path']);
return ['exists' => $exists ? 1 : 0];
}
// проверка на существование файла с таким же именем
function checkSameName($params) {
global $path, $_SESSION;
if (!empty($params['managerSettingsInsert'])) {
$clipboard = $_SESSION['managerClipboardFile']['path'];
$newPath = $path . $params['currentPath'] . '/' . basename($clipboard);
} else {
$newPath = $path . $params['currentPath'] . DIRECTORY_SEPARATOR . ($params['name'] ?? '');
}
return ['exists' => file_exists($newPath) ? 1 : 0];
}
// проверка буфера обмена
function managerClipboard($params) {
global $path, $_SESSION;
$in = $params['managerClipboard'] ?? '';
$filePath = realpath($path . '/' . $in);
if ($filePath && file_exists($filePath)) {
$_SESSION['managerClipboardFile'] = ['path' => $filePath, 'action' => $params['action'] ?? ''];
return ['message' => 1];
}
return ['message' => 0];
}
// вставка из буфера обмена
function managerSettingsInsert($params) {
global $path, $_SESSION;
$dest = realpath($path . '/' . ($params['managerSettingsInsert'] ?? ''));
if (!$dest) return ['message' => 0, 'error' => 'Invalid destination'];
if (empty($_SESSION['managerClipboardFile']['path'])) return ['message' => 0, 'error' => 'Clipboard empty'];
$clipboard = $_SESSION['managerClipboardFile']['path'];
$action = $_SESSION['managerClipboardFile']['action'];
$newPath = $dest . '/' . basename($clipboard);
if ($action === 'cut') {
$ok = rename($clipboard, $newPath);
return ['message' => $ok ? 1 : 0];
}
if ($action === 'copy') {
$copyDir = function($src, $dst) use (&$copyDir) {
if (is_dir($src)) {
if (!is_dir($dst)) mkdir($dst, 0755, true);
foreach (array_diff(scandir($src), ['.','..']) as $f) {
$copyDir($src."/".$f, $dst."/".$f);
}
} else {
copy($src, $dst);
}
};
$copyDir($clipboard, $newPath);
return ['message' => 1];
}
return ['message' => 0, 'error' => 'Invalid action'];
}
// переименование
function managerSettingsRename($params) {
$curr = realpath($GLOBALS['path'] . '/' . ($params['managerSettingsRename'] ?? ''));
$new = $params['managerNamePath'] ?? '';
$ok = $curr && rename($curr, dirname($curr).'/'.$new);
return ['message' => $ok ? 1 : 0];
}
// удаление
function managerSettingsDelete($params) {
$target = realpath($GLOBALS['path'] . '/' . ($params['managerSettingsDelete'] ?? ''));
$del = function($p) use (&$del) {
if (is_dir($p)) {
foreach (array_diff(scandir($p), ['.','..']) as $f) $del($p.'/'.$f);
return rmdir($p);
}
return unlink($p);
};
$ok = $target ? $del($target) : false;
return ['message' => $ok ? 1 : 0];
}
// свойства файла/папки
function managerSettingsProperties($params) {
global $config, $path, $_SESSION;
$lang = include $path . 'main_plugin/manager/lang.php';
$curr = realpath($path . '/' . ($params['managerSettingsProperties'] ?? ''));
if (!$curr) return ['error' => 'not_found'];
$info = [
['label'=>$lang[$_SESSION['lng']]['name'],'value'=>basename($curr)],
['label'=>$lang[$_SESSION['lng']]['type'],'value'=>is_dir($curr)?$lang[$_SESSION['lng']]['folder']:$lang[$_SESSION['lng']]['file']],
['label'=>$lang[$_SESSION['lng']]['location'],'value'=>str_replace($path,'',dirname('/'.$curr))],
['label'=>$lang[$_SESSION['lng']]['size'],'value'=>is_dir($curr)?'-':filesize($curr).' байт'],
['label'=>$lang[$_SESSION['lng']]['creation_time'],'value'=>date('Y-m-d H:i:s',filectime($curr))],
['label'=>$lang[$_SESSION['lng']]['last_modified_time'],'value'=>date('Y-m-d H:i:s',filemtime($curr))]
];
return ['properties'=>$info];
}
// создание
function managerSettingsCreate($params) {
$name = $params['managerSettingsCreate'] ?? '';
$type = $params['managerType'] ?? '';
$parent = realpath($GLOBALS['path'].'/'.($params['managerNamePath'] ?? ''));
if (!$parent) return ['message'=>'invalid_parent'];
$full = $parent.'/'.$name;
if (file_exists($full)) return ['message'=>'exists'];
$ok = ($type==='папка')?mkdir($full):file_put_contents($full,'')!==false;
return ['message'=>$ok?1:'noSuccess'];
}
// открыть страницу
function newPath($params) {
global $path, $_SESSION;
$page = simplexml_load_file($path.'/'.($params['newPath']??'').'.page.php');
$out = [
'right'=>GetBlock($page->rblock->block,'right'),
'left'=>GetBlock($page->lblock->block,'left'),
'content'=>(string)$page->content->{$_SESSION['lng']}
];
$_SESSION['page_url']=$params['newPath']??'';
return $out;
}
// загрузка файла менеджером
function pathLoad($params) {
global $path;
$f = $_FILES['pathFile'] ?? null;
if (!$f || $f['error']!==UPLOAD_ERR_OK) return ['error'=>'upload_error'];
$ext=strtolower(pathinfo($f['name'],PATHINFO_EXTENSION));
if (!in_array($ext,['jpg','png','txt','pdf'])) return ['error'=>'ext'];
$dir=realpath($path.'/'.($params['pathLoad']??''));
if (!$dir||!is_writable($dir)) return ['error'=>'dir'];
$name=pathinfo($f['name'],PATHINFO_FILENAME); $i=1; $final=$name;
while(file_exists("$dir/$final.$ext")) $final=$name.'_'.($i++);
$file="$dir/$final.$ext";
return move_uploaded_file($f['tmp_name'],$file)?['path'=>str_replace('\\','/',$file)]:['error'=>'move'];
}
?>

View File

@@ -0,0 +1,8 @@
<?php
$lang = include $path . 'lang.php';
$lng = $_GET['lng'] ?? ($_SESSION['lng'] ?? 'en');
$placeholders = [];
foreach ($lang[$lng] as $key => $value) {
$placeholders['{{' . $key . '}}'] = $value;
}
echo strtr(file_get_contents($path . 'manager.js'), $placeholders);

View File

@@ -0,0 +1,169 @@
<?php
$lang = [
'ru' => [
'copy' => 'Копировать',
'cut' => 'Вырезать',
'rename' => 'Переименовать',
'delete' => 'Удалить',
'properties' => 'Свойства',
'upload_file' => 'Загрузить файл',
'paste' => 'Вставить',
'create_file' => 'Создать файл',
'create_folder' => 'Создать папку',
'rights' => 'Права',
'ok' => 'Ок',
'cancel' => 'Отмена',
'file' => 'Файл',
'to_clipboard' => 'в буфер обмена!',
'error_when' => 'Ошибка при',
'right_click_to_select_file' => 'Кликните правой кнопкой мыши на файл для выбора файла!',
'file_with_same_name_exists' => 'Файл с таким именем уже существует!',
'file_pasted_successfully' => 'Файл вставлен из буфера обмена!',
'file_paste_unknown_error' => 'Неизвестная ошибка при вставке файла!',
'error' => 'Ошибка',
'enter_new_name' => 'Введите новое имя:',
'rename_success' => 'Переименование выполнено успешно!',
'rename_error' => 'Ошибка при переименовании!',
'invalid_name_error' => 'Некорректное имя. Использование запрещенных символов...',
'delete_confirm' => 'Подтвердите удаление!',
'delete_success' => 'Удаление выполнено успешно!',
'delete_error' => 'Ошибка при удалении!',
'folder' => 'Папка',
'enter_new_folder_name' => 'Введите имя новой папки:',
'invalid_folder_name' => 'Некорректное имя папки',
'folder_created_successfully' => 'Папка создана успешно!',
'enter_new_file_name' => 'Введите имя нового файла:',
'invalid_file_name' => 'Некорректное имя файла',
'file_created_successfully' => 'Файл создан успешно!',
'create' => 'Создать',
'with_name' => 'с именем',
'create_error' => 'Ошибка при создании',
'item_already_exists' => 'с таким же именем уже есть!',
'unknown_error' => 'Неизвестная ошибка!',
'no_rights_yet' => 'прав пока что нету',
'file_upload_error' => 'Ошибка загрузки файла!',
'file_uploaded_successfully' => 'Файл успешно загружен!',
'select_file_ending_with_page_php' => 'Выберите файл с расширением .page.php!',
'name' => 'Имя',
'type' => 'Тип',
'location' => 'Расположение',
'size' => 'Размер',
'creation_time' => 'Время создания',
'last_modified_time' => 'Время последнего изменения',
'error' => 'Ошибка',
'file_or_folder_not_found' => 'Файл или папка не найдены'
],
'en' => [
'copy' => 'Copy',
'cut' => 'Cut',
'rename' => 'Rename',
'delete' => 'Delete',
'properties' => 'Properties',
'upload_file' => 'Upload file',
'paste' => 'Paste',
'create_file' => 'Create file',
'create_folder' => 'Create folder',
'rights' => 'Permissions',
'ok' => 'OK',
'cancel' => 'Cancel',
'file' => 'File',
'to_clipboard' => 'to clipboard!',
'error_when' => 'Error when',
'right_click_to_select_file' => 'Right-click to select a file!',
'file_with_same_name_exists' => 'File with this name already exists!',
'file_pasted_successfully' => 'File pasted successfully!',
'file_paste_unknown_error' => 'Unknown error while pasting!',
'error' => 'Error',
'enter_new_name' => 'Enter new name:',
'rename_success' => 'Renamed successfully!',
'rename_error' => 'Error renaming!',
'invalid_name_error' => 'Invalid name contains forbidden characters',
'delete_confirm' => 'Confirm deletion!',
'delete_success' => 'Deleted successfully!',
'delete_error' => 'Error deleting!',
'folder' => 'Folder',
'enter_new_folder_name' => 'Enter folder name:',
'invalid_folder_name' => 'Invalid folder name',
'folder_created_successfully' => 'Folder created successfully!',
'enter_new_file_name' => 'Enter file name:',
'invalid_file_name' => 'Invalid file name',
'file_created_successfully' => 'File created successfully!',
'create' => 'Create',
'with_name' => 'with name',
'create_error' => 'Error creating',
'item_already_exists' => 'already exists!',
'unknown_error' => 'Unknown error!',
'no_rights_yet' => 'No permissions set',
'file_upload_error' => 'File upload error!',
'file_uploaded_successfully' => 'File uploaded successfully!',
'select_file_ending_with_page_php' => 'Select file ending with .page.php!',
'name' => 'Name',
'type' => 'Type',
'location' => 'Location',
'size' => 'Size',
'creation_time' => 'Creation Time',
'last_modified_time' => 'Last Modified Time',
'file' => 'File',
'error' => 'Error',
'file_or_folder_not_found' => 'File or folder not found'
],
'lv' => [
'copy' => 'Kopēt',
'cut' => 'Izgriezt',
'rename' => 'Pārdēvēt',
'delete' => 'Dzēst',
'properties' => 'Īpašības',
'upload_file' => 'Augšupielādēt failu',
'paste' => 'Ielīmēt',
'create_file' => 'Izveidot failu',
'create_folder' => 'Izveidot mapi',
'rights' => 'Tiesības',
'ok' => 'Labi',
'cancel' => 'Atcelt',
'file' => 'Fails',
'to_clipboard' => 'starpliktuvi!',
'error_when' => 'Kļūda, mēģinot',
'right_click_to_select_file' => 'Ar peles labo pogu atlasiet failu!',
'file_with_same_name_exists' => 'Fails ar šādu nosaukumu jau pastāv!',
'file_pasted_successfully' => 'Fails veiksmīgi ielīmēts!',
'file_paste_unknown_error' => 'Nezināma kļūda ielīmējot!',
'error' => 'Kļūda',
'enter_new_name' => 'Ievadiet jaunu nosaukumu:',
'rename_success' => 'Pārdēvēts veiksmīgi!',
'rename_error' => 'Kļūda pārdēvējot!',
'invalid_name_error' => 'Nederīgs nosaukums',
'delete_confirm' => 'Apstipriniet dzēšanu!',
'delete_success' => 'Dzēsts veiksmīgi!',
'delete_error' => 'Kļūda dzēšot!',
'folder' => 'Mape',
'enter_new_folder_name' => 'Ievadiet mapes nosaukumu:',
'invalid_folder_name' => 'Nederīgs mapes nosaukums',
'folder_created_successfully' => 'Mape izveidota veiksmīgi!',
'enter_new_file_name' => 'Ievadiet faila nosaukumu:',
'invalid_file_name' => 'Nederīgs faila nosaukums',
'file_created_successfully' => 'Fails izveidots veiksmīgi!',
'create' => 'Izveidot',
'with_name' => 'ar nosaukumu',
'create_error' => 'Kļūda izveidojot',
'item_already_exists' => 'jau eksistē!',
'unknown_error' => 'Nezināma kļūda!',
'no_rights_yet' => 'Nav piešķirtu tiesību',
'file_upload_error' => 'Kļūda augšupielādējot failu!',
'file_uploaded_successfully' => 'Fails augšupielādēts veiksmīgi!',
'select_file_ending_with_page_php' => 'Atlasiet failu ar paplašinājumu .page.php!',
'name' => 'Vārds',
'type' => 'Tips',
'location' => 'Atrašanās vieta',
'size' => 'Izmērs',
'creation_time' => 'Izveidošanas laiks',
'last_modified_time' => 'Pēdējās izmaiņas',
'file' => 'Fails',
'error' => 'Kļūda',
'file_or_folder_not_found' => 'Fails vai mape nav atrasti'
]
];
return $lang;

View File

@@ -0,0 +1,254 @@
/* менеджер */
#managerDiv {
display: inline-block;
position: fixed;
z-index: 100;
user-select: none;
background-color: rgba(255, 255, 255, 0.92);
border: 1px solid #000000;
width: 800px;
border-radius: 5px;
height: 600px;
font-size: 1em;
box-shadow: 0px 0px 5px #777;
}
#managerCloseFun {
float: right;
width: 20px;
height: 20px;
background-position: -159px -121px;
cursor: pointer;
}
#managerHistoryBackFun {
margin-right: 2px;
float: left;
width: 20px;
height: 14px;
background-position: -400px -43px;
cursor: pointer;
}
#managerHistoryForwFun {
margin-right: 2px;
float: left;
width: 20px;
height: 14px;
background-position: -441px -43px;
cursor: pointer;
}
#managerBackFun {
margin-right: 12px;
float: left;
width: 20px;
height: 14px;
background-position: -481px -43px;
cursor: pointer;
}
#managerTop {
text-align: center;
border-bottom: 1px #40464d solid;
padding: 5px;
background-color: rgba(255, 255, 255, 0.6);
}
#managerTopTitle {
text-align: center;
}
#managerPath {
display: inline-block;
flex: 1;
height: 18px;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 5px;
padding: 2px;
}
#managerPath.active {
border: 1px #40464d solid;
}
.managerPathButton {
background-color: rgba(255, 255, 255, 1);
border-radius: 5px;
cursor: pointer;
}
.managerPathButton:hover {
color: #787878;
}
#managerTopDiv {
display: flex;
align-items: center;
flex-wrap: wrap;
}
#managerTableDiv {
height: 480px;
margin: 0px 20px 0px 20px;
border: 1px #40464d solid;
overflow-y: overlay;
border-radius: 5px;
}
#managerTable {
font-size: 1em;
border-collapse: collapse;
background-color: rgba(255, 255, 255, 0.8);
width: -webkit-fill-available;
}
#managerTableTitle {
position: sticky;
top: 0;
font-weight: bold;
background-color: rgba(255, 255, 255, 1);
}
#managerTable td {
padding: 5px;
}
.managerTableDivFile:hover td {
background-color: #c5e7f9;
cursor: pointer;
}
/* #managerTableDiv::-webkit-scrollbar {
width: 10px;
}
#managerTableDiv::-webkit-scrollbar-track {
border: 1px solid #000;
padding: 2px 0;
background-color: #ffffff;
}
#managerTableDiv::-webkit-scrollbar-thumb {
border-radius: 10px;
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
background-color: #ffffff;
border: 1px solid #000;
border-right: 0px solid #000;
} */
/* сохронение как*/
#saveHowDiv {
margin: 8px 20px 0px 20px;
white-space: nowrap;
display: flex;
align-items: center;
}
#saveHowName {
border: 1px #40464d solid;
border-radius: 5px;
padding: 5px;
width: 594px;
font-size: 1em;
display: inline-block;
margin-left: 10px;
}
#saveHowButton {
border: 1px #40464d solid;
border-radius: 5px;
padding: 5px;
margin: 0px 0px 0px 10px;
cursor: pointer;
display: inline-block;
width: 91px;
}
#saveHowButton:hover {
color: #787878;
}
/* окно менеджер */
#managerSettings {
display: inline-block;
position: fixed;
z-index: 100;
user-select: none;
background-color: rgba(255, 255, 255, 0.92);
border: 1px solid #000000;
border-radius: 5px;
font-size: 1em;
box-shadow: 0px 0px 5px #777;
padding: 5px;
animation: fadeIn 0.5s ease-in forwards;
}
.managerSettingsButtonButtons {
background-color: rgba(255, 255, 255, 0.8);
border-radius: 5px;
padding: 5px;
border: 1px #40464d solid;
cursor: pointer;
}
.managerSettingsButtonButtons:hover {
color: #787878;
}
/* окно свойств */
#managerProperties {
display: inline-block;
position: fixed;
z-index: 100;
user-select: none;
background-color: rgba(255, 255, 255, 0.97);
border: 1px solid #000000;
border-radius: 5px;
font-size: 1em;
box-shadow: 0px 0px 5px #777;
width: 600px;
}
#managerPropertiesMiddle {
margin: 0px 20px 0px 20px;
}
#managerPropertiesTop {
border-bottom: 1px solid #000000;
padding: 5px;
text-align: center;
}
#managerPropertiesTopName {
text-align: center;
}
#managerPropertiesTopClose {
float: right;
width: 20px;
height: 20px;
background-position: -159px -121px;
cursor: pointer;
}
#managerPropertiesWindow {
text-align: center;
display: flex;
}
.managerPropertiesWindowDiv {
cursor: pointer;
text-align: center;
width: 50%;
display: inline-block;
padding: 9px;
}
.managerPropertiesWindowDiv:hover {
color: #787878;
}
#managerPropertiesDiv {
border: 1px solid #000000;
border-radius: 5px;
}
.managerPropertiesDivDivs {
padding: 6px 8px 6px 8px;
border-radius: 5px;
}
#managerPropertiesDivButtons {
padding: 9px;
display: flex;
justify-content: right;
align-items: center;
}
#managerPropertiesDivButtons {
text-align: center;
}
.managerPropertiesDivButton {
margin: 3px 3px 3px 15px;
cursor: pointer;
display: inline-block;
}
.managerPropertiesDivButton:hover {
color: #787878;
}

View File

@@ -0,0 +1,485 @@
addEventListener("load", function() {
movementMenu("managerDiv");
movementMenu("managerProperties");
//менеджер папок
let managerDiv = document.getElementById('managerDiv');
managerData(currentPath);
function managerFun() { //кнопки и редактируемые поля в менеджере
document.getElementById('managerCloseFun').onclick = function() {
managerDiv.style.visibility = "hidden";
};
document.getElementById('managerHistoryBackFun').onclick = function() {
if (managerHistoryIndex > 0) {
managerHistoryIndex--;
managerData(managerHistoryPaths[managerHistoryIndex]);
}
};
document.getElementById('managerHistoryForwFun').onclick = function() {
if (managerHistoryIndex < managerHistoryPaths.length - 1) {
managerHistoryIndex++;
managerData(managerHistoryPaths[managerHistoryIndex]);
}
};
document.getElementById('managerBackFun').onclick = function() {
managerData(removeLastSegment(currentPath));
};
document.getElementById('managerSettingsCopy').onclick = function() {
managerClipboard("copy", "{{copy}}");
};
document.getElementById('managerSettingsCut').onclick = function() {
managerClipboard("cut", "{{cut}}");
};
function managerClipboard(action, messageText) {
if (managerTableDivFilePath) {
createAjaxRequest({ managerClipboard: managerTableDivFilePath, action: action, handleRequestAction: "managerClipboard" }, function(data) {
if (data.message === 1) {
messageFunction("{{file}}" + messageText + " {{to clipboard}}!");
} else {
messageFunction("{{error when}}" + messageText + " {{file}}!");
}
/* managerData(currentPath); */
});
} else {
messageFunction("{{right_click_to_select_file}}");
}
}
let managerSettingsInsertId = document.getElementById('managerSettingsInsert');
managerSettingsInsertId.onclick = function() {
let title;
createAjaxRequest({ name: title, currentPath: currentPath, managerSettingsInsert: "managerSettingsInsert", handleRequestAction: "checkSameName" }, function(data) {
if (data.exists) {
messageFunction("{{file_with_same_name_exists}}");
} else {
createAjaxRequest({ managerSettingsInsert: currentPath, handleRequestAction: "managerSettingsInsert" }, function(data) {
if (data.message === 1) {
messageFunction("{{file_pasted_successfully}}");
} else {
let errorMessage = data.error ? data.error : "{{file_paste_unknown_error}}";
messageFunction("{{error}}: " + errorMessage);
}
managerData(currentPath);
});
}
});
};
let managerSettingsRenameId = document.getElementById('managerSettingsRename');
managerSettingsRenameId.onclick = function() {
if (managerTableDivFilePath) {
let invalidCharacters = /[\/\\:*?"<>|]/;
let managerTableDivFileName = managerTableDivFilePath.split(/[/\\]/).pop();
let title = prompt("{{enter_new_name}}", managerTableDivFileName);
let isFolder = !/\./.test(managerTableDivFileName);
if (title !== null) {
if (title && !invalidCharacters.test(title) && (!isFolder || !title.includes('.'))) {
if (confirm("{{rename_confirm}} " + title + "?")) {
createAjaxRequest({ name: title, currentPath: currentPath, handleRequestAction: "checkSameName" }, function(data) {
if (data.exists) {
messageFunction("{{file_with_same_name_exists}}");
} else {
createAjaxRequest({ managerSettingsRename: managerTableDivFilePath, managerNamePath: title, handleRequestAction: "managerSettingsRename" }, function(data) {
if (data.message === 1) {
messageFunction("{{rename_success}}");
} else {
messageFunction("{{rename_error}}");
}
managerData(currentPath);
});
}
});
}
} else {
messageFunction("{{invalid_name_error}}");
}
}
} else {
messageFunction("{{right_click_to_select_file}}");
}
};
let managerSettingsDeleteId = document.getElementById('managerSettingsDelete');
managerSettingsDeleteId.onclick = function() {
if (managerTableDivFilePath) {
if (confirm("{{delete_confirm}}")) {
createAjaxRequest({ managerSettingsDelete: managerTableDivFilePath, handleRequestAction: "managerSettingsDelete" }, function(data) {
if (data.message === 1) {
messageFunction("{{delete_success}}");
} else {
messageFunction("{{delete_error}}");
}
managerData(currentPath);
});
}
} else {
messageFunction("{{right_click_to_select_file}}");
}
};
document.getElementById('managerSettingsButtonCreateFolder').onclick = function() {
createManagerItem("{{folder}}", "{{enter_new_folder_name}}", "{{invalid_folder_name}}", "{{folder_created_successfully}}");
};
document.getElementById('managerSettingsButtonCreateFile').onclick = function() {
createManagerItem("{{file}}", "{{enter_new_file_name}}", "{{invalid_file_name}}", "{{file_created_successfully}}");
};
function createManagerItem(type, promptMessage, errorMessage, successMessage, nameSuffix = '') {
let title = prompt(promptMessage);
if (title !== null) {
let invalidCharacters = /[\/\\:*?"<>|]/;
let isValidTitle = title && !invalidCharacters.test(title) && !title.startsWith('.') && !title.endsWith('.');
if (type === "{{folder}}") {
isValidTitle = isValidTitle && !title.includes('.');
}
if (isValidTitle) {
title += nameSuffix;
if (confirm("{{create}} " + type + " {{with_name}} " + title + "?")) {
createAjaxRequest({ name: title, currentPath: currentPath, handleRequestAction: "checkSameName" }, function(data) {
if (data.exists) {
messageFunction("{{file_with_same_name_exists}}!");
} else {
createAjaxRequest({ managerSettingsCreate: title, managerType: type, managerNamePath: currentPath, handleRequestAction: "managerSettingsCreate", },
function (data) {
if (data.message === 0) {
messageFunction(successMessage);
} else if (data.message === "noSuccess") {
messageFunction("{{create_error}} " + type + "!");
} else if (data.message === "checkItemExists") {
messageFunction(type + " {{item_already_exists}}");
} else {
messageFunction("{{unknown_error}}");
}
managerData(currentPath);
}
);
}
});
}
} else {
messageFunction(errorMessage);
}
}
}
let managerSettingsPropertiesId = document.getElementById('managerSettingsProperties');;
managerSettingsPropertiesId.onclick = function() {
if (managerTableDivFilePath) {
createAjaxRequest({ managerSettingsProperties: managerTableDivFilePath, handleRequestAction: "managerSettingsProperties" }, function(data) {
let managerPropertiesId = document.getElementById('managerProperties');
let managerPropertiesDivId = document.getElementById('managerPropertiesDiv');
let managerPropertiesTopNameId = document.getElementById('managerPropertiesTopName');
let managerPropertiesWindowPropertiesId = document.getElementById('managerPropertiesWindowProperties');
let managerPropertiesWindowRightsId = document.getElementById('managerPropertiesWindowRights');
let tableProperties = document.createElement('table');
tableProperties.style.width = "100%";
data.forEach(item => {
let row = document.createElement('tr');
let labelCell = document.createElement('td');
let valueCell = document.createElement('td');
labelCell.className = 'managerPropertiesDivDivs';
valueCell.className = 'managerPropertiesDivDivs';
labelCell.textContent = item.label;
valueCell.textContent = item.value;
row.appendChild(labelCell);
row.appendChild(valueCell);
tableProperties.appendChild(row);
});
let tableRights = document.createElement('div');
tableRights.innerHTML= "{{no_rights_yet}}";
managerPropertiesTopNameId.textContent = "{{properties}} " + data[0].value;
managerPropertiesDivId.innerHTML = '';
managerPropertiesWindowPropertiesId.onclick = function() {
managerPropertiesDivId.innerHTML = '';
managerPropertiesDivId.appendChild(tableProperties);
managerPropertiesWindowPropertiesId.style.backgroundColor = "#f3f3f3";
managerPropertiesWindowRightsId.style.backgroundColor = "";
};
managerPropertiesWindowRightsId.onclick = function() {
managerPropertiesDivId.innerHTML = '';
managerPropertiesDivId.appendChild(tableRights);
managerPropertiesWindowPropertiesId.style.backgroundColor = "";
managerPropertiesWindowRightsId.style.backgroundColor = "#f3f3f3";
};
managerPropertiesWindowPropertiesId.click();
if (managerPropertiesId.style.visibility == 'hidden') {
managerPropertiesId.style.visibility = 'visible';
}
let managerPropertiesTopCloseId = document.getElementById('managerPropertiesTopClose');
let managerPropertiesDivButtonOkId = document.getElementById('managerPropertiesDivButtonOk');
let managerPropertiesDivButtonCancelId = document.getElementById('managerPropertiesDivButtonCancel');
managerPropertiesTopCloseId.onclick = function() {
managerPropertiesId.style.visibility = 'hidden';
};
managerPropertiesDivButtonOkId.onclick = function() {
managerPropertiesId.style.visibility = 'hidden';
};
managerPropertiesDivButtonCancelId.onclick = function() {
managerPropertiesId.style.visibility = 'hidden';
};
});
} else {
messageFunction("{{right_click_to_select_file}}");
}
};
//загрузка файла для менеджера
let managerSettingsLoadId = document.getElementById('managerSettingsLoad');
managerSettingsLoadId.onclick = function() {
let fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.addEventListener('change', function() {
createAjaxRequest({ name: fileInput.files[0].name, currentPath: currentPath, handleRequestAction: "checkSameName" }, function(data) {
if (data.exists) {
messageFunction("{{file_with_same_name_exists}}");
} else {
let formData = new FormData()
formData.append('pathFile', fileInput.files[0])
formData.append('pathLoad', currentPath)
handleJsonRpcRequest('pathLoad', formData, 1)
.then(result => {
if (result.error) {
messageFunction("{{file_with_same_name_exists}}")
} else {
messageFunction("{{file_uploaded_successfully}}")
managerData(currentPath)
}
})
.catch(e => {
console.error('Upload error:', e)
})
}
});
});
fileInput.click();
};
}
function removeLastSegment(str) { //удаление текста после последнего "/"
const segments = str.split('/');
if (segments.length > 1) {
segments.pop();
}
return segments.join('/');
}
//окно менеджера настроек
function managerSettings() {
let managerDiv = document.getElementById('managerDiv');
let managerSettingsDiv = document.getElementById('managerSettings');
managerDiv.addEventListener('contextmenu', managerSettingsClick);
touchLong(managerDiv, managerSettingsClick);
}
if (isPhone) document.getElementById('managerDiv').style.paddingBottom = "150px"
if (!isPhone) {
document.querySelectorAll('.managerSettingsButtons').forEach(btn=>{
btn.style.backgroundColor='rgba(255, 255, 255, 1)'
btn.style.borderRadius='5px'
btn.style.padding='2px'
btn.style.margin='3px'
btn.style.cursor='pointer'
btn.style.display='block'
btn.addEventListener('mouseover',()=>btn.style.color='#787878')
btn.addEventListener('mouseout',()=>btn.style.color='')
})
} else {
document.querySelectorAll('.managerSettingsButtons').forEach(btn=>{
btn.style.backgroundImage='url(../../img/pict/b_iconslyb.svg)'
btn.style.height='42px'
btn.style.minWidth='42px'
btn.style.setProperty('background-size','calc(1122px* 1.5)','important')
btn.style.display='inline-block'
btn.style.borderRadius='5px'
btn.style.cursor='pointer'
btn.style.display='flex'
btn.style.flexDirection='column'
btn.style.alignItems='center'
btn.style.fontSize='10px'
btn.style.lineHeight='1'
btn.style.justifyContent = 'flex-end'
btn.style.top='2px'
btn.style.position = 'relative'
btn.style.width = 'auto'
})
let wrap = document.getElementById('managerSettings')
wrap.style.display = 'flex'
wrap.style.maxWidth = '-webkit-fill-available'
wrap.style.overflowX = 'auto'
wrap.style.overflowY = 'hidden'
wrap.style.justifyContent = 'center'
let div = document.getElementById('managerSettingsDiv')
div.style.height = '-webkit-fill-available'
div.style.display = 'inline-flex'
div.style.whiteSpace = 'nowrap'
div.style.width = 'max-content'
div.style.gap = '7px'
div.style.alignItems = 'center'
}
function managerSettingsClick(event) {
event.preventDefault();
let managerSettingsDiv = document.getElementById('managerSettings');
if (!isPhone) {
managerSettingsDiv.style.left = `${touchX}px`;
managerSettingsDiv.style.top = `${touchY}px`;
} else {
managerSettingsDiv.style.bottom = '15px';
managerSettingsDiv.style.width = 'calc(100vw - 42px)';
managerSettingsDiv.style.height = '42px';
managerSettingsDiv.style.left = '15px';
managerSettingsDiv.style.top = 'auto';
managerSettingsDiv.style.boxShadow = 'none';
}
let ids = [
'managerSettingsCopy',
'managerSettingsCut',
'managerSettingsRename',
'managerSettingsDelete',
'managerSettingsProperties',
'managerSettingsLoad',
'managerSettingsInsert',
'managerSettingsButtonCreateFolder',
'managerSettingsButtonCreateFile'
];
ids.forEach(id => {
let el = document.getElementById(id);
if (el) {
if (el.dataset.oldDisplay === undefined) {
el.dataset.oldDisplay = getComputedStyle(el).display;
}
el.style.display = 'none';
}
});
if (event.target.closest('.managerTableDivFile')) {
['managerSettingsCopy','managerSettingsCut','managerSettingsRename','managerSettingsDelete','managerSettingsProperties']
.forEach(id => {
let el = document.getElementById(id);
el.style.display = el.dataset.oldDisplay;
});
} else {
document.getElementById('managerSettingsLoad').style.display = document.getElementById('managerSettingsLoad').dataset.oldDisplay;
createAjaxRequest(
{ checkFolderForFile: "$_SESSION['managerClipboardFile']['path']", handleRequestAction: "checkFolderForFile" },
function(data) {
if (data.message === 1) {
let el = document.getElementById('managerSettingsInsert');
el.style.display = el.dataset.oldDisplay;
}
}
);
['managerSettingsButtonCreateFolder','managerSettingsButtonCreateFile']
.forEach(id => {
let el = document.getElementById(id);
el.style.display = el.dataset.oldDisplay;
});
}
managerSettingsDiv.style.visibility = 'visible';
document.addEventListener('pointerdown', function hideMenu(e) {
if (!managerSettingsDiv.contains(e.target)) {
managerSettingsDiv.style.visibility = 'hidden';
document.removeEventListener('pointerdown', hideMenu);
}
});
}
function managerPathContext(event){
let targetElement=event.target.closest('[path]')
if(targetElement){
let pathValue=targetElement.getAttribute('path')
managerTableDivFilePath=pathValue
}
}
document.addEventListener('contextmenu',managerPathContext)
touchLong(document, managerPathContext)
/* функция сохранение файла через сохронить как */
function saveHow() {
let currentPathHow = currentPath;
if (currentPathHow.startsWith('/')) {
currentPathHow = currentPathHow.slice(1);
}
if (!currentPathHow.endsWith('/')) {
currentPathHow += '/';
}
window.saveContentIdHow(currentPathHow);
}
/* функции открытие страницы */
function openPageBut() {
if (openPageButPath != "no/Select") {
openPage(openPageButPath);
} else {
messageFunction('{{select_file_ending_with_page_php}}');
}
}
/* функции выбора страницы */
function propertiesUrlFun() {
let saveHowNameValue = document.getElementById('saveHowName').value;
if (!saveHowNameValue.includes('.page.php')) return;
let newValue = saveHowNameValue.replace(/\.page\.php/, "");
let cp = currentPath;
if (cp.charAt(0) === "/") {
cp = cp.substring(1);
}
document.getElementById('treePropertiesDivUrlValue').innerHTML = cp + "/" + newValue;
window.managerDataAction = "";
managerDiv.style.visibility = "hidden";
}
/* функции выбора страницы */
function selectImgFormButFun() {
var rawPath = document.getElementById('managerPath').textContent;
var cleanPath = rawPath.trim().replace(/\s*\/\s*/g, '/').replace(/\s+/g, '');
var fileName = document.getElementById('saveHowName').value.trim();
var fullPath = cleanPath + fileName;
if (fullPath.startsWith('/')) {
fullPath = fullPath.slice(1);
}
var img = document.createElement("img");
img.src = fullPath;
img.setAttribute("style", "float: left; margin: 10px; width: 250px; border: 0px solid rgb(0, 0, 0); overflow: hidden;");
var sel = window.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode(img);
}
window.managerDataAction = "";
managerDiv.style.visibility = "hidden";
}
window.managerSettings = managerSettings;
window.managerFun = managerFun;
window.saveHow = saveHow;
window.openPageBut = openPageBut;
window.propertiesUrlFun = propertiesUrlFun;
window.selectImgFormButFun = selectImgFormButFun;
});/* начало */

View File

@@ -0,0 +1,33 @@
<div id="managerDiv" style="visibility: hidden; top: 20%; left: 50%; transform: translate(-50%, -20%);">
</div>
<div id="managerSettings" style="visibility: hidden; top: 0px; left: 0px;">
<div id="managerSettingsDiv">
<span id="managerSettingsCopy" class="managerSettingsButtons" style="background-position: -890px -840px;">{{copy}}</span>
<span id="managerSettingsCut" class="managerSettingsButtons" style="background-position: -1372px -419px;">{{cut}}</span>
<span id="managerSettingsRename" class="managerSettingsButtons" style="background-position: -96px -359px;">{{rename}}</span>
<span id="managerSettingsDelete" class="managerSettingsButtons" style="background-position: -654px -1018px;">{{delete}}</span>
<span id="managerSettingsProperties" class="managerSettingsButtons" style="background-position: -1195px -1076px;">{{properties}}</span>
<span id="managerSettingsLoad" class="managerSettingsButtons" style="background-position: -1059px -2px;">{{upload_file}}</span>
<span id="managerSettingsInsert" class="managerSettingsButtons" style="background-position: -1435px -419px;">{{paste}}</span>
<span id="managerSettingsButtonCreateFile" class="managerSettingsButtons" style="background-position: -642px -839px;">{{create_file}}</span>
<span id="managerSettingsButtonCreateFolder" class="managerSettingsButtons" style="background-position: -1121px -840px;">{{create_folder}}</span>
</div>
</div>
<div id="managerProperties" style="visibility: hidden; top: 20%; left: 50%; transform: translate(-50%, -20%);">
<div id="managerPropertiesTop">
<span id="managerPropertiesTopName" class="managerPropertiesTop"></span>
<span id="managerPropertiesTopClose" class="editib"></span>
</div>
<div id="managerPropertiesMiddle">
<div id="managerPropertiesWindow">
<span id="managerPropertiesWindowProperties" class="managerPropertiesWindowDiv">{{properties}}</span>
<span id="managerPropertiesWindowRights" class="managerPropertiesWindowDiv">{{rights}}</span>
</div>
<div id="managerPropertiesDiv">
</div>
<div id="managerPropertiesDivButtons">
<div id="managerPropertiesDivButtonOk" class="managerPropertiesDivButton">{{ok}}</div>
<div id="managerPropertiesDivButtonCancel" class="managerPropertiesDivButton">{{cancel}}</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,18 @@
<?php
global $path, $_SESSION, $configAdmins;
$lang = include $path . 'main_plugin/manager/lang.php';
$lng = $_SESSION['lng'] ?? 'en';
if (in_array($_SESSION['username'], $configAdmins, true)) {
include_once $path . 'main_plugin/manager/func.manager.php';
$Html = file_get_contents($path . 'main_plugin/manager/manager.php');
foreach ($lang[$lng] as $key => $value) {
$Html = str_replace('{{' . $key . '}}', $value, $Html);
}
echo $Html;
echo '<link rel="stylesheet" href="/main_plugin/manager/manager.css">';
echo '<script type="text/javascript" src="/main_plugin/manager/lang.js.php?lng=' . $lng . '"></script>';
}
?>

View File

@@ -0,0 +1,8 @@
<?php
$lang = include $path . 'lang.php';
$lng = $_GET['lng'] ?? ($_SESSION['lng'] ?? 'en');
$placeholders = [];
foreach ($lang[$lng] as $key => $value) {
$placeholders['{{' . $key . '}}'] = $value;
}
echo strtr(file_get_contents($path . 'pickr.js'), $placeholders);

511
main_plugin/pickr/pickr.css Normal file
View File

@@ -0,0 +1,511 @@
.pcr-app {
position: absolute;
z-index: 1;
}
.pcr-app.hide {
display: none;
}
.theme-container button {
font-family: 'Montserrat', sans-serif;
font-weight: 500;
font-size: 0.95em;
color: #36425b;
outline: none;
background: #e4f1ff;
border: none;
border-bottom: 2px solid rgba(80, 139, 234, 0.67);
padding: 0.6em 0.8em 0.5em;
cursor: pointer;
transition: all 0.3s;
margin: 0 0.5em;
opacity: 0.45;
text-transform: capitalize;
}
.theme-container button.active {
opacity: 1;
}
.theme-container h3 {
font-weight: 500;
color: #36425b;
}
.pickr-container {
margin-top: 2em;
display: none;
}
main > p {
margin-top: 0.35em;
font-size: 0.75em;
font-weight: 500;
color: #42445a;
}
@-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@media screen and (max-width: 1000px) {
body header {
font-size: 0.6em;
padding: 7vh 0;
}
body header a {
padding: 1em 2em;
font-weight: 600;
font-size: 1.05em;
}
main > section {
min-width: 90%;
}
main > section h2 {
font-size: 1em;
}
main > section pre {
font-size: 0.9em;
}
main section.demo .hint svg {
height: 1.2em;
}
main section.demo .hint span {
transform: translate3d(-3em, -1.4em, 0);
font-size: 0.6em;
}
}
/* --------------------- */
/*! Pickr 1.9.1 MIT | https://github.com/Simonwep/pickr */
.pickr {
position: relative;
overflow: visible;
transform: translateY(0)
}
.pickr * {
box-sizing: border-box;
outline: none;
border: none;
-webkit-appearance: none
}
.pickr .pcr-button {
position: relative;
height: 2em;
width: 2em;
padding: .5em;
cursor: pointer;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Helvetica Neue",Arial,sans-serif;
border-radius: .15em;
background: url("data:image/svg+xml;utf8, <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 50 50\" stroke=\"%2342445A\" stroke-width=\"5px\" stroke-linecap=\"round\"><path d=\"M45,45L5,5\"></path><path d=\"M45,5L5,45\"></path></svg>") no-repeat center;
background-size: 0;
transition: all .3s
}
.pickr .pcr-button::before {
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url("data:image/svg+xml;utf8, <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 2 2\"><path fill=\"white\" d=\"M1,0H2V1H1V0ZM0,1H1V2H0V1Z\"/><path fill=\"gray\" d=\"M0,0H1V1H0V0ZM1,1H2V2H1V1Z\"/></svg>");
background-size: .5em;
border-radius: .15em;
z-index: -1
}
.pickr .pcr-button::before {
z-index: initial
}
.pickr .pcr-button::after {
position: absolute;
content: "";
top: 0;
left: 0;
height: 100%;
width: 100%;
transition: background .3s;
background: var(--pcr-color);
border-radius: .15em
}
.pickr .pcr-button.clear {
background-size: 70%
}
.pickr .pcr-button.clear::before {
opacity: 0
}
.pickr .pcr-button.clear:focus {
box-shadow: 0 0 0 1px rgba(255,255,255,.85),0 0 0 3px var(--pcr-color)
}
.pickr .pcr-button.disabled {
cursor: not-allowed
}
.pickr *,.pcr-app * {
box-sizing: border-box;
outline: none;
border: none;
-webkit-appearance: none
}
.pickr input:focus,.pickr input.pcr-active,.pickr button:focus,.pickr button.pcr-active,.pcr-app input:focus,.pcr-app input.pcr-active,.pcr-app button:focus,.pcr-app button.pcr-active {
box-shadow: 0 0 0 1px rgba(255,255,255,.85),0 0 0 3px var(--pcr-color)
}
.pickr .pcr-palette,.pickr .pcr-slider,.pcr-app .pcr-palette,.pcr-app .pcr-slider {
transition: box-shadow .3s
}
.pickr .pcr-palette:focus,.pickr .pcr-slider:focus,.pcr-app .pcr-palette:focus,.pcr-app .pcr-slider:focus {
box-shadow: 0 0 0 1px rgba(255,255,255,.85),0 0 0 3px rgba(0,0,0,.25)
}
.pcr-app {
display: flex;
flex-direction: column;
z-index: 10000;
border-radius: .1em;
background: #fff;
transition: opacity .3s,visibility 0s .3s;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Helvetica Neue",Arial,sans-serif;
box-shadow: 0 .15em 1.5em 0 rgba(0,0,0,.1),0 0 1em 0 rgba(0,0,0,.03);
}
.pcr-app.visible {
transition: opacity .3s;
visibility: visible;
opacity: 1
}
.pcr-app .pcr-swatches {
display: flex;
flex-wrap: wrap;
margin-top: .75em
}
.pcr-app .pcr-swatches.pcr-last {
margin: 0
}
@supports(display: grid) {
.pcr-app .pcr-swatches {
display:grid;
align-items: center;
grid-template-columns: repeat(auto-fit, 1.75em)
}
}
.pcr-app .pcr-swatches>button {
font-size: 1em;
position: relative;
width: calc(1.75em - 5px);
height: calc(1.75em - 5px);
border-radius: .15em;
cursor: pointer;
margin: 2.5px;
flex-shrink: 0;
justify-self: center;
transition: all .15s;
overflow: hidden;
background: rgba(0,0,0,0);
z-index: 1
}
.pcr-app .pcr-swatches>button::before {
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url("data:image/svg+xml;utf8, <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 2 2\"><path fill=\"white\" d=\"M1,0H2V1H1V0ZM0,1H1V2H0V1Z\"/><path fill=\"gray\" d=\"M0,0H1V1H0V0ZM1,1H2V2H1V1Z\"/></svg>");
background-size: 6px;
border-radius: .15em;
z-index: -1
}
.pcr-app .pcr-swatches>button::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--pcr-color);
border: 1px solid rgba(0,0,0,.05);
border-radius: .15em;
box-sizing: border-box
}
.pcr-app .pcr-swatches>button:hover {
filter: brightness(1.05)
}
.pcr-app .pcr-swatches>button:not(.pcr-active) {
box-shadow: none
}
.pcr-app .pcr-interaction {
display: flex;
flex-wrap: wrap;
align-items: center;
margin: 0 -0.2em 0 -0.2em
}
.pcr-app .pcr-interaction>* {
/* margin: 0 .2em */
}
.pcr-app .pcr-interaction input {
letter-spacing: .07em;
font-size: .75em;
text-align: center;
cursor: pointer;
color: #75797e;
background: #f1f3f4;
border-radius: .15em;
transition: all .15s;
padding: .45em .5em;
}
.pcr-app .pcr-interaction input:hover {
filter: brightness(0.975)
}
.pcr-app .pcr-interaction input:focus {
box-shadow: 0 0 0 1px rgba(255,255,255,.85),0 0 0 3px rgba(66,133,244,.75)
}
.pcr-app .pcr-interaction .pcr-result {
color: #75797e;
text-align: left;
/* flex: 1 1 8em; */
width: 6em;
transition: all .2s;
border-radius: .15em;
background: #f1f3f4;
cursor: text
}
.pcr-app .pcr-interaction .pcr-result::-moz-selection {
background: #4285f4;
color: #fff
}
.pcr-app .pcr-interaction .pcr-result::selection {
background: #4285f4;
color: #fff
}
.pcr-app .pcr-interaction .pcr-type.active {
color: #fff;
background: #4285f4
}
.pcr-app .pcr-interaction .pcr-save,.pcr-app .pcr-interaction .pcr-cancel,.pcr-app .pcr-interaction .pcr-clear {
color: #fff;
width: auto
}
.pcr-app .pcr-interaction .pcr-save,.pcr-app .pcr-interaction .pcr-cancel,.pcr-app .pcr-interaction .pcr-clear {
color: #fff
}
.pcr-app .pcr-interaction .pcr-save:hover,.pcr-app .pcr-interaction .pcr-cancel:hover,.pcr-app .pcr-interaction .pcr-clear:hover {
filter: brightness(0.925)
}
.pcr-app .pcr-interaction .pcr-save {
background: #4285f4
}
.pcr-app .pcr-interaction .pcr-clear,.pcr-app .pcr-interaction .pcr-cancel {
background: #f44250
}
.pcr-app .pcr-interaction .pcr-clear:focus,.pcr-app .pcr-interaction .pcr-cancel:focus {
box-shadow: 0 0 0 1px rgba(255,255,255,.85),0 0 0 3px rgba(244,66,80,.75)
}
.pcr-app .pcr-selection .pcr-picker {
position: absolute;
height: 18px;
width: 18px;
border: 2px solid #fff;
border-radius: 100%;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none
}
.pcr-app .pcr-selection .pcr-color-palette,.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity {
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
display: flex;
flex-direction: column;
cursor: grab;
cursor: -webkit-grab
}
.pcr-app .pcr-selection .pcr-color-palette:active,.pcr-app .pcr-selection .pcr-color-chooser:active,.pcr-app .pcr-selection .pcr-color-opacity:active {
cursor: grabbing;
cursor: -webkit-grabbing
}
.pcr-app[data-theme=nano] {
width: 150px;
max-width: 150px;
}
.pcr-app[data-theme=nano] .pcr-swatches {
margin-top: .6em;
padding: 0 .6em
}
.pcr-app[data-theme=nano] .pcr-interaction {
padding: 0 .6em .6em .6em
}
.pcr-app[data-theme=nano] .pcr-selection {
display: grid;
/* grid-gap: .6em;
grid-template-columns: 1fr 4fr; */
grid-template-rows: 5fr auto auto;
align-items: center;
width: 100%;
align-self: flex-start
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview {
grid-area: 2/1/4/1;
height: 100%;
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
margin-left: .6em
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview .pcr-last-color {
display: none
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview .pcr-current-color {
position: relative;
background: var(--pcr-color);
width: 2em;
height: 2em;
border-radius: 50em;
overflow: hidden
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview .pcr-current-color::before {
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url("data:image/svg+xml;utf8, <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 2 2\"><path fill=\"white\" d=\"M1,0H2V1H1V0ZM0,1H1V2H0V1Z\"/><path fill=\"gray\" d=\"M0,0H1V1H0V0ZM1,1H2V2H1V1Z\"/></svg>");
background-size: .5em;
border-radius: .15em;
z-index: -1
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-palette {
grid-area: 1/1/2/3;
width: 150px;
height: 100px;
z-index: 1
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-palette .pcr-palette {
border-radius: .15em;
width: 100%;
height: 100%
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-palette .pcr-palette::before {
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url("data:image/svg+xml;utf8, <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 2 2\"><path fill=\"white\" d=\"M1,0H2V1H1V0ZM0,1H1V2H0V1Z\"/><path fill=\"gray\" d=\"M0,0H1V1H0V0ZM1,1H2V2H1V1Z\"/></svg>");
background-size: .5em;
border-radius: .15em;
z-index: -1
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser {
grid-area: 2/2/2/2
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity {
grid-area: 3/2/3/2
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-selection .pcr-color-opacity {
margin: 0 .6em
}
.pcr-color-chooser {
height: .5em;
width: 140px;
margin: 10px 5px 0px 5px;
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser .pcr-picker,.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity .pcr-picker {
top: 50%;
transform: translateY(-50%)
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser .pcr-slider,.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity .pcr-slider {
flex-grow: 1;
border-radius: 50em
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser .pcr-slider {
background: linear-gradient(to right, hsl(0, 100%, 50%), hsl(60, 100%, 50%), hsl(120, 100%, 50%), hsl(180, 100%, 50%), hsl(240, 100%, 50%), hsl(300, 100%, 50%), hsl(0, 100%, 50%))
}
.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity .pcr-slider {
background: linear-gradient(to right, transparent, black),url("data:image/svg+xml;utf8, <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 2 2\"><path fill=\"white\" d=\"M1,0H2V1H1V0ZM0,1H1V2H0V1Z\"/><path fill=\"gray\" d=\"M0,0H1V1H0V0ZM1,1H2V2H1V1Z\"/></svg>");
background-size: 100%,.25em
}

4992
main_plugin/pickr/pickr.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
<?php
global $path, $_SESSION, $configAdmins;
if (in_array($_SESSION['username'], $configAdmins, true)) {
echo '<link rel="stylesheet" href="/main_plugin/pickr/pickr.css">';
echo '<script type="text/javascript" src="/main_plugin/pickr/lang.js.php?lng=' . $lng . '"></script>';
}
?>

View File

@@ -0,0 +1,8 @@
<?php
$lang = include $path . 'lang.php';
$lng = $_GET['lng'] ?? ($_SESSION['lng'] ?? 'en');
$placeholders = [];
foreach ($lang[$lng] as $key => $value) {
$placeholders['{{' . $key . '}}'] = $value;
}
echo strtr(file_get_contents($path . 'siteSettings.js'), $placeholders);

View File

@@ -0,0 +1,77 @@
<?php
$lang = [
'ru' => [
'authorization' => 'Авторизация',
'login_label' => 'Логин',
'password_label' => 'Пароль',
'incorrect_login_password' => 'Неверный логин или пароль!',
'repeat_password_label' => 'Повторите пароль',
'email_label' => 'Почта',
'fill_all_fields' => 'Вы должны заполнить все поля!',
'passwords_do_not_match' => 'Пароли не совпадают!',
'account_creation_request_sent' => 'Запрос на создание аккаунта отправлен!',
'user_exists' => 'Пользователь с таким логином уже существует!',
'account_creation_error' => 'Ошибка при создании аккаунта!',
'incorrect_email' => 'Вы ввели неправильную почту!',
'account_creation_request_error' => 'Ошибка при отправке запроса на создание аккаунта!',
'account_authorization' => 'Авторизация аккаунта',
'login' => 'Войти',
'register' => 'Зарегистрироваться',
'logoff' => 'Выйти',
'editor_page' => 'Редактор страницы',
'file_manager' => 'Файловый менеджер',
'site_tree' => 'Дерево сайта',
'save_data_question' => 'Сохранить данные?',
'save_new_page' => 'Сохраните новую страницу!',
],
'en' => [
'authorization' => 'Authorization',
'login_label' => 'Login',
'password_label' => 'Password',
'incorrect_login_password' => 'Incorrect login or password!',
'repeat_password_label' => 'Repeat password',
'email_label' => 'Email',
'fill_all_fields' => 'You must fill out all fields!',
'passwords_do_not_match' => 'Passwords do not match!',
'account_creation_request_sent' => 'Account creation request sent!',
'user_exists' => 'User with this login already exists!',
'account_creation_error' => 'Error while creating the account!',
'incorrect_email' => 'Incorrect email!',
'account_creation_request_error' => 'Error sending account creation request!',
'account_authorization' => 'Account authorization',
'login' => 'Login',
'register' => 'Register',
'logoff' => 'Log out',
'editor_page' => 'Page editor',
'file_manager' => 'File manager',
'site_tree' => 'Site tree',
'save_data_question' => 'Save changes?',
'save_new_page' => 'Save the new page!',
],
'lv' => [
'authorization' => 'Autentifikācija',
'login_label' => 'Lietotājvārds',
'password_label' => 'Parole',
'incorrect_login_password' => 'Nepareizs lietotājvārds vai parole!',
'repeat_password_label' => 'Atkārtot paroli',
'email_label' => 'E-pasts',
'fill_all_fields' => 'Jums jāaizpilda visi lauki!',
'passwords_do_not_match' => 'Paroles nesakrīt!',
'account_creation_request_sent' => 'Pieprasījums par konta izveidi nosūtīts!',
'user_exists' => 'Lietotājs ar šo lietotājvārdu jau pastāv!',
'account_creation_error' => 'Kļūda, izveidojot kontu!',
'incorrect_email' => 'Nepareizs e-pasts!',
'account_creation_request_error' => 'Kļūda, nosūtot pieprasījumu par konta izveidi!',
'account_authorization' => 'Konta autentifikācija',
'login' => 'Ieiet',
'register' => 'Reģistrēties',
'logoff' => 'Iziet',
'editor_page' => 'Lapas redaktors',
'file_manager' => 'Failu pārvaldnieks',
'site_tree' => 'Saites koks',
'save_data_question' => 'Saglabāt datus?',
'save_new_page' => 'Saglabājiet jauno lapu!',
],
];
return $lang;

View File

@@ -0,0 +1,16 @@
<?php
global $path, $_SESSION, $configAdmins;
$lang = include $path . 'main_plugin/siteSettings/lang.php';
$lng = $_SESSION['lng'] ?? 'en';
if (in_array($_SESSION['username'], $configAdmins, true)) {
$Html = file_get_contents($path . 'main_plugin/siteSettings/siteSettings.php');
foreach ($lang[$lng] as $key => $value) {
$Html = str_replace('{{' . $key . '}}', $value, $Html);
}
echo $Html;
echo '<link rel="stylesheet" href="/main_plugin/siteSettings/siteSettings.css">';
echo '<script type="text/javascript" src="/main_plugin/siteSettings/lang.js.php?lng=' . $lng . '"></script>';
}
?>

View File

@@ -0,0 +1,33 @@
#siteSettingsButton {
background: url(../../img/pict/mc_iconslyb.svg) -1840px 1664px;
width: 22px;
height: 22px;
cursor: pointer;
user-select: none;
float: right;
margin-left: 5px;
}
#siteSettingsButton:hover {
background-image: url(../../img/pict/g_iconslyb.svg);
}
#siteSettings {
margin: -2px -63px 0px 0px;
position: absolute;
top: 30px;
right: 80px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 1001;
font-family: Arial, sans-serif;
padding: 2px;
}
.siteSettingsOption {
padding: 2px;
cursor: pointer;
user-select: none;
}
.siteSettingsOption:hover {
color: rgb(153, 153, 153);
text-shadow: -1px -1px #666, 1px 1px #FFF;
}

View File

@@ -0,0 +1,46 @@
addEventListener("load", function() {
let menu = document.getElementById('siteSettings');
let button = document.getElementById('siteSettingsButton');
menu.onclick = function() {
menu.style.display = 'none';
};
function hbodyHref() {
let hbody = document.getElementById('hbody');
let links = hbody.querySelectorAll('a[href]');
links.forEach(link => {
let originalHref = link.getAttribute('href');
link.removeAttribute('href');
link.onclick = function(event) {
event.preventDefault();
hbodyHrefFunction(originalHref);
};
});
}
async function hbodyHrefFunction(href) {
if (basis3.style.visibility === "visible" && window.contentIsEdit == true) {
messageQueue.push("{{save_data_question}}");
try {
const userConfirmed = await messageCreateQuestion();
if (userConfirmed) {
if (window.newPageFunValue == "newPage") {
document.getElementById("saveHow").click();
messageFunction("{{save_new_page}}");
return;
} else {
await saveChanges();
}
}
} catch (error) {
console.log("Ошибка: ", error);
}
}
window.location.href = href;
}
hbodyHref();
});

View File

@@ -0,0 +1,25 @@
<span id="siteSettingsButton" onclick="toggleMenu()"></span>
<div id="siteSettings" class="borderStyle" style="display: none;">
<div id="editor" class="siteSettingsOption" onclick="basisVis()">{{editor_page}}</div>
<div id="manager" class="siteSettingsOption" onclick="basisVisManager()">{{file_manager}}</div>
<div id="siteTree" class="siteSettingsOption" onclick="basisVisSiteTree()">{{site_tree}}</div>
</div>
<script>
window.addEventListener("load", function() {
try {
var siteSettingsButton = document.getElementById("siteSettingsButton").outerHTML;
var siteSettings = document.getElementById("siteSettings").outerHTML;
document.getElementById("siteSettingsButton").remove();
document.getElementById("siteSettings").remove();
var container = document.getElementById("hbody");
if (!container) throw new Error("#hbody не найден для siteSettings");
container.insertAdjacentHTML("beforeend", siteSettingsButton);
container.insertAdjacentHTML("beforeend", siteSettings);
} catch (e) {
console.error("Ошибка в блоке siteSettings:", e);
}
});
</script>

View File

@@ -0,0 +1,145 @@
<?php
/* перебор файлов и папок */
function scanDirTree() {
global $path, $_SESSION;
$file = $path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'filepath.' . $_SESSION['lng'] . '.php';
$content = file_get_contents($file);
$xml = simplexml_load_string($content);
function generateArray($xml, $urlParts = [], $isOpen = false) {
$result = [];
foreach ($xml->children() as $child) {
$item = [
'name' => (string) $child->attributes()->name,
'tag' => $child->getName(),
'children' => generateArray($child, $urlParts, $isOpen),
'isOpen' => false,
'url' => (string) $child->attributes()->url,
'title' => (string) $child->attributes()->title,
'template' => (string) $child->attributes()->template,
'PageMenu' => (string) $child->attributes()->PageMenu,
'users' => (string) $child->attributes()->users,
'group' => (string) $child->attributes()->group,
'content' => (string)$child
];
if (!empty($urlParts) && $urlParts[0] == $item['tag']) {
array_shift($urlParts);
if (empty($urlParts)) {
if ($item['tag'] !== 'index') {
$item['isOpen'] = true;
}
}
}
$result[] = $item;
}
return $result;
}
$url = $_SERVER['REQUEST_URI'];
$urlParts = array_filter(explode('/', trim($url, '/')));
$urlParts = array_map(function($part) {
return pathinfo($part, PATHINFO_FILENAME);
}, $urlParts);
$result = generateArray($xml, $urlParts);
return ['items' => $result];
}
/* сохронения древа */
function saveTree($params) {
global $path, $_SESSION;
$file = $path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'filepath.' . ($_SESSION['lng'] ?? 'en') . '.php';
if (!isset($params['data']) || !is_array($params['data'])) {
return ['status' => 'error', 'message' => 'Invalid data'];
}
$treeData = $params['data'];
$siteName = isset($treeData['sitename']) ? htmlspecialchars($treeData['sitename'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '';
$slogan = isset($treeData['slogan']) ? htmlspecialchars($treeData['slogan'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '';
$xmlContent = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".
"<site>\n".
" <sitename>$siteName</sitename>\n".
" <slogan>$slogan</slogan>\n".
buildXml($treeData['children'] ?? []).
"</site>\n";
$result = @file_put_contents($file, $xmlContent);
if ($result === false) {
return ['status' => 'error', 'message' => 'Failed to write file'];
}
if (!file_exists($file)) {
return ['status' => 'error', 'message' => 'File does not exist after write'];
}
return ['status' => 'success', 'message' => 'File saved successfully'];
}
function buildXml($data, $level = 1) {
$xml = "";
foreach ($data as $item) {
if (!isset($item['name']) || empty($item['name'])) continue;
$tag = htmlspecialchars(trim(explode(' ', $item['name'])[0]), ENT_XML1 | ENT_QUOTES, 'UTF-8');
$nameAttr = htmlspecialchars(trim($tag), ENT_XML1 | ENT_QUOTES, 'UTF-8');
$attributes = [
'url' => isset($item['url']) ? htmlspecialchars($item['url'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
'title' => isset($item['title']) ? htmlspecialchars($item['title'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
'name' => $nameAttr,
'template' => isset($item['template']) ? htmlspecialchars($item['template'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
'PageMenu' => isset($item['PageMenu']) ? htmlspecialchars($item['PageMenu'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
'users' => isset($item['users']) ? htmlspecialchars($item['users'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
'group' => isset($item['group']) ? htmlspecialchars($item['group'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : ''
];
$attrString = "";
foreach ($attributes as $key => $value) {
$attrString .= " $key='$value'";
}
$xml .= str_repeat(" ", $level) . "<$tag$attrString>\n";
if (!empty($item['children'])) {
$xml .= buildXml($item['children'], $level + 1);
}
$xml .= str_repeat(" ", $level) . "</$tag>\n";
}
return $xml;
}
/* текущий файл страницы */
function currentPageFile() {
global $_SESSION, $path;
return ['folders' => $folders];
}
/* текущий файл страницы */
function getFolderNames() {
global $path;
$folder = $path . DIRECTORY_SEPARATOR . $_POST['folder'];
$folders = array();
if ($folder && is_dir($folder)) {
$files = scandir($folder);
foreach ($files as $file) {
if ($file != '.' && $file != '..' && is_dir($folder . DIRECTORY_SEPARATOR . $file)) {
$folders[] = $file;
}
}
}
return ['folders' => $folders];
}
?>

View File

@@ -0,0 +1,8 @@
<?php
$lang = include $path . 'lang.php';
$lng = $_GET['lng'] ?? ($_SESSION['lng'] ?? 'en');
$placeholders = [];
foreach ($lang[$lng] as $key => $value) {
$placeholders['{{' . $key . '}}'] = $value;
}
echo strtr(file_get_contents($path . 'site_tree.js'), $placeholders);

View File

@@ -0,0 +1,83 @@
<?php
$lang = [
'ru' => [
'tree_site_title' => 'Дерево сайта',
'save' => 'Сохранить',
'add' => 'Добавить',
'paste' => 'Вставить',
'copy' => 'Копировать',
'rename' => 'Переименовать',
'properties' => 'Свойства',
'delete' => 'Удалить',
'choose' => 'Выбрать',
'enter_new_name' => 'Введите новое имя',
'name_only_english_letters' => 'Имя должно содержать только английские буквы без пробелов и символов.',
'no_item_selected' => 'Нет выбранного элемента.',
'delete_all_subpages' => 'Удалить все подстраницы страницы',
'save_new_page' => 'Сохраните новую страницу!',
'enter_tag_for_new_page' => 'Введите тег для новой страницы:',
'tag_only_english_letters' => 'Тег должен содержать только английские буквы без пробелов и символов.',
'tag_already_exists' => 'Элемент с таким тегом уже существует.',
'select_page_for_link' => 'Выбор страницы для ссылки',
'rights' => 'Права',
'ok' => 'ОК',
'cancel' => 'Отмена',
'select' => 'Выбрать',
'no_rights' => 'Прав пока что нету',
'properties' => 'Свойства',
],
'en' => [
'tree_site_title' => 'Site Tree',
'save' => 'Save',
'add' => 'Add',
'paste' => 'Paste',
'copy' => 'Copy',
'rename' => 'Rename',
'properties' => 'Properties',
'delete' => 'Delete',
'choose' => 'Choose',
'enter_new_name' => 'Enter new name',
'name_only_english_letters' => 'Name must contain only English letters without spaces and symbols.',
'no_item_selected' => 'No item selected.',
'delete_all_subpages' => 'Delete all subpages of the page',
'save_new_page' => 'Save the new page!',
'enter_tag_for_new_page' => 'Enter tag for the new page:',
'tag_only_english_letters' => 'Tag must contain only English letters without spaces and symbols.',
'tag_already_exists' => 'An element with this tag already exists.',
'select_page_for_link' => 'Select page for the link',
'rights' => 'Rights',
'ok' => 'OK',
'cancel' => 'Cancel',
'select' => 'Select',
'no_rights' => 'No rights yet',
'properties' => 'Properties',
],
'lv' => [
'tree_site_title' => 'Saites koks',
'save' => 'Saglabāt',
'add' => 'Pievienot',
'paste' => 'Ielīmēt',
'copy' => 'Kopēt',
'rename' => 'Pārdēvēt',
'properties' => 'Īpašības',
'delete' => 'Dzēst',
'choose' => 'Izvēlēties',
'enter_new_name' => 'Ievadiet jaunu nosaukumu',
'name_only_english_letters' => 'Nosaukumam jābūt tikai angļu burtiem bez atstarpēm un simboliem.',
'no_item_selected' => 'Nav izvēlēts neviens elements.',
'delete_all_subpages' => 'Dzēst visas apakšlapas',
'save_new_page' => 'Saglabājiet jauno lapu!',
'enter_tag_for_new_page' => 'Ievadiet taga nosaukumu jaunai lapai:',
'tag_only_english_letters' => 'Tagam jābūt tikai angļu burtiem bez atstarpēm un simboliem.',
'tag_already_exists' => 'Tādā pašā tagā jau pastāv elements.',
'select_page_for_link' => 'Izvēlieties lapu saitei',
'rights' => 'Tiesības',
'ok' => 'Labi',
'cancel' => 'Atcelt',
'select' => 'Izvēlēties',
'no_rights' => 'Nav tiesību vēl',
'properties' => 'Īpašības',
],
];
return $lang;

View File

@@ -0,0 +1,18 @@
<?php
global $path, $_SESSION, $configAdmins;
$lang = include $path . 'main_plugin/site_tree/lang.php';
$lng = $_SESSION['lng'] ?? 'en';
if (in_array($_SESSION['username'], $configAdmins, true)) {
include_once $path . 'main_plugin/site_tree/func.site_tree.php';
$Html = file_get_contents($path . 'main_plugin/site_tree/site_tree.php');
foreach ($lang[$lng] as $key => $value) {
$Html = str_replace('{{' . $key . '}}', $value, $Html);
}
echo $Html;
echo '<link rel="stylesheet" href="/main_plugin/site_tree/site_tree.css">';
echo '<script type="text/javascript" src="/main_plugin/site_tree/lang.js.php?lng=' . $lng . '"></script>';
}
?>

View File

@@ -0,0 +1,189 @@
/* основной div */
#treeDiv {
display: inline-block;
position: fixed;
z-index: 100;
user-select: none;
background-color: rgba(255, 255, 255, 0.92);
border: 1px solid #000000;
width: 800px;
border-radius: 5px;
height: 600px;
font-size: 1em;
box-shadow: 0px 0px 5px #777;
max-width: calc(100% - 20px);
}
/* верхний див */
#treeTop {
text-align: center;
border-bottom: 1px #40464d solid;
padding: 5px;
background-color: rgba(255, 255, 255, 0.6);
}
#treeTopTitle {
text-align: center;
}
#treeCloseFun {
float: right;
width: 20px;
height: 20px;
background-position: -159px -121px;
cursor: pointer;
}
/* основное древо сайта */
#treeTableDiv {
top: 36px;
height: 480px;
position: relative;
margin: 0px 20px 0px 20px;
border: 1px #40464d solid;
overflow-y: overlay;
border-radius: 5px;
width: calc(100% - 40px);
}
li.has-children::marker {
content: "► ";
}
li.has-children.open::marker {
content: "▼ ";
}
li.no-children::marker {
content: "□ ";
}
/* окно страницы */
.tree-details {
display: none;
background: white;
border: 1px solid black;
padding: 3px;
margin: 3px 0px 10px 0px;
z-index: 10;
position: relative;
width: max-content;
}
.tree-details div {
margin: 3px;
}
/* окно настроек */
#treeSettings {
display: inline-block;
position: fixed;
z-index: 100;
user-select: none;
background-color: rgba(255, 255, 255, 0.92);
border: 1px solid #000000;
border-radius: 5px;
font-size: 1em;
box-shadow: 0px 0px 5px #777;
padding: 5px;
animation: fadeIn 0.5s ease-in forwards;
}
.treeSettingsButtons {
background-color: rgba(255, 255, 255, 1);
border-radius: 5px;
padding: 2px;
margin: 3px;
cursor: pointer;
display: block;
}
.treeSettingsButtons:hover {
color: #787878;
}
#treeSettingsSave {
border: 1px #40464d solid;
border-radius: 5px;
padding: 5px;
margin: 44px 20px 0px 10px;
cursor: pointer;
display: block;
width: 91px;
float: right;
}
#treeSettingsSave:hover {
color: #787878;
}
/* окно свойств */
#treeProperties {
display: inline-block;
position: fixed;
z-index: 100;
user-select: none;
background-color: rgba(255, 255, 255, 0.97);
border: 1px solid #000000;
border-radius: 5px;
font-size: 1em;
box-shadow: 0px 0px 5px #777;
width: 600px;
max-width: calc(100% - 20px);
}
#treePropertiesMiddle {
margin: 0px 20px 0px 20px;
}
#treePropertiesTop {
border-bottom: 1px solid #000000;
padding: 5px;
text-align: center;
}
#treePropertiesTopName {
text-align: center;
}
#treePropertiesTopClose {
float: right;
width: 20px;
height: 20px;
background-position: -159px -121px;
cursor: pointer;
}
#treePropertiesWindow {
text-align: center;
display: flex;
}
.treePropertiesWindowDiv {
cursor: pointer;
text-align: center;
width: 50%;
display: inline-block;
padding: 9px;
}
.treePropertiesWindowDiv:hover {
color: #787878;
}
#treePropertiesDiv {
border: 1px solid #000000;
border-radius: 5px;
}
.treePropertiesDivDivs {
padding: 6px 8px 6px 8px;
border-radius: 5px;
}
#treePropertiesDivButtons {
padding: 9px;
display: flex;
justify-content: right;
align-items: center;
}
#treePropertiesDivButtons {
text-align: center;
}
.treePropertiesDivButton {
margin: 3px 3px 3px 15px;
cursor: pointer;
display: inline-block;
}
.treePropertiesDivButton:hover {
color: #787878;
}

View File

@@ -0,0 +1,795 @@
/* показ окна древа */
let idCounter = 0;
siteTreeGeneration();
/* генерация html древа */
function siteTreeGeneration() {
handleJsonRpcRequest('scanDirTree', {}, 1).then(data => {
if (data && Array.isArray(data.items)) {
let treeContainer = document.getElementById('treeTableDiv');
treeContainer.innerHTML = generateTreeHtml(data.items, "");
let firstSpan = treeContainer.querySelector('span');
if (!treeContainer.innerHTML.includes('background-color: #e5f0ff;')) {
firstSpan.style.backgroundColor = '#e5f0ff';
}
}
}).catch(err => {
console.error(err);
});
idCounter = 0;
}
window.siteTreeGeneration = siteTreeGeneration;
let selectedTreeItem = "";
let selectedTreeItemAdd = "";
let firstLi = true;
function generateTreeHtml(items, checkChildren) {
let html = '<ul style="margin-top: 10px; margin-bottom: 10px; list-style-type: none;">';
items.forEach(item => {
if (!item.name && item.tag == "sitename" && checkChildren == "") {
html += generateTreeHtmlSitename(item, "treeHtmlSitename");
return;
}
if (!item.name && item.tag == "slogan" && checkChildren == "") {
html += generateTreeHtmlSitename(item, "treeHtmlSlogan");
return;
}
let hasChildren = item.children && item.children.length;
let isOpen = (item.isOpen || item.tag === 'index') ? 'block' : 'none';
let markerText = hasChildren ? (isOpen === 'block' ? '▼' : '►') : '■';
let style = item.isOpen ? 'background-color: #e5f0ff;' : '';
id = "";
if (firstLi == true) {
id = 'id="treeHtmlIndex"';
firstLi = false;
}
html += `<li ${id} style="position: relative; margin: 0px 0px 8px -20px;">`;
html += `<span class="tree-item" style="cursor: pointer; ${style} padding: 3px 6px 3px 3px;" onclick="toggleChildren(this)">`;
html += `<span class="tree-marker">${markerText}</span> <span class="tree-text">${item.tag} <span class="tree-text-name">&nbsp;(${item.title})</span></span>`;
html += `<div class="tree-data" style="display: none;">`;
html += `url: ${item.url}<br>`;
html += `title: ${item.title}<br>`;
html += `name: ${item.name}<br>`;
html += `template: ${item.template}<br>`;
html += `PageMenu: ${item.PageMenu}<br>`;
html += `users: ${item.users}<br>`;
html += `group: ${item.group}`;
html += `</div>`;
html += `</span>`;
if (hasChildren) {
html += `<div class="details" style="display: ${isOpen};">` + generateTreeHtml(item.children, "children") + `</div>`;
}
html += `</li>`;
if (style) {
selectedTreeItemAdd = `url: ${item.url}<br>title: ${item.title}<br>name: ${item.name}<br>template: ${item.template}<br>PageMenu: ${item.PageMenu}<br>users: ${item.users}<br>group: ${item.group}`;
}
});
html += `</ul>`;
if (checkChildren == "") {
firstLi = true;
}
moveTreePage();
return html;
}
function generateTreeHtmlSitename(item, id) {
let html = `<li style="position: relative; margin: 0px 0px 8px -20px;">`;
html += `<span id="${id}" class="tree-item" style="cursor: pointer; padding: 3px 6px 3px 3px;" onclick="toggleChildren(this)">`;
html += `<span class="tree-marker">${item.tag}:</span> <span class="tree-text">${item.content}</span>`;
html += `</span>`;
html += `</li>`;
return html;
}
/* перемещение страниц */
function moveTreePage() {
let treeTableDiv = document.getElementById('treeTableDiv');
let draggedItem = null;
let offsetY = 0;
let startX = 0;
function isDescendant(parent, child) {
while (child) {
if (child === parent) return true;
child = child.parentNode;
}
return false;
}
treeTableDiv.addEventListener('pointerdown', function(event) {
if (window.treeSettingsMode != '') return;
let li = event.target.closest('li');
if (li && event.button === 0) {
if (li.id === 'treeHtmlIndex') return;
let treeItem = event.target.closest('.tree-item');
if (!treeItem) return;
draggedItem = li;
offsetY = event.clientY - treeItem.getBoundingClientRect().top;
li.style.opacity = '0.5';
event.preventDefault();
}
});
document.addEventListener('pointermove', function(event) {
if (window.treeSettingsMode != '') return;
if (draggedItem && event.target.tagName !== "LI" && event.target.tagName !== "UL") {
let elemBelow = document.elementFromPoint(event.clientX, event.clientY);
let liBelow = elemBelow ? elemBelow.closest('li') : null;
if (liBelow && liBelow !== draggedItem && !isDescendant(draggedItem, liBelow)) {
let rect = liBelow.getBoundingClientRect();
let isTargetIndex = liBelow.parentElement?.closest('#treeHtmlIndex') !== null && liBelow.parentElement?.closest('#treeTableDiv')?.querySelector('#treeHtmlIndex')?.contains(liBelow.parentElement);
if (isTargetIndex) {
let parentDetails = draggedItem.parentElement.closest('.details');
if (event.clientY < rect.top + rect.height / 2) {
liBelow.parentNode.insertBefore(draggedItem, liBelow);
} else {
liBelow.parentNode.insertBefore(draggedItem, liBelow.nextSibling);
}
if (parentDetails) {
let parentUl = parentDetails.querySelector('ul');
if (parentUl && parentUl.children.length === 0) {
let parentLi = parentDetails.closest('li');
parentDetails.remove();
if (parentLi) {
let marker = parentLi.querySelector('.tree-marker');
if (marker) marker.textContent = '■';
}
}
}
}
}
}
});
document.addEventListener('pointerup', function() {
if (window.treeSettingsMode != '') return;
if (draggedItem) {
draggedItem.style.opacity = '';
draggedItem = null;
}
});
treeTableDiv.addEventListener('pointermove', function(event) {
if (window.treeSettingsMode != '') return;
let li = event.target.closest('li');
if (li && event.button === 0 && draggedItem) {
let treeItem = event.target.closest('.tree-item');
if (!treeItem) return;
startX = event.clientX - treeItem.getBoundingClientRect().left;
let upperLi = draggedItem.previousElementSibling;
if (upperLi) {
if (startX > 60) {
let details = upperLi.querySelector('.details');
if (!details) {
details = document.createElement('div');
details.className = 'details';
let ul = document.createElement('ul');
ul.setAttribute('style', 'margin-top: 10px; margin-bottom: 10px; list-style-type: none;');
details.appendChild(ul);
upperLi.appendChild(details);
} else {
if (details.style.display === 'none') {
details.style.display = 'block';
}
}
let marker = upperLi.querySelector('.tree-marker');
if (marker) {
marker.textContent = '▼';
}
draggedItem._attachedTo = upperLi;
let detailsUl = details.querySelector('ul');
if (detailsUl && draggedItem.parentNode !== detailsUl) {
detailsUl.appendChild(draggedItem);
}
} else if (startX < 20) {
let details = upperLi.querySelector('.details');
if (details && details.contains(draggedItem)) {
let parentUl = upperLi.parentNode;
parentUl.insertBefore(draggedItem, upperLi.nextSibling);
delete draggedItem._attachedTo;
let detailsUl = details.querySelector('ul');
if (detailsUl && detailsUl.children.length === 0) {
details.style.display = 'none';
let marker = upperLi.querySelector('.tree-marker');
if (marker) {
marker.textContent = '►';
}
}
}
}
}
}
});
}
addEventListener("load", function() {
movementMenu("treeDiv");
movementMenu("treeProperties");
/* сохронения древа */
let treeSettingsSaveId = document.getElementById("treeSettingsSave");
treeSettingsSaveId.addEventListener('click', saveTree);
function saveTree() {
let treeTableDiv = document.getElementById('treeTableDiv');
let ul = treeTableDiv.querySelector('ul');
let treeData = ul ? parseUl(ul) : [];
let siteNameElement = document.getElementById("treeHtmlSitename");
let siteName = siteNameElement ? siteNameElement.querySelector('.tree-text').textContent.trim() : '';
let sloganElement = document.getElementById("treeHtmlSlogan");
let slogan = sloganElement ? sloganElement.querySelector('.tree-text').textContent.trim() : '';
let fullData = { sitename: siteName, slogan: slogan, children: treeData };
handleJsonRpcRequest('saveTree', fullData, 1).then(response => {
console.log(response);
});
}
function parseUl(ul) {
let result = [];
let items = ul.children;
for (let item of items) {
let span = item.querySelector('.tree-item .tree-text');
let textName = item.querySelector('.tree-text-name');
let dataDiv = item.querySelector('.tree-data');
let childrenUl = item.querySelector('.details > ul');
if (span && dataDiv) {
let data = parseDataDiv(dataDiv);
let mainText = span.childNodes[0].textContent.trim();
let extraText = textName ? textName.textContent.trim() : "";
data['tag'] = mainText;
data['name'] = mainText + (extraText ? " " + extraText : "");
if (childrenUl) data['children'] = parseUl(childrenUl);
result.push(data);
}
}
return result;
}
function parseDataDiv(div) {
let data = {};
let lines = div.innerHTML.split(/<br\s*\/?>/i);
for (let line of lines) {
let parts = line.split(': ');
if (parts.length === 2) data[parts[0].trim()] = parts[1].trim();
}
return data;
}
/* окно настроек древа */
let targetTreeItem = "";
let treeSettingsDiv = document.getElementById('treeSettings');
function treeSettings() {
const treeDivDiv = document.getElementById('treeDiv');
if (!treeDivDiv) return;
if (window.treeSettingsMode == 'linkFromPage') {
document.getElementById('treeTopTitle').innerHTML = "{{select_page_for_link}}";
document.getElementById('treeSettingsSave').style.display = "none";
} else {
document.getElementById('treeTopTitle').innerHTML = "{{tree_site_title}}";
document.getElementById('treeSettingsSave').style.display = "block";
}
function showTreeSettings(event) {
event.preventDefault();
let treeItem = event.target.closest('.tree-item');
targetTreeItem = treeItem ? treeItem : "";
treeSettingsDiv.style.left = `${touchX}px`;
treeSettingsDiv.style.top = `${touchY}px`;
document.getElementById('treeSettingsAdd').style.display = '';
document.getElementById('treeSettingsPaste').style.display = '';
document.getElementById('treeSettingsCopy').style.display = '';
document.getElementById('treeSettingsRename').style.display = '';
document.getElementById('treeSettingsProperties').style.display = '';
document.getElementById('treeSettingsDelete').style.display = '';
document.getElementById('treeSettingsChoose').style.display = '';
treeSettingsDiv.style.visibility = targetTreeItem ? "visible" : "hidden";
let tag = targetTreeItem instanceof Element
? targetTreeItem.querySelector('.tree-text')?.textContent.trim()
: null;
if (tag == "index" && !targetTreeItem.closest('li li')) {
document.getElementById('treeSettingsRename').style.display = 'none';
document.getElementById('treeSettingsDelete').style.display = 'none';
}
if (targetTreeItem) {
let firstId = targetTreeItem.closest('li')?.firstElementChild?.id;
if (firstId == "treeHtmlSitename" || firstId == "treeHtmlSlogan") {
['Add','Copy','Paste','Delete','Properties','Choose'].forEach(id=>{
document.getElementById('treeSettings'+id).style.display = 'none';
});
}
}
if (selectedTreeItem == "") {
document.getElementById('treeSettingsPaste').style.display = 'none';
}
document.addEventListener('pointerdown', function hideMenu(e) {
if (!treeSettingsDiv.contains(e.target)) {
treeSettingsDiv.style.visibility = "hidden";
document.removeEventListener('pointerdown', hideMenu);
}
});
if (window.treeSettingsMode == 'linkFromPage') {
['Add','Copy','Paste','Delete','Rename','Properties'].forEach(id=>{
document.getElementById('treeSettings'+id).style.display = 'none';
});
} else {
document.getElementById('treeSettingsChoose').style.display = 'none';
}
if ([].slice.call(document.getElementById('treeSettingsDiv').children).every(el=>
getComputedStyle(el).display === 'none'
)) {
treeSettingsDiv.style.visibility = 'hidden';
}
}
function setupTreeSettingsHandler(){
const treeDiv=document.getElementById('treeDiv')
if(!treeDiv) return
treeDiv.removeEventListener('click',showTreeSettings)
treeDiv.oncontextmenu=null
if(isPhone){
touchLong(treeDiv,showTreeSettings)
}else{
treeDiv.oncontextmenu=showTreeSettings
}
}
setupTreeSettingsHandler();
window.addEventListener('resize', setupTreeSettingsHandler);
}
window.treeSettings = treeSettings;
/* кнопки окна настроек древа */
/* кнопки добовление страниц / начало */
let treeSettingsAddId = document.getElementById('treeSettingsAdd');
treeSettingsAddId.addEventListener('click', treeSettingsAddFun);
function treeSettingsAddFun() {
if (window.newPageFunValue == "newPage") {
document.getElementById("saveHow").click();
messageFunction("{{save_new_page}}");
return;
}
let container = getContainer();
let pageUrl = selectedTreeItemAdd;
let treeText = prompt("{{enter_tag_for_new_page}}");
treeText = treeText ? treeText.trim() : "";
if (!/^[A-Za-z]+$/.test(treeText)) {
messageFunction("{{tag_only_english_letters}}");
return;
}
if (treeText !== "") {
let exists = false;
let lis = container.querySelectorAll('li');
lis.forEach(function(li) {
let txt = li.querySelector('.tree-text');
if (txt && txt.textContent.trim() === treeText) {
exists = true;
}
});
if (exists) {
alert("{{tag_already_exists}}");
return;
}
let newItem = createNewTreeItem(pageUrl, treeText);
let newLi = document.createElement('li');
newLi.style.position = 'relative';
newLi.style.margin = '0px 0px 8px -20px';
newLi.appendChild(newItem);
container.appendChild(newLi);
if (targetTreeItem) {
targetTreeItem.querySelector('.tree-marker').textContent = '▼';
}
}
treeSettingsDiv.style.visibility = "hidden";
}
let treeSettingsPasteId = document.getElementById('treeSettingsPaste');
treeSettingsPasteId.addEventListener('click', treeSettingsPasteFun);
function treeSettingsPasteFun() {
let container = getContainer();
let clonedItem = selectedTreeItem.cloneNode(true);
let treeText = prompt("{{enter_tag_for_new_page}}");
treeText = treeText ? treeText.trim() : "";
if (!/^[A-Za-z]+$/.test(treeText)) {
messageFunction("{{tag_only_english_letters}}");
return;
}
if (treeText !== "") {
let exists = false;
let lis = container.querySelectorAll('li');
lis.forEach(function(li) {
let txt = li.querySelector('.tree-text');
if (txt && txt.textContent.trim() === treeText) {
exists = true;
}
});
if (exists) {
messageFunction("{{tag_already_exists}}");
return;
}
let textSpan = clonedItem.querySelector('.tree-text');
let extractedTitle = selectedTreeItem.querySelector('.tree-data').innerHTML.match(/title:\s*([^<]+)/)?.[1].trim();
textSpan.innerHTML = `${treeText} <span class="tree-text-name">&nbsp;(${extractedTitle})</span>`;
let newLi = document.createElement('li');
newLi.style.position = 'relative';
newLi.style.margin = '0px 0px 8px -20px';
newLi.appendChild(clonedItem);
container.appendChild(newLi);
if (targetTreeItem) {
targetTreeItem.querySelector('.tree-marker').textContent = '▼';
}
}
treeSettingsDiv.style.visibility = "hidden";
}
function createNewTreeItem(pageUrl, treeText) {
let newItem = document.createElement('span');
newItem.className = 'tree-item';
newItem.style.cursor = 'pointer';
newItem.style.padding = '3px 6px 3px 3px';
let marker = document.createElement('span');
marker.className = 'tree-marker';
marker.textContent = '■';
let textSpan = document.createElement('span');
textSpan.className = 'tree-text';
let extractedTitle = selectedTreeItemAdd.match(/title:\s*([^<]+)/)?.[1].trim() || "";
textSpan.innerHTML = `${treeText} <span class="tree-text-name">&nbsp;(${extractedTitle})</span>`;
let dataDiv = document.createElement('div');
dataDiv.className = 'tree-data';
dataDiv.style.display = 'none';
dataDiv.innerHTML = `${pageUrl}`;
newItem.appendChild(marker);
newItem.insertAdjacentText('beforeend', ' ');
newItem.appendChild(textSpan);
newItem.appendChild(dataDiv);
newItem.setAttribute('onclick', 'toggleChildren(this)');
return newItem;
}
function getContainer() {
let container;
if (targetTreeItem) {
let li = targetTreeItem.closest('li');
let details = li.querySelector('.details');
if (!details) {
details = document.createElement('div');
details.className = 'details';
details.style.display = 'block';
li.appendChild(details);
}
let detailsUl = details.querySelector('ul');
if (!detailsUl) {
detailsUl = document.createElement('ul');
detailsUl.style.marginTop = '10px';
detailsUl.style.marginBottom = '10px';
detailsUl.style.listStyleType = 'none';
details.appendChild(detailsUl);
}
container = detailsUl;
} else {
let treeTableDiv = document.getElementById('treeTableDiv');
let mainUl = treeTableDiv.querySelector('ul');
if (!mainUl) {
mainUl = document.createElement('ul');
mainUl.style.marginTop = '10px';
mainUl.style.marginBottom = '10px';
mainUl.style.listStyleType = 'none';
treeTableDiv.appendChild(mainUl);
}
container = mainUl;
}
return container;
}
/* кнопки добовление страниц / конец */
let treeSettingsCopyId = document.getElementById('treeSettingsCopy');
treeSettingsCopyId.addEventListener('click', treeSettingsCopyFun);
function treeSettingsCopyFun() {
selectedTreeItem = targetTreeItem.cloneNode(true);
selectedTreeItem.querySelector('.tree-marker').textContent = '■';
if (selectedTreeItem.classList.contains('tree-item')) {
selectedTreeItem.style.backgroundColor = '';
} else {
let treeItem = selectedTreeItem.querySelector('.tree-item');
if (treeItem) treeItem.style.backgroundColor = '';
}
treeSettingsDiv.style.visibility = "hidden";
}
let treeSettingsRenameId = document.getElementById('treeSettingsRename');
treeSettingsRenameId.addEventListener('click', treeSettingsRenameFun);
function treeSettingsRenameFun() {
if (targetTreeItem) {
let li = targetTreeItem.closest('li');
if (li) {
let treeText = li.querySelector('.tree-text');
if (treeText) {
let firstTextNode = treeText.firstChild;
let currentName = firstTextNode.nodeValue.trim();
let newText = prompt("{{enter_new_name}}", currentName);
if (newText !== null) {
newText = newText.trim();
if (!/^[A-Za-z]+$/.test(newText)) {
messageFunction("{{name_only_english_letters}}");
return;
}
firstTextNode.nodeValue = newText + ' ';
}
}
}
} else {
messageFunction("{{no_item_selected}}");
}
treeSettingsDiv.style.visibility = "hidden";
}
let treeSettingsDeleteId = document.getElementById('treeSettingsDelete');
treeSettingsDeleteId.addEventListener('click', treeSettingsDeleteFun);
async function treeSettingsDeleteFun() {
if (targetTreeItem) {
let li = targetTreeItem.closest('li');
if (li) {
let parentUl = li.parentElement;
if (li.querySelector('li')) {
messageQueue.push(`{{delete_all_subpages}} ${targetTreeItem.querySelector('.tree-text').textContent}?`);
const userConfirmed = await messageCreateQuestion();
if (userConfirmed) {
li.remove();
}
} else {
li.remove();
}
if (parentUl && parentUl.children.length === 0) {
let detailsDiv = parentUl.parentElement;
if (detailsDiv && detailsDiv.classList.contains('details')) {
let parentLi = detailsDiv.closest('li');
if (parentLi) {
let marker = parentLi.querySelector('.tree-marker');
if (marker) marker.textContent = '■';
}
detailsDiv.remove();
}
}
}
} else {
messageFunction("{{no_item_selected}}");
}
let treeSettingsDiv = document.getElementById('treeSettings');
treeSettingsDiv.style.visibility = "hidden";
}
/* свойтсва страниц */
let treeSettingsPropertiesId = document.getElementById('treeSettingsProperties');;
treeSettingsPropertiesId.onclick = function() {
let treePropertiesId = document.getElementById('treeProperties');
let treePropertiesDivId = document.getElementById('treePropertiesDiv');
let treePropertiesTopNameId = document.getElementById('treePropertiesTopName');
let treePropertiesWindowPropertiesId = document.getElementById('treePropertiesWindowProperties');
let treePropertiesWindowRightsId = document.getElementById('treePropertiesWindowRights');
let tableProperties = document.createElement('table');
tableProperties.style.width = "100%";
tableProperties.innerHTML= treePropertiesDiv();
let tableRights = document.createElement('div');
tableRights.innerHTML = `{{no_rights}}`;
treePropertiesTopNameId.textContent = `{{properties}}`;
treePropertiesDivId.innerHTML = '';
treePropertiesWindowPropertiesId.onclick = function() {
treePropertiesDivId.innerHTML = '';
treePropertiesDivId.appendChild(tableProperties);
treePropertiesWindowPropertiesId.style.backgroundColor = "#f3f3f3";
treePropertiesWindowRightsId.style.backgroundColor = "";
};
treePropertiesWindowRightsId.onclick = function() {
treePropertiesDivId.innerHTML = '';
treePropertiesDivId.appendChild(tableRights);
treePropertiesWindowPropertiesId.style.backgroundColor = "";
treePropertiesWindowRightsId.style.backgroundColor = "#f3f3f3";
};
treePropertiesWindowPropertiesId.click();
if (treePropertiesId.style.visibility == 'hidden') {
treePropertiesId.style.visibility = 'visible';
}
let treePropertiesTopCloseId = document.getElementById('treePropertiesTopClose');
let treePropertiesDivButtonOkId = document.getElementById('treePropertiesDivButtonOk');
let treePropertiesDivButtonCancelId = document.getElementById('treePropertiesDivButtonCancel');
treePropertiesTopCloseId.onclick = function() {
treePropertiesId.style.visibility = 'hidden';
if (window.managerDataAction == "propertiesUrl") {
window.managerDataAction = "";
managerDiv.style.visibility = "hidden";
}
};
treePropertiesDivButtonOkId.onclick = function() {
saveTreePropertiesDiv();
treePropertiesId.style.visibility = 'hidden';
if (window.managerDataAction == "propertiesUrl") {
window.managerDataAction = "";
managerDiv.style.visibility = "hidden";
}
};
treePropertiesDivButtonCancelId.onclick = function() {
treePropertiesId.style.visibility = 'hidden';
if (window.managerDataAction == "propertiesUrl") {
window.managerDataAction = "";
managerDiv.style.visibility = "hidden";
}
};
};
function saveTreePropertiesDiv() {
let treeDataDiv = lastRightClickedItem.querySelector('.tree-data');
let rows = document.querySelectorAll('#treePropertiesDiv table tr');
let newData = [];
rows.forEach(row => {
let key = row.querySelector('td:first-child').textContent.trim();
let valueCell = row.querySelector('td:last-child');
let value = '';
if (key.toLowerCase() === 'pagemenu') {
let inputs = valueCell.querySelectorAll('input');
value = Array.from(inputs)
.map(input => input.value.trim())
.filter(v => v)
.join(',');
}
else if (key.toLowerCase() === 'template') {
value = valueCell.querySelector('select').value;
}
else if (key.toLowerCase() === 'url') {
value = document.getElementById('treePropertiesDivUrlValue').textContent;
}
else {
let input = valueCell.querySelector('input');
value = input ? input.value : valueCell.textContent.trim();
}
newData.push(`${key}: ${value}`);
});
if (treeDataDiv) {
treeDataDiv.innerHTML = newData.join('<br>');
let name = newData.find(d => d.startsWith('name: '))?.split(': ')[1] || '';
let title = newData.find(d => d.startsWith('title: '))?.split(': ')[1] || '';
let textSpan = lastRightClickedItem.querySelector('.tree-text');
if (textSpan) {
textSpan.childNodes[0].textContent = name + ' ';
let nameSpan = textSpan.querySelector('.tree-text-name');
if (nameSpan) nameSpan.innerHTML = `&nbsp;(${title})`;
}
}
}
/* Выбор страницы для ссылки */
let treeSettingsChooseId = document.getElementById('treeSettingsChoose');
treeSettingsChooseId.addEventListener('click', treeSettingsChooseFun);
function treeSettingsChooseFun() {
var parts = [];
var span = targetTreeItem;
var li = span.closest('li');
while (li) {
var itemSpan = li.querySelector(':scope > span.tree-item');
var text = itemSpan.querySelector('.tree-text').firstChild.textContent.trim();
parts.unshift(text);
li = li.parentElement.closest('li');
}
if (parts[0] === 'index') {
parts.shift();
}
var url;
if (parts.length) {
url = 'http://slava.home/' + parts.join('/') + '.html';
} else {
url = 'http://slava.home';
}
document.getElementById('link2').value = url;
document.getElementById("treeDiv").style.visibility = "hidden";
document.getElementById("treeProperties").style.visibility = "hidden";
document.getElementById("treeSettings").style.visibility = "hidden";
}
function treePropertiesDiv() {
if (!treePropertiesDivElement) return "";
let dataHTML = treePropertiesDivElement.querySelector('.tree-data')?.innerHTML || "";
let lines = dataHTML.split('<br>');
let rows = [];
for (let line of lines) {
if (!line.trim()) continue;
let parts = line.split(':');
let key = parts[0].trim();
let value = parts.slice(1).join(':').trim();
let inputHtml = value;
if (key.toLowerCase() === "url") {
inputHtml = `<span id="treePropertiesDivUrlValue" style="font-size: inherit;">${value}</span> <button id="treePropertiesDivUrl" type="button">{{select}}</button>`;
} else if (key.toLowerCase() === "title") {
inputHtml = `<input type="text" value="${value}" style="font-size: inherit;">`;
} else if (key.toLowerCase() === "name") {
inputHtml = `<input type="text" value="${value}" style="font-size: inherit;" pattern="[A-Za-z]+" oninput="this.value = this.value.replace(/[^A-Za-z]/g, '')">`;
} else if (key.toLowerCase() === "template") {
let defaultTemplate = value;
inputHtml = `<select id="templateSelect" style="font-size: inherit;"><option selected>${defaultTemplate}</option></select>`;
setTimeout(function() {
handleJsonRpcRequest('getFolderNames', { folder: '/template' }, 1).then(data => {
let select = document.getElementById('templateSelect');
if (select && data && data.folders) {
select.innerHTML = '';
data.folders.forEach(folder => {
select.innerHTML += `<option${folder === defaultTemplate ? ' selected' : ''}>${folder}</option>`;
});
}
});
}, 0);
} else if (key.toLowerCase() === "pagemenu") {
let values = value.split(",");
while (values.length < 3) {
values.push("");
}
inputHtml = values.map((val, index) =>
`<input type="text" value="${val}" style="width: 30px; font-size: inherit; text-align: center;"
oninput="this.value = this.value.replace(/[^0-9]/g, '');">`
).join(" , ");
} else if (key.toLowerCase() === "users") {
inputHtml = `<input type="text" value="${value}" style="font-size: inherit;" readonly disabled>`;
} else if (key.toLowerCase() === "group") {
inputHtml = `<input type="text" value="${value}" style="font-size: inherit;" readonly disabled>`;
}
rows.push(`<tr><td class="managerPropertiesDivDivs">${key}</td><td class="managerPropertiesDivDivs">${inputHtml}</td></tr>`);
}
setTimeout(treePropertiesDivFunc, 0);
return `<table style="width: 100%;">${rows.join('')}</table>`;
}
function treePropertiesDivFunc() {
document.getElementById('treePropertiesDivUrl').onclick = function() {
window.managerDataAction = "propertiesUrl";
managerData("/content");
managerDiv.style.visibility = "visible";
document.getElementById("settingsMain_d").style.visibility="hidden";
};
}
let lastRightClickedItem = null;
let treePropertiesDivElement = null;
function treeContext(event){
let treeItem=event.target.closest('.tree-item')
if(treeItem){
lastRightClickedItem=treeItem
treePropertiesDivElement=treeItem
}
}
document.addEventListener('contextmenu',treeContext)
touchLong(document,treeContext)
}); /* начало */

View File

@@ -0,0 +1,39 @@
<div id="treeDiv" style="visibility: hidden; top: 20%; left: 50%; transform: translate(-50%, -20%);">
<div id="treeTop">
<span id="treeTopTitle">{{tree_site_title}}</span>
<span id="treeCloseFun" class="editib"></span>
</div>
<div id="treeTableDiv"></div>
<span id="treeSettingsSave">{{save}}</span>
</div>
<div id="treeSettings" style="visibility: hidden; top: 0px; left: 0px;">
<div id="treeSettingsDiv">
<span id="treeSettingsAdd" class="treeSettingsButtons">{{add}}</span>
<span id="treeSettingsPaste" class="treeSettingsButtons">{{paste}}</span>
<span id="treeSettingsCopy" class="treeSettingsButtons">{{copy}}</span>
<span id="treeSettingsRename" class="treeSettingsButtons">{{rename}}</span>
<span id="treeSettingsProperties" class="treeSettingsButtons">{{properties}}</span>
<span id="treeSettingsDelete" class="treeSettingsButtons">{{delete}}</span>
<span id="treeSettingsChoose" class="treeSettingsButtons">{{choose}}</span>
</div>
</div>
<div id="treeProperties" style="visibility: hidden; top: 20%; left: 50%; transform: translate(-50%, -20%);">
<div id="treePropertiesTop">
<span id="treePropertiesTopName" class="treePropertiesTop"></span>
<span id="treePropertiesTopClose" class="editib"></span>
</div>
<div id="treePropertiesMiddle">
<div id="treePropertiesWindow">
<span id="treePropertiesWindowProperties" class="treePropertiesWindowDiv">{{properties}}</span>
<span id="treePropertiesWindowRights" class="treePropertiesWindowDiv">{{rights}}</span>
</div>
<div id="treePropertiesDiv">
</div>
<div id="treePropertiesDivButtons">
<div id="treePropertiesDivButtonOk" class="treePropertiesDivButton">{{ok}}</div>
<div id="treePropertiesDivButtonCancel" class="treePropertiesDivButton">{{cancel}}</div>
</div>
</div>
</div>