targetj 1.0.202 → 1.0.203

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
@@ -1,42 +1,40 @@
1
- # TargetJS: A Novel JavaScript UI Framework for Simplified Development and Enhanced User Experience
1
+ # TargetJS: JavaScript UI Framework for Simplified Development and Enhanced User Experience
2
2
 
3
3
  **[targetjs.io](https://targetjs.io)**
4
4
  [![MIT LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/livetrails/targetjs/blob/main/LICENSE)
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 key concepts: unifying class methods and fields, 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 extreme compact code and an introduction of a new development paradigm.
8
+ TargetJS is a modern JavaScript UI framework that simplifies front-end development with a code-ordered reactivity model and a compact, Rebol-like syntax. It provides a unified solution for key aspects like UI rendering, animations, APIs, state management, and event handling.
9
9
  It can be used as a full-featured framework or as a lightweight library alongside other frameworks. 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
  ## The Philosophy Behind TargetJS
12
12
 
13
- Frameworks often promise simplicity, but frequently require extensive boilerplate and libraries as they inherit the same software approach rooted in early programming models and force it to fit building user interfaces by adding more complexity. User interfaces are dynamic and asynchronous and require a different paradigm.
13
+ Frameworks often promise simplicity, but frequently require extensive boilerplate and libraries as they inherit the same software approach rooted in early programming models and try to force it to fit UI development by adding more complexity. User interfaces are dynamic and asynchronous and require a different paradigm.
14
14
 
15
15
  TargetJS adopts a new approach. First, it unifies class methods and fields into a single construct called targets. Each target is given state, lifecycles, timing, iterations, and the autonomy to execute mimicking the behavior of living cells. Targets are essentially self-contained, intelligent blocks of code.
16
16
 
17
- The second challenge is making these targets to fit and work together especially since UI operations are highly asynchronous. Instead of relying on traditional method calls and callbacks that don't address asynchronous nature well, TargetJS allows targets to react to the execution or completion of preceding targets. A subsequent target can run independently, execute whenever the previous one does, or wait until the previous target completes. Targets stack together like Lego pieces. It can address complex asynchronous workflow yet easy to understand.
17
+ The second challenge is making these targets fit and work together especially since UI operations are highly asynchronous. Instead of relying on traditional method calls and callbacks that don't address asynchronous nature well, TargetJS allows targets to react to the execution or completion of preceding targets. A subsequent target can run independently, execute whenever the previous one does, or wait until the previous target completes. Targets stack together like Lego pieces. It can address complex asynchronous workflow while remaining easy to understand.
18
18
 
19
- For example, setting a value can implicitly define an animation, where the current value iteratively progresses until it reaches the new value. When the animation completes, the next target might initiate a fetch API call. Once the data is received, it can trigger another target that creates 10 new elements, each with its own animation and API call. A subsequent target can then be set to run only after all elements have completed their tasks. Throughout this sequence, no direct method calls are made. Targets simply react and chain together based on how the code is written.
19
+ For example, setting a value can implicitly define an animation, where the current value iteratively progresses until it reaches the new value. When the animation completes, the next target might initiate a fetch API call. Once the data is received, it can trigger another target that creates 10 new elements, each with its own animation and API call. A subsequent target can then be set to run only after all 10 elements have completed their tasks. Targets simply react and chain together based on how the code is written.
20
20
 
21
- Targets unlock a fundamentally new way of coding that simplifies everything from animation, UI updates, API calls, and state management. It also makes the code significantly more compact.
21
+ Furthermore, TargetJS adopts a Rebol-like style to make the code more compact.
22
22
 
23
23
  ## Key Innovations and Concepts
24
24
 
25
- 1. Unifying Class Methods and Fields with Targets: A new construct called “targets” combines methods and fields, providing state, lifecycles, iteration, and timing mechanisms for both.
26
- 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.
27
- 3. All-in-One Solution: Offers a unified approach to UI rendering, API integration, state management, event handling, and animation.
28
- 4. Code-Ordered Execution: Targets are chained top to bottom and the execution flow generally follows the order in which the code is written.
29
- 5. Autonomous Methods: Methods in TargetJS are not directly callable. Instead, they are designed to execute themselves or react dynamically to the execution or completion of preedings targets. This enables declarative programming that inherently supports asynchronous operations without explicit plumbing like using async/await keywords.
30
- 6. Compactness: TargetJS allows developers to achieve interactive UIs with significantly less code.
25
+ 1. Reactive targets: A new construct called “targets” unifies class methods and fields. Targets are self-contained units of code with their own state, lifecycles, and timing. They are designed to execute themselves or react dynamically to the run or completion of preceding targets. This enables the declarative programming of complex asynchronous flows without explicit callbacks.
26
+ 2. All-in-One solution: Offers a unified approach to UI rendering, API integration, state management, event handling, and animation.
27
+ 3. Code-ordered execution, Rebol-like style: less code and more readable code.
31
28
 
29
+ ---
32
30
 
33
- ## Examples: From like button animated like + API (in 7 steps)
31
+ ## Examples: Like ButtonAnimated Like with 4 Async Ops (in 7 Steps)
34
32
 
35
- ---
33
+ The example demonstrates how to run four asynchronous operations in a strict sequential sequence, where each step waits for the previous ones to complete. Any restart or delay in an operation delays the ones that follow. This is to showcase managing async operations rather than focusing on the user experience. We will show the example in 7 steps.
36
34
 
37
- ## 1) Like button (view only)
35
+ ### 1) Like button (view only)
38
36
 
39
- **What this shows:** One object defines a UI element without separate HTML/CSS. Static targets map directly to DOM styles/attributes.
37
+ **What this shows:** One object defines a UI element without separate HTML/CSS. Static targets map directly to DOM styles/attributes. You can still use CSS if wanted.
40
38
 
41
39
  <img src="https://targetjs.io/img/likeButton.png" width="130" />
42
40
 
@@ -57,7 +55,7 @@ App({
57
55
  ---
58
56
 
59
57
 
60
- ## 2) Animation
58
+ ### 2) Animation
61
59
 
62
60
  **What this shows:** A mount-time animation that scales and changes the background over 12 steps, with 12ms pauses between steps. Targets without (`$`, `$$`, `_`) execute immediately in the order they are defined.
63
61
 
@@ -78,7 +76,7 @@ App({
78
76
  });
79
77
  ```
80
78
 
81
- ## 3) Click → animation (imperative `setTarget`)
79
+ ### 3) Click → animation (imperative `setTarget`)
82
80
 
83
81
  **What this shows:** Clicking plays the animations from the previous step using imperative `setTarget`.
84
82
 
@@ -103,9 +101,9 @@ App({
103
101
 
104
102
  ---
105
103
 
106
- ## 4) Sequencing with `$$`: Adding a small heart after click
104
+ ### 4) Sequencing with `$$`: Adding a small heart after click animation (first async op)
107
105
 
108
- **What this shows:** A `$$` target (deferred) runs only after all prior targets finish (including `onClick()` and its animations). Here it adds a new heart element and runs its fly motion only once the click sequence has completed.
106
+ **What this shows:** A `$$` target (deferred) runs only after all prior targets finish (including `onClick()` and its animations). Here it adds a new heart element and runs its fly motion only once the click sequence has completed. Repeated clicks will delay adding the heart.
109
107
 
110
108
  <img src="https://targetjs.io/img/likeButton7.gif" width="130" />
111
109
 
@@ -139,9 +137,9 @@ App({
139
137
 
140
138
  ---
141
139
 
142
- ## 5) Another `$$`: big heart, different motion
140
+ ### 5) Another `$$`: Adding a big heart (second async op)
143
141
 
144
- **What this shows:** Deferred addition of a new element using $$. `bigHeart$$` waits for `heart$$` to complete its animation, then adds a larger heart and runs its own animation.
142
+ **What this shows:** Deferred addition of a new element using $$. `bigHeart$$` waits for `heart$$` and the click sequence to complete their animation, then adds a larger heart and runs its own happy animation.
145
143
 
146
144
  <img src="https://targetjs.io/img/likeButton8.gif" width="130" />
147
145
 
@@ -174,7 +172,7 @@ App({
174
172
  },
175
173
  bigHeart$$: {
176
174
  html: "♥", color: "blue", fontSize: 100,
177
- fly() {
175
+ happyFly() {
178
176
  const cx = this.getCenterX(), cy = this.getCenterY();
179
177
  this.setTarget({
180
178
  opacity: { list: [0, 1, 1, 0.85, 0.6, 0.1] },
@@ -190,9 +188,9 @@ App({
190
188
 
191
189
  ---
192
190
 
193
- ## 6) `fetch$$`
191
+ ### 6) `fetch$$` (third async op)
194
192
 
195
- **What this shows:** Networking is just another target. The POST happens **only after** all prior visual steps complete, since the target is postfixed with `$$`.
193
+ **What this shows:** Networking is just another target. The POST happens **only after** all prior visual steps complete, since the target is postfixed with `$$`. Similarly, repeated clicks delay `fetch$$`.
196
194
 
197
195
  ```javascript
198
196
  App({
@@ -204,9 +202,9 @@ App({
204
202
 
205
203
  ---
206
204
 
207
- ## 7) Final version
205
+ ### 7) Final version
208
206
 
209
- **What this shows:** A Like button that consolidates the previous steps into a single component. After the POST completes, a cleanup `removeHearts$$` target runs to remove the two heart elements. The button also includes basic accessibility (role, tabIndex, and Enter to activate).
207
+ **What this shows:** A Like button that consolidates the previous steps into a single component. After the POST completes, a cleanup `removeHearts$$` target (fourth async op) runs to remove the two heart elements. The button also includes basic accessibility (role, tabIndex, and Enter to activate). Demo: [Like button](https://targetj.io/examples/quick.html).
210
208
 
211
209
  <img src="https://targetjs.io/img/likeButton9.gif" width="130" />
212
210
 
@@ -241,7 +239,7 @@ App({
241
239
 
242
240
  bigHeart$$: {
243
241
  html: "♥", color: "blue", fontSize: 100,
244
- fly() {
242
+ happyFly() {
245
243
  const cx = this.getCenterX(), cy = this.getCenterY();
246
244
  this.setTarget({
247
245
  opacity: { list: [0, 1, 1, 0.85, 0.6, 0.1] },
@@ -258,90 +256,30 @@ App({
258
256
  }
259
257
  });
260
258
  ```
261
-
262
- Or in HTML (no JavaScript required), using tg- attributes that mirror object literal keys:
263
-
264
- ```html
265
- <div
266
- id="likeButton"
267
- tg-width="220"
268
- tg-height="60"
269
- tg-lineHeight="60"
270
- tg-textAlign="center"
271
- tg-borderRadius="10"
272
- tg-background="#f5f5f5"
273
- tg-cursor="pointer"
274
- tg-userSelect="none"
275
- tg-role="button"
276
- tg-html="♡ Like"
277
- tg-tabIndex="0"
278
- tg-onClick="function() {
279
- this.setTarget('scale', { list: [1.2, 1] }, 12, 12);
280
- this.setTarget('background', { list: ['#ffe8ec', '#f5f5f5'] }, 12, 12);
281
- this.setTarget('html', '♥ Liked');
282
- }"
283
- tg-heart$$="{
284
- html: '♥',
285
- color: 'crimson',
286
- fontSize: 20,
287
- fly() {
288
- const cx = this.getCenterX(), cy = this.getCenterY();
289
- this.setTarget({
290
- opacity: { list: [0, 1, 1, 0.8, 0.1] },
291
- scale: { list: [0.8, 1.4, 1.1, 0.9, 0.8] },
292
- rotate: { list: [0, 12, -8, 6, 0] },
293
- x: { list: [cx, cx + 22, cx - 16, cx + 10, cx] },
294
- y: { list: [cy - 8, cy - 70, cy - 90, cy - 120, cy - 150] }
295
- }, 20);
296
- }
297
- }"
298
- tg-bigHeart$$="{
299
- html: '♥',
300
- color: 'blue',
301
- fontSize: 100,
302
- fly() {
303
- const cx = this.getCenterX(), cy = this.getCenterY();
304
- this.setTarget({
305
- opacity: { list: [0, 1, 1, 0.85, 0.6, 0.1] },
306
- scale: { list: [0.4, 1.9, 1.2, 1.6, 1.0, 0.95] },
307
- rotate: { list: [0, 4, -3, 4, -2, 0] },
308
- x: { list: [cx, cx + 14, cx + 10, cx - 6, cx - 14, cx] },
309
- y: { list: [cy, cy - 30, cy - 55, cy - 80, cy - 100, cy - 130] }
310
- }, 30);
311
- }
312
- }"
313
- tg-fetch$$='{"method":"POST","id":123,"url":"/api/like"}'
314
- tg-removeHearts$$="function() { this.removeAll(); }"
315
- tg-onKey="function(e) { if (e.key === 'Enter') this.activateTarget('onClick'); }"
316
- /></div>
317
- ```
318
-
319
259
  ---
320
260
 
321
- ## Final takeaway
261
+ ### Final takeaway
322
262
 
323
- - TargetJS treats time as a first-class concept. Instead of wiring callbacks and effects, you write a sequence of targets.
324
- $ reacts to the previous step; $$ defers until all prior steps finish. Animations, API calls, and child creation are all the same kind of thing: targets.
325
- So complex flows read top-to-bottom.
263
+ - Instead of wiring callbacks and effects, you write a sequence of targets. `$$` defers until all prior steps finish. Animations, API calls, and child creation are all the same kind of thing: targets.
326
264
  - Minimal plumbing yet full control to manage a flow of complex asynchronous operations.
327
265
 
328
266
  ## Table of Contents
329
267
 
330
268
  1. [Targets: The Building Blocks of TargetJS](#targets-the-building-blocks-of-targetjs)
331
- 2. [Understanding TargetJS Syntax: Reactive Postfixes](#understanding-targetjs-syntax-reactive-postfixes)
332
- 3. [📦 Installation](#-installation)
333
- 6. [What Problems Does TargetJS Solve?](#what-problems-does-targetjs-solve)
334
- 11. More Examples:
335
- - [Loading Two Users Example](#loading-two-users-example)
269
+ 1. [Understanding TargetJS Syntax: Reactive Postfixes](#understanding-targetjs-syntax-reactive-postfixes)
270
+ 1. [📦 Installation](#-installation)
271
+ 1. [What Problems Does TargetJS Solve?](#what-problems-does-targetjs-solve)
272
+ 1. More Examples:
273
+ - [Loading Five Users Example](#loading-two-users-example)
336
274
  - [Infinite Loading and Scrolling Example](#infinite-loading-and-scrolling-example)
337
- 12. [Target Methods](#target-methods)
338
- 10. [Target Variables](#target-variables)
339
- 13. [Special Target Names](#special-target-names)
340
- 14. [How to Debug in TargetJS](#how-to-debug-in-targetjs)
341
- 15. [Documentation](#documentation)
342
- 16. [License](#license)
343
- 17. [Contact](#contact)
344
- 18. [💖 Support TargetJS](#-support-targetjs)
275
+ 1. [Target Methods](#target-methods)
276
+ 1. [Target Variables](#target-variables)
277
+ 1. [Special Target Names](#special-target-names)
278
+ 1. [How to Debug in TargetJS](#how-to-debug-in-targetjs)
279
+ 1. [Documentation](#documentation)
280
+ 1. [License](#license)
281
+ 1. [Contact](#contact)
282
+ 1. [💖 Support TargetJS](#-support-targetjs)
345
283
 
346
284
  ## Targets: The Building Blocks of TargetJS
347
285
 
@@ -355,33 +293,48 @@ Targets provide a unified interface for both class methods and fields. Each Targ
355
293
 
356
294
  ## Understanding TargetJS Syntax: Reactive Postfixes
357
295
 
358
- TargetJS doesn't use `async/await` and rarely relies on traditional JavaScript constructs like loops or conditionals. Instead, it defines reactive behaviors using the `$` and `$$` postfixes on target names, unifying asynchronous operations such as API calls, animations, timers, and UI transitions. Although this convention may seem a bit cryptic at first, it offers a compact syntax.
296
+ TargetJS defines reactive behaviors using the `$` and `$$` postfixes on target names, unifying asynchronous operations such as API calls, animations, timers, and UI transitions. Although this convention may seem a bit cryptic at first, it offers a compact syntax.
359
297
 
360
298
  **`$` Postfix (Immediate Reactivity):**
361
299
 
362
300
  A target name ending with a single `$` (e.g., `height$`) indicates that this target will execute every time its immediately preceding target runs or emits a new value. If the preceding target involves an asynchronous operation like an API call, the reactive target activates when the response is received. If there are multiple API calls made, `$` postfix ensures that the target reacts to the first API result when it becomes available, then the second, and so on, maintaining a strict, code-ordered sequence of operations.
363
301
 
364
- **`$$` Postfix (Full Completion Reactivity):**
302
+ **`$$` Postfix (Deferred Reactivity):**
365
303
 
366
- A target name ending with a double `$$` (e.g., `fetch$$`) will activate only after its immediately preceding targets have fully and comprehensively completed all of their operations. This includes:
304
+ A target name ending with a double `$$` (e.g., `fetch$$`) will activate only after all the preceding targets have fully and comprehensively completed all of their operations. This includes:
367
305
 
368
306
  - The successful resolution of any timed sequences, such as animations.
369
307
  - The completion and return of results from all associated API calls.
370
308
  - The finalization of all tasks, animations, and API calls initiated by any dependent child targets that were themselves triggered by a preceding target.
371
309
 
310
+ ---
372
311
 
373
312
  ## **📦 Installation**
374
313
 
314
+ **Via package manager**
315
+
316
+ Install TargetJS via npm (note: there's no "s" at the end):
317
+
318
+ ```bash
319
+ npm install targetj
320
+ ```
321
+
322
+ Then import it into your JavaScript code:
323
+
324
+ ```javascript
325
+ import { App } from "targetj";
326
+ ```
327
+
375
328
  **Via CDN**
376
329
 
377
- Add the following `<script>` tag to your HTML to load TargetJS from a CDN (only 47KB compressed):
330
+ Add the following `<script>` tag to your HTML to load TargetJS from a CDN (only 67KB):
378
331
 
379
332
  ```html
380
333
  <script src="https://unpkg.com/targetj@latest/dist/targetjs.js"></script>
381
334
  ```
382
335
 
383
336
  This will add `TargetJS` to the global `window` object, making it accessible throughout your JavaScript such as `TargetJS.App(YourApp)`.
384
- You can also use it directly in your HTML with custom attributes:
337
+ You can also use it directly in your HTML with `tg-` attributes:
385
338
 
386
339
  ```html
387
340
  <div
@@ -391,36 +344,25 @@ You can also use it directly in your HTML with custom attributes:
391
344
  </div>
392
345
  ```
393
346
 
394
- **Via package manager**
395
-
396
- Install TargetJS via npm (note: there's no "s" at the end):
397
-
398
- ```bash
399
- npm install targetj
400
- ```
401
-
402
- Then import it into your JavaScript code:
403
-
404
- ```javascript
405
- import { App } from "targetj";
406
- ```
347
+ ---
407
348
 
408
349
  ## What Problems Does TargetJS Solve?
409
350
 
410
351
  TargetJS addresses several common pain points in front-end development:
411
352
 
412
- 1. **Scattered State Management:** Many frameworks require separate libraries or complex patterns for state management. In TargetJS, state management is inherently handled throught its core concept of “targets” eliminating the need for explicit state management.
413
- 2. **Complexity of Asynchronous Operations:** Traditional JavaScript often involves complex handling of asynchronous operations (Promises, callbacks, `async/await`). TargetJS addresses this by providing a delactive reactive targets and synchronous execution flow.
414
- 3. **Disjointed Development Workflow:** Developers often juggle multiple tools and concepts (UI libraries, animation libraries, state managers, event handlers). TargetJS provides a unified solution.
415
- 4. **Rigid Static Layer of HTML:** Many frameworks use HTML as the primary medium for generating the user interface. TargetJS makes JavaScript the primary driver, either by running directly or through a handful of HTML elements extended with superpowers.
416
- 5. **Boilerplate and Verbosity:** TargetJS aims to reduce boilerplate code. The code is compact and follows a predictable execution flow. Direct method calls are not allowed. Explicit loops and conditional statements are rarely needed.
353
+ 1. **Scattered State Management:** Many frameworks require separate libraries or complex patterns for state management. In TargetJS, state management is inherently handled through its core concept of “targets”.
354
+ 2. **Complexity of Asynchronous Operations:** Traditional JavaScript often involves complex handling of asynchronous operations (Promises, callbacks, `async/await`). TargetJS addresses this by providing a declarative reactive targets and synchronous execution flow.
355
+ 3. **Disjointed Development Workflow:** Developers often juggle multiple tools and concepts (UI libraries, animation libraries, event handlers). TargetJS provides a unified solution.
356
+ 4. **Rigid Static Layer of HTML:** Many frameworks use HTML as the primary medium for generating the user interface. TargetJS makes JavaScript the primary driver.
357
+ 5. **Boilerplate and Verbosity:** TargetJS aims to reduce boilerplate code. The code is compact and follows a predictable execution flow.
417
358
  6. **Difficult Animation Control:** TargetJS makes animations first-class citizens with fine-grained control.
418
- 7. **Complicated execution flow:** TargetJS execution flow follows the order the code is written.
419
359
  8. **Performance Bottlenecks with Large Lists:** TargetJS optimizes rendering for large lists by using a tree structure that renders only the visible branches.
420
-
360
+
361
+ ---
362
+
421
363
  ## More Examples
422
364
 
423
- ## Loading Five Users Example
365
+ ### Loading Five Users Example
424
366
 
425
367
  In this example, we load five separate users and display five boxes, each containing a user's name and email.
426
368
 
@@ -461,7 +403,7 @@ App({
461
403
  });
462
404
  ```
463
405
 
464
- It can also be written using a target’s `cycles` and `intervals` properties/methods to fetch users at intervals instead of in a single batch. In this example, we set interval to 1000, making the API call once every second.
406
+ It can also be written using a target’s `cycles` and `interval` properties/methods to fetch users at intervals instead of in a single batch. In this example, we set interval to 1000, making the API call once every second.
465
407
 
466
408
  <img src="https://targetjs.io/img/fetch-5-users2.gif" width="130" />
467
409
 
@@ -484,7 +426,15 @@ App({
484
426
 
485
427
  ### Infinite Loading and Scrolling Example
486
428
 
487
- In this advanced example, we demonstrate an infinite scrolling application where each item is animated, and upon completing its animation, it dynamically triggers an API call to fetch and display its details.
429
+ In this advanced example, we implement an infinite-scrolling application. The asynchronous flow that we want to achieve:
430
+ 1. Insert new items, and animate their width and background.
431
+ 2. On animation completion, trigger the API request for the visible items.
432
+ 3. Await for all API responses of all the items and then populate their names.
433
+
434
+ This example could use other flows such as calling the API as soon as items are added, or populating each item’s name as its result arrives instead of waiting for all visible items.
435
+ All of these are doable, but we chose the above to showcase a more complex, sequential async flow.
436
+
437
+ **Explanation:**
488
438
 
489
439
  - children: `children` is a special target that adds several items to the container's children each time it is executed. The `onVisibleChildrenChange` event function detects changes in the visible children and activates the `children` target to add new items that fill the gaps.
490
440
 
@@ -494,15 +444,13 @@ In this advanced example, we demonstrate an infinite scrolling application where
494
444
 
495
445
  TargetJS employs a tree-like structure to track visible branches, optimizing the scroller performance.
496
446
 
497
- 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.
498
447
 
499
448
  <img src="https://targetjs.io/img/infiniteScrolling.gif" width="130" />
500
449
 
501
450
  ```javascript
502
451
  import { App, TModel, getEvents, fetch, getScreenWidth, getScreenHeight } from "targetj";
503
452
 
504
- App(new TModel("scroller", {
505
- domHolder: true,
453
+ App({
506
454
  preventDefault: true,
507
455
  containerOverflowMode: "always",
508
456
  children() {
@@ -540,7 +488,7 @@ App(new TModel("scroller", {
540
488
  width: getScreenWidth,
541
489
  height: getScreenHeight,
542
490
  onResize: 'width'
543
- }));
491
+ });
544
492
  ```
545
493
 
546
494
  We can reduce the number of API calls by triggering them only after scrolling stops as follows:
@@ -558,50 +506,7 @@ We can reduce the number of API calls by triggering them only after scrolling st
558
506
  }
559
507
  }
560
508
  ```
561
-
562
- Finally, in HTML:
563
-
564
- ```HTML
565
- <div
566
- id="scroller"
567
- tg-domHolder="true"
568
- tg-preventDefault="true"
569
- tg-containerOverflowMode="always"
570
- tg-width="return TargetJS.getScreenWidth();"
571
- tg-height="return TargetJS.getScreenHeight();"
572
- tg-children="function() {
573
- const childrenCount = this.getChildren().length;
574
- return Array.from({ length: 20 }, (_, i) => ({
575
- width: [{list: [100, 250, 100]}, 50],
576
- x$() { return this.getCenterX(); },
577
- background: [{ list: ['#FCE961', '#B388FF'] }, 15, 15],
578
- height: 48,
579
- color: '#C2FC61',
580
- textAlign: 'center',
581
- lineHeight: 48,
582
- bottomMargin: 2,
583
- html: childrenCount + i
584
- }));
585
- }"
586
- tg-load$$="function() {
587
- this.visibleChildren.filter(child => !child.loaded).forEach(child => {
588
- child.loaded = true;
589
- TargetJS.fetch(this, `https://targetjs.io/api/randomUser?id=${child.oid}`);
590
- });
591
- }"
592
- tg-populate$$="function() {
593
- if (this.prevTargetValue) {
594
- this.prevTargetValue.forEach(data => this.getChildByOid(data.id).setTarget('html', data.name));
595
- }
596
- }"
597
- tg-onScroll="function() {
598
- this.setTarget('scrollTop', Math.max(0, this.getScrollTop() + TargetJS.getEvents().deltaY()));
599
- }"
600
- tg-onVisibleChildrenChange="function() {
601
- return !this.visibleChildren.length || this.getLastChild().getY() < this.getHeight() ? 'children' : 'load$$';
602
- }"
603
- ></div>
604
- ```
509
+ ---
605
510
 
606
511
  ## Target Methods
607
512
 
@@ -609,60 +514,61 @@ All methods and properties are optional, but they play integral roles in making
609
514
 
610
515
  1. **value**
611
516
  If defined, value is the primary target method that will be executed. The target value will be calculated based on the result of this method.
517
+ `Value` can also be defined as a property.
612
518
 
613
- 2. **Prefix `_` to the target name**
614
- It indicates that the target is in an inactive state and must be activated by an event or other targets.
615
-
616
- 3. **active**
617
- This is only a property. It indicates whether the target is ready for execution. When set to false, it behaves similarly to a `_ `prefix. By default, all targets are active, so setting it to true is unnecessary.
618
-
619
- 15. **Postfix `$` to the target name**
519
+ 1. **Postfix `$` to the target name** (Reactive):
620
520
  A target name ending with $ indicates that it will be only activated when the preceding target is executed. If the preceding target involves API calls, it will be activated
621
521
  each time an API response is received, while ensuring the order of API calls is enforced. This means it will remain inactive until the first API result is received,
622
522
  then the second, and so on.
623
523
 
624
- 17. **Postfix `$$` to the target name**
625
- A target name ending with `$$` indicates indicates that it will be activated only after the preceding target has completed, along with all its imperative targets,
524
+ 1. **Postfix `$$` to the target name** (Deferred):
525
+ A target name ending with `$$` indicates that it will be activated only after all the preceding target has completed, along with all its imperative targets,
626
526
  and after all API results have been received.
627
527
 
628
- 2. **enabledOn**
528
+ 1. **Prefix `_` to the target name** (Inactive):
529
+ It indicates that the target is in an inactive state and must be activated by an event or other targets explicitly.
530
+
531
+ 1. **enabledOn**
629
532
  Determines whether the target is eligible for execution. If enabledOn() returns false, the target remains active until it is enabled and gets executed.
630
533
 
631
- 3. **loop**
534
+ 1. **loop**
632
535
  Controls the repetition of target execution. If loop() returns true, the target will continue to execute indefinitely. It can also be defined as a boolean instead of a method.
633
536
 
634
- 4. **cycles**
635
- It works similarly to `loop`, but it specifies an explicit number of repetitions. It can also be combined with `loop`, in which case, once the specified cycles complete, they will rerun as long as `loop` returns true.
537
+ 1. **cycles**
538
+ It works similarly to `loop`, but it specifies an explicit number of repetitions. It can also be combined with `loop`, in which case, once the specified cycles complete, they will rerun as long as `loop` returns true. In other words, `loop` functions as an outer loop for `cycles`.
636
539
 
637
- 6. **interval**
540
+ 1. **interval**
638
541
  It specifies the pause between each target execution or each actual value update when steps are defined.
639
542
 
640
- 7. **steps**
543
+ 1. **steps**
641
544
  By default, the actual value is updated immediately after the target value. The steps option allows the actual value to be updated in iterations specified by the number of steps.
642
545
 
643
- 8. **easing**
546
+ 1. **easing**
644
547
  An easing function that operates when steps are defined. It controls how the actual value is updated in relation to the steps.
645
548
 
646
- 9. **onValueChange**
647
- This callback is triggered whenever there is a change returned by the target method, which is called value().
549
+ 1. **onValueChange**
550
+ This callback is triggered whenever there is a change returned by the target method/property `value`.
648
551
 
649
- 10. **onStepsEnd**
552
+ 1. **onStepsEnd**
650
553
  This method is invoked only after the final step of updating the actual value is completed, assuming the target has a defined steps value.
651
554
 
652
- 11. **onImperativeStep**
555
+ 1. **onImperativeStep**
653
556
  This callback tracks the progress of imperative targets defined within a declarative target. If there are multiple imperative targets, this method is called at each step,
654
557
  identifiable by their target name. You can also use `on${targetName}Step` to track individual targets with their own callbacks. For example, `onWidthStep()` is called on each update of the `width` target.
655
558
 
656
- 13. **onImperativeEnd**
559
+ 1. **onImperativeEnd**
657
560
  Similar to `onImperativeStep`, but it is triggered when an imperative target completes. If multiple targets are expected to complete, you can use `on${targetName}End` instead. For example, `onWidthEnd` is called when the `width` target gets completed.
658
561
 
659
- 13. **initialValue**
660
- This is only property. It defines the initial value of the actual value.
562
+ 1. **initialValue**
563
+ This is only a property. It defines the initial value of the actual value.
564
+
565
+ 1. **active**
566
+ This is only a property. It indicates whether the target is ready for execution. When set to false, it behaves similarly to a `_` prefix. By default, all targets are active, so setting it to true is unnecessary.
661
567
 
662
- 18. **onSuccess**
568
+ 1. **onSuccess**
663
569
  An optional callback for targets that make API calls. It will be invoked for each API response received.
664
570
 
665
- 19. **onError**
571
+ 1. **onError**
666
572
  Similar to the `onSuccess` but it will be invoked on every error.
667
573
 
668
574
  ## Target Variables
@@ -696,6 +602,7 @@ In addition to styles and attribute names, we have the following special names:
696
602
 
697
603
  1. **html**: Sets the content of the object, interpreted as text by default.
698
604
  2. **children**: Adds new items to the parent each time it executes. Items can be either plain objects or instances of TModel for greater control.
605
+ 3. **Child**: Similar to `children` but adds only one item.
699
606
  4. **css**: A string that sets the CSS of the object.
700
607
  5. **element**: Sets the HTML tag of the object, defaulting to `div`.
701
608
  6. **shouldBeBracketed**: A boolean flag that, when set to true (the default), enables the creation of an optimization tree for a container with more items than the `bracketThreshold` (another target with a default value of 10). This optimization ensures only the visible branch receives updates and get executed.
@@ -755,13 +662,13 @@ Here are all the event targets:
755
662
  TargetJS provides built-in debugging tools:
756
663
 
757
664
  ```bash
758
- TargetJS.tApp.stop(); //Stops the application.
759
- TargetJS.tApp.start(); //Restarts the application
760
- TargetJS.tApp.throttle; //Slows down execution (in ms)
761
- TargetJS.tApp.debugLevel = 1; // Logs cycle execution
665
+ TargetJS.tApp.stop(); // Stop the application.
666
+ TargetJS.tApp.start(); // Restart the application
667
+ TargetJS.tApp.throttle = 0; // Slow down execution (milliseconds between cycles)
668
+ TargetJS.tApp.debugLevel = 1; // Log cycle execution
762
669
  ```
763
670
  - Use `t()` in the browser console to find an object by its oid.
764
- - Use `t(oid).bug()` to inspect all the vital properities.
671
+ - Use `t(oid).bug()` to inspect all the vital properties.
765
672
  - Use `t(oid).logTree()` to inspect the UI structure.
766
673
 
767
674
  ## Documentation
@@ -774,6 +681,9 @@ Distributed under the MIT License. See LICENSE for more information.
774
681
  Ahmad Wasfi - wasfi2@gmail.com
775
682
 
776
683
  ## 💖 Support TargetJS
684
+
685
+ If you would like to show some appreciation:
686
+
777
687
  - ⭐ Star this repo on GitHub to show your support!
778
688
  - 🐛 Report issues & suggest features.
779
689
  - 📢 Share TargetJS with your network.
package/build/$Dom.js CHANGED
@@ -403,6 +403,16 @@ var $Dom = exports.$Dom = /*#__PURE__*/function () {
403
403
  value: function findFirstByTag(tagName) {
404
404
  return $Dom.findFirstByTag(tagName, this.element);
405
405
  }
406
+ }, {
407
+ key: "getScrollTop",
408
+ value: function getScrollTop() {
409
+ return this.element.scrollTop;
410
+ }
411
+ }, {
412
+ key: "getScrollLeft",
413
+ value: function getScrollLeft() {
414
+ return this.element.scrollLeft;
415
+ }
406
416
  }], [{
407
417
  key: "createTemplate",
408
418
  value: function createTemplate(html) {
package/build/App.js CHANGED
@@ -130,20 +130,31 @@ var AppFn = function AppFn() {
130
130
  }
131
131
  }, _callee2);
132
132
  }));
133
- my.reset = function () {
134
- my.manager.getVisibles().forEach(function (tmodel) {
135
- tmodel.transformMap = {};
136
- tmodel.styleMap = {};
137
- tmodel.allStyleTargetList.forEach(function (key) {
138
- if (_TUtil.TUtil.isDefined(tmodel.val(key))) {
139
- tmodel.addToStyleTargetList(key);
140
- }
141
- });
142
- });
143
- my.manager.clearAll();
144
- my.locationManager.clear();
145
- _SearchUtil.SearchUtil.clear();
146
- };
133
+ my.reset = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
134
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
135
+ while (1) switch (_context3.prev = _context3.next) {
136
+ case 0:
137
+ my.manager.getVisibles().forEach(function (tmodel) {
138
+ tmodel.transformMap = {};
139
+ tmodel.styleMap = {};
140
+ tmodel.allStyleTargetList.forEach(function (key) {
141
+ if (_TUtil.TUtil.isDefined(tmodel.val(key))) {
142
+ tmodel.addToStyleTargetList(key);
143
+ }
144
+ });
145
+ });
146
+ _context3.next = 3;
147
+ return my.runScheduler.resetRuns();
148
+ case 3:
149
+ my.manager.clearAll();
150
+ my.locationManager.clear();
151
+ _SearchUtil.SearchUtil.clear();
152
+ case 6:
153
+ case "end":
154
+ return _context3.stop();
155
+ }
156
+ }, _callee3);
157
+ }));
147
158
  my.isRunning = function () {
148
159
  return my.runningFlag;
149
160
  };