targetj 1.0.73 → 1.0.74
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 +324 -122
- package/package.json +3 -2
- package/src/$Dom.js +13 -6
- package/src/Bracket.js +0 -1
- package/src/Browser.js +14 -115
- package/src/ColorUtil.js +3 -1
- package/src/EventListener.js +15 -5
- package/src/LoadingManager.js +18 -6
- package/src/LocationManager.js +9 -3
- package/src/Moves.js +0 -1
- package/src/PageManager.js +0 -1
- package/src/SearchUtil.js +18 -6
- package/src/TModel.js +6 -4
- package/src/TModelManager.js +1 -2
- package/src/TUtil.js +6 -2
- package/src/TargetExecutor.js +0 -1
- package/src/TargetManager.js +3 -2
- package/src/TargetUtil.js +1 -2
- package/src/Viewport.js +0 -2
- package/webpack.config.js +40 -10
package/README.md
CHANGED
|
@@ -4,36 +4,44 @@ Welcome to TargetJ, a powerful JavaScript UI framework designed to simplify deve
|
|
|
4
4
|
|
|
5
5
|
TargetJ distinguishes itself by introducing a novel concept known as 'targets', which forms its core. Targets are used as the main building blocks of components instead of direct variables and methods. Each component in TargetJ is a set of targets. Targets are employed across all aspects of the program. They are used in animation, controlling program flow, loading data from external APIs, handling user events, and more.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### Installation
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
To install TargetJ, run the following command in your terminal:
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
```bash
|
|
12
|
+
npm install targetj
|
|
13
|
+
```
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
## What are targets?
|
|
16
|
+
|
|
17
|
+
Targets provide a unified interface for variables and methods, giving them life cycles and the autonomy to operate independently, with various callbacks to adapt to changes, mimicking the behavior of living cells.
|
|
14
18
|
|
|
15
|
-
Similarly, targets enhance methods by allowing them to manage their own life cycles. They execute under specific conditions, control the number of executions, and offer the same capabilities as those provided to variables.
|
|
19
|
+
For variables, targets enhance functionality by giving them the ability to iterate in steps until they reach the specified value, rather than being immediately assigned their values. They can introduce pauses between iterations and offer callbacks to monitor progress, track the progress of other variables, and manage their life cycles accordingly. Similarly, targets enhance methods by allowing them to manage their own life cycles. They can execute themselves under specific conditions, control the number of executions, and offer the same capabilities as those provided to variables.
|
|
16
20
|
|
|
17
21
|
## What does a target consist of?
|
|
18
22
|
|
|
19
23
|
Each target consists of the following:
|
|
20
|
-
1. Target Value and Actual Value. The target value represents a variable or the outcome of a method. The actual value
|
|
24
|
+
1. Target Value and Actual Value. The target value represents a variable or the outcome of a method. The actual value is typically the value used by the rest of the application. When the target value differs from the actual value, TargetJ iteratively updates the actual value until it matches the target value. This process is managed by two additional variables: Step, which dictates the number of iterations, and Interval, which specifies the duration (in milliseconds) the system waits before executing the next iteration.
|
|
21
25
|
|
|
22
|
-
2. State: Targets have
|
|
26
|
+
2. State: Targets have four states that control their lifecycle: Active, Inactive, Updating, and Complete. Active: This is the default state for all targets. It indicates that the target is ready to be executed, and the target value needs to be initialized from the variable it represents or its value() method needs to be executed to calculate its output. Inactive: Indicates that the target is not ready to be executed. Updating: Indicates that the actual value is being adjusted to reach the target value. Complete: Indicates that the target execution is finished, and the actual value has matched the target value.
|
|
23
27
|
|
|
24
28
|
3. Target Methods: All methods are optional. They are used to control the lifecycle of targets or serve as callbacks to reflect changes. The controlling methods are: enabledOn, loop, steps, cycles. The callbacks are: onValueChange, onStepsEnd, onImperativeStep, onImperativeEnd. More details in the method section.
|
|
25
29
|
|
|
26
30
|
## Brief overview of how it operates
|
|
27
31
|
|
|
28
|
-
All targets are in the active state by default. They can include an enabledOn function that delays their execution until the specified conditions are met. Targets can also be set to inactive and activated externally when needed.
|
|
32
|
+
All targets are in the active state by default and ready to be executed. They can include an enabledOn function that delays their execution until the specified conditions are met. Targets can also be set to inactive and activated externally when needed.
|
|
33
|
+
|
|
34
|
+
The target task monitors all active targets, and if a target is enabled, it will be executed. The target value is generated either from the result of a method or from a static value defined in the target. For simple targets without steps, cycles, or loops, the actual value is set immediately based on the target value. Once executed, the target’s state becomes complete, and it will not be executed again.
|
|
29
35
|
|
|
30
36
|
If the target has loop or cycle methods defined, its value method will be re-executed after a pause specified by the interval. The number of executions will be determined by the cycles or will continue as long as the loop condition returns true. If the target has steps defined, its state changes to updating, and the actual value is updated iteratively until it reaches the target value, according to the number of steps and pauses specified by steps and intervals.
|
|
31
37
|
|
|
32
|
-
A target can reactivate itself
|
|
38
|
+
A target can reactivate itself in the `onStepsEnd` callback once all steps are completed, or in the `onImperativeEnd` callback when all imperative targets initiated by that target are finished, allowing it to re-execute. It can also be reactivated externally, either directly or through an event.
|
|
33
39
|
|
|
34
40
|
## Target methods
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
All methods and properties are optional, but they play integral roles in making targets useful for animation, API loading, event handling, and more:
|
|
43
|
+
|
|
44
|
+
1. **value**
|
|
37
45
|
If defined, value is the primary target method that will be executed. The target value will be calculated based on the result of value().
|
|
38
46
|
|
|
39
47
|
2. **onEnabled**
|
|
@@ -66,10 +74,20 @@ onImperativeStep() This callback tracks the progress of imperative targets defin
|
|
|
66
74
|
11. **onImperativeEnd**
|
|
67
75
|
It is similar to onImperativeStep, but it is called when the imperative target is completed.
|
|
68
76
|
|
|
77
|
+
12. **active**
|
|
78
|
+
This is only property. It indicates that the target is in an inactive state and is ready to be executed.
|
|
79
|
+
|
|
80
|
+
13. **initialValue**
|
|
81
|
+
This is only property. It defines the initial value of the actual value.
|
|
82
|
+
|
|
83
|
+
|
|
69
84
|
### Simple example
|
|
70
85
|
|
|
71
86
|
In the example below, we incrementally increase the value of width, height, and opacity in 30 steps, with a 50-milliseconds pause between each step.
|
|
72
87
|
|
|
88
|
+

|
|
89
|
+
|
|
90
|
+
|
|
73
91
|
```bash
|
|
74
92
|
import { App, TModel } from 'targetj';
|
|
75
93
|
|
|
@@ -110,166 +128,350 @@ App(new TModel({
|
|
|
110
128
|
|
|
111
129
|
Targets in TargetJ can be defined in two ways: declaratively or imperatively.
|
|
112
130
|
|
|
113
|
-
The declarative approach offers a structured method for defining targets, as seen in the previous example. However, orchestrating multiple targets with varying speeds and timings can be challenging. For instance, tracking the completion of multiple targets to trigger a new set of targets is not easily done using only declarative targets. To address this, TargetJ provides the setTarget function, allowing you to define multiple targets from within a single declarative target. Additionally, the onImperativeStep and onImperativeEnd callbacks, defined in the declarative target, enable you to track each step of the imperative targets or just their completion.
|
|
131
|
+
The declarative approach offers a structured method for defining targets, as seen in the previous example. However, orchestrating multiple targets with varying speeds and timings can be challenging. For instance, tracking the completion of multiple targets to trigger a new set of targets is not easily done using only declarative targets. To address this, TargetJ provides the setTarget function, allowing you to define multiple imperative targets from within a single declarative target. Additionally, the onImperativeStep and onImperativeEnd callbacks, defined in the declarative target, enable you to track each step of the imperative targets or just their completion.
|
|
114
132
|
|
|
115
133
|
By combining both declarative and imperative targets, you gain a powerful toolset for designing complex interactions.
|
|
116
134
|
|
|
117
|
-
##
|
|
118
|
-
|
|
119
|
-
The following are special target names to impact the UI or control properties of TargetJ objects (called TModel):
|
|
120
|
-
|
|
121
|
-
1. x, y, width, height: Set the location and dimensions of the object.
|
|
122
|
-
2. opacity, scale, rotate: Set the opacity, scale, and rotation of the object.
|
|
123
|
-
3. zIndex: Sets the z-order of the object.
|
|
124
|
-
4. html: Sets the content of the object. By default, it will be interpreted as text.
|
|
125
|
-
5. style: An object that sets the style of the object.
|
|
126
|
-
6. css: A string that sets the CSS of the object.
|
|
127
|
-
7. scrollLeft and scrollTop: Used for scrolling the object.
|
|
128
|
-
8. leftMargin, rightMargin, topMargin, bottomMargin: Set the margins between objects.
|
|
129
|
-
9. children: Sets the TModel children of the object.
|
|
130
|
-
10. domHolder and domParent: Set to control the HTML element containment and how HTML is nested.
|
|
131
|
-
11. isVisible: An optional boolean flag to explicitly control the visibility of the object instead of leaving it to TargetJ to calculate.
|
|
132
|
-
12. canHaveDom: A boolean flag that sets if the object can have a DOM element in the page.
|
|
133
|
-
13. canHandleEvents: Sets what events the object can handle
|
|
134
|
-
14. widthFromDom and heightFromDom: Boolean flags that control if the width and height should be calculated from the DOM element.
|
|
135
|
-
15. textOnly: A boolean flag that sets the type of content to be text or HTML.
|
|
136
|
-
16. canBeBracketed: A boolean flag that controls if the object will be optimized and included in the TargetJ task process only when visible.
|
|
137
|
-
17. isInFlow: A boolean flag that determines if the object will be used to calculate the content height and width of its parent.
|
|
138
|
-
18. onResize: An array of targets that will be reset and re-executed after a resize event.
|
|
139
|
-
19. onClickEvent: An array of targets that will be reset and re-executed after a click event.
|
|
140
|
-
20. onTouchEvent: An array of targets that will be reset and re-executed after a touch event.
|
|
141
|
-
21. onScrollEvent: An array of targets that will be reset and re-executed after a scroll event.
|
|
142
|
-
22. onKeyEvent: An array of targets that will be reset and re-executed after a key event.
|
|
143
|
-
|
|
144
|
-
## Features
|
|
145
|
-
|
|
146
|
-
As a result of using targets, we can develop web sites or apps with the following features:
|
|
147
|
-
|
|
148
|
-
- **No HTML required**: HTML tags are seldom necessary except for images.
|
|
149
|
-
- **No HTML nesting**: HTML nesting is seldom required in TargetJ. If it is required, nesting is done at runtime. Elements can be dynamically detached and incorporated into other elements, facilitating the easy reuse of components regardless of their location or attachment. It also opens the door for a new user experiences.
|
|
150
|
-
- **Next-level animation**: Users can program objects to move at varying speeds, pause at certain intervals, and repeat sequences based on various conditions. It allows the creation of complicated animations.
|
|
151
|
-
- **Control the flow of execution with time**: TargetJ simplifies the execution of various program segments at specific times, making it easy to sequence or parallelize numerous actions.
|
|
152
|
-
- **Handle events effortlessly**: In TargetJ, events are triggered synchronously and are designed so that any component can detect when an event occurs. Event handling can be simply implemented as conditions in the enabling functions of \'targets.\' This ensures that managing events is both simple and effective.
|
|
153
|
-
- **Easy to learn**: TargetJ simplifies development by employing the single concept of \'targets\' making it easy to learn.
|
|
154
|
-
- **Handle 100,000s of items**: TargetJ efficiently manages large collections of objects on a single page. This is done by its data structure and optimization algorithm. It divides a long list into a tree structure, monitoring only the branches that are visible to the user at any given time.
|
|
155
|
-
- **AI friendly**: With a unified concept of targets for all development, the ability to add and remove targets at runtime, and the capability to inspect various statuses of running objects, TargetJ is a strong candidate for AI-powered UI development.
|
|
156
|
-
|
|
157
|
-
## Getting Started
|
|
135
|
+
## Declarative an imperative example
|
|
158
136
|
|
|
159
|
-
|
|
137
|
+
The following example demonstrates the use of both declarative and imperative approaches. In the animate target, we set two imperative targets to move a square across the screen. When x reaches the end of the screen, onImperativeEnd is triggered, reactivating the target and restarting the animation.
|
|
160
138
|
|
|
161
|
-
|
|
139
|
+

|
|
162
140
|
|
|
163
141
|
```bash
|
|
164
|
-
|
|
142
|
+
import { App, TModel, getScreenWidth, getScreenHeight } from "targetj";
|
|
143
|
+
|
|
144
|
+
App(new TModel('declarative', {
|
|
145
|
+
add() {
|
|
146
|
+
for (var i = 0; i < 10; i++) {
|
|
147
|
+
this.addChild(new TModel("square", {
|
|
148
|
+
width: 50,
|
|
149
|
+
height: 50,
|
|
150
|
+
background: 'brown',
|
|
151
|
+
animate: {
|
|
152
|
+
value() {
|
|
153
|
+
var width = this.getWidth();
|
|
154
|
+
var parentWidth = this.getParentValue('width');
|
|
155
|
+
this.setTarget('x', { list: [ -width, parentWidth + width ] }, Math.floor(30 + parentWidth * Math.random()));
|
|
156
|
+
this.setTarget('y', Math.floor(Math.random() * (this.getParentValue('height') - this.getHeight())), 30);
|
|
157
|
+
},
|
|
158
|
+
onImperativeEnd(key) {
|
|
159
|
+
if (key === 'x') {
|
|
160
|
+
this.activateTarget(this.key);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
width() { return getScreenWidth(); },
|
|
168
|
+
height() { return getScreenHeight(); }
|
|
169
|
+
}));
|
|
165
170
|
```
|
|
166
171
|
|
|
167
|
-
##
|
|
172
|
+
## Loading data example
|
|
168
173
|
|
|
169
|
-
|
|
174
|
+
Calling backend APIs is simplified through the use of targets in TargetJ. It includes a loader that streamlines API integration.
|
|
170
175
|
|
|
171
|
-
|
|
172
|
-
import { App, TModel } from 'targetj';
|
|
176
|
+
In the example below, we define a target named 'load' that attempts to fetch a random user. Within the value() function, we initialize the API call. The first parameter specifies an ID that identifies the API call, which can also be used to access cached data.
|
|
173
177
|
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
The target will remain active using the loop function, with value() continuing to return undefined while polling the system every 20ms (as specified in the interval property) until the loader retrieves the API result. When the API result arrives, it triggers onValueChange, which creates a user object based on the retrieved data. Additionally, we define two targets to handle scenarios for both fast and slow connections. The slow target is enabled if polling exceeds 100 times, while the fast target is enabled if the API result is retrieved in less than 600ms. If you restart the example, the result will be fetched from the cache instead of the API.
|
|
179
|
+
|
|
180
|
+

|
|
176
181
|
|
|
177
|
-
### Simple animation example
|
|
178
182
|
```bash
|
|
179
|
-
import { App, TModel } from
|
|
183
|
+
import { App, TModel, getLoader, browser } from "targetj";
|
|
180
184
|
|
|
181
|
-
App(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
App(
|
|
186
|
+
new TModel("apiCall", {
|
|
187
|
+
load: {
|
|
188
|
+
loop() { return !this.val(this.key); },
|
|
189
|
+
interval: 20,
|
|
190
|
+
value: function () {
|
|
191
|
+
var fetchId = "user";
|
|
192
|
+
getLoader().initSingleLoad(fetchId, { url: "https://targetj.io/api/randomUser", data: { id: fetchId } });
|
|
193
|
+
return getLoader().fetchResult(fetchId);
|
|
194
|
+
},
|
|
195
|
+
onValueChange(newValue) {
|
|
196
|
+
var user = newValue.result;
|
|
197
|
+
this.addChild(new TModel("userApi", {
|
|
198
|
+
width: 60,
|
|
199
|
+
height: 30,
|
|
200
|
+
html: user.name,
|
|
201
|
+
background: "#f00",
|
|
202
|
+
}));
|
|
203
|
+
},
|
|
187
204
|
},
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
205
|
+
slowLoad: {
|
|
206
|
+
value() {
|
|
207
|
+
console.log("Connection issue: please try again later.");
|
|
208
|
+
},
|
|
209
|
+
enabledOn() {
|
|
210
|
+
return this.getTargetExecutionCount("load") > 100;
|
|
211
|
+
}
|
|
192
212
|
},
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
213
|
+
fastLoad: {
|
|
214
|
+
value() {
|
|
215
|
+
//Loading is fast: We can load additional details about the user.
|
|
216
|
+
console.log(`Loading time was only ${this.val("load").loadingTime}ms`);
|
|
217
|
+
console.log(`Load target execution time was ${browser.now() - this.getTargetCreationTime("load")}ms`);
|
|
218
|
+
console.log(`Load target was executed ${this.getTargetExecutionCount("load")} times`);
|
|
219
|
+
},
|
|
220
|
+
enabledOn() {
|
|
221
|
+
return this.val("load") && this.val("load").loadingTime < 600;
|
|
222
|
+
}
|
|
197
223
|
}
|
|
198
|
-
|
|
224
|
+
})
|
|
225
|
+
);
|
|
199
226
|
```
|
|
200
227
|
|
|
201
|
-
|
|
228
|
+
## Event handling example
|
|
229
|
+
|
|
230
|
+
In the following example, the background color of the pane changes randomly whenever you click on it. The `canHandleEvents` target ensures that the object can handle touch events, such as clicks. However, we’ve set a limit of 10 executions for the background change. After reaching this limit, the component will no longer respond to click events. The `onClickEvent` is a system target that activates all associated targets when a click occurs. The `html` target tracks the number of executions and displays it within the pane.
|
|
231
|
+
|
|
232
|
+

|
|
202
233
|
|
|
203
234
|
```bash
|
|
204
|
-
import { App, TModel } from
|
|
235
|
+
import { App, TModel } from "targetj";
|
|
205
236
|
|
|
206
|
-
App(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
237
|
+
App(
|
|
238
|
+
new TModel("events", {
|
|
239
|
+
canHandleEvents() {
|
|
240
|
+
return this.getTargetExecutionCount("background") < 10 ? "touch" : "";
|
|
241
|
+
},
|
|
242
|
+
width: 120,
|
|
243
|
+
height: 120,
|
|
244
|
+
background: {
|
|
245
|
+
active: false,
|
|
246
|
+
initialValue: "#f00",
|
|
247
|
+
value() {
|
|
248
|
+
return "#" + Math.random().toString(16).slice(-6);
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
html() {
|
|
252
|
+
return this.getTargetExecutionCount("background");
|
|
253
|
+
},
|
|
254
|
+
onClickEvent: ["background", "canHandleEvents", "html"],
|
|
255
|
+
})
|
|
256
|
+
);
|
|
212
257
|
```
|
|
213
258
|
|
|
214
|
-
|
|
259
|
+
## Animation API example
|
|
260
|
+
|
|
261
|
+
TargetJ offers efficient and easy-to-control UI animation and manipulation through special targets such as x, y, width, height, scale, rotate, and opacity, which directly impact the UI. A complete list of these targets can be found in the "Special target names" section. For very intensive UI animations, you can leverage the Animation API. An example is provided below.
|
|
215
262
|
|
|
216
|
-
|
|
263
|
+

|
|
217
264
|
|
|
218
265
|
```bash
|
|
219
|
-
import { App, TModel
|
|
266
|
+
import { App, TModel } from "targetj";
|
|
220
267
|
|
|
221
268
|
App(
|
|
222
|
-
new TModel({
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
width: 50,
|
|
228
|
-
height: 50,
|
|
229
|
-
style: { backgroundColor: "#f00" },
|
|
230
|
-
rotate: {
|
|
231
|
-
cycles: 1000,
|
|
232
|
-
steps: 15,
|
|
233
|
-
stepInterval: 50,
|
|
234
|
-
value(key, cycle) {
|
|
235
|
-
return [360, 0][cycle % 2];
|
|
236
|
-
},
|
|
237
|
-
},
|
|
238
|
-
})
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
},
|
|
269
|
+
new TModel("TargetJ vs Animation Api", {
|
|
270
|
+
x: 0,
|
|
271
|
+
y: 0,
|
|
272
|
+
width: 150,
|
|
273
|
+
height: 150,
|
|
242
274
|
animate: {
|
|
243
|
-
loop: true,
|
|
244
|
-
stepInterval: 1600,
|
|
245
275
|
value() {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
276
|
+
const keyframes = [
|
|
277
|
+
{
|
|
278
|
+
transform: "translate(0, 0) rotate(0deg) scale(1)",
|
|
279
|
+
width: "80px",
|
|
280
|
+
height: "80px",
|
|
281
|
+
background: "orange",
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
transform: "translate(50px, 100px) rotate(180deg) scale(1.5)",
|
|
285
|
+
width: "120px",
|
|
286
|
+
height: "120px",
|
|
287
|
+
background: "brown",
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
transform: "translate(200px, 0) rotate(360deg) scale(1)",
|
|
291
|
+
width: "100px",
|
|
292
|
+
height: "100px",
|
|
293
|
+
background: "crimson",
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
transform: "translate(0, 0) rotate(360deg) scale(1)",
|
|
297
|
+
width: "150px",
|
|
298
|
+
height: "150px",
|
|
299
|
+
background: "purple",
|
|
300
|
+
},
|
|
301
|
+
];
|
|
302
|
+
|
|
303
|
+
return this.$dom.animate(keyframes, {
|
|
304
|
+
duration: 5000,
|
|
305
|
+
iterations: 1,
|
|
306
|
+
easing: "ease-in-out",
|
|
250
307
|
});
|
|
251
308
|
},
|
|
252
309
|
enabledOn() {
|
|
253
|
-
return this.
|
|
310
|
+
return this.hasDom();
|
|
254
311
|
},
|
|
255
312
|
},
|
|
256
|
-
|
|
257
|
-
|
|
313
|
+
trackProgress: {
|
|
314
|
+
loop: true,
|
|
315
|
+
interval: 100,
|
|
316
|
+
value() {
|
|
317
|
+
const currentTime = this.val("animate").currentTime;
|
|
318
|
+
this.setTarget("html", (currentTime / 5000).toFixed(1));
|
|
319
|
+
return currentTime < 5000 ? false : true;
|
|
320
|
+
},
|
|
321
|
+
onValueChange(newValue) {
|
|
322
|
+
if (newValue) {
|
|
323
|
+
this.activateTarget("animate");
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
enabledOn() {
|
|
327
|
+
return this.isTargetComplete("animate");
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
})
|
|
331
|
+
);
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Simple Single Page App Example
|
|
335
|
+
|
|
336
|
+
Below is a simple single-page app that demonstrates how to develop a full application using TargetJ.
|
|
337
|
+
|
|
338
|
+

|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
import { App, TModel, getScreenHeight, getScreenWidth, getEvents, getPager } from "targetj";
|
|
342
|
+
|
|
343
|
+
App(
|
|
344
|
+
new TModel("app", {
|
|
345
|
+
start() {
|
|
346
|
+
const urlParts = window.location.href.split("/");
|
|
347
|
+
this.pageName = urlParts[urlParts.length - 1];
|
|
258
348
|
},
|
|
259
|
-
|
|
260
|
-
|
|
349
|
+
canHandleEvents: "touch",
|
|
350
|
+
width: () => getScreenWidth(),
|
|
351
|
+
height: () => getScreenHeight(),
|
|
352
|
+
children() {
|
|
353
|
+
switch (this.pageName) {
|
|
354
|
+
case "page1":
|
|
355
|
+
return [Toolbar(), Page1()];
|
|
356
|
+
case "page2":
|
|
357
|
+
return [Toolbar(), Page2()];
|
|
358
|
+
default:
|
|
359
|
+
return [Toolbar(), HomePage()];
|
|
360
|
+
}
|
|
261
361
|
},
|
|
362
|
+
onResize: ["width", "height"]
|
|
262
363
|
})
|
|
263
364
|
);
|
|
365
|
+
|
|
366
|
+
const Toolbar = () =>
|
|
367
|
+
new TModel("toolbar", {
|
|
368
|
+
start() {
|
|
369
|
+
["home", "page1", "page2"].forEach((menu) => {
|
|
370
|
+
this.addChild(
|
|
371
|
+
new TModel("toolItem", {
|
|
372
|
+
canHandleEvents: "touch",
|
|
373
|
+
background: "bisque",
|
|
374
|
+
width: 100,
|
|
375
|
+
height: 50,
|
|
376
|
+
lineHeight: 50,
|
|
377
|
+
outerXEast: 0,
|
|
378
|
+
opacity: {
|
|
379
|
+
loop() { return this.getOpacity() === 1; },
|
|
380
|
+
value () { return getEvents().isTouchHandler(this) ? [1, 20] : [0.5, 20]; }
|
|
381
|
+
},
|
|
382
|
+
activePage: {
|
|
383
|
+
active: false,
|
|
384
|
+
value: () => getPager().openLink(menu),
|
|
385
|
+
},
|
|
386
|
+
onTouchEvent: ["opacity"],
|
|
387
|
+
onClickEvent: ["activePage"],
|
|
388
|
+
html: menu
|
|
389
|
+
})
|
|
390
|
+
);
|
|
391
|
+
});
|
|
392
|
+
},
|
|
393
|
+
height: 50,
|
|
394
|
+
width: () => getScreenWidth(),
|
|
395
|
+
onResize: ["width"],
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
const HomePage = () =>
|
|
399
|
+
new TModel("homePage", {
|
|
400
|
+
background: "yellow",
|
|
401
|
+
width: () => getScreenWidth(),
|
|
402
|
+
height: () => getScreenHeight(),
|
|
403
|
+
html: "home page",
|
|
404
|
+
onResize: ["width", "height"]
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
const Page1 = () =>
|
|
408
|
+
new TModel("page1", {
|
|
409
|
+
background: "blue",
|
|
410
|
+
width: () => getScreenWidth(),
|
|
411
|
+
height: () => getScreenHeight(),
|
|
412
|
+
html: "page 1",
|
|
413
|
+
onResize: ["width", "height"]
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
const Page2 = () =>
|
|
417
|
+
new TModel("page2", {
|
|
418
|
+
background: "green",
|
|
419
|
+
width: () => getScreenWidth(),
|
|
420
|
+
height: () => getScreenHeight(),
|
|
421
|
+
html: "page 2",
|
|
422
|
+
onResize: ["width", "height"]
|
|
423
|
+
});
|
|
264
424
|
```
|
|
265
425
|
|
|
426
|
+
## Special target names
|
|
427
|
+
|
|
428
|
+
The following are special target names to impact the UI or control properties of TargetJ objects (called TModel):
|
|
429
|
+
|
|
430
|
+
1. x, y, width, height: Set the location and dimensions of the object.
|
|
431
|
+
2. opacity, scale, rotate: Set the opacity, scale, and rotation of the object.
|
|
432
|
+
3. zIndex: Sets the z-order of the object.
|
|
433
|
+
4. html: Sets the content of the object. By default, it will be interpreted as text.
|
|
434
|
+
5. style: An object that sets the style of the object.
|
|
435
|
+
6. css: A string that sets the CSS of the object.
|
|
436
|
+
7. scrollLeft and scrollTop: Used for scrolling the object.
|
|
437
|
+
8. leftMargin, rightMargin, topMargin, bottomMargin: Set the margins between objects.
|
|
438
|
+
9. children: Sets the TModel children of the object.
|
|
439
|
+
10. domHolder and domParent: Set to control the HTML element containment and how HTML is nested.
|
|
440
|
+
11. isVisible: An optional boolean flag to explicitly control the visibility of the object instead of leaving it to TargetJ to calculate.
|
|
441
|
+
12. canHaveDom: A boolean flag that sets if the object can have a DOM element in the page.
|
|
442
|
+
13. canHandleEvents: Sets what events the object can handle
|
|
443
|
+
14. widthFromDom and heightFromDom: Boolean flags that control if the width and height should be calculated from the DOM element.
|
|
444
|
+
15. textOnly: A boolean flag that sets the type of content to be text or HTML.
|
|
445
|
+
16. canBeBracketed: A boolean flag that controls if the object will be optimized and included in the TargetJ task process only when visible.
|
|
446
|
+
17. isInFlow: A boolean flag that determines if the object will be used to calculate the content height and width of its parent.
|
|
447
|
+
18. onResize: An array of targets that will be activated and executed after a resize event.
|
|
448
|
+
19. onClickEvent: An array of targets that will be activated and executed after a click event.
|
|
449
|
+
20. onTouchEvent: An array of targets that will be activated and executed after a touch event.
|
|
450
|
+
21. onScrollEvent: An array of targets that will be activated and executed after a scroll event.
|
|
451
|
+
22. onKeyEvent: An array of targets that will be activated and executed after a key event.
|
|
452
|
+
22. onInvisibleEvent: An array of targets that will be activated and executed after the component becomes invisisble.
|
|
453
|
+
|
|
454
|
+
## Features
|
|
455
|
+
|
|
456
|
+
As a result of using targets, we can develop web sites or apps with the following features:
|
|
457
|
+
|
|
458
|
+
- **No HTML required**: HTML tags are seldom necessary except for images.
|
|
459
|
+
- **No HTML nesting**: HTML nesting is seldom required in TargetJ. If it is required, nesting is done at runtime. Elements can be dynamically detached and incorporated into other elements, facilitating the easy reuse of components regardless of their location or attachment. It also opens the door for a new user experiences.
|
|
460
|
+
- **Next-level animation**: Users can program objects to move at varying speeds, pause at certain intervals, and repeat sequences based on various conditions. It allows the creation of complicated animations.
|
|
461
|
+
- **Control the flow of execution with time**: TargetJ simplifies the execution of various program segments at specific times, making it easy to sequence or parallelize numerous actions.
|
|
462
|
+
- **Handle events effortlessly**: In TargetJ, events are triggered synchronously and are designed so that any component can detect when an event occurs. Event handling can be simply implemented as conditions in the enabling functions of \'targets.\' This ensures that managing events is both simple and effective.
|
|
463
|
+
- **Easy to learn**: TargetJ simplifies development by employing the single concept of \'targets\' making it easy to learn.
|
|
464
|
+
- **Handle 100,000s of items**: TargetJ efficiently manages large collections of objects on a single page. This is done by its data structure and optimization algorithm. It divides a long list into a tree structure, monitoring only the branches that are visible to the user at any given time.
|
|
465
|
+
- **AI friendly**: With a unified concept of targets for all development, the ability to add and remove targets at runtime, and the capability to inspect various statuses of running objects, TargetJ is a strong candidate for AI-powered UI development.
|
|
466
|
+
|
|
467
|
+
|
|
266
468
|
## How to debug in TargetJ
|
|
267
469
|
1. TargetJ.tapp.stop(): Stops the application.
|
|
268
470
|
2. TargetJ.tapp.start(): Restarts the application
|
|
269
471
|
3. TargetJ.tapp.throttle: Slows down the application. This represents the pause in milliseconds before starting another TargetJ task cycle. It is zero by default.
|
|
270
472
|
4. TargetJ.tapp.debugLevel: Logs information about the TargetJ task cycle and its efficiency. It is zero by default. Set it to 1 to log basic information and 2 to log more detailed information.
|
|
271
|
-
5. Use `t()` to find an object from the browser console using its `oid
|
|
272
|
-
|
|
473
|
+
5. Use `t()` to find an object from the browser console using its `oid`. Inspect all the vital properities using `t(oid).bug`.
|
|
474
|
+
|
|
273
475
|
## Documentation
|
|
274
476
|
Explore the full potential of TargetJ and dive into our interactive documentation at www.targetj.io.
|
|
275
477
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "targetj",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.74",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"targetj"
|
|
6
6
|
],
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"webpack": "^5.91.0",
|
|
26
26
|
"webpack-cli": "^5.1.4",
|
|
27
|
-
"wepback": "^1.0.0"
|
|
27
|
+
"wepback": "^1.0.0",
|
|
28
|
+
"eslint-webpack-plugin": "^4.2.0"
|
|
28
29
|
}
|
|
29
30
|
}
|
package/src/$Dom.js
CHANGED
|
@@ -41,7 +41,9 @@ $Dom.prototype.focus = function() {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
$Dom.prototype.attr = function(name, value) {
|
|
44
|
-
if (!this.element)
|
|
44
|
+
if (!this.element) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
45
47
|
|
|
46
48
|
if (TUtil.isDefined(value)) {
|
|
47
49
|
this.element.setAttribute(name, value);
|
|
@@ -51,8 +53,10 @@ $Dom.prototype.attr = function(name, value) {
|
|
|
51
53
|
};
|
|
52
54
|
|
|
53
55
|
$Dom.prototype.value = function(value) {
|
|
54
|
-
if (!this.element)
|
|
55
|
-
|
|
56
|
+
if (!this.element) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
56
60
|
if (TUtil.isDefined(value)) {
|
|
57
61
|
this.element.value = value;
|
|
58
62
|
} else {
|
|
@@ -61,8 +65,9 @@ $Dom.prototype.value = function(value) {
|
|
|
61
65
|
};
|
|
62
66
|
|
|
63
67
|
$Dom.prototype.select = function() {
|
|
64
|
-
if (!this.element || typeof this.element.select !== 'function')
|
|
65
|
-
|
|
68
|
+
if (!this.element || typeof this.element.select !== 'function') {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
66
71
|
|
|
67
72
|
this.element.select();
|
|
68
73
|
};
|
|
@@ -138,7 +143,9 @@ $Dom.prototype.parent = function() {
|
|
|
138
143
|
|
|
139
144
|
$Dom.prototype.detach = function() {
|
|
140
145
|
$Dom.detach(this.element);
|
|
141
|
-
if (this.$domParent && this.$domParent.childrenCount > 0)
|
|
146
|
+
if (this.$domParent && this.$domParent.childrenCount > 0) {
|
|
147
|
+
this.$domParent.childrenCount--;
|
|
148
|
+
}
|
|
142
149
|
};
|
|
143
150
|
|
|
144
151
|
$Dom.prototype.append$Dom = function($dom) {
|
package/src/Bracket.js
CHANGED
package/src/Browser.js
CHANGED
|
@@ -2,29 +2,12 @@ var browser = {
|
|
|
2
2
|
style: undefined,
|
|
3
3
|
delayProcess: {},
|
|
4
4
|
setup: function () {
|
|
5
|
-
|
|
6
|
-
if (typeof String.prototype.trim !== 'function') {
|
|
7
|
-
String.prototype.trim = function () {
|
|
8
|
-
return this.replace(/^\s+|\s+$/g, '');
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
if (typeof String.prototype.startsWith !== 'function') {
|
|
12
|
-
String.prototype.startsWith = function (str) {
|
|
13
|
-
return this.indexOf(str) === 0;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (typeof String.prototype.endsWith !== 'function') {
|
|
18
|
-
String.prototype.endsWith = function (suffix) {
|
|
19
|
-
return this.indexOf(suffix, this.length - suffix.length) !== -1;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
5
|
if (typeof String.prototype.hashCode !== 'function') {
|
|
24
6
|
String.prototype.hashCode = function () {
|
|
25
7
|
var hash = 0, i, chr, len;
|
|
26
|
-
if (this.length === 0)
|
|
8
|
+
if (this.length === 0) {
|
|
27
9
|
return hash;
|
|
10
|
+
}
|
|
28
11
|
for (i = 0, len = this.length; i < len; i++) {
|
|
29
12
|
chr = this.charCodeAt(i);
|
|
30
13
|
hash = ((hash << 5) - hash) + chr;
|
|
@@ -39,69 +22,21 @@ var browser = {
|
|
|
39
22
|
return this.map(function(o) { return o.oid; }).join(separator || " ");
|
|
40
23
|
};
|
|
41
24
|
}
|
|
42
|
-
|
|
43
|
-
if (!Array.spaces) {
|
|
44
|
-
Array.spaces = function(count) {
|
|
45
|
-
return Array(count).join(' ');
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (!Array.prototype.find) {
|
|
52
|
-
Object.defineProperty(Array.prototype, 'find', {
|
|
53
|
-
value: function(predicate) {
|
|
54
|
-
if (this === null) {
|
|
55
|
-
throw new TypeError('"this" is null or not defined');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
var o = Object(this);
|
|
59
|
-
|
|
60
|
-
var len = o.length >>> 0;
|
|
61
|
-
|
|
62
|
-
if (typeof predicate !== 'function') {
|
|
63
|
-
throw new TypeError('predicate must be a function');
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
var thisArg = arguments[1];
|
|
67
|
-
|
|
68
|
-
var k = 0;
|
|
69
|
-
|
|
70
|
-
while (k < len) {
|
|
71
|
-
var kValue = o[k];
|
|
72
|
-
if (predicate.call(thisArg, kValue, k, o)) {
|
|
73
|
-
return kValue;
|
|
74
|
-
}
|
|
75
|
-
k++;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return undefined;
|
|
79
|
-
},
|
|
80
|
-
configurable: true,
|
|
81
|
-
writable: true
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
25
|
|
|
86
26
|
if (!document.getElementsByClassName) {
|
|
87
|
-
var indexOf = [].indexOf || function (prop) {
|
|
88
|
-
for (var i = 0; i < this.length; i++) {
|
|
89
|
-
if (this[i] === prop)
|
|
90
|
-
return i;
|
|
91
|
-
}
|
|
92
|
-
return -1;
|
|
93
|
-
};
|
|
94
27
|
var getElementsByClassName = function (className, context) {
|
|
95
|
-
var elems
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
28
|
+
var elems;
|
|
29
|
+
if (document.querySelectorAll) {
|
|
30
|
+
elems = context.querySelectorAll("." + className);
|
|
31
|
+
} else {
|
|
32
|
+
var all = context.getElementsByTagName("*");
|
|
33
|
+
elems = [];
|
|
34
|
+
for (var i = 0; i < all.length; i++) {
|
|
35
|
+
if (all[i].className && (" " + all[i].className + " ").indexOf(" " + className + " ") > -1 && elems.indexOf(all[i]) === -1) {
|
|
36
|
+
elems.push(all[i]);
|
|
37
|
+
}
|
|
102
38
|
}
|
|
103
|
-
|
|
104
|
-
})();
|
|
39
|
+
}
|
|
105
40
|
return elems;
|
|
106
41
|
};
|
|
107
42
|
document.getElementsByClassName = function (className) {
|
|
@@ -112,39 +47,11 @@ var browser = {
|
|
|
112
47
|
};
|
|
113
48
|
}
|
|
114
49
|
|
|
115
|
-
var lastTime = 0;
|
|
116
|
-
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
|
117
|
-
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
|
118
|
-
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
|
|
119
|
-
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||
|
|
120
|
-
window[vendors[x] + 'CancelRequestAnimationFrame'];
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (!window.requestAnimationFrame) {
|
|
124
|
-
window.requestAnimationFrame = function (callback, element) {
|
|
125
|
-
var currTime = new Date().getTime();
|
|
126
|
-
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
|
127
|
-
var id = window.setTimeout(function () {
|
|
128
|
-
callback(currTime + timeToCall);
|
|
129
|
-
},
|
|
130
|
-
timeToCall);
|
|
131
|
-
lastTime = currTime + timeToCall;
|
|
132
|
-
return id;
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (!window.cancelAnimationFrame) {
|
|
137
|
-
window.cancelAnimationFrame = function (id) {
|
|
138
|
-
clearTimeout(id);
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
50
|
this.style = {
|
|
143
51
|
transform: this.prefixStyle('transform'),
|
|
144
52
|
transitionTimingFunction: this.prefixStyle('transitionTimingFunction'),
|
|
145
53
|
transitionDuration: this.prefixStyle('transitionDuration')
|
|
146
54
|
};
|
|
147
|
-
|
|
148
55
|
},
|
|
149
56
|
log: function(condition) {
|
|
150
57
|
if (condition === true) {
|
|
@@ -156,9 +63,7 @@ var browser = {
|
|
|
156
63
|
prefixStyle: function (style) {
|
|
157
64
|
var elementStyle = document.createElement('div').style;
|
|
158
65
|
|
|
159
|
-
var vendor = '';
|
|
160
|
-
|
|
161
|
-
var vendors = ['webkitT', 'MozT', 'msT', 'OT', 't'];
|
|
66
|
+
var vendor = '', vendors = ['webkitT', 'MozT', 'msT', 'OT', 't'];
|
|
162
67
|
|
|
163
68
|
for (var i = 0; i < vendors.length; i++) {
|
|
164
69
|
var transform = vendors[i] + 'ransform';
|
|
@@ -171,12 +76,6 @@ var browser = {
|
|
|
171
76
|
|
|
172
77
|
return style;
|
|
173
78
|
},
|
|
174
|
-
getParameterByName: function (name) {
|
|
175
|
-
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
|
|
176
|
-
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
|
|
177
|
-
results = regex.exec(location.search);
|
|
178
|
-
return results === null ? 0 : decodeURIComponent(results[1].replace(/\+/g, " "));
|
|
179
|
-
},
|
|
180
79
|
now: Date.now || function () {
|
|
181
80
|
return new Date().getTime();
|
|
182
81
|
},
|
package/src/ColorUtil.js
CHANGED
|
@@ -148,7 +148,9 @@ ColorUtil.color2Integers = function(color) {
|
|
|
148
148
|
color = color ? color + '' : '';
|
|
149
149
|
color = ColorUtil.colors[color.toLowerCase()] ? ColorUtil.colors[color.toLowerCase()] : color;
|
|
150
150
|
|
|
151
|
-
if (!color)
|
|
151
|
+
if (!color) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
152
154
|
|
|
153
155
|
if (color.startsWith('#')) {
|
|
154
156
|
color = color.slice(1);
|
package/src/EventListener.js
CHANGED
|
@@ -120,7 +120,9 @@ EventListener.prototype.captureEvents = function() {
|
|
|
120
120
|
};
|
|
121
121
|
|
|
122
122
|
EventListener.prototype.handleEvent = function (event) {
|
|
123
|
-
if (!event)
|
|
123
|
+
if (!event) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
124
126
|
|
|
125
127
|
var eventName, inputType, eventType, eventOrder;
|
|
126
128
|
|
|
@@ -167,7 +169,9 @@ EventListener.prototype.handleEvent = function (event) {
|
|
|
167
169
|
this.clearTouch();
|
|
168
170
|
|
|
169
171
|
this.touchCount = this.countTouches(event);
|
|
170
|
-
if (this.preventDefault(tmodel, eventName))
|
|
172
|
+
if (this.preventDefault(tmodel, eventName)) {
|
|
173
|
+
event.preventDefault();
|
|
174
|
+
}
|
|
171
175
|
|
|
172
176
|
this.start0 = this.getTouch(event);
|
|
173
177
|
this.start1 = this.getTouch(event, 1);
|
|
@@ -184,7 +188,9 @@ EventListener.prototype.handleEvent = function (event) {
|
|
|
184
188
|
var touch = this.getTouch(event);
|
|
185
189
|
this.cursor.x = touch.x;
|
|
186
190
|
this.cursor.y = touch.y;
|
|
187
|
-
if (this.preventDefault(tmodel, eventName))
|
|
191
|
+
if (this.preventDefault(tmodel, eventName)) {
|
|
192
|
+
event.preventDefault();
|
|
193
|
+
}
|
|
188
194
|
if (this.touchCount > 0) {
|
|
189
195
|
this.move(event);
|
|
190
196
|
event.stopPropagation();
|
|
@@ -194,7 +200,9 @@ EventListener.prototype.handleEvent = function (event) {
|
|
|
194
200
|
case 'mouseup':
|
|
195
201
|
case 'touchend':
|
|
196
202
|
|
|
197
|
-
if (this.preventDefault(tmodel, eventName))
|
|
203
|
+
if (this.preventDefault(tmodel, eventName)) {
|
|
204
|
+
event.preventDefault();
|
|
205
|
+
}
|
|
198
206
|
this.end(event);
|
|
199
207
|
|
|
200
208
|
if (this.start0) {
|
|
@@ -219,7 +227,9 @@ EventListener.prototype.handleEvent = function (event) {
|
|
|
219
227
|
|
|
220
228
|
case 'wheel':
|
|
221
229
|
|
|
222
|
-
if (this.preventDefault(tmodel, eventName))
|
|
230
|
+
if (this.preventDefault(tmodel, eventName)) {
|
|
231
|
+
event.preventDefault();
|
|
232
|
+
}
|
|
223
233
|
this.wheel(event);
|
|
224
234
|
break;
|
|
225
235
|
|
package/src/LoadingManager.js
CHANGED
|
@@ -20,7 +20,9 @@ function LoadingManager() {
|
|
|
20
20
|
|
|
21
21
|
LoadingManager.prototype.initSingleLoad = function (fetchId, query, forceLoad) {
|
|
22
22
|
|
|
23
|
-
if (this.isLoading(fetchId) || (this.isLoaded(fetchId) && !forceLoad) || this.getLoadingAttempts(fetchId) > this.stopLoadingAfterAttempts)
|
|
23
|
+
if (this.isLoading(fetchId) || (this.isLoaded(fetchId) && !forceLoad) || this.getLoadingAttempts(fetchId) > this.stopLoadingAfterAttempts) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
24
26
|
|
|
25
27
|
this.initLoadingMap(fetchId);
|
|
26
28
|
|
|
@@ -31,7 +33,9 @@ LoadingManager.prototype.initSingleLoad = function (fetchId, query, forceLoad)
|
|
|
31
33
|
LoadingManager.prototype.initGroupLoad = function (fetchId, dataId, query, idKey, separator) {
|
|
32
34
|
var groupId = JSON.stringify({ query: query, idKey: idKey, separator: separator });
|
|
33
35
|
|
|
34
|
-
if (this.isLoading(fetchId) || this.isLoaded(fetchId) || this.getLoadingAttempts(fetchId) > this.stopLoadingAfterAttempts)
|
|
36
|
+
if (this.isLoading(fetchId) || this.isLoaded(fetchId) || this.getLoadingAttempts(fetchId) > this.stopLoadingAfterAttempts) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
35
39
|
|
|
36
40
|
this.initLoadingMap(fetchId);
|
|
37
41
|
|
|
@@ -45,7 +49,9 @@ LoadingManager.prototype.initGroupLoad = function (fetchId, dataId, query, idKey
|
|
|
45
49
|
|
|
46
50
|
LoadingManager.prototype.initImgLoad = function (fetchId, src) {
|
|
47
51
|
|
|
48
|
-
if (this.isLoading(fetchId) || this.isLoaded(fetchId) || this.getLoadingAttempts(fetchId) > this.stopLoadingAfterAttempts)
|
|
52
|
+
if (this.isLoading(fetchId) || this.isLoaded(fetchId) || this.getLoadingAttempts(fetchId) > this.stopLoadingAfterAttempts) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
49
55
|
|
|
50
56
|
this.initLoadingMap(fetchId, 'image');
|
|
51
57
|
|
|
@@ -110,7 +116,9 @@ LoadingManager.prototype.initLoadingMap = function(fetchId, category) {
|
|
|
110
116
|
};
|
|
111
117
|
|
|
112
118
|
LoadingManager.prototype.groupLoad = function () {
|
|
113
|
-
if (!this.groupLoadList)
|
|
119
|
+
if (!this.groupLoadList) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
114
122
|
|
|
115
123
|
var groupIds = Object.keys(this.groupLoadList);
|
|
116
124
|
|
|
@@ -140,7 +148,9 @@ LoadingManager.prototype.groupLoad = function () {
|
|
|
140
148
|
};
|
|
141
149
|
|
|
142
150
|
LoadingManager.prototype.singleLoad = function () {
|
|
143
|
-
if (!this.singleLoadList)
|
|
151
|
+
if (!this.singleLoadList) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
144
154
|
|
|
145
155
|
var keys = Object.keys(this.singleLoadList);
|
|
146
156
|
|
|
@@ -154,7 +164,9 @@ LoadingManager.prototype.singleLoad = function () {
|
|
|
154
164
|
};
|
|
155
165
|
|
|
156
166
|
LoadingManager.prototype.imgLoad = function () {
|
|
157
|
-
if (!this.imgLoadList)
|
|
167
|
+
if (!this.imgLoadList) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
158
170
|
|
|
159
171
|
var keys = Object.keys(this.imgLoadList);
|
|
160
172
|
|
package/src/LocationManager.js
CHANGED
|
@@ -63,7 +63,9 @@ LocationManager.prototype.calculateContainer = function(container) {
|
|
|
63
63
|
while (i < length && tapp.isRunning()) {
|
|
64
64
|
|
|
65
65
|
var child = allChildren[i++];
|
|
66
|
-
if (!child)
|
|
66
|
+
if (!child) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
67
69
|
|
|
68
70
|
var outerXEast = undefined, innerXEast = undefined;
|
|
69
71
|
|
|
@@ -137,7 +139,9 @@ LocationManager.prototype.calculateContainer = function(container) {
|
|
|
137
139
|
child.val('contentHeight').forEach(function(key) {
|
|
138
140
|
var preVal = child.val(key);
|
|
139
141
|
child.val(key, child.getContentHeight());
|
|
140
|
-
if (preVal !== child.val(key))
|
|
142
|
+
if (preVal !== child.val(key)) {
|
|
143
|
+
child.addToStyleTargetList(key);
|
|
144
|
+
}
|
|
141
145
|
});
|
|
142
146
|
}
|
|
143
147
|
|
|
@@ -145,7 +149,9 @@ LocationManager.prototype.calculateContainer = function(container) {
|
|
|
145
149
|
child.val('contentWidth').forEach(function(key) {
|
|
146
150
|
var preVal = child.val(key);
|
|
147
151
|
child.val(key, child.getContentWidth());
|
|
148
|
-
if (preVal !== child.val(key))
|
|
152
|
+
if (preVal !== child.val(key)) {
|
|
153
|
+
child.addToStyleTargetList(key);
|
|
154
|
+
}
|
|
149
155
|
});
|
|
150
156
|
}
|
|
151
157
|
|
package/src/Moves.js
CHANGED
package/src/PageManager.js
CHANGED
package/src/SearchUtil.js
CHANGED
|
@@ -92,7 +92,9 @@ SearchUtil.findByType = function (type) {
|
|
|
92
92
|
|
|
93
93
|
function search(container) {
|
|
94
94
|
|
|
95
|
-
if (container.type === type)
|
|
95
|
+
if (container.type === type) {
|
|
96
|
+
return container;
|
|
97
|
+
}
|
|
96
98
|
|
|
97
99
|
var children = container.getChildren();
|
|
98
100
|
var found;
|
|
@@ -101,7 +103,9 @@ SearchUtil.findByType = function (type) {
|
|
|
101
103
|
|
|
102
104
|
tmodel = children[i];
|
|
103
105
|
|
|
104
|
-
if (!tmodel)
|
|
106
|
+
if (!tmodel) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
105
109
|
|
|
106
110
|
if (tmodel.hasChildren()) {
|
|
107
111
|
found = search(tmodel);
|
|
@@ -128,7 +132,9 @@ SearchUtil.findByTarget = function (target) {
|
|
|
128
132
|
|
|
129
133
|
function search(container) {
|
|
130
134
|
|
|
131
|
-
if (container.targets[target])
|
|
135
|
+
if (container.targets[target]) {
|
|
136
|
+
return container;
|
|
137
|
+
}
|
|
132
138
|
|
|
133
139
|
var children = container.getChildren();
|
|
134
140
|
var found;
|
|
@@ -137,7 +143,9 @@ SearchUtil.findByTarget = function (target) {
|
|
|
137
143
|
|
|
138
144
|
tmodel = children[i];
|
|
139
145
|
|
|
140
|
-
if (!tmodel)
|
|
146
|
+
if (!tmodel) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
141
149
|
|
|
142
150
|
if (tmodel.hasChildren()) {
|
|
143
151
|
found = search(tmodel);
|
|
@@ -164,7 +172,9 @@ SearchUtil.find = function (oid) {
|
|
|
164
172
|
|
|
165
173
|
function search(container) {
|
|
166
174
|
|
|
167
|
-
if (container.oid === oid)
|
|
175
|
+
if (container.oid === oid) {
|
|
176
|
+
return container;
|
|
177
|
+
}
|
|
168
178
|
|
|
169
179
|
var children = container.getChildren();
|
|
170
180
|
var found;
|
|
@@ -173,7 +183,9 @@ SearchUtil.find = function (oid) {
|
|
|
173
183
|
|
|
174
184
|
tmodel = children[i];
|
|
175
185
|
|
|
176
|
-
if (!tmodel)
|
|
186
|
+
if (!tmodel) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
177
189
|
|
|
178
190
|
if (tmodel.hasChildren()) {
|
|
179
191
|
found = search(tmodel);
|
package/src/TModel.js
CHANGED
|
@@ -5,8 +5,6 @@ import { TUtil } from "./TUtil.js";
|
|
|
5
5
|
import { TargetUtil } from "./TargetUtil.js";
|
|
6
6
|
import { TargetExecutor } from "./TargetExecutor";
|
|
7
7
|
import { Viewport } from "./Viewport.js";
|
|
8
|
-
import { Easing } from "./Easing.js";
|
|
9
|
-
import { $Dom } from "./$Dom.js";
|
|
10
8
|
|
|
11
9
|
function TModel(type, targets) {
|
|
12
10
|
|
|
@@ -119,7 +117,9 @@ TModel.prototype.getDomHolder = function() {
|
|
|
119
117
|
};
|
|
120
118
|
|
|
121
119
|
TModel.prototype.addToStyleTargetList = function(key) {
|
|
122
|
-
if (!TargetUtil.styleTargetMap[key])
|
|
120
|
+
if (!TargetUtil.styleTargetMap[key]) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
123
|
|
|
124
124
|
key = TargetUtil.transformMap[key] ? 'transform' : TargetUtil.dimMap[key] ? 'dim' : key;
|
|
125
125
|
|
|
@@ -541,7 +541,9 @@ TModel.prototype.resetTargetInitialValue = function(key) {
|
|
|
541
541
|
TModel.prototype.updateTargetStatus = function(key) {
|
|
542
542
|
var targetValue = this.targetValues[key];
|
|
543
543
|
|
|
544
|
-
if (!targetValue)
|
|
544
|
+
if (!targetValue) {
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
545
547
|
|
|
546
548
|
var cycle = this.getTargetCycle(key);
|
|
547
549
|
var cycles = this.getTargetCycles(key);
|
package/src/TModelManager.js
CHANGED
|
@@ -67,8 +67,7 @@ TModelManager.prototype.clear = function() {
|
|
|
67
67
|
this.targetMethodMap = {};
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
TModelManager.prototype.visibles = function(type
|
|
71
|
-
list = !list ? this.lists.visible : list;
|
|
70
|
+
TModelManager.prototype.visibles = function(type) {
|
|
72
71
|
return this.lists.visible.filter(function(tmodel) { return tmodel.type === type || !type ; }).map(function(tmodel) { return tmodel.oid; });
|
|
73
72
|
};
|
|
74
73
|
|
package/src/TUtil.js
CHANGED
|
@@ -132,7 +132,9 @@ TUtil.limit = function (num, low, high) {
|
|
|
132
132
|
};
|
|
133
133
|
|
|
134
134
|
TUtil.formatNum = function (num, precision) {
|
|
135
|
-
if (!num)
|
|
135
|
+
if (!num) {
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
136
138
|
var s = num.toString();
|
|
137
139
|
var n = parseFloat(s);
|
|
138
140
|
return n.toFixed(precision);
|
|
@@ -143,7 +145,9 @@ TUtil.distance = function(x1, y1, x2, y2) {
|
|
|
143
145
|
};
|
|
144
146
|
|
|
145
147
|
TUtil.getFullLink = function(link) {
|
|
146
|
-
if (!TUtil.isDefined(link))
|
|
148
|
+
if (!TUtil.isDefined(link)) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
147
151
|
|
|
148
152
|
if (link.indexOf('http') === 0) {
|
|
149
153
|
return link;
|
package/src/TargetExecutor.js
CHANGED
package/src/TargetManager.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { browser } from "./Browser.js";
|
|
2
1
|
import { TUtil } from "./TUtil.js";
|
|
3
2
|
import { TargetUtil } from "./TargetUtil.js";
|
|
4
3
|
import { TargetExecutor } from "./TargetExecutor";
|
|
@@ -80,7 +79,9 @@ TargetManager.prototype.setActualValues = function(tmodel) {
|
|
|
80
79
|
TargetManager.prototype.setActualValue = function(tmodel, key) {
|
|
81
80
|
var targetValue = tmodel.targetValues[key];
|
|
82
81
|
|
|
83
|
-
if (!targetValue)
|
|
82
|
+
if (!targetValue) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
84
85
|
|
|
85
86
|
if (!tmodel.isTargetEnabled(key)) {
|
|
86
87
|
tapp.manager.scheduleRun(10, "setActualValue-disabled-" + tmodel.oid + "__" + key);
|
package/src/TargetUtil.js
CHANGED
|
@@ -3,7 +3,6 @@ import { TModel } from "./TModel.js";
|
|
|
3
3
|
import { getManager } from "./App.js";
|
|
4
4
|
import { TUtil } from "./TUtil.js";
|
|
5
5
|
import { ColorUtil } from "./ColorUtil.js";
|
|
6
|
-
import { Easing } from "./Easing.js";
|
|
7
6
|
|
|
8
7
|
function TargetUtil() {}
|
|
9
8
|
|
|
@@ -228,7 +227,7 @@ TargetUtil.handleValueChange = function(tmodel, key, newValue, lastValue, step,
|
|
|
228
227
|
}
|
|
229
228
|
};
|
|
230
229
|
|
|
231
|
-
TargetUtil.morph = function(tmodel, key, fromValue, toValue, step
|
|
230
|
+
TargetUtil.morph = function(tmodel, key, fromValue, toValue, step) {
|
|
232
231
|
|
|
233
232
|
var easing = tmodel.getTargetEasing(key);
|
|
234
233
|
var easingStep = easing ? easing(tmodel.getTargetStepPercent(key, step)) : tmodel.getTargetStepPercent(key, step);
|
package/src/Viewport.js
CHANGED
package/webpack.config.js
CHANGED
|
@@ -1,13 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const ESLintPlugin = require('eslint-webpack-plugin');
|
|
2
3
|
|
|
3
4
|
module.exports = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
entry: './Exports.js',
|
|
6
|
+
output: {
|
|
7
|
+
library: {
|
|
8
|
+
name: 'TargetJ',
|
|
9
|
+
type: 'window'
|
|
10
|
+
},
|
|
11
|
+
path: path.resolve(__dirname, './dist'),
|
|
12
|
+
filename: 'targetj.js'
|
|
9
13
|
},
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
plugins: [
|
|
15
|
+
new ESLintPlugin({
|
|
16
|
+
extensions: ['js'],
|
|
17
|
+
exclude: 'node_modules',
|
|
18
|
+
overrideConfig: {
|
|
19
|
+
env: {
|
|
20
|
+
browser: true,
|
|
21
|
+
es2021: true
|
|
22
|
+
},
|
|
23
|
+
extends: [
|
|
24
|
+
'eslint:recommended'
|
|
25
|
+
],
|
|
26
|
+
parserOptions: {
|
|
27
|
+
ecmaVersion: 12,
|
|
28
|
+
sourceType: 'module'
|
|
29
|
+
},
|
|
30
|
+
rules: {
|
|
31
|
+
'curly': 'error',
|
|
32
|
+
'eqeqeq': 'error',
|
|
33
|
+
'dot-notation': 'off',
|
|
34
|
+
'no-console': 'warn',
|
|
35
|
+
'no-loop-func': 'off'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
],
|
|
40
|
+
resolve: {
|
|
41
|
+
extensions: ['.js']
|
|
42
|
+
}
|
|
43
|
+
};
|