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 CHANGED
@@ -5,12 +5,12 @@
5
5
  [![Stars](https://img.shields.io/github/stars/livetrails/targetjs.svg)](https://github.com/livetrails/targetjs/stargazers)
6
6
  [![npm version](https://img.shields.io/npm/v/targetj.svg)](https://www.npmjs.com/package/targetj)
7
7
 
8
- TargetJS is a modern JavaScript UI framework that simplifies front-end development by introducing two new key concepts: unifying methods and variables, and reactive methods. 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 and allows for a stronger focus on user experience. It can be used as a full-featured framework or as a lightweight library alongside other frameworks.
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 44KB compressed):
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://ltstaticfiles.s3.us-east-1.amazonaws.com/targetjs.js"></script>
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
  ![Single page app](https://targetjs.io/img/infiniteScrolling11.gif)
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
- width: [{list: [100, 250]}, 15],
582
- background: [{list: ["#FCE961", "#B388FF"]}, 15, 15],
583
- height: 48,
584
- color: "#C2FC61",
585
- textAlign: "center",
586
- lineHeight: 48,
587
- bottomMargin: 2,
588
- x() { return this.getCenterX(); },
589
- validateVisibilityInParent: true,
590
- html: childrenCount + i
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
- load$() {
594
- this.prevTargetValue.forEach(data =>
595
- fetch(this, "https://targetjs.io/api/randomUser", { id: data.oid }));
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.forEach((data) => this.getChildByOid(data.id).setTarget("html", data.name));
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() === "down" && this.visibleChildren.length * 50 < this.getHeight()) {
605
- this.activateTarget("children");
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
- tg-domHolder="true"
618
- tg-preventDefault="true"
619
- tg-containerOverflowMode="always"
620
- tg-width="return TargetJS.getScreenWidth();"
621
- tg-height="return TargetJS.getScreenHeight();"
622
- tg-children="function() {
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: [{ list: [100, 250] }, 15],
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
- tg-load$="function() {
638
- this.prevTargetValue.forEach(data =>
639
- TargetJS.fetch(this, 'https://targetjs.io/api/randomUser', { id: data.oid })
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
- tg-populate$$="function() {
643
- this.prevTargetValue.forEach((data) =>
644
- this.getChildByOid(data.id).setTarget('html', data.name)
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
- tg-onScroll="function() {
656
+ tg-onScroll="function() {
648
657
  this.setTarget('scrollTop', Math.max(0, this.getScrollTop() + TargetJS.getEvents().deltaY()));
649
658
  }"
650
- tg-onVisibleChildrenChange="function() {
659
+ tg-onVisibleChildrenChange="function() {
651
660
  if (TargetJS.getEvents().dir() === 'down' && this.visibleChildren.length * 50 < this.getHeight()) {
652
- this.activateTarget('children');
661
+ this.activateTarget('children');
662
+ } else {
663
+ this.activateTarget('load');
653
664
  }
654
665
  }"
655
666
  ></div>
@@ -327,7 +327,7 @@ var LocationManager = exports.LocationManager = /*#__PURE__*/function () {
327
327
  if (!target) {
328
328
  return;
329
329
  }
330
- if (target.active !== 'active' && tmodel.isTargetEnabled(key) && !tmodel.isTargetUpdating(key) && !tmodel.isTargetImperative(key)) {
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
  }
@@ -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;
@@ -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() {
@@ -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'],
@@ -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
- return;
159
- }
160
- var nextTarget = target.activateNextTarget;
161
- var cleanNextTarget = TargetUtil.getTargetName(nextTarget);
162
- var isEndTrigger = nextTarget.endsWith('$');
163
- var fetchAction = target.fetchAction;
164
- if (fetchAction) {
165
- if (isEndTrigger) {
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
- (0, _App.getLoader)().nextActiveItem(tmodel, key);
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.isTargetComplete(tmodel, key) || tmodel.hasUpdatingImperativeTargets(key) || !TargetUtil.arePreviousTargetsComplete(tmodel, key) ? false : true;
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.isTargetComplete(tmodel, cleanTargetName) || tmodel.hasUpdatingImperativeTargets(cleanTargetName)) {
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: "isTargetComplete",
271
- value: function isTargetComplete(tmodel, key) {
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);