patron-oop 1.45.0 → 1.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/patron.cjs +106 -35
- package/dist/patron.cjs.map +1 -1
- package/dist/patron.d.ts +40 -1
- package/dist/patron.js +103 -36
- package/dist/patron.js.map +1 -1
- package/dist/patron.min.js +1 -1
- package/dist/patron.min.mjs +1 -1
- package/dist/patron.min.mjs.map +1 -1
- package/dist/patron.mjs +103 -36
- package/dist/patron.mjs.map +1 -1
- package/docs/README.md +3 -0
- package/docs/assets/css/base.css +42 -0
- package/docs/assets/favicon/android-icon-144x144.png +0 -0
- package/docs/assets/favicon/android-icon-192x192.png +0 -0
- package/docs/assets/favicon/android-icon-36x36.png +0 -0
- package/docs/assets/favicon/android-icon-48x48.png +0 -0
- package/docs/assets/favicon/android-icon-72x72.png +0 -0
- package/docs/assets/favicon/android-icon-96x96.png +0 -0
- package/docs/assets/favicon/apple-icon-114x114.png +0 -0
- package/docs/assets/favicon/apple-icon-120x120.png +0 -0
- package/docs/assets/favicon/apple-icon-144x144.png +0 -0
- package/docs/assets/favicon/apple-icon-152x152.png +0 -0
- package/docs/assets/favicon/apple-icon-180x180.png +0 -0
- package/docs/assets/favicon/apple-icon-57x57.png +0 -0
- package/docs/assets/favicon/apple-icon-60x60.png +0 -0
- package/docs/assets/favicon/apple-icon-72x72.png +0 -0
- package/docs/assets/favicon/apple-icon-76x76.png +0 -0
- package/docs/assets/favicon/apple-icon-precomposed.png +0 -0
- package/docs/assets/favicon/apple-icon.png +0 -0
- package/docs/assets/favicon/browserconfig.xml +2 -0
- package/docs/assets/favicon/favicon-16x16.png +0 -0
- package/docs/assets/favicon/favicon-32x32.png +0 -0
- package/docs/assets/favicon/favicon-96x96.png +0 -0
- package/docs/assets/favicon/favicon.ico +0 -0
- package/docs/assets/favicon/manifest.json +41 -0
- package/docs/assets/favicon/ms-icon-144x144.png +0 -0
- package/docs/assets/favicon/ms-icon-150x150.png +0 -0
- package/docs/assets/favicon/ms-icon-310x310.png +0 -0
- package/docs/assets/favicon/ms-icon-70x70.png +0 -0
- package/docs/assets/img/404.jpg +0 -0
- package/docs/assets/img/angular_16.jpg +0 -0
- package/docs/assets/img/angular_32.jpg +0 -0
- package/docs/assets/img/eo_16.jpg +0 -0
- package/docs/assets/img/eo_big.png +0 -0
- package/docs/assets/img/github_16.jpg +0 -0
- package/docs/assets/img/logo.jpg +0 -0
- package/docs/assets/img/philosofy/observable.jpg +0 -0
- package/docs/assets/img/philosofy/responsible.jpg +0 -0
- package/docs/assets/img/philosofy/result.jpg +0 -0
- package/docs/assets/img/philosofy/tell.jpg +0 -0
- package/docs/assets/img/react_16.jpg +0 -0
- package/docs/assets/img/react_32.jpg +0 -0
- package/docs/assets/img/vue_16.jpg +0 -0
- package/docs/assets/img/vue_32.jpg +0 -0
- package/docs/assets/js/components/linkDynamic.mjs +11 -0
- package/docs/assets/js/components/linkReloadable.mjs +13 -0
- package/docs/assets/js/entrypoints/compatibility.mjs +31 -0
- package/docs/assets/js/entrypoints/components.mjs +2 -0
- package/docs/assets/js/entrypoints/examples.mjs +25 -0
- package/docs/assets/js/entrypoints/factory.mjs +20 -0
- package/docs/assets/js/entrypoints/guest.mjs +61 -0
- package/docs/assets/js/entrypoints/index.mjs +110 -0
- package/docs/assets/js/entrypoints/integrations.mjs +36 -0
- package/docs/assets/js/entrypoints/patron.mjs +46 -0
- package/docs/assets/js/entrypoints/source.mjs +76 -0
- package/docs/assets/js/entrypoints/terminology.mjs +51 -0
- package/docs/assets/js/entrypoints/utils.mjs +61 -0
- package/docs/assets/js/lib/StyleFetched.mjs +14 -0
- package/docs/assets/js/routing.mjs +110 -0
- package/docs/assets/schemes/dip.html +28 -0
- package/docs/favicon.ico +0 -0
- package/docs/index-dev.html +346 -0
- package/docs/index.html +346 -0
- package/docs/manifest.json +41 -0
- package/docs/pages/404.html +9 -0
- package/docs/pages/common/layout.html +17 -0
- package/docs/pages/compatibility/dip.html +82 -0
- package/docs/pages/compatibility/elegant-objects.html +373 -0
- package/docs/pages/compatibility/layout.html +17 -0
- package/docs/pages/examples/errors.html +167 -0
- package/docs/pages/examples/index.html +10 -0
- package/docs/pages/examples.html +41 -0
- package/docs/pages/factory/index.html +18 -0
- package/docs/pages/factory.html +36 -0
- package/docs/pages/guest/guest-applied.html +51 -0
- package/docs/pages/guest/guest-cast.html +219 -0
- package/docs/pages/guest/guest-disposable.html +147 -0
- package/docs/pages/guest/guest-executor-applied.html +65 -0
- package/docs/pages/guest/guest-object.html +101 -0
- package/docs/pages/guest/guest-pool.html +107 -0
- package/docs/pages/guest/guest-sync.html +66 -0
- package/docs/pages/guest/index.html +115 -0
- package/docs/pages/guest.html +59 -0
- package/docs/pages/index.html +72 -0
- package/docs/pages/integrations/angular.html +5 -0
- package/docs/pages/integrations/layout.html +17 -0
- package/docs/pages/integrations/react.html +7 -0
- package/docs/pages/integrations/vue.html +102 -0
- package/docs/pages/patron/index.html +140 -0
- package/docs/pages/patron/patron-applied.html +66 -0
- package/docs/pages/patron/patron-executor-applied.html +94 -0
- package/docs/pages/patron/patron-once.html +110 -0
- package/docs/pages/patron/patron-pool.html +99 -0
- package/docs/pages/patron.html +50 -0
- package/docs/pages/philosofy.html +210 -0
- package/docs/pages/source/index.html +167 -0
- package/docs/pages/source/source-active.html +113 -0
- package/docs/pages/source/source-all.html +129 -0
- package/docs/pages/source/source-applied.html +73 -0
- package/docs/pages/source/source-dynamic.html +93 -0
- package/docs/pages/source/source-executor-applied.html +64 -0
- package/docs/pages/source/source-map.html +192 -0
- package/docs/pages/source/source-once.html +73 -0
- package/docs/pages/source/source-race.html +171 -0
- package/docs/pages/source/source-sequence.html +160 -0
- package/docs/pages/source/source-with-pool.html +102 -0
- package/docs/pages/source/source.html +167 -0
- package/docs/pages/source.html +68 -0
- package/docs/pages/terminology/guest.html +14 -0
- package/docs/pages/terminology/index.html +6 -0
- package/docs/pages/terminology/introduction.html +25 -0
- package/docs/pages/terminology/patron.html +10 -0
- package/docs/pages/terminology/source.html +55 -0
- package/docs/pages/terminology/visitor.html +19 -0
- package/docs/pages/terminology.html +53 -0
- package/docs/pages/utils/give.html +47 -0
- package/docs/pages/utils/index.html +24 -0
- package/docs/pages/utils/is-guest-aware.html +22 -0
- package/docs/pages/utils/is-guest.html +21 -0
- package/docs/pages/utils/is-patron-in-pools.html +53 -0
- package/docs/pages/utils/private.html +44 -0
- package/docs/pages/utils/remove-patron-from-pools.html +57 -0
- package/docs/pages/utils/value.html +47 -0
- package/docs/pages/utils.html +61 -0
- package/eslint.config.mjs +6 -0
- package/package.json +1 -1
- package/src/Patron/PatronApplied.ts +22 -0
- package/src/Patron/PatronExecutorApplied.ts +25 -0
- package/src/index.ts +4 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
{
|
2
|
+
"name": "App",
|
3
|
+
"icons": [
|
4
|
+
{
|
5
|
+
"src": ".\/assets\/favicon\/android-icon-36x36.png",
|
6
|
+
"sizes": "36x36",
|
7
|
+
"type": "image\/png",
|
8
|
+
"density": "0.75"
|
9
|
+
},
|
10
|
+
{
|
11
|
+
"src": ".\/assets\/favicon\/android-icon-48x48.png",
|
12
|
+
"sizes": "48x48",
|
13
|
+
"type": "image\/png",
|
14
|
+
"density": "1.0"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"src": ".\/assets\/favicon\/android-icon-72x72.png",
|
18
|
+
"sizes": "72x72",
|
19
|
+
"type": "image\/png",
|
20
|
+
"density": "1.5"
|
21
|
+
},
|
22
|
+
{
|
23
|
+
"src": ".\/assets\/favicon\/android-icon-96x96.png",
|
24
|
+
"sizes": "96x96",
|
25
|
+
"type": "image\/png",
|
26
|
+
"density": "2.0"
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"src": ".\/assets\/favicon\/android-icon-144x144.png",
|
30
|
+
"sizes": "144x144",
|
31
|
+
"type": "image\/png",
|
32
|
+
"density": "3.0"
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"src": ".\/assets\/favicon\/android-icon-192x192.png",
|
36
|
+
"sizes": "192x192",
|
37
|
+
"type": "image\/png",
|
38
|
+
"density": "4.0"
|
39
|
+
}
|
40
|
+
]
|
41
|
+
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div class="text-center">
|
2
|
+
<img class="mb-5 inline" src="./assets/img/404.jpg" width="200" height="200" />
|
3
|
+
<h1 class="pb-3 text-xl font-semibold text-gray-600">
|
4
|
+
Страница не найдена
|
5
|
+
</h1>
|
6
|
+
<p>
|
7
|
+
Попробуйте другой раздел или вернитесь на главную
|
8
|
+
</p>
|
9
|
+
</div>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<div class="common-menu"></div>
|
2
|
+
<div class="w-full sm:w-2/3 mt-4 sm:mt-0 mx-auto">
|
3
|
+
<div class="common-loader">
|
4
|
+
<div class="w-full flex justify-center">
|
5
|
+
<div
|
6
|
+
class="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-e-transparent align-[-0.125em] text-indigo-500 motion-reduce:animate-[spin_1.5s_linear_infinite]"
|
7
|
+
role="status"
|
8
|
+
>
|
9
|
+
<span
|
10
|
+
class="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]"
|
11
|
+
>Loading...</span
|
12
|
+
>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
<div class="common-page-area"></div>
|
17
|
+
</div>
|
@@ -0,0 +1,82 @@
|
|
1
|
+
<h1 class="pb-3 text-xl font-semibold text-gray-600">
|
2
|
+
Dependency Inversion Principal
|
3
|
+
</h1>
|
4
|
+
|
5
|
+
<p class="text-gray-600 text-lg mb-4">
|
6
|
+
<b>DIP</b> - принцип инверсии зависимостей, описанный Робертом Мартином.
|
7
|
+
Принцип говорит о том, что архитектор системы может изменить направление
|
8
|
+
зависимости от процедурного - когда большее зависит от меньшего на
|
9
|
+
противополложное когда меньшее зависит от большего. Большее - это higher
|
10
|
+
policy (бизнес логика) и от потребностей бизнес логики зависят плагины
|
11
|
+
конкретных систем, например плагин работы с БД, обеспечивающий нашу бизнес
|
12
|
+
логику данными из БД.
|
13
|
+
</p>
|
14
|
+
|
15
|
+
<p class="text-gray-600 text-lg mb-4">
|
16
|
+
Библиотека Patron - это реализация DIP принципа. Ваша бизнес логика может
|
17
|
+
зависеть от интерфейсов
|
18
|
+
<link-reloadable
|
19
|
+
target-blank
|
20
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Source/Source.ts#L9"
|
21
|
+
>
|
22
|
+
SourceType
|
23
|
+
</link-reloadable>
|
24
|
+
или
|
25
|
+
<link-reloadable
|
26
|
+
target-blank
|
27
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Guest/Guest.ts#L17"
|
28
|
+
>
|
29
|
+
GuestType
|
30
|
+
</link-reloadable>
|
31
|
+
или
|
32
|
+
<link-reloadable
|
33
|
+
target-blank
|
34
|
+
href="https://github.com/kosukhin/patron/blob/main/src/Source/SourceActive.ts#L9"
|
35
|
+
>
|
36
|
+
ActionType
|
37
|
+
</link-reloadable>
|
38
|
+
. Эти общие интерфейсы позволяют либо получить данные(SourceType) либо
|
39
|
+
принять того кому данные нужно передать(GuestType) либо принять объект который
|
40
|
+
умеет делать действия(ActionType)
|
41
|
+
</p>
|
42
|
+
|
43
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">
|
44
|
+
Схема 1. Пример приложения с DIP + Patron
|
45
|
+
</p>
|
46
|
+
|
47
|
+
<iframe
|
48
|
+
src="./assets/schemes/dip.html"
|
49
|
+
border="0"
|
50
|
+
width="100%"
|
51
|
+
height="500"
|
52
|
+
></iframe>
|
53
|
+
|
54
|
+
<p> </p>
|
55
|
+
<p class="text-gray-600 text-lg mb-4">
|
56
|
+
Как видно из схемы 1 все классы зависят только от интерфейсов из библиотеки
|
57
|
+
Patron, только дополняя параметры дженериков нужными типами.
|
58
|
+
</p>
|
59
|
+
|
60
|
+
<p class="text-gray-600 text-lg mb-4">
|
61
|
+
Прикладной код может выглядеть следующим образом, как показано в примере 1.
|
62
|
+
</p>
|
63
|
+
|
64
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Пример 1.</p>
|
65
|
+
<pre
|
66
|
+
class="mb-4"
|
67
|
+
><code class="language-js">// Условный код, для демонстрации композиции классов схемы 1
|
68
|
+
const credentials = new CredentialsFromPostRequest(request);
|
69
|
+
|
70
|
+
const user = new UserStatus(
|
71
|
+
new SQLUserOfCredentials(credentials)
|
72
|
+
);
|
73
|
+
|
74
|
+
const card = new UserCard();
|
75
|
+
user.value(card);
|
76
|
+
</code></pre>
|
77
|
+
|
78
|
+
<p class="text-gray-600 text-lg mb-4">
|
79
|
+
Выгода использования Patron - хорошо видна, каждый класс не зависит ни от чего
|
80
|
+
кроме библиотеки Patron и тех библиотек плагином которых является, а в случае
|
81
|
+
класса бизнес - логики зависимость будет только от Patron.
|
82
|
+
</p>
|
@@ -0,0 +1,373 @@
|
|
1
|
+
<h1 class="pb-3 text-xl font-semibold text-gray-600">Elegant Objects</h1>
|
2
|
+
|
3
|
+
<img
|
4
|
+
src="./assets/img/eo_big.png"
|
5
|
+
width="150"
|
6
|
+
height="170"
|
7
|
+
class="float-left m-3"
|
8
|
+
/>
|
9
|
+
|
10
|
+
<p class="text-gray-600 text-lg mb-4">
|
11
|
+
Работы по библиотеке Patron вдохновлены двумя книгами:
|
12
|
+
<a
|
13
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
14
|
+
href="https://www.elegantobjects.org/"
|
15
|
+
target="_blank"
|
16
|
+
>
|
17
|
+
Elegant Objects
|
18
|
+
</a>
|
19
|
+
и
|
20
|
+
<a
|
21
|
+
class="inline-block whitespace-nowrap rounded-[0.27rem] bg-primary-100 px-[0.65em] pb-[0.25em] pt-[0.35em] text-center align-baseline text-[0.75em] font-bold leading-none text-white bg-slate-900"
|
22
|
+
href="https://www.amazon.com/Object-Thinking-Developer-Reference-David/dp/0735619654"
|
23
|
+
target="_blank"
|
24
|
+
>
|
25
|
+
Object Thinking
|
26
|
+
</a>
|
27
|
+
</p>
|
28
|
+
|
29
|
+
<div class="clear-both"></div>
|
30
|
+
|
31
|
+
<p class="text-gray-600 text-lg mb-4">
|
32
|
+
В этом разделе сделаем пример кода по расчету простой арифметической формулы с
|
33
|
+
возможностью изменять переменные и одна из переменных будет таймером.
|
34
|
+
</p>
|
35
|
+
|
36
|
+
<p> </p>
|
37
|
+
|
38
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">
|
39
|
+
Результат 1. Вычисление на лету
|
40
|
+
</p>
|
41
|
+
<div class="example mb-4">
|
42
|
+
<span class="guest-result">
|
43
|
+
(
|
44
|
+
<input
|
45
|
+
type="number"
|
46
|
+
class="input-1"
|
47
|
+
style="
|
48
|
+
width: 60px;
|
49
|
+
background: rgba(255, 255, 255, 0.3);
|
50
|
+
border: solid 1px #eee;
|
51
|
+
color: #000;
|
52
|
+
"
|
53
|
+
/>
|
54
|
+
+
|
55
|
+
<span class="eo-counter">?</span>
|
56
|
+
) *
|
57
|
+
<input
|
58
|
+
type="number"
|
59
|
+
class="input-2"
|
60
|
+
style="
|
61
|
+
width: 60px;
|
62
|
+
background: rgba(255, 255, 255, 0.3);
|
63
|
+
border: solid 1px #eee;
|
64
|
+
color: #000;
|
65
|
+
"
|
66
|
+
/>
|
67
|
+
= <span class="eo-result">??</span>
|
68
|
+
</span>
|
69
|
+
<div class="mt-4">
|
70
|
+
<button
|
71
|
+
onclick="window.numberTimer.stop()"
|
72
|
+
class="stop inline-flex gap-1 items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-black mt-4 md:mt-0"
|
73
|
+
>
|
74
|
+
Остановить
|
75
|
+
</button>
|
76
|
+
<button
|
77
|
+
onclick="window.numberTimer.start()"
|
78
|
+
class="begin inline-flex gap-1 items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-black mt-4 md:mt-0"
|
79
|
+
>
|
80
|
+
Запустить
|
81
|
+
</button>
|
82
|
+
<button
|
83
|
+
onclick="window.numberTimer.reset()"
|
84
|
+
class="inline-flex gap-1 items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-black mt-4 md:mt-0"
|
85
|
+
>
|
86
|
+
Сбросить
|
87
|
+
</button>
|
88
|
+
</div>
|
89
|
+
</div>
|
90
|
+
|
91
|
+
<script type="module">
|
92
|
+
import {
|
93
|
+
Guest,
|
94
|
+
Source,
|
95
|
+
Patron,
|
96
|
+
SourceAll,
|
97
|
+
GuestCast,
|
98
|
+
GuestDisposable,
|
99
|
+
} from "patron-oop";
|
100
|
+
import { Text, Input } from "patron-components";
|
101
|
+
|
102
|
+
class NumberFromTimer {
|
103
|
+
timerHead = null;
|
104
|
+
|
105
|
+
constructor() {
|
106
|
+
this.source = new Source(1);
|
107
|
+
this.isStoppedSource = new Source(false);
|
108
|
+
}
|
109
|
+
|
110
|
+
number(guest) {
|
111
|
+
this.source.value(guest);
|
112
|
+
}
|
113
|
+
|
114
|
+
start() {
|
115
|
+
this.isStoppedSource.give(false);
|
116
|
+
if (this.timerHead) {
|
117
|
+
return;
|
118
|
+
}
|
119
|
+
const repeat = () => {
|
120
|
+
this.source.value((value) => {
|
121
|
+
this.timerHead = setTimeout(() => {
|
122
|
+
this.source.give(value + 1);
|
123
|
+
repeat();
|
124
|
+
if (!this.source.pool().size()) {
|
125
|
+
this.stop();
|
126
|
+
}
|
127
|
+
}, 1000);
|
128
|
+
});
|
129
|
+
};
|
130
|
+
repeat();
|
131
|
+
}
|
132
|
+
|
133
|
+
stop() {
|
134
|
+
this.isStoppedSource.give(true);
|
135
|
+
clearTimeout(this.timerHead);
|
136
|
+
this.timerHead = null;
|
137
|
+
}
|
138
|
+
|
139
|
+
reset() {
|
140
|
+
this.stop();
|
141
|
+
this.source.give(1);
|
142
|
+
this.start();
|
143
|
+
}
|
144
|
+
|
145
|
+
isStopped(guest) {
|
146
|
+
this.isStoppedSource.value(guest);
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
class NumberFromInput {
|
151
|
+
constructor(selector) {
|
152
|
+
this.source = new Source(1);
|
153
|
+
this.input = new Input(this.source, selector);
|
154
|
+
}
|
155
|
+
|
156
|
+
number(guest) {
|
157
|
+
this.source.value(
|
158
|
+
new GuestCast(guest, (value) => {
|
159
|
+
guest.give(+value);
|
160
|
+
})
|
161
|
+
);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
class Addition {
|
166
|
+
constructor(num1, num2) {
|
167
|
+
this.num1 = num1;
|
168
|
+
this.num2 = num2;
|
169
|
+
}
|
170
|
+
|
171
|
+
number(guest) {
|
172
|
+
const all = new SourceAll();
|
173
|
+
this.num1.number(new GuestCast(guest, all.guestKey("n1")));
|
174
|
+
this.num2.number(new GuestCast(guest, all.guestKey("n2")));
|
175
|
+
all.value(
|
176
|
+
new GuestCast(guest, ({ n1, n2 }) => {
|
177
|
+
guest.give(n1 + n2);
|
178
|
+
})
|
179
|
+
);
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
class Multiplication {
|
184
|
+
constructor(num1, num2) {
|
185
|
+
this.num1 = num1;
|
186
|
+
this.num2 = num2;
|
187
|
+
}
|
188
|
+
|
189
|
+
number(guest) {
|
190
|
+
const all = new SourceAll();
|
191
|
+
this.num1.number(new GuestCast(guest, all.guestKey("n1")));
|
192
|
+
this.num2.number(new GuestCast(guest, all.guestKey("n2")));
|
193
|
+
all.value(
|
194
|
+
new GuestCast(guest, ({ n1, n2 }) => {
|
195
|
+
guest.give(n1 * n2);
|
196
|
+
})
|
197
|
+
);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
const disposeIfNoSelector = (selector) => () =>
|
202
|
+
!document.querySelector(selector);
|
203
|
+
|
204
|
+
window.numberTimer = new NumberFromTimer();
|
205
|
+
const numberInput1 = new NumberFromInput(".input-1");
|
206
|
+
const numberInput2 = new NumberFromInput(".input-2");
|
207
|
+
const result = new Multiplication(
|
208
|
+
new Addition(numberInput1, numberTimer),
|
209
|
+
numberInput2
|
210
|
+
);
|
211
|
+
numberTimer.start();
|
212
|
+
numberTimer.number(
|
213
|
+
new Patron(
|
214
|
+
new GuestDisposable(
|
215
|
+
new Text(".eo-counter"),
|
216
|
+
disposeIfNoSelector(".eo-counter")
|
217
|
+
)
|
218
|
+
)
|
219
|
+
);
|
220
|
+
numberTimer.isStopped(
|
221
|
+
new Patron((isStopped) => {
|
222
|
+
document
|
223
|
+
.querySelector(".stop")
|
224
|
+
.classList[isStopped ? "add" : "remove"]("opacity-20");
|
225
|
+
document
|
226
|
+
.querySelector(".begin")
|
227
|
+
.classList[!isStopped ? "add" : "remove"]("opacity-20");
|
228
|
+
})
|
229
|
+
);
|
230
|
+
result.number(
|
231
|
+
new Patron(
|
232
|
+
new GuestDisposable(
|
233
|
+
new Text(".eo-result"),
|
234
|
+
disposeIfNoSelector(".eo-result")
|
235
|
+
)
|
236
|
+
)
|
237
|
+
);
|
238
|
+
</script>
|
239
|
+
|
240
|
+
<p class="text-gray-600 text-lg mb-0 font-bold">Листинг 1.</p>
|
241
|
+
<pre class="mb-4"><code class="language-js">import {
|
242
|
+
Guest,
|
243
|
+
Source,
|
244
|
+
Patron,
|
245
|
+
SourceAll,
|
246
|
+
GuestCast,
|
247
|
+
GuestDisposable,
|
248
|
+
} from "patron-oop";
|
249
|
+
import { Text, Input } from "patron-components";
|
250
|
+
|
251
|
+
// Переместил клиентский код наверх,
|
252
|
+
// чтобы не крутить до самой интересной части.
|
253
|
+
window.numberTimer = new NumberFromTimer();
|
254
|
+
const numberInput1 = new NumberFromInput(".input-1");
|
255
|
+
const numberInput2 = new NumberFromInput(".input-2");
|
256
|
+
const result = new Multiplication(
|
257
|
+
new Addition(numberInput1, numberTimer),
|
258
|
+
numberInput2
|
259
|
+
);
|
260
|
+
numberTimer.start();
|
261
|
+
numberTimer.number(
|
262
|
+
new Patron(
|
263
|
+
new GuestDisposable(
|
264
|
+
new Text(".eo-counter"),
|
265
|
+
disposeIfNoSelector(".eo-counter")
|
266
|
+
)
|
267
|
+
)
|
268
|
+
);
|
269
|
+
result.number(
|
270
|
+
new Patron(
|
271
|
+
new GuestDisposable(
|
272
|
+
new Text(".eo-result"),
|
273
|
+
disposeIfNoSelector(".eo-result")
|
274
|
+
)
|
275
|
+
)
|
276
|
+
);
|
277
|
+
|
278
|
+
class NumberFromTimer {
|
279
|
+
timerHead = null;
|
280
|
+
|
281
|
+
constructor() {
|
282
|
+
this.source = new Source(1);
|
283
|
+
}
|
284
|
+
|
285
|
+
number(guest) {
|
286
|
+
this.source.value(guest);
|
287
|
+
}
|
288
|
+
|
289
|
+
start() {
|
290
|
+
if (this.timerHead) {
|
291
|
+
return;
|
292
|
+
}
|
293
|
+
const repeat = () => {
|
294
|
+
this.source.value((value) => {
|
295
|
+
this.timerHead = setTimeout(() => {
|
296
|
+
this.source.give(value + 1);
|
297
|
+
repeat();
|
298
|
+
if (!this.source.pool().size()) {
|
299
|
+
this.stop();
|
300
|
+
}
|
301
|
+
}, 1000);
|
302
|
+
});
|
303
|
+
};
|
304
|
+
repeat();
|
305
|
+
}
|
306
|
+
|
307
|
+
stop() {
|
308
|
+
clearTimeout(this.timerHead);
|
309
|
+
this.timerHead = null;
|
310
|
+
}
|
311
|
+
|
312
|
+
reset() {
|
313
|
+
this.stop();
|
314
|
+
this.source.give(1);
|
315
|
+
this.start();
|
316
|
+
}
|
317
|
+
}
|
318
|
+
|
319
|
+
class NumberFromInput {
|
320
|
+
constructor(selector) {
|
321
|
+
this.source = new Source(1);
|
322
|
+
this.input = new Input(this.source, selector);
|
323
|
+
}
|
324
|
+
|
325
|
+
number(guest) {
|
326
|
+
this.source.value(
|
327
|
+
new GuestCast(guest, (value) => {
|
328
|
+
guest.give(+value);
|
329
|
+
})
|
330
|
+
);
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
class Addition {
|
335
|
+
constructor(num1, num2) {
|
336
|
+
this.num1 = num1;
|
337
|
+
this.num2 = num2;
|
338
|
+
}
|
339
|
+
|
340
|
+
number(guest) {
|
341
|
+
const all = new SourceAll();
|
342
|
+
this.num1.number(new GuestCast(guest, all.guestKey("n1")));
|
343
|
+
this.num2.number(new GuestCast(guest, all.guestKey("n2")));
|
344
|
+
all.value(
|
345
|
+
new GuestCast(guest, ({ n1, n2 }) => {
|
346
|
+
guest.give(n1 + n2);
|
347
|
+
})
|
348
|
+
);
|
349
|
+
}
|
350
|
+
}
|
351
|
+
|
352
|
+
class Multiplication {
|
353
|
+
constructor(num1, num2) {
|
354
|
+
this.num1 = num1;
|
355
|
+
this.num2 = num2;
|
356
|
+
}
|
357
|
+
|
358
|
+
number(guest) {
|
359
|
+
const all = new SourceAll();
|
360
|
+
this.num1.number(new GuestCast(guest, all.guestKey("n1")));
|
361
|
+
this.num2.number(new GuestCast(guest, all.guestKey("n2")));
|
362
|
+
all.value(
|
363
|
+
new GuestCast(guest, ({ n1, n2 }) => {
|
364
|
+
guest.give(n1 * n2);
|
365
|
+
})
|
366
|
+
);
|
367
|
+
}
|
368
|
+
}
|
369
|
+
|
370
|
+
const disposeIfNoSelector = (selector) => () =>
|
371
|
+
!document.querySelector(selector);
|
372
|
+
|
373
|
+
</code></pre>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<div class="compatibility-menu"></div>
|
2
|
+
<div class="w-full sm:w-2/3 mt-4 sm:mt-0 mx-auto">
|
3
|
+
<div class="compatibility-loader">
|
4
|
+
<div class="w-full flex justify-center">
|
5
|
+
<div
|
6
|
+
class="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-e-transparent align-[-0.125em] text-indigo-500 motion-reduce:animate-[spin_1.5s_linear_infinite]"
|
7
|
+
role="status"
|
8
|
+
>
|
9
|
+
<span
|
10
|
+
class="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]"
|
11
|
+
>Loading...</span
|
12
|
+
>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
<div class="compatibility-page-area"></div>
|
17
|
+
</div>
|