@@ -0,0 +1,26 @@ | |||
Главред | Glavred | |||
1.0.0 | |||
https://git.opengamestudio.org/kornerr/glavred | |||
/макет|template.html | |||
/макет|template.css | |||
/макет|template.json | |||
x /функции|functions.js | |||
x /загрузка|load.js | |||
/загрузка|load.череда | |||
/пуск|run.js | |||
/пуск|run.череда | |||
/выбор-файла|file-selection.js | |||
/выбор-файла|file-selection.череда | |||
/редактирование|editing.js | |||
/редактирование|editing.череда | |||
/сохранение|saving.js | |||
/сохранение|saving.череда | |||
/меню-публикации|publication-menu.js | |||
/меню-публикации|publication-menu.череда |
@@ -0,0 +1,67 @@ | |||
ЗадатьУказанныйФайл = function(мир) | |||
{ | |||
мир.файл = мир.файлы[мир.номерВыбранногоФайла]; | |||
}; | |||
// // // // | |||
НеОтслеживатьРедактирование = function(мир) | |||
{ | |||
мир.отслеживатьРедактирование = false; | |||
}; | |||
// // // // | |||
ОтслеживатьРедактирование = function(мир) | |||
{ | |||
мир.отслеживатьРедактирование = true; | |||
}; | |||
// // // // | |||
ЗадатьПараметрФайла = function(мир) | |||
{ | |||
var файл = мир.файлы[мир.номерВыбранногоФайла]; | |||
задатьПараметрВСтрокеПоиска("📁", файл); | |||
}; | |||
// // // // | |||
ОтобразитьСодержимоеВыбранногоФайла = function(мир) | |||
{ | |||
var файл = мир.файлы[мир.номерВыбранногоФайла]; | |||
var содержимое = мир.временноеСодержимое[файл]; | |||
if (!содержимое) | |||
{ | |||
содержимое = мир.редактируемыйМодуль.содержимое[файл]; | |||
}; | |||
мир.редактор.session.setValue(содержимое); | |||
}; | |||
// // // // | |||
ОтобразитьВыборФайла = function(мир) | |||
{ | |||
var id = мир.макет.константы.файл; | |||
// Очищаем выбор. | |||
for (var номер in мир.файлы) | |||
{ | |||
$(`#${id}-${номер}-элемент`).removeClass("uk-active"); | |||
} | |||
// Отображаем выбор. | |||
$(`#${id}-${мир.номерВыбранногоФайла}-элемент`).addClass("uk-active"); | |||
}; | |||
@@ -0,0 +1,7 @@ | |||
выбрали файл | |||
задать указанный файл | |||
не отслеживать редактирование | |||
отобразить выбор файла | |||
отобразить содержимое выбранного файла | |||
задать параметр файла | |||
отслеживать редактирование |
@@ -0,0 +1,57 @@ | |||
const ИМЯ = "Редактор | Editor"; | |||
// // // // | |||
ЗапуститьРедактор = function(мир) | |||
{ | |||
var модуль = мир.модули.модульПоИмени(ИМЯ); | |||
var составляющие = [ | |||
"/пуск|run", | |||
"/выбор-файла|file-selection", | |||
"/редактирование|editing", | |||
"/сохранение|saving", | |||
"/меню-публикации|publication-menu", | |||
]; | |||
for (var номер in составляющие) | |||
{ | |||
var составляющая = составляющие[номер]; | |||
модуль.исполнитьФайл(`${составляющая}.js`); | |||
модуль.исполнитьЧереду(мир, `${составляющая}.череда`); | |||
} | |||
мир.уведомить("пуск редактора"); | |||
}; | |||
// // // // | |||
ЗагрузитьБиблиотекиРедактора = function(мир) | |||
{ | |||
var указатели = [ | |||
"https://bitbucket.org/gitjs/ace/raw/1.4.12/0000", | |||
"https://bitbucket.org/gitjs/jquery/raw/3.5.1/0000", | |||
"https://bitbucket.org/gitjs/uikit/raw/3.2.0/0000", | |||
]; | |||
var сообщение = "Загрузка библиотек | Loading libraries"; | |||
console.debug(сообщение, указатели); | |||
var html = ""; | |||
for (var номер in указатели) | |||
{ | |||
var указатель = указатели[номер]; | |||
html += `<li>${указатель}</li>`; | |||
} | |||
document.body.innerHTML += `<p>${сообщение}</p><ul>${html}</ul>`; | |||
мир.модули.использовали.подписатьРаз(function() { | |||
мир.уведомить("ручной пуск"); | |||
мир.уведомить("загрузили библиотеки редактора"); | |||
}); | |||
мир.модули.использовать(указатели); | |||
}; | |||
@@ -0,0 +1,4 @@ | |||
пуск | |||
загрузить библиотеки редактора | |||
загрузили библиотеки редактора | |||
запустить редактор |
@@ -0,0 +1,32 @@ | |||
.tm-sidebar-left | |||
{ | |||
width: 240px !important; | |||
position: fixed; | |||
top: 80px; | |||
bottom: 0; | |||
padding: 40px; | |||
border-right: 1px #e5e5e5 solid; | |||
overflow: auto; | |||
} | |||
.tm-nav .uk-nav-header | |||
{ | |||
padding: 8px 0; | |||
border-bottom: 1px #e5e5e5 solid; | |||
} | |||
#редактор | |||
{ | |||
width: calc(100% - 320px); | |||
height: calc(100% - 80px); | |||
position: fixed; | |||
top: 80px; | |||
left: 320px; | |||
right: 0; | |||
bottom: 0; | |||
} | |||
.ошибка | |||
{ | |||
margin: 1em; | |||
} |
@@ -0,0 +1,87 @@ | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<meta charset="utf-8"> | |||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | |||
<link rel="stylesheet" href="макет|template.css"> | |||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.2.0/dist/css/uikit.min.css" /> | |||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.2.0/dist/js/uikit.min.js"></script> | |||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.2.0/dist/js/uikit-icons.min.js"></script> | |||
<script src="https://cdn.jsdelivr.net/gh/ajaxorg/ace-builds@v1.4.11/src-min-noconflict/ace.js"></script> | |||
<script src="https://cdn.jsdelivr.net/gh/ajaxorg/ace-builds@v1.4.11/src-min-noconflict/mode-javascript.js"></script> | |||
<script> | |||
function настроитьAce() | |||
{ | |||
var редактор = window.ace.edit("редактор"); | |||
редактор.session.setMode("ace/mode/javascript"); | |||
} | |||
</script> | |||
</head> | |||
<body onload="настроитьAce()"> | |||
<!-- МАКЕТ_НАЧАЛО --> | |||
<!-- TEMPLATE_BEGIN --> | |||
<div class="tm-navbar uk-navbar-container" uk-sticky> | |||
<div class="uk-container uk-container-expand"> | |||
<nav class="uk-navbar"> | |||
<div class="uk-navbar-left"> | |||
<a id="${заголовок}" class="uk-navbar-item uk-logo"> | |||
<!-- ПРИМЕР_НАЧАЛО --> | |||
<!-- SAMPLE_BEGIN --> | |||
Редактор | Editor | |||
<!-- ПРИМЕР_КОНЕЦ --> | |||
<!-- SAMPLE_END --> | |||
</a> | |||
<a id="${версия}"> | |||
<!-- ПРИМЕР_НАЧАЛО --> | |||
<!-- SAMPLE_BEGIN --> | |||
1.0.0 | |||
<!-- ПРИМЕР_КОНЕЦ --> | |||
<!-- SAMPLE_END --> | |||
</a> | |||
</div> | |||
<div class="uk-navbar-right"> | |||
<ul id="${действия}" class="uk-navbar-nav"> | |||
<!-- ПРИМЕР_НАЧАЛО --> | |||
<!-- SAMPLE_BEGIN --> | |||
<li> | |||
<a>💾</a> | |||
</li> | |||
<!-- ПРИМЕР_КОНЕЦ --> | |||
<!-- SAMPLE_END --> | |||
</ul> | |||
</div> | |||
</nav> | |||
</div> | |||
</div> | |||
<div class="tm-sidebar-left"> | |||
<ul id="${меню}" class="uk-nav uk-nav-default tm-nav"> | |||
<!-- ПРИМЕР_НАЧАЛО --> | |||
<!-- SAMPLE_BEGIN --> | |||
<li class="uk-nav-header">📦 Зав | Mgr</li> | |||
<li class="uk-active"><a>/загрузка|load.js</a></li> | |||
<li><a>/загрузка|load.череда</a></li> | |||
<li><a>/основа|main.js</a></li> | |||
<li><a>/основа|main.череда</a></li> | |||
<!-- ПРИМЕР_КОНЕЦ --> | |||
<!-- SAMPLE_END --> | |||
</ul> | |||
</div> | |||
<div id="редактор"></div> | |||
<!-- МАКЕТ_КОНЕЦ --> | |||
<!-- TEMPLATE_END --> | |||
</body> | |||
</html> |
@@ -0,0 +1,6 @@ | |||
{ | |||
"действие": "<li id='${id}-элемент'><a id='${id}-ссылка'>${название}</a></li>", | |||
"заголовокМеню": "<li class='uk-nav-header'>${название}</li>", | |||
"пунктМеню": "<li id='${id}-элемент'><a id='${id}-ссылка'><span id='${id}-изменение' hidden>• </span>${название}</a></li>", | |||
"выбранныйПунктМеню": "<li class='uk-active' id='${id}-элемент'><a id='${id}-ссылка'><span id='${id}-изменение' hidden>• </span>${название}</a></li>" | |||
} |
@@ -0,0 +1 @@ | |||
@@ -0,0 +1,353 @@ | |||
const ИМЯ = "Редактор | Editor"; | |||
// // // // | |||
ЗадатьВременноеСодержимое = function(мир) | |||
{ | |||
мир.временноеСодержимое = {}; | |||
}; | |||
// // // // | |||
ЗадатьКнопкуСохранения = function(мир) | |||
{ | |||
var кнопка = мир.макет.элементы.действие | |||
.replace("${название}", "💾") | |||
.replace(/\$\{id\}/g, `${мир.макет.константы.сохранить}`) | |||
; | |||
$(`#${мир.макет.константы.действия}`).append(кнопка); | |||
$(`#${мир.макет.константы.сохранить}-ссылка`).click(function() { | |||
мир.уведомить("выбрали сохранить"); | |||
}); | |||
}; | |||
// // // // | |||
НастроитьОтслеживаниеРедактирования = function(мир) | |||
{ | |||
мир.отслеживатьРедактирование = true; | |||
мир.редактор.session.on("change", function(delta) { | |||
if (мир.отслеживатьРедактирование) | |||
{ | |||
мир.уведомить("редактирование"); | |||
} | |||
}); | |||
}; | |||
// // // // | |||
ВыбратьУказанныйФайл = function(мир) | |||
{ | |||
мир.номерВыбранногоФайла = мир.файлы.indexOf(мир.файл); | |||
мир.уведомить("выбрали файл"); | |||
} | |||
// // // // | |||
ВыбратьПервыйФайл = function(мир) | |||
{ | |||
мир.номерВыбранногоФайла = 0; | |||
мир.уведомить("выбрали файл"); | |||
} | |||
// // // // | |||
ПроверитьНаличиеУказанногоФайла = function(мир) | |||
{ | |||
if ( | |||
мир.файл && | |||
мир.файлы.includes(мир.файл) | |||
) { | |||
мир.уведомить("указанный файл существует"); | |||
} | |||
else | |||
{ | |||
мир.уведомить("указанный файл не существует"); | |||
} | |||
}; | |||
// // // // | |||
НастроитьAce = function(мир) | |||
{ | |||
мир.редактор = window.ace.edit("редактор"); | |||
мир.редактор.session.setMode("ace/mode/javascript"); | |||
}; | |||
// // // // | |||
ОтслеживатьВыборФайла = function(мир) | |||
{ | |||
var id = мир.макет.константы.файл; | |||
for (var номер in мир.файлы) | |||
{ | |||
const номерФайла = номер; | |||
$(`#${id}-${номер}-ссылка`).click(function() { | |||
мир.номерВыбранногоФайла = номерФайла; | |||
мир.уведомить("выбрали файл"); | |||
}); | |||
} | |||
}; | |||
// // // // | |||
ЗадатьСписокФайлов = function(мир) | |||
{ | |||
var м = мир.редактируемыйМодуль; | |||
мир.файлы = Object.keys(м.структура).sort(); | |||
var содержимое = ""; | |||
var заголовок = мир.макет.элементы.заголовокМеню.replace("${название}", "📦 " + м.имя); | |||
содержимое += заголовок; | |||
var id = мир.макет.константы.файл; | |||
for (var номер in мир.файлы) | |||
{ | |||
var файл = мир.файлы[номер]; | |||
содержимое += мир.макет.элементы.пунктМеню | |||
.replace("${название}", файл) | |||
.replace(/\$\{id\}/g, `${id}-${номер}`) | |||
; | |||
} | |||
$(`#${мир.макет.константы.меню}`).html(содержимое); | |||
}; | |||
// // // // | |||
УведомитьОбОшибкеЗагрузкиСодержимогоРедактируемогоМодуля = function(мир) | |||
{ | |||
var сообщение = "ОШИБКА Не удалось загрузить редактируемый модуль из хранилища бразуера | ERROR The module to be edited couldn't be loaded from the browser's storage"; | |||
console.error(сообщение); | |||
console.error(мир.указатель); | |||
$(`#${мир.макет.константы.содержимое}`).html(` | |||
<div class="ошибка"> | |||
<p>${сообщение}</p> | |||
<p>${мир.указатель}</p> | |||
</div> | |||
`); | |||
}; | |||
// // // // | |||
ЗагрузитьСодержимоеРедактируемогоМодуля = function(мир) | |||
{ | |||
// Пропускаем загрузку, если содержимое уже присутствует. | |||
if (мир.редактируемыйМодуль.содержимое) | |||
{ | |||
мир.уведомить("загрузили содержимое"); | |||
return; | |||
} | |||
// Загружаем содержимое. | |||
мир.модули.загрузилиСодержимоеСохранённогоМодуля.подписатьРаз(function() { | |||
мир.уведомить("загрузили содержимое"); | |||
}); | |||
мир.модули.неЗагрузилиСодержимоеСохранённогоМодуля.подписатьРаз(function() { | |||
мир.уведомить("не загрузили содержимое"); | |||
}); | |||
мир.модули.загрузитьСодержимоеСохранённогоМодуля(мир.указатель); | |||
}; | |||
// // // // | |||
ПродолжитьЗагрузку = мир => | |||
{ | |||
мир.уведомить("загрузили содержимое"); | |||
}; | |||
// // // // | |||
ЗадатьПараметрМодуляРедактором = function(мир) | |||
{ | |||
задатьПараметрВСтрокеПоиска("📦", мир.редактируемыйМодуль.указатель); | |||
}; | |||
// // // // | |||
НазначитьРедактируемымМодульРедактора = function(мир) | |||
{ | |||
мир.редактируемыйМодуль = мир.модули.модульПоИмени(ИМЯ); | |||
}; | |||
// // // // | |||
ПроверитьНаличиеРедактируемогоМодуля = function(мир) | |||
{ | |||
мир.редактируемыйМодуль = мир.модули.модульПоУказателю(мир.указатель); | |||
if (мир.редактируемыйМодуль) | |||
{ | |||
мир.уведомить("редактируемый модуль существует"); | |||
} | |||
else | |||
{ | |||
мир.уведомить("редактируемый модуль не существует"); | |||
} | |||
}; | |||
// // // // | |||
ЗадатьЗаголовокИВерсию = function(мир) | |||
{ | |||
var м = мир.ведущийМодуль; | |||
$(`#${мир.макет.константы.заголовок}`).text(м.имя); | |||
$(`#${мир.макет.константы.версия}`).text(м.версия); | |||
}; | |||
// // // // | |||
ОчиститьМакетОтЗаглушек = function(мир) | |||
{ | |||
$(`#${мир.макет.константы.заголовок}`).text(""); | |||
$(`#${мир.макет.константы.версия}`).text(""); | |||
$(`#${мир.макет.константы.действия}`).text(""); | |||
$(`#${мир.макет.константы.меню}`).text(""); | |||
}; | |||
// // // // | |||
УстановитьМакет = function(мир) | |||
{ | |||
document.body.innerHTML = мир.макет.структура; | |||
var вид = document.createElement("style"); | |||
document.head.appendChild(вид); | |||
вид.innerHTML = мир.макет.вид; | |||
}; | |||
// // // // | |||
НастроитьМакет = function(мир) | |||
{ | |||
// Вырезаем тело из макета. | |||
var html = мир.макет.структура; | |||
var начало = html.indexOf("<!-- МАКЕТ_НАЧАЛО -->"); | |||
var конец = html.indexOf("<!-- МАКЕТ_КОНЕЦ -->"); | |||
html = html.substring(начало, конец); | |||
var название = "редактор"; | |||
мир.макет.константы = { | |||
"заголовок": `${название}-макет-шапка-заголовок`, | |||
"версия": `${название}-макет-шапка-версия`, | |||
"действия": `${название}-макет-шапка-действия`, | |||
"меню": `${название}-макет-меню`, | |||
"файл": `${название}-макет-меню-файл`, | |||
"содержимое": "редактор", | |||
"сохранить": `${название}-макет-сохранить`, | |||
}; | |||
// Заменяем константы в макете. | |||
for (var константа in мир.макет.константы) | |||
{ | |||
var старое = "${" + константа + "}"; | |||
var новое = мир.макет.константы[константа]; | |||
html = html.replace(старое, новое); | |||
} | |||
мир.макет.структура = html; | |||
}; | |||
// // // // | |||
ЗагрузитьМакет = function(мир) | |||
{ | |||
var м = мир.ведущийМодуль; | |||
var json = JSON.parse(м.содержимое["/макет|template.json"]); | |||
мир.макет = { | |||
"структура": м.содержимое["/макет|template.html"], | |||
"вид": м.содержимое["/макет|template.css"], | |||
"элементы": json, | |||
}; | |||
}; | |||
// // // // | |||
ЗадатьВедущийМодуль = function(мир) | |||
{ | |||
// Редактор является ведущим модулем. | |||
мир.ведущийМодуль = мир.модули.модульПоИмени(ИМЯ); | |||
}; | |||
// // // // | |||
РазобратьПараметры = function(мир) | |||
{ | |||
мир.указатель = null; | |||
мир.файл = null; | |||
var параметры = new URLSearchParams(window.location.search); | |||
for (var имя of параметры.keys()) | |||
{ | |||
var значение = decodeURI(параметры.get(имя)); | |||
var имя = decodeURI(имя); | |||
if (имя == "📦") | |||
{ | |||
мир.указатель = значение; | |||
} | |||
else if (имя == "📁") | |||
{ | |||
мир.файл = значение; | |||
} | |||
} | |||
}; | |||
// // // // | |||
ВывестиРазобранныеПараметры = function(мир) | |||
{ | |||
console.debug(` | |||
Разобранные параметры редактора: | |||
* 📦: '${мир.указатель}' | |||
* 📁: '${мир.файл}' | |||
`); | |||
}; | |||
@@ -0,0 +1,30 @@ | |||
пуск редактора | |||
разобрать параметры | |||
вывести разобранные параметры | |||
задать ведущий модуль | |||
загрузить макет | |||
настроить макет | |||
установить макет | |||
очистить макет от заглушек | |||
задать заголовок и версию | |||
проверить наличие редактируемого модуля | |||
редактируемый модуль не существует | |||
назначить редактируемым модуль редактора | |||
задать параметр модуля редактором | |||
продолжить загрузку | |||
редактируемый модуль существует | |||
загрузить содержимое редактируемого модуля | |||
не загрузили содержимое | |||
уведомить об ошибке загрузки содержимого редактируемого модуля | |||
загрузили содержимое | |||
настроить Ace | |||
настроить отслеживание редактирования | |||
задать кнопку сохранения | |||
задать временное содержимое | |||
задать список файлов | |||
отслеживать выбор файла | |||
проверить наличие указанного файла | |||
указанный файл не существует | |||
выбрать первый файл | |||
указанный файл существует | |||
выбрать указанный файл |
@@ -0,0 +1,28 @@ | |||
СохранитьВременноеСодержимоеРедактируемогоФайла = function(мир) | |||
{ | |||
var файл = мир.файлы[мир.номерВыбранногоФайла]; | |||
var содержимое = мир.редактор.session.getValue(); | |||
мир.временноеСодержимое[файл] = содержимое; | |||
}; | |||
// // // // | |||
ПометитьВыбранныйФайлКакИзменённый = function(мир) | |||
{ | |||
$(`#${мир.макет.константы.файл}-${мир.номерВыбранногоФайла}-изменение`).removeAttr("hidden"); | |||
}; | |||
// // // // | |||
ВывестиРедактирование = function(мир) | |||
{ | |||
console.debug("Редактирование"); | |||
}; | |||
@@ -0,0 +1,4 @@ | |||
редактирование | |||
# вывести редактирование | |||
пометить выбранный файл как изменённый | |||
сохранить временное содержимое редактируемого файла |
@@ -0,0 +1,42 @@ | |||
УведомитьОНеудачномСохраненииИзменений = function(мир) | |||
{ | |||
UIkit.notification("Не удалось сохранить изменения", {status: "danger"}); | |||
UIkit.notification("Could not save changes", {status: "danger"}); | |||
}; | |||
// // // // | |||
УведомитьОбУспешномСохраненииИзменений = function(мир) | |||
{ | |||
UIkit.notification("Сохранили успешно", {status: "success"}); | |||
UIkit.notification("Saved successfully", {status: "success"}); | |||
}; | |||
// // // // | |||
СохранитьИзменения = function(мир) | |||
{ | |||
for (var файл in мир.временноеСодержимое) | |||
{ | |||
var содержимое = мир.временноеСодержимое[файл]; | |||
мир.редактируемыйМодуль.содержимое[файл] = содержимое; | |||
} | |||
мир.временноеСодержимое = {}; | |||
мир.модули.сохранили.подписатьРаз(function() { | |||
мир.уведомить("сохранили изменения"); | |||
}); | |||
мир.модули.неСохранили.подписатьРаз(function() { | |||
мир.уведомить("не сохранили изменения"); | |||
}); | |||
мир.модули.сохранить(мир.редактируемыйМодуль.указатель); | |||
}; | |||
@@ -0,0 +1,9 @@ | |||
выбрали сохранить | |||
сохранить изменения | |||
не сохранили изменения | |||
уведомить о неудачном сохранении изменений | |||
сохранили изменения | |||
уведомить об успешном сохранении изменений | |||
задать список файлов | |||
отслеживать выбор файла | |||
выбрать указанный файл |
@@ -0,0 +1,37 @@ | |||
задатьПараметрВСтрокеПоиска = (ключПараметра, значениеПараметра) => | |||
{ | |||
var строкаПоиска = decodeURI(window.location.search); | |||
var текущийАдрес = decodeURI(window.location.href); | |||
// Заменить параметр. | |||
if (строкаПоиска.includes(`${ключПараметра}=`)) | |||
{ | |||
var части = строкаПоиска.split(/[\?&]/); | |||
for (var номер in части) | |||
{ | |||
var часть = части[номер]; | |||
if (часть.startsWith(`${ключПараметра}=`)) | |||
{ | |||
var значение = часть.split("=")[1]; | |||
var адрес = текущийАдрес.replace(значение, значениеПараметра); | |||
history.pushState(null, "", адрес); | |||
break; | |||
} | |||
} | |||
} | |||
// Добавить параметр. | |||
else | |||
{ | |||
var префикс = "?"; | |||
if (строкаПоиска.startsWith("?")) | |||
{ | |||
префикс = "&"; | |||
} | |||
var адрес = текущийАдрес + префикс + `${ключПараметра}=` + значениеПараметра; | |||
history.pushState(null, "", адрес); | |||
} | |||
}; | |||
setSearchQueryParameter = задатьПараметрВСтрокеПоиска; | |||