This commit is contained in:
2021-09-16 09:49:10 +03:00
parent 5449e11870
commit 543c4be5a0
75 changed files with 1622 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
function События()
{
this.создать = function()
{
this.обработчики = [];
};
this.подписать = function(обработчик)
{
this.обработчики.push(обработчик);
};
this.отписать = function(обработчик) {
var номер = this.обработчики.indexOf(обработчик);
if (номер != -1)
{
this.обработчики.splice(номер, 1);
}
};
this.уведомить = function(событие) {
for (var номер in this.обработчики)
{
var обработчик = this.обработчики[номер];
обработчик.обработатьСобытие(событие);
}
};
// Конструктор.
this.создать();
}

View File

@@ -0,0 +1,61 @@
function Состояние()
{
this.создать = function()
{
this.обработчик = null;
this.значения = {};
};
this.выпрямить = function(obj)
{
// https://stackoverflow.com/a/42121920
var newObj = {};
for (var key in obj)
{
if (typeof obj[key] === 'object' && obj[key] !== null)
{
var temp = this.выпрямить(obj[key])
for (var key2 in temp)
{
newObj[key + "." + key2] = temp[key2];
}
}
else
{
newObj[key] = obj[key];
}
}
return newObj;
};
this.лишьНовыеЗначения = function(значения) {
var новые = {};
for (var ключ in значения)
{
var было = this.значения[ключ];
var стало = значения[ключ];
if (!(было != null && было == стало))
{
новые[ключ] = стало;
this.значения[ключ] = стало;
}
}
return новые;
};
this.разобрать = function(словарь) {
var значения = this.лишьНовыеЗначения(this.выпрямить(словарь));
for (var ключ in значения)
{
var путь = ключ.split(".");
var значение = значения[ключ];
if (this.обработчик)
{
this.обработчик(ключ, путь, значение);
}
}
};
// Конструктор.
this.создать();
}

View File

@@ -0,0 +1,73 @@
var мир = {};
мир.uuid = function()
{
// https://stackoverflow.com/a/2117523
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
function(c)
{
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
}
);
};
мир.вZ64 = function(строка)
{
var байты = new TextEncoder("utf-8").encode(строка);
var архив = pako.deflate(байты, { to: 'string' });
return base64js.fromByteArray(архив);
};
мир.изZ64 = function(строка)
{
var архив = base64js.toByteArray(строка);
var байты = pako.inflate(архив);
return new TextDecoder("utf-8").decode(байты);
};
мир.назначитьКнопкамСобытия = function(события, список)
{
for (var номер in список)
{
const пара = список[номер];
var кнопка = document.getElementById(пара[0]);
кнопка.addEventListener("click", function(_) {
события.уведомить(пара[1]);
});
}
};
мир.параметрыЗапуска = function()
{
var параметры = {};
var запрос = window.location.search.substring(1);
var аргументы = запрос.split("&");
for (var номер in аргументы)
{
var арг = аргументы[номер];
var позицияЗнака = арг.indexOf("=");
// Лишь ключ.
if (позицияЗнака == -1)
{
var ключ = decodeURIComponent(арг);
параметры[ключ] = null;
}
// Ключ со значением.
else
{
var сыройКлюч = арг.slice(0, позицияЗнака);
var сыроеЗначение = арг.slice(позицияЗнака + 1);
var ключ = decodeURIComponent(сыройКлюч);
var значение = decodeURIComponent(сыроеЗначение);
параметры[ключ] = значение;
}
}
return параметры;
};
мир.разобрать = function(словарь)
{
мир.состояние.разобрать(словарь);
};

View File

@@ -0,0 +1 @@
https://github.com/beatgammit/base64-js/blob/master/base64js.min.js

View File

@@ -0,0 +1 @@
(function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,b.base64js=a()}})(function(){return function(){function b(d,e,g){function a(j,i){if(!e[j]){if(!d[j]){var f="function"==typeof require&&require;if(!i&&f)return f(j,!0);if(h)return h(j,!0);var c=new Error("Cannot find module '"+j+"'");throw c.code="MODULE_NOT_FOUND",c}var k=e[j]={exports:{}};d[j][0].call(k.exports,function(b){var c=d[j][1][b];return a(c||b)},k,k.exports,b,d,e,g)}return e[j].exports}for(var h="function"==typeof require&&require,c=0;c<g.length;c++)a(g[c]);return a}return b}()({"/":[function(a,b,c){'use strict';function d(a){var b=a.length;if(0<b%4)throw new Error("Invalid string. Length must be a multiple of 4");var c=a.indexOf("=");-1===c&&(c=b);var d=c===b?0:4-c%4;return[c,d]}function e(a,b,c){return 3*(b+c)/4-c}function f(a){var b,c,f=d(a),g=f[0],h=f[1],j=new m(e(a,g,h)),k=0,n=0<h?g-4:g;for(c=0;c<n;c+=4)b=l[a.charCodeAt(c)]<<18|l[a.charCodeAt(c+1)]<<12|l[a.charCodeAt(c+2)]<<6|l[a.charCodeAt(c+3)],j[k++]=255&b>>16,j[k++]=255&b>>8,j[k++]=255&b;return 2===h&&(b=l[a.charCodeAt(c)]<<2|l[a.charCodeAt(c+1)]>>4,j[k++]=255&b),1===h&&(b=l[a.charCodeAt(c)]<<10|l[a.charCodeAt(c+1)]<<4|l[a.charCodeAt(c+2)]>>2,j[k++]=255&b>>8,j[k++]=255&b),j}function g(a){return k[63&a>>18]+k[63&a>>12]+k[63&a>>6]+k[63&a]}function h(a,b,c){for(var d,e=[],f=b;f<c;f+=3)d=(16711680&a[f]<<16)+(65280&a[f+1]<<8)+(255&a[f+2]),e.push(g(d));return e.join("")}function j(a){for(var b,c=a.length,d=c%3,e=[],f=16383,g=0,j=c-d;g<j;g+=f)e.push(h(a,g,g+f>j?j:g+f));return 1===d?(b=a[c-1],e.push(k[b>>2]+k[63&b<<4]+"==")):2===d&&(b=(a[c-2]<<8)+a[c-1],e.push(k[b>>10]+k[63&b>>4]+k[63&b<<2]+"=")),e.join("")}c.byteLength=function(a){var b=d(a),c=b[0],e=b[1];return 3*(c+e)/4-e},c.toByteArray=f,c.fromByteArray=j;for(var k=[],l=[],m="undefined"==typeof Uint8Array?Array:Uint8Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o=0,p=n.length;o<p;++o)k[o]=n[o],l[n.charCodeAt(o)]=o;l[45]=62,l[95]=63},{}]},{},[])("/")});

View File

@@ -0,0 +1 @@
https://github.com/nodeca/pako/blob/master/dist/pako.min.js

2
M/3.2/общее/pako/pako.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
function Заголовок()
{
this.обработатьКлюч = function(ключ, путь, значение)
{
if (ключ == "заголовок")
{
document.title = значение;
}
}
}

View File

@@ -0,0 +1,104 @@
function Изображения(корень)
{
this.создать = function()
{
this.умолчание = {
x: 0,
y: 0,
ширина: 100,
высота: 100,
угол: 0,
};
this.задано = {};
this.элементы = {};
};
this.создатьИлиПолучитьЭлемент = function(имя)
{
var эл = this.элементы[имя];
if (эл)
{
return эл;
}
var ум = this.умолчание;
эл = document.createElement("div");
эл.id = `изображения-${имя}`;
эл.style.position = "absolute";
эл.style.display = "block";
// Свойства по умолчанию.
эл.style.left = `${ум.x}px`;
эл.style.top = `${ум.y}px`;
эл.style.width = `${ум.ширина}px`;
эл.style.height = `${ум.высота}px`;
эл.style.transform = `rotate(${ум.угол}rad)`;
this.элементы[имя] = эл;
корень.appendChild(эл);
return эл;
};
this.обновитьЭлемент = function(имя, свойство, значение)
{
if (!this.задано[имя])
{
this.задано[имя] = {};
}
this.задано[имя][свойство] = значение;
var за = this.задано[имя];
var эл = this.создатьИлиПолучитьЭлемент(имя);
if (свойство == "ширина")
{
эл.style.width = `${за.ширина}px`;
}
else if (свойство == "высота")
{
эл.style.height = `${за.высота}px`;
}
else if (
(свойство == "x") ||
(свойство == "y") ||
(свойство == "угол") ||
(свойство == "вид.transform")
) {
var ум = this.умолчание;
var x = за.x ? за.x : ум.x;
var y = за.y ? за.y : ум.y;
var угол = за.угол ? за.угол : ум.угол;
this.обновитьРасположение(имя, x, y, угол);
}
else if (свойство.startsWith("вид"))
{
var параметр = свойство.substring(4);
эл.style.setProperty(параметр, значение);
}
};
this.обновитьРасположение = function(имя, x, y, угол)
{
var за = this.задано[имя];
var эл = this.элементы[имя];
эл.style.left = `${x}px`;
эл.style.top = `${y}px`;
var transform = `rotate(${угол}deg) `;
if (за["вид.transform"])
{
transform += за["вид.transform"];
}
эл.style.transform = transform;
};
this.обработатьКлюч = function(ключ, путь, значение)
{
if (путь[0] == "изображения")
{
var имя = путь[1];
var свойство = путь.slice(2).join(".");
this.обновитьЭлемент(имя, свойство, значение);
}
};
// Конструктор.
this.создать();
}

View File

@@ -0,0 +1,47 @@
function Игра()
{
this.создать = function()
{
var корень = document.getElementById("корень");
мир.события = new События();
мир.состояние = new Состояние();
мир.состояние.обработчик = (к, п, з) => { this.обработатьКлюч(к, п, з) };
this.ключники = [
new Заголовок(),
new Изображения(корень),
];
var z64 = мир.параметрыЗапуска()["z64"];
this.исполнитьКод(z64);
this.отслеживатьОбновленияКода();
};
this.исполнитьКод = function(z64)
{
if (z64)
{
var код = мир.изZ64(z64);
eval(код);
}
};
this.обработатьКлюч = function(ключ, путь, значение)
{
for (var номер in this.ключники)
{
var ключник = this.ключники[номер];
ключник.обработатьКлюч(ключ, путь, значение);
}
};
this.отслеживатьОбновленияКода = function()
{
var тут = this;
window.addEventListener("message", function(событие) {
тут.исполнитьКод(событие.data);
});
};
// Конструктор.
this.создать();
}

View File

@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script src="../общее/base64-js/base64js.min.js"></script>
<script src="../общее/pako/pako.min.js"></script>
<script src="matter-js/matter.min.js"></script>
<style>
/*
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
body {
height: 100vh;
width: 100vw;
}
*/
#корень
{
position: relative;
}
</style>
</head>
<body>
<div id="заставка"></div>
<div id="корень"></div>
<div id="отладка"></div>
<script src="../общее/100.События.js"></script>
<script src="../общее/150.Состояние.js"></script>
<script src="../общее/200.функции.js"></script>
<script src="050.Заголовок.js"></script>
<script src="100.Изображения.js"></script>
<script src="700.Игра.js"></script>
<script>
var игра = new Игра();
</script>
</body>
</html>

View File

@@ -0,0 +1 @@
https://github.com/liabru/matter-js/blob/master/build/matter.min.js

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,127 @@
function Редактор(события, имяРедактора)
{
this.создать = function()
{
this.первоначальныйЗаголовок = document.title;
this.установитьAce();
this.улавливатьЗавершениеРедактирования();
this.задатьКодПриЗапуске();
события.подписать(this);
};
this.задатьКодПриЗапуске = function()
{
var z64 = мир.параметрыЗапуска()["z64"];
if (z64)
{
var код = мир.изZ64(z64);
this.ace.session.setValue(код);
}
};
this.запуститьОтдельно = function()
{
var содержимое = this.ace.session.getValue();
var z64 = мир.вZ64(содержимое);
var путь = window.location.pathname + "/../../проигрыватель/index.html?z64=" + z64;
window.open(путь);
};
this.исполнитьКод = function()
{
var содержимое = this.ace.session.getValue();
var z64 = мир.вZ64(содержимое);
// Исполняем явно код лишь первый раз.
var проигрыватель = document.getElementById("проигрыватель");
if (!проигрыватель.src)
{
проигрыватель.src = "../проигрыватель/index.html?z64=" + z64;
}
// После запуска уведомляем iframe о новом коде без перезагрузки.
else
{
window.frames.проигрыватель.postMessage(z64, "*");
}
};
this.обновитьАдреснуюСтрокуИЗаголовок = function()
{
var содержимое = this.ace.session.getValue();
var z64 = мир.вZ64(содержимое);
var путь = window.location.pathname + "?z64=" + z64;
history.pushState(null, "", путь);
document.title = `${this.первоначальныйЗаголовок} ${z64.length}:${z64.slice(z64.length - 5)}`;
};
this.обработатьСобытие = function(событие)
{
if (событие == "завершили редактирование")
{
this.обновитьАдреснуюСтрокуИЗаголовок();
this.проверитьКорректностьКода();
}
else if (событие == "код корректен")
{
this.исполнитьКод();
}
else if (событие == "перезапустить")
{
this.перезапуститьКод();
}
else if (событие == "запустить отдельно")
{
this.запуститьОтдельно();
}
};
this.перезапуститьКод = function()
{
var содержимое = this.ace.session.getValue();
var z64 = мир.вZ64(содержимое);
var проигрыватель = document.getElementById("проигрыватель");
проигрыватель.src = "../проигрыватель/index.html?z64=" + z64;
};
this.проверитьКорректностьКода = function()
{
try
{
eval(this.ace.session.getValue());
события.уведомить("код корректен");
}
catch (ошибка)
{
события.уведомить("код некорректен");
}
};
this.улавливатьЗавершениеРедактирования = function()
{
var тут = this;
this.ace.session.on("change", function(дельта) {
const билет = мир.uuid();
тут.билет = билет;
setTimeout(
function()
{
if (билет == тут.билет)
{
события.уведомить("завершили редактирование");
}
},
300
);
});
};
this.установитьAce = function()
{
var область = document.getElementById(имяРедактора);
this.ace = window.ace.edit(имяРедактора);
this.ace.session.setMode("ace/mode/javascript");
this.ace.session.setUseWrapMode(true);
};
// Конструктор.
this.создать();
}

View File

@@ -0,0 +1,48 @@
function Пульт(события, имяОшибки, имяПерезапуска, имяОтдельно, имяСсылки)
{
this.создать = function()
{
var ошибка = document.getElementById(имяОшибки);
мир.назначитьКнопкамСобытия(
события,
[
[имяПерезапуска, "перезапустить"],
[имяОтдельно, "запустить отдельно"],
[имяСсылки, "скопировать ссылку"],
]
);
события.подписать(this);
};
this.обработатьСобытие = function(событие)
{
if (событие == "код корректен")
{
this.показатьОшибку(false);
}
else if (событие == "код некорректен")
{
this.показатьОшибку(true);
}
else if (событие == "скопировать ссылку")
{
navigator.clipboard.writeText(window.location)
.then(() => {
UIkit.notification("Скопировали ссылку", { status: "success", timeout: 1000 });
})
.catch(err => {
UIkit.notification("Не удалось скопировать ссылку :(", { status: "danger", timeout: 5000 });
});
}
};
this.показатьОшибку = function(показать)
{
ошибка.innerHTML = показать ? "<span uk-icon=\"icon: warning\"></span>" : "&nbsp;";
};
// Конструктор.
this.создать();
}

View File

@@ -0,0 +1,13 @@
function Муром()
{
this.создать = function()
{
мир.события = new События();
мир.состояние = new Состояние();
мир.редактор = new Редактор(мир.события, "редактор");
мир.пульт = new Пульт(мир.события, "ошибка", "перезапустить", "отдельно", "ссылка");
};
// Конструктор.
this.создать();
}

View File

@@ -0,0 +1 @@
https://github.com/ajaxorg/ace-builds/tree/master/src-min-noconflict

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>M-3.2</title>
<script src="../общее/base64-js/base64js.min.js"></script>
<script src="../общее/pako/pako.min.js"></script>
<script src="ace/ace.js"></script>
<script src="ace/mode-javascript.js"></script>
<script src="ace/worker-javascript.js"></script>
<link rel="stylesheet" type="text/css" href="uikit/uikit.min.css" />
<script src="uikit/uikit.min.js"></script>
<script src="uikit/uikit-icons.min.js"></script>
<style>
#редактор
{
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: calc(50% - 2em);
}
#пульт
{
position: absolute;
left: calc(50% - 2em);
top: 0;
bottom: 0;
width: 4em;
display: flex;
flex-direction: column;
border: 1px dashed gainsboro;
}
#проигрыватель
{
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: calc(50% - 2em);
height: 100%;
border: 0px none;
}
.впульте
{
margin: 0 auto;
}
</style>
</head>
<body>
<div id="редактор"></div>
<div id="пульт">
<span id="ошибка" class="впульте">&nbsp;</span>
<a id="перезапустить" class="впульте uk-icon-button uk-margin-top" uk-icon="refresh" uk-tooltip="Перезапустить"></a>
<a id="отдельно" class="впульте uk-icon-button uk-margin-top" uk-icon="desktop" uk-tooltip="Запустить в отдельной вкладке"></a>
<a id="ссылка" class="впульте uk-icon-button uk-margin-top" uk-icon="link" uk-tooltip="Скопировать ссылку"></a>
<a id="версия" class="впульте uk-icon-button uk-margin-top" uk-icon="git-branch" uk-tooltip="Версия"></a>
<div uk-dropdown="mode: click">
<table class="uk-table">
<tbody>
<tr>
<td>3.2</td>
<td>Заголовок...? раз два три четыре пять шесть семь восемь девять десять</td>
</tr>
<tr>
<td><a href="../../3.1/редактор/index.html">3.1</a></td>
<td>Кнопки перезапуска, копирования ссылки, запуска в отдельной вкладке</td>
</tr>
<tr>
<td><a href="../../3.0/редактор/index.html">3.0</a></td>
<td>Проверка введённого кода на отсутствие синтаксических ошибок</td>
</tr>
</tbody>
</table>
</div>
</div>
<iframe id="проигрыватель" name="проигрыватель"></iframe>
<script src="../общее/100.События.js"></script>
<script src="../общее/150.Состояние.js"></script>
<script src="../общее/200.функции.js"></script>
<script src="100.Редактор.js"></script>
<script src="200.Пульт.js"></script>
<script src="700.Муром.js"></script>
<script>
var муром = new Муром();
</script>
</body>
</html>

View File

@@ -0,0 +1 @@
https://getuikit.com/download

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long