targetj 1.0.190 → 1.0.191
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/README.md +59 -48
- package/build/LocationManager.js +1 -1
- package/build/RunScheduler.js +0 -4
- package/build/TModelManager.js +0 -13
- package/build/TargetData.js +3 -1
- package/build/TargetUtil.js +32 -27
- package/dist/targetjs.js +1 -1
- package/dist/targetjs.js.gz +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
[](https://github.com/livetrails/targetjs/stargazers)
|
|
6
6
|
[](https://www.npmjs.com/package/targetj)
|
|
7
7
|
|
|
8
|
-
TargetJS is a modern JavaScript UI framework that simplifies front-end development by introducing
|
|
8
|
+
TargetJS is a modern JavaScript UI framework that simplifies front-end development by introducing key concepts: unifying methods and variables, autonomous and reactive methods, and execution flow that follows the written code. It provides a unified solution for key aspects like UI rendering, animations, APIs, state management, and event handling. This integrated approach leads to more compact code, introduces a new development paradigm, and prioritizes user experience. It can be used as a full-featured framework or as a lightweight library alongside other frameworks.
|
|
9
9
|
Furthermore, it is also a highly performant web framework, as shown in the [framework benchmark](https://krausest.github.io/js-framework-benchmark/current.html).
|
|
10
10
|
|
|
11
11
|
## Key Innovations and Concepts
|
|
12
12
|
|
|
13
|
-
1. Unifying Methods and Variables with Targets: A new construct called “targets” combines methods and variables, providing state, iteration, and timing mechanisms for both.
|
|
13
|
+
1. Unifying Methods and Variables with Targets: A new construct called “targets” combines methods and variables, providing state, lifecycles, iteration, and timing mechanisms for both.
|
|
14
14
|
2. Declarative Reactive Targets: Targets can explicitly declare reactive execution triggered by the run or completion of their immediately preceding targets, whether synchronous or asynchronous.
|
|
15
15
|
3. All-in-One Solution: Offers a unified approach to UI rendering, API integration, state management, event handling, and animation.
|
|
16
16
|
4. Code-Ordered Execution: The execution flow generally follows the order in which the code is written.
|
|
@@ -220,10 +220,10 @@ A target name ending with a double `$$` (e.g., `fetch$$`) will activate only aft
|
|
|
220
220
|
|
|
221
221
|
**Via CDN**
|
|
222
222
|
|
|
223
|
-
Add the following `<script>` tag to your HTML to load TargetJS from a CDN (only
|
|
223
|
+
Add the following `<script>` tag to your HTML to load TargetJS from a CDN (only 47KB compressed):
|
|
224
224
|
|
|
225
225
|
```html
|
|
226
|
-
<script src="https://
|
|
226
|
+
<script src="https://unpkg.com/targetj@latest/dist/targetjs.js"></script>
|
|
227
227
|
```
|
|
228
228
|
|
|
229
229
|
This will add `TargetJS` to the global `window` object, making it accessible throughout your JavaScript such as `TargetJS.App(YourApp)`.
|
|
@@ -563,66 +563,75 @@ In this example, we demonstrate a simple infinite scrolling application where ea
|
|
|
563
563
|
|
|
564
564
|
TargetJS employs a tree-like structure to track visible branches, optimizing the scroller performance.
|
|
565
565
|
|
|
566
|
+
We use the TModel class instead of a plain object to demonstrate how it can provide additional functionality and control. A plain object would also have worked in this example.
|
|
567
|
+
|
|
566
568
|
If you inspect the HTML elements in the browser's developer tools, you'll notice that the scroller’s elements are not nested inside the container. This is because nesting itself is a dynamic target that determines how elements are structured. This enables efficient reuse of HTML elements and unlocks new user experiences.
|
|
567
569
|
|
|
568
570
|

|
|
569
571
|
|
|
570
572
|
```javascript
|
|
571
|
-
import { App, getEvents, fetch, getScreenWidth, getScreenHeight } from "targetj";
|
|
573
|
+
import { App, TModel, getEvents, fetch, getScreenWidth, getScreenHeight } from "targetj";
|
|
572
574
|
|
|
573
|
-
App({
|
|
574
|
-
id: "scroller",
|
|
575
|
+
App(new TModel("scroller", {
|
|
575
576
|
domHolder: true,
|
|
576
577
|
preventDefault: true,
|
|
577
578
|
containerOverflowMode: "always",
|
|
578
|
-
children() {
|
|
579
|
-
const childrenCount = this.getChildren().length;
|
|
579
|
+
children() {
|
|
580
|
+
const childrenCount = this.getChildren().length;
|
|
580
581
|
return Array.from({ length: 20 }, (_, i) => ({
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
}));
|
|
582
|
+
width: [{list: [100, 250, 100]}, 50],
|
|
583
|
+
background: [{list: ["#FCE961", "#B388FF"]}, 15, 15],
|
|
584
|
+
height: 48,
|
|
585
|
+
color: "#C2FC61",
|
|
586
|
+
textAlign: "center",
|
|
587
|
+
lineHeight: 48,
|
|
588
|
+
bottomMargin: 2,
|
|
589
|
+
x() { return this.getCenterX(); },
|
|
590
|
+
html: childrenCount + i
|
|
591
|
+
}));
|
|
592
592
|
},
|
|
593
|
-
|
|
594
|
-
this.
|
|
595
|
-
|
|
593
|
+
loadItems$$() {
|
|
594
|
+
this.visibleChildren.filter(child => !child.loaded).forEach(child => {
|
|
595
|
+
child.loaded = true;
|
|
596
|
+
fetch(this, `https://targetjs.io/api/randomUser?id=${child.oid}`);
|
|
597
|
+
});
|
|
596
598
|
},
|
|
597
599
|
populate$$() {
|
|
598
|
-
this.prevTargetValue
|
|
600
|
+
if (this.prevTargetValue) {
|
|
601
|
+
this.prevTargetValue.forEach(data => this.getChildByOid(data.id).setTarget('html', data.name));
|
|
602
|
+
}
|
|
599
603
|
},
|
|
600
604
|
onScroll() {
|
|
601
605
|
this.setTarget("scrollTop", Math.max(0, this.getScrollTop() + getEvents().deltaY()));
|
|
602
606
|
},
|
|
603
607
|
onVisibleChildrenChange() {
|
|
604
|
-
if (getEvents().dir() ===
|
|
605
|
-
this.activateTarget(
|
|
608
|
+
if (getEvents().dir() === 'down' && this.visibleChildren.length * 50 < this.getHeight()) {
|
|
609
|
+
this.activateTarget('children');
|
|
610
|
+
} else {
|
|
611
|
+
this.activateTarget('loadItems');
|
|
606
612
|
}
|
|
607
613
|
},
|
|
608
614
|
width: getScreenWidth,
|
|
609
|
-
height: getScreenHeight
|
|
610
|
-
|
|
615
|
+
height: getScreenHeight,
|
|
616
|
+
onResize: 'width'
|
|
617
|
+
}));
|
|
611
618
|
```
|
|
612
619
|
|
|
613
620
|
Or in HTML:
|
|
614
621
|
|
|
615
622
|
```HTML
|
|
616
|
-
<div
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
+
<div
|
|
624
|
+
id="scroller"
|
|
625
|
+
tg-domHolder="true"
|
|
626
|
+
tg-preventDefault="true"
|
|
627
|
+
tg-background="red"
|
|
628
|
+
tg-containerOverflowMode="always"
|
|
629
|
+
tg-width="return TargetJS.getScreenWidth();"
|
|
630
|
+
tg-height="return TargetJS.getScreenHeight();"
|
|
631
|
+
tg-children="function() {
|
|
623
632
|
const childrenCount = this.getChildren().length;
|
|
624
633
|
return Array.from({ length: 20 }, (_, i) => ({
|
|
625
|
-
width: [{
|
|
634
|
+
width: [{list: [100, 250, 100]}, 50],
|
|
626
635
|
background: [{ list: ['#FCE961', '#B388FF'] }, 15, 15],
|
|
627
636
|
height: 48,
|
|
628
637
|
color: '#C2FC61',
|
|
@@ -630,26 +639,28 @@ Or in HTML:
|
|
|
630
639
|
lineHeight: 48,
|
|
631
640
|
bottomMargin: 2,
|
|
632
641
|
x: function() { return this.getCenterX(); },
|
|
633
|
-
validateVisibilityInParent: true,
|
|
634
642
|
html: childrenCount + i
|
|
635
643
|
}));
|
|
636
644
|
}"
|
|
637
|
-
|
|
638
|
-
this.
|
|
639
|
-
|
|
640
|
-
|
|
645
|
+
tg-load$$="function() {
|
|
646
|
+
this.visibleChildren.filter(child => !child.loaded).forEach(child => {
|
|
647
|
+
child.loaded = true;
|
|
648
|
+
TargetJS.fetch(this, `https://targetjs.io/api/randomUser?id=${child.oid}`);
|
|
649
|
+
});
|
|
641
650
|
}"
|
|
642
|
-
|
|
643
|
-
this.prevTargetValue
|
|
644
|
-
|
|
645
|
-
|
|
651
|
+
tg-populate$$="function() {
|
|
652
|
+
if (this.prevTargetValue) {
|
|
653
|
+
this.prevTargetValue.forEach(data => this.getChildByOid(data.id).setTarget('html', data.name));
|
|
654
|
+
}
|
|
646
655
|
}"
|
|
647
|
-
|
|
656
|
+
tg-onScroll="function() {
|
|
648
657
|
this.setTarget('scrollTop', Math.max(0, this.getScrollTop() + TargetJS.getEvents().deltaY()));
|
|
649
658
|
}"
|
|
650
|
-
|
|
659
|
+
tg-onVisibleChildrenChange="function() {
|
|
651
660
|
if (TargetJS.getEvents().dir() === 'down' && this.visibleChildren.length * 50 < this.getHeight()) {
|
|
652
|
-
|
|
661
|
+
this.activateTarget('children');
|
|
662
|
+
} else {
|
|
663
|
+
this.activateTarget('load');
|
|
653
664
|
}
|
|
654
665
|
}"
|
|
655
666
|
></div>
|
package/build/LocationManager.js
CHANGED
|
@@ -327,7 +327,7 @@ var LocationManager = exports.LocationManager = /*#__PURE__*/function () {
|
|
|
327
327
|
if (!target) {
|
|
328
328
|
return;
|
|
329
329
|
}
|
|
330
|
-
if (target.active !==
|
|
330
|
+
if (target.active !== false && tmodel.isTargetEnabled(key) && !tmodel.isTargetUpdating(key) && !tmodel.isTargetImperative(key)) {
|
|
331
331
|
_TargetExecutor.TargetExecutor.resolveTargetValue(tmodel, key, tmodel.getTargetCycle(key));
|
|
332
332
|
_TargetExecutor.TargetExecutor.updateTarget(tmodel, tmodel.targetValues[key], key, false);
|
|
333
333
|
}
|
package/build/RunScheduler.js
CHANGED
|
@@ -125,10 +125,6 @@ var RunScheduler = exports.RunScheduler = /*#__PURE__*/function () {
|
|
|
125
125
|
this.runStartTime = _TUtil.TUtil.now();
|
|
126
126
|
if (this.phase === 0) {
|
|
127
127
|
(0, _App.getEvents)().captureEvents();
|
|
128
|
-
if ((0, _App.getManager)().doneTargets.length) {
|
|
129
|
-
(0, _App.getManager)().completeDoneTModels();
|
|
130
|
-
(0, _App.getManager)().doneTargets.length = 0;
|
|
131
|
-
}
|
|
132
128
|
_App.tApp.targetManager.applyTargetValues(_App.tApp.tRoot);
|
|
133
129
|
(0, _App.getLocationManager)().calculateAll();
|
|
134
130
|
this.phase = 1;
|
package/build/TModelManager.js
CHANGED
|
@@ -399,19 +399,6 @@ var TModelManager = exports.TModelManager = /*#__PURE__*/function () {
|
|
|
399
399
|
value: function getDomExchangeKey(tmodel) {
|
|
400
400
|
return "".concat(tmodel.type, "-").concat(tmodel.getDomParent().oid, "-").concat(tmodel.getBaseElement());
|
|
401
401
|
}
|
|
402
|
-
}, {
|
|
403
|
-
key: "completeDoneTModels",
|
|
404
|
-
value: function completeDoneTModels() {
|
|
405
|
-
this.doneTargets.forEach(function (target) {
|
|
406
|
-
var tmodel = target.tmodel;
|
|
407
|
-
var key = target.key;
|
|
408
|
-
if (tmodel.isTargetDone(key)) {
|
|
409
|
-
tmodel.setTargetComplete(key);
|
|
410
|
-
tmodel.removeFromActiveTargets(key);
|
|
411
|
-
tmodel.removeFromUpdatingTargets(key);
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
402
|
}, {
|
|
416
403
|
key: "createDoms",
|
|
417
404
|
value: function createDoms() {
|
package/build/TargetData.js
CHANGED
|
@@ -634,7 +634,9 @@ _defineProperty(TargetData, "attributesToTargets", {
|
|
|
634
634
|
onvisiblechildrenchange: 'onVisibleChildrenChange',
|
|
635
635
|
onchildrenchange: 'onChildrenChange',
|
|
636
636
|
isvisible: 'isVisible',
|
|
637
|
-
isinflow: 'isInFlow'
|
|
637
|
+
isinflow: 'isInFlow',
|
|
638
|
+
basewidth: 'baseWidth',
|
|
639
|
+
baseheight: 'baseHeight'
|
|
638
640
|
});
|
|
639
641
|
_defineProperty(TargetData, "targetToEventsMapping", {
|
|
640
642
|
onStart: ['touchStart', 'mouseStart'],
|
package/build/TargetUtil.js
CHANGED
|
@@ -132,8 +132,10 @@ var TargetUtil = exports.TargetUtil = /*#__PURE__*/function () {
|
|
|
132
132
|
}
|
|
133
133
|
var originalTarget = originalTModel.targets[originalTargetName];
|
|
134
134
|
var activeNextTarget = originalTarget.activateNextTarget;
|
|
135
|
-
if (activeNextTarget && (!activeNextTarget.endsWith('$') || !tmodel.isTargetUpdating(key))) {
|
|
135
|
+
if (!originalTModel.isTargetComplete(originalTargetName) && activeNextTarget && (!activeNextTarget.endsWith('$') || !tmodel.isTargetUpdating(key))) {
|
|
136
136
|
TargetUtil.shouldActivateNextTarget(originalTModel, originalTargetName, level + 1);
|
|
137
|
+
} else {
|
|
138
|
+
TargetUtil.cleanupTarget(originalTModel, originalTargetName);
|
|
137
139
|
}
|
|
138
140
|
}
|
|
139
141
|
}, {
|
|
@@ -141,6 +143,7 @@ var TargetUtil = exports.TargetUtil = /*#__PURE__*/function () {
|
|
|
141
143
|
value: function shouldActivateNextTarget(tmodel, key) {
|
|
142
144
|
var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
143
145
|
if (tmodel.isTargetImperative(key)) {
|
|
146
|
+
TargetUtil.cleanupTarget(tmodel, key);
|
|
144
147
|
var _tmodel$targetValues$ = tmodel.targetValues[key],
|
|
145
148
|
originalTModel = _tmodel$targetValues$.originalTModel,
|
|
146
149
|
originalTargetName = _tmodel$targetValues$.originalTargetName;
|
|
@@ -155,37 +158,39 @@ var TargetUtil = exports.TargetUtil = /*#__PURE__*/function () {
|
|
|
155
158
|
var _originalTModel = target.originalTModel,
|
|
156
159
|
_originalTargetName = target.originalTargetName;
|
|
157
160
|
TargetUtil.shouldActivateOriginalTModel(tmodel, key, _originalTModel, _originalTargetName, level);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (TargetUtil.hasTargetEnded(tmodel, key)) {
|
|
167
|
-
tmodel.activateTarget(cleanNextTarget);
|
|
168
|
-
}
|
|
169
|
-
} else {
|
|
170
|
-
while ((0, _App.getLoader)().isNextLoadingItemSuccessful(tmodel, key)) {
|
|
171
|
-
if (tmodel.activatedTargets.indexOf(cleanNextTarget) >= 0) {
|
|
172
|
-
tmodel.activatedTargets.push(cleanNextTarget);
|
|
173
|
-
} else {
|
|
161
|
+
} else {
|
|
162
|
+
var nextTarget = target.activateNextTarget;
|
|
163
|
+
var cleanNextTarget = TargetUtil.getTargetName(nextTarget);
|
|
164
|
+
var isEndTrigger = nextTarget.endsWith('$');
|
|
165
|
+
var fetchAction = target.fetchAction;
|
|
166
|
+
if (fetchAction) {
|
|
167
|
+
if (isEndTrigger) {
|
|
168
|
+
if (TargetUtil.hasTargetEnded(tmodel, key)) {
|
|
174
169
|
tmodel.activateTarget(cleanNextTarget);
|
|
175
170
|
}
|
|
176
|
-
|
|
171
|
+
} else {
|
|
172
|
+
while ((0, _App.getLoader)().isNextLoadingItemSuccessful(tmodel, key)) {
|
|
173
|
+
if (tmodel.activatedTargets.indexOf(cleanNextTarget) >= 0) {
|
|
174
|
+
tmodel.activatedTargets.push(cleanNextTarget);
|
|
175
|
+
} else {
|
|
176
|
+
tmodel.activateTarget(cleanNextTarget);
|
|
177
|
+
}
|
|
178
|
+
(0, _App.getLoader)().nextActiveItem(tmodel, key);
|
|
179
|
+
}
|
|
177
180
|
}
|
|
181
|
+
} else if (isEndTrigger && TargetUtil.hasTargetEnded(tmodel, key) || !isEndTrigger) {
|
|
182
|
+
tmodel.activateTarget(cleanNextTarget);
|
|
178
183
|
}
|
|
179
|
-
} else if (isEndTrigger && TargetUtil.hasTargetEnded(tmodel, key) || !isEndTrigger) {
|
|
180
|
-
tmodel.activateTarget(cleanNextTarget);
|
|
181
|
-
}
|
|
182
|
-
if (TargetUtil.isTargetComplete(tmodel, key)) {
|
|
183
|
-
TargetUtil.cleanupTarget(tmodel, key);
|
|
184
184
|
}
|
|
185
|
+
TargetUtil.cleanupTarget(tmodel, key);
|
|
185
186
|
}
|
|
186
187
|
}, {
|
|
187
188
|
key: "cleanupTarget",
|
|
188
189
|
value: function cleanupTarget(tmodel, key) {
|
|
190
|
+
if (tmodel.isTargetComplete(key) || !TargetUtil.hasTargetEnded(tmodel, key)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
tmodel.setTargetComplete(key);
|
|
189
194
|
var target = tmodel.targets[key];
|
|
190
195
|
var fetchAction = target === null || target === void 0 ? void 0 : target.fetchAction;
|
|
191
196
|
var childAction = target === null || target === void 0 ? void 0 : target.childAction;
|
|
@@ -242,7 +247,7 @@ var TargetUtil = exports.TargetUtil = /*#__PURE__*/function () {
|
|
|
242
247
|
}, {
|
|
243
248
|
key: "hasTargetEnded",
|
|
244
249
|
value: function hasTargetEnded(tmodel, key) {
|
|
245
|
-
var result = !TargetUtil.
|
|
250
|
+
var result = !TargetUtil.isTModelTargetComplete(tmodel, key) || tmodel.hasUpdatingImperativeTargets(key) || !TargetUtil.arePreviousTargetsComplete(tmodel, key) ? false : true;
|
|
246
251
|
return result;
|
|
247
252
|
}
|
|
248
253
|
}, {
|
|
@@ -257,7 +262,7 @@ var TargetUtil = exports.TargetUtil = /*#__PURE__*/function () {
|
|
|
257
262
|
if (tmodel.isTargetImperative(cleanTargetName)) {
|
|
258
263
|
continue;
|
|
259
264
|
}
|
|
260
|
-
if (!TargetUtil.
|
|
265
|
+
if (!TargetUtil.isTModelTargetComplete(tmodel, cleanTargetName) || tmodel.hasUpdatingImperativeTargets(cleanTargetName)) {
|
|
261
266
|
return false;
|
|
262
267
|
}
|
|
263
268
|
if (!targetName.endsWith('$')) {
|
|
@@ -267,8 +272,8 @@ var TargetUtil = exports.TargetUtil = /*#__PURE__*/function () {
|
|
|
267
272
|
return true;
|
|
268
273
|
}
|
|
269
274
|
}, {
|
|
270
|
-
key: "
|
|
271
|
-
value: function
|
|
275
|
+
key: "isTModelTargetComplete",
|
|
276
|
+
value: function isTModelTargetComplete(tmodel, key) {
|
|
272
277
|
var target = tmodel.targets[key];
|
|
273
278
|
if (target) {
|
|
274
279
|
var targetType = _typeof(target.value);
|