@joyzl/eno 1.1.2 → 1.1.5

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.
Files changed (3) hide show
  1. package/README.md +465 -35
  2. package/index.js +293 -155
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -7,13 +7,36 @@ npm install @joyzl/eno
7
7
  ```
8
8
 
9
9
  ``` javascript
10
- import eno from `eno`;
10
+ import eno from '@joyzl/eno';
11
11
  ```
12
12
 
13
13
  ## 使用
14
14
 
15
- ### sets
16
- 将数据对象(例如从服务器获取的JSON对象)设置到HTML元素以显示数据。
15
+ ### eno.sets()
16
+
17
+ eno.sets() 将数据对象(通常为JSON实例)设置到HTML标签显示。
18
+
19
+ 参数形式:
20
+ * eno.sets(element, parameter);
21
+ * eno.sets(selector, parameter);
22
+ * eno.sets(element, selector, parameter);
23
+ * eno.sets(element, parameter, converter);
24
+ * eno.sets(element, selector, parameter, converter);
25
+
26
+ 参数含义:
27
+ * element 元素实例/元素查找范围;
28
+ * selector 选择器字符串;
29
+ * parameter 数据对象/数据对象数组;
30
+ * converter 转换函数 function(element, parameter, name){};
31
+
32
+ 转换函数参数含义:
33
+ * element 元素实例;
34
+ * parameter 对象实例;
35
+ * name 情形值;
36
+
37
+ #### 单个对象设置到HTML显示
38
+
39
+ 将单个数据对象(例如从服务器获取的JSON对象)设置到HTML元素以显示数据。
17
40
 
18
41
  首先建立HTML标签元素如下所示:
19
42
  ```html
@@ -41,9 +64,193 @@ eno.sets(div, user);
41
64
  </div>
42
65
  ```
43
66
 
44
- ### gets
45
- 从HTML元素获取JSON对象以获得用户数据。
46
- 与sets方法的功能正好相反。
67
+ #### 多个对象设置到HTML显示
68
+
69
+ 将多个数据对象(例如从服务器获取的JSON对象数组)设置到HTML元素以显示数据;
70
+ 此时eno将自动克隆创建对应数量的HTML元素以对应多项数据。
71
+
72
+ 首先建立HTML标签元素如下所示:
73
+ ```html
74
+ <div id="users">
75
+ <div>
76
+ <span name="realname"></span>
77
+ <span name="birthday"></span>
78
+ </div>
79
+ </div>
80
+ ```
81
+
82
+ 将数据对象设置到HTML标签元素。
83
+ ```javascript
84
+ let users = [{
85
+ realname: "小明",
86
+ birthday: "1992-5-27"
87
+ },
88
+ {
89
+ realname: "小王",
90
+ birthday: "1993-8-16"
91
+ }
92
+ ];
93
+ eno.sets("#users", users);
94
+ ```
95
+
96
+ 数据对象的字段值将根据HTML标签元素指定的name属性插入到标签中;
97
+ 此时eno将 "#users" DIV 的子元素作为模板,自动克隆以显示多项数据。
98
+ ```html
99
+ <div id="users">
100
+ <div>
101
+ <span name="realname">小明</span>
102
+ <span name="birthday">1992-5-27</span>
103
+ </div>
104
+ <div>
105
+ <span name="realname">小王</span>
106
+ <span name="birthday">1993-8-16</span>
107
+ </div>
108
+ </div>
109
+ ```
110
+
111
+ 在相同元素实例多次执行eno.sets方法时,eno将自动维护对应的数量的子元素,以保持正确的显示;
112
+ 如果传入的对象数组为[]或null这将清除所有子元素,eno会通过隐藏以保留原始模板。
113
+
114
+ #### 多个对象设置到HTML显示并指定模板
115
+
116
+ 通过模板&lt;template&gt;显示多个对象到HTML中具有更好的灵活性,eno将保留模板标签之外的HTML。
117
+ ```html
118
+ <div id="users">
119
+ <div>
120
+ <span>用户列表</span>
121
+ </div>
122
+ <template>
123
+ <div>
124
+ <span name="realname"></span>
125
+ <span name="birthday"></span>
126
+ </div>
127
+ </template>
128
+ </div>
129
+ ```
130
+
131
+ 执行eno.sets("#users",users)将得到如下HTML实例:
132
+ ```html
133
+ <div id="users">
134
+ <div>
135
+ <span>用户列表</span>
136
+ </div>
137
+ <template>
138
+ <div>
139
+ <span name="realname"></span>
140
+ <span name="birthday"></span>
141
+ </div>
142
+ </template>
143
+ <div>
144
+ <span name="realname">小明</span>
145
+ <span name="birthday">1992-5-27</span>
146
+ </div>
147
+ <div>
148
+ <span name="realname">小王</span>
149
+ <span name="birthday">1993-8-16</span>
150
+ </div>
151
+ </div>
152
+ ```
153
+ eno根据"#users"中的&lt;template&gt;创建对应数量的HTML元素显示数据,
154
+ 并保留其它HTML标签(也保留&lt;template&gt;本身,因为此标签不会被显示)。
155
+
156
+ #### 在HTML指示对象字段
157
+
158
+ 将对象通过HTML显示时,eno通过标签的"name"属性值确定对象字段(区分大小写);
159
+ 属性值支持点语法分隔多级字段,例如:"department.name";
160
+
161
+ eno确定对象字段后将根据标签类型执行默认的值设置:
162
+ * input标签设置为value属性值;
163
+ * img标签设置为src属性值;
164
+ * 其它标签设置为内部文本(innerText);
165
+
166
+ ```html
167
+ <div id="users">
168
+ <template>
169
+ <div>
170
+ <img name="avatar"/>
171
+ <span name="realname"></span>
172
+ <span name="birthday"></span>
173
+ <span name="department.name"></span>
174
+ </div>
175
+ </template>
176
+ </div>
177
+ ```
178
+ ```javascript
179
+ let users = [{
180
+ realname: "小明",
181
+ birthday: "1992-5-27",
182
+ avatar: "okjniybu.png",
183
+ department: {
184
+ name: "A部"
185
+ }
186
+ },
187
+ {
188
+ realname: "小王",
189
+ birthday: "1993-8-16",
190
+ avatar: "likjudde.png",
191
+ department: {
192
+ name: "B部"
193
+ }
194
+ }
195
+ ];
196
+ eno.sets("#users", users);
197
+ ```
198
+
199
+ #### 自定义对象字段与HTML显示方式
200
+
201
+ 如果默认行为无法满足显示需求,例如根据状态字段更改颜色,
202
+ 可通过"case"属性值和自定义转换函数执行特殊处理;
203
+ ```html
204
+ <div id="users">
205
+ <template>
206
+ <div>
207
+ <img case="url"/>
208
+ <span name="realname"></span>
209
+ <span name="birthday"></span>
210
+ <span name="department.name"></span>
211
+ </div>
212
+ </template>
213
+ </div>
214
+ ```
215
+ 转换函数将在遇到的每一个"case"属性时触发,并传入三个参数
216
+ 分别为element表示"case"所在的元素实例,
217
+ parameter表示当前数据对象,
218
+ name指示"case"的值;
219
+ ```javascript
220
+ let users = [...];
221
+ eno.sets("#users", users, function(element, parameter, name){
222
+ if(name=="url"){
223
+ element.src = "http://joyzl.net/" + parameter.avatar;
224
+ }
225
+ });
226
+ ```
227
+ 通过转换函数可以执行任何需要的自定义处理;
228
+ 但须注意的是,每个模板实例中的多个"case"都将调用转换函数,
229
+ 如果同时指定"name"属性,将在调用转换函数后执行默认行为。
230
+
231
+ ### eno.gets()
232
+
233
+ 从HTML元素获取用户数据以形成JSON对象实例。
234
+ 与eno.sets方法的行为正好相反,将从HTML中具有"name"属性的标签提取数据。
235
+
236
+ 参数形式:
237
+ * eno.gets(element);
238
+ * eno.gets(selector);
239
+ * eno.gets(element, converter);
240
+ * eno.gets(selector, converter);
241
+ * eno.gets(element, selector, converter);
242
+
243
+ 参数含义:
244
+ * element 元素实例;
245
+ * selector 选择器字符串;
246
+ * converter 转换函数 function(element, parameter, name){};
247
+
248
+ 转换函数参数含义:
249
+ * element 元素实例;
250
+ * parameter 对象实例;
251
+ * name 情形值;
252
+
253
+ #### 从HTML中提取数据
47
254
 
48
255
  假设有以下HTML实例:
49
256
  ```html
@@ -56,11 +263,15 @@ eno.sets(div, user);
56
263
  执行gets方法获取数据对象:
57
264
  ```javascript
58
265
  let values = eno.gets(element);
59
- //{
60
- // realname: "小明",
61
- // birthday: "1992-5-27"
62
- //}
266
+ // values 实例字段如下
267
+ // {
268
+ // realname: "小明",
269
+ // birthday: "1992-5-27"
270
+ // }
63
271
  ```
272
+ eno.gets将普通标签获取内部普通文本内容(innetText)。
273
+
274
+ #### 从表单中提取数据
64
275
 
65
276
  获取表单输入值,gets将识别传入参数是否表单。
66
277
  ```html
@@ -73,52 +284,271 @@ let values = eno.gets(element);
73
284
  执行gets方法获取form数据对象:
74
285
  ```javascript
75
286
  let values = eno.gets(element);
76
- //{
77
- // realname: "小张",
78
- // birthday: "1982-10-30"
79
- //}
287
+ // values 实例字段如下
288
+ // {
289
+ // realname: "小张",
290
+ // birthday: "1982-10-30"
291
+ // }
80
292
  ```
293
+ eno.gets将表单标签获取控件值内容(control.value)。
294
+
295
+ #### 自定义数据提取方式
81
296
 
297
+ 与eno.sets方法相同,eno.gets也支持同样参数的数据转换函数用于自定义提取方式。
298
+ ```javascript
299
+ let values = eno.gets(element, function(element, parameter, name){
300
+ if(name=="url"){
301
+ parameter.avatar = element.src.replace("http://joyzl.net/","");
302
+ }
303
+ });
304
+ // values 实例字段如下
305
+ // {
306
+ // realname: "小张",
307
+ // birthday: "1982-10-30",
308
+ // avatar: "okjniybu.png"
309
+ // }
310
+ ```
82
311
 
83
- ### query
84
- 获取指定URL或当前URL中的查询字符串参数。
312
+ ### eno.create()
313
+
314
+ eno.create() 用于将字符串形式的HTML标签创建为HTML实例。
315
+
316
+ 参数形式:
317
+ * eno.create(html);
318
+
319
+ 参数含义:
320
+ * html 字符串;
85
321
 
86
322
  ```javascript
87
- // 从当前URL获取参数
88
- let token = eno.query("token");
323
+ let element = eno.create("<div><a href='http://www.joyzl.com'>joyzl</a></div>");
324
+ ```
89
325
 
90
- // 从指定URL获取参数
91
- let url = "http://www.joyzl.net/test?name=value";
92
- let value = eno.query(url, "name");
326
+ 注意:此时创建的标签实例未插入文档中,因此不会在浏览器网页呈现。
327
+
328
+ ### eno.append()
329
+
330
+ eno.append() 用于将字符串形式的HTML标签创建为HTML实例,并插入文档指定的位置尾部。
331
+
332
+ 参数形式:
333
+ * eno.append(element, html);
334
+ * eno.append(selector, html);
335
+
336
+ 参数含义:
337
+ * element 元素实例;
338
+ * selector 选择器字符串;
339
+ * html 字符串;
340
+
341
+ ```javascript
342
+ // 添加到<body>中尾部
343
+ let element1 = eno.append("<div><a href='http://www.joyzl.com'>joyzl</a></div>");
344
+
345
+ // 添加到指定元素中尾部
346
+ let parent = document.getElementById("main");
347
+ let element2 = eno.append(parent, "<div><a href='http://www.joyzl.com'>joyzl</a></div>");
93
348
  ```
94
349
 
95
- ### select
96
- 获取符合指定选择器字符串的第一个元素。
350
+ ### eno.replace()
351
+
352
+ eno.replace() 用于将字符串形式的HTML标签创建为HTML实例,并替换指定的元素。
353
+
354
+ 参数形式:
355
+ * eno.replace(element, html);
356
+ * eno.replace(selector, html);
357
+
358
+ 参数含义:
359
+ * element 元素实例;
360
+ * selector 选择器字符串;
361
+ * html 字符串;
97
362
 
98
- 在整个文档实例范围中查找:
99
363
  ```javascript
100
- let element = eno.select("#user");
364
+ let element = document.getElementById("customer-define");
365
+ element = eno.replace(element, "<div><a href='http://www.joyzl.com'>joyzl</a></div>");
101
366
  ```
102
367
 
103
- 在指定元素实例范围中查找:
368
+ ### eno.select()
369
+
370
+ eno.select() 用于在文档或指定范围查找元素。
371
+
372
+ 参数形式:
373
+ * eno.select(selector);
374
+ * eno.select(element, selector);
375
+
376
+ 参数含义:
377
+ * element 元素实例;
378
+ * selector 选择器字符串;
379
+
104
380
  ```javascript
105
- let form = eno.select("form");
106
- let user = eno.select(form, "#user");
381
+ // 在整个文档中查找
382
+ let element = eno.select("#id");
383
+
384
+ // 在指定元素中查找
385
+ element = eno.select(element, "div");
107
386
  ```
108
387
 
388
+ 支持标准的CSS选择器字符串,如果匹配多个元素将以数组返回结果集,仅匹配单个时仅返回匹配的元素实例。
389
+
390
+ ### eno.remove()
391
+
392
+ eno.remove() 用于移除文档中的指定元素。
393
+
394
+ 参数形式:
395
+ * eno.remove(element);
396
+ * eno.remove(selector);
397
+ * eno.remove(element, selector);
398
+
399
+ 参数含义:
400
+ * element 元素实例;
401
+ * selector 选择器字符串;
402
+
403
+ ### eno.hide()
404
+
405
+ eno.hide() 用于隐藏元素。
406
+
407
+ 参数形式:
408
+ * eno.hide(element);
409
+ * eno.hide(selector);
410
+ * eno.hide(element, selector);
411
+
412
+ 参数含义:
413
+ * element 元素实例;
414
+ * selector 选择器字符串;
415
+
416
+ ### eno.show()
417
+
418
+ eno.show() 用于显示元素。
419
+
420
+ 参数形式:
421
+ * eno.show(element);
422
+ * eno.show(selector);
423
+ * eno.show(element, selector);
424
+
425
+ 参数含义:
426
+ * element 元素实例;
427
+ * selector 选择器字符串;
428
+
429
+ ### eno.toggle()
430
+
431
+ eno.toggle() 用于切换元素显示或样式类。
432
+ 调用此方法仅指定元素或选择器参数,指定或匹配的元素将显示,其余同级元素全部隐藏;
433
+ 如果指定了样式类参数(applyClass, otherClass),则匹配的元素将应用applyClass,其余同级元素应用otherClass样式类。
109
434
 
110
- ### selects
111
- 获取符合指定选择器字符串的所有元素。
435
+ 参数形式:
436
+ * eno.toggle(element);
437
+ * eno.toggle(selector);
438
+ * eno.toggle(element, selector);
439
+ * eno.toggle(element, applyClass, otherClass);
440
+ * eno.toggle(element, selector, applyClass, otherClass);
112
441
 
442
+ 参数含义:
443
+ * element 元素实例;
444
+ * selector 选择器字符串;
445
+ * applyClass 当前元素应用的样式类;
446
+ * otherClass 其它元素应用的样式类;
113
447
 
114
- 在整个文档实例范围中查找:
448
+ 此功能可用于层叠卡片显示切换或选中项高亮。
449
+
450
+
451
+
452
+ ### eno.bind()
453
+
454
+ eno.bind() 用于绑定元素的事件。
455
+
456
+ 参数形式:
457
+ * eno.bind(element, eventName, listener);
458
+ * eno.bind(selector, eventName, listener);
459
+ * eno.bind(element, selector, eventName, listener);
460
+
461
+ 参数含义:
462
+ * element 元素实例;
463
+ * selector 选择器字符串;
464
+ * eventName 事件名称 "click"、"submit" ...;
465
+ * listener 事件处理函数 function(event){};
466
+
467
+ 处理函数参数含义:
468
+ * this 元素实例;
469
+ * event 事件实例;
470
+
471
+ 此方法的事件绑定与DOM API并无任何差异,其行为与Element.addEventListener()完全相同。
472
+
473
+ #### eno.sets()的事件处理
474
+
475
+ 对于通过eno.sets()方法生成并填充值的元素,如果要监听每个元素的事件,
476
+ 可通过eno.bind()配合eno.entity()和eno.element()方法优化事件处理,而无须为每个子元素绑定事件;
477
+
478
+ 具体方法如下:
479
+ + 容器绑定所需事件;
480
+ + 在处理函数中通过eno.element()获取目标元素实例;
481
+ + 在处理函数中通过eno.entity()获取目标对象实例;
482
+
483
+ 示例代码:
115
484
  ```javascript
116
- let elements = eno.selects("#user");
485
+ const element = eno.append(`
486
+ <div id="users">
487
+ <div>
488
+ <span>用户列表</span>
489
+ </div>
490
+ <template>
491
+ <div>
492
+ <span name="realname"></span>
493
+ <span name="birthday"></span>
494
+ </div>
495
+ </template>
496
+ </div>
497
+ `);
498
+ eno.bind(element,"click",function(event){
499
+ // 获取数据对象实例
500
+ eno.entity(event)
501
+
502
+ // 获取元素对象实例
503
+ eno.element(event);
504
+ });
505
+ eno.sets(element,data);
117
506
  ```
118
507
 
508
+ ### eno.entity()
509
+
510
+ eno.entity() 用于获取通过eno.sets()方法填充元素的数据对象。
511
+
512
+ 参数形式:
513
+ * eno.entity(event);
514
+ * eno.entity(element);
515
+ * eno.entity(element, selector);
516
+
517
+ 参数含义:
518
+ * event 事件实例;
519
+ * element 元素实例;
520
+ * selector 选择器字符串;
521
+
522
+ ### eno.element()
523
+
524
+ eno.element() 用于获取通过eno.sets()方法填充元素的实例。
525
+
526
+ 参数形式:
527
+ * eno.element(event);
528
+
529
+ 参数含义:
530
+ * event 事件实例;
531
+
532
+ ### eno.query()
533
+
534
+ eno.query() 用于获取指定URL或当前URL中的查询字符串参数。
535
+
536
+ 参数形式:
537
+ * eno.query();
538
+ * eno.query(url);
539
+ * eno.query(name);
540
+ * eno.query(url, name);
541
+
542
+ 参数含义:
543
+ * url 字符串,如果未指定则默认当前页面URL;
544
+ * name 参数名字符串,区分大小写;
545
+
119
546
 
120
- 在指定元素实例范围中查找:
121
547
  ```javascript
122
- let forms = eno.selects("form");
123
- let users = eno.selects(form, "#user");
548
+ // 从当前URL获取参数
549
+ let token = eno.query("token");
550
+
551
+ // 从指定URL获取参数
552
+ let url = "http://www.joyzl.net/test?name=value";
553
+ let value = eno.query(url, "name");
124
554
  ```
package/index.js CHANGED
@@ -6,6 +6,7 @@ export default {
6
6
  create,
7
7
  append,
8
8
  replace,
9
+ selects,
9
10
  select,
10
11
  remove,
11
12
 
@@ -68,19 +69,22 @@ function append(element, html) {
68
69
  // append(element,html);
69
70
  element = select(element);
70
71
  } else {
71
- return;
72
- }
73
- if (html.trim) {
74
- html = create(html);
72
+ return null;
75
73
  }
76
- if (Array.isArray(html)) {
77
- for (let i = 0; i < html.length; i++) {
78
- element.appendChild(html[i]);
74
+ if (element) {
75
+ if (html.trim) {
76
+ html = create(html);
79
77
  }
80
- } else {
81
- element.appendChild(html);
78
+ if (Array.isArray(html)) {
79
+ for (let i = 0; i < html.length; i++) {
80
+ element.appendChild(html[i]);
81
+ }
82
+ } else {
83
+ element.appendChild(html);
84
+ }
85
+ return html;
82
86
  }
83
- return html;
87
+ return null;
84
88
  }
85
89
 
86
90
  /**
@@ -93,42 +97,45 @@ function replace(element, html) {
93
97
  if (arguments.length == 2) {
94
98
  element = select(element);
95
99
  } else {
96
- return;
100
+ return null;
97
101
  }
98
- if (html.trim) {
99
- html = create(html);
100
- }
101
- if (element.parentElement) {
102
- if (Array.isArray(html)) {
103
- let item;
104
- for (let i = 0; i < html.length; i++) {
105
- item = html[i];
102
+ if (element) {
103
+ if (html.trim) {
104
+ html = create(html);
105
+ }
106
+ if (element.parentElement) {
107
+ if (Array.isArray(html)) {
108
+ let item;
109
+ for (let i = 0; i < html.length; i++) {
110
+ item = html[i];
111
+ if (element.className) {
112
+ item.className += " " + element.className;
113
+ }
114
+ if (element.style.cssText) {
115
+ item.style.cssText += element.style.cssText;
116
+ }
117
+ }
118
+ element.replaceWith(html);
119
+ } else {
106
120
  if (element.className) {
107
- item.className += element.className;
121
+ html.className += " " + element.className;
108
122
  }
109
123
  if (element.style.cssText) {
110
- item.style.cssText += element.style.cssText;
124
+ html.style.cssText += element.style.cssText;
111
125
  }
126
+ element.parentElement.replaceChild(html, element);
112
127
  }
113
- element.replaceWith(html);
114
- } else {
115
- if (element.className) {
116
- html.className += element.className;
117
- }
118
- if (element.style.cssText) {
119
- html.style.cssText += element.style.cssText;
120
- }
121
- element.parentElement.replaceChild(html, element);
122
128
  }
129
+ return html;
123
130
  }
124
- return html;
131
+ return null;
125
132
  }
126
133
 
127
134
  /**
128
135
  * 在指定范围内/整个文档查找
129
136
  * @param {Element} element 标签元素
130
137
  * @param {String} selector 筛选字符
131
- * @return {Element} 匹配的单个/多个标签元素
138
+ * @return {Element} 匹配的单个标签元素
132
139
  */
133
140
  function select(element, selector) {
134
141
  if (arguments.length == 1) {
@@ -190,6 +197,65 @@ function select(element, selector) {
190
197
  }
191
198
  }
192
199
 
200
+ /**
201
+ * 在指定范围内/整个文档查找
202
+ * @param {Element} element 标签元素
203
+ * @param {String} selector 筛选字符
204
+ * @return {[Element]} 匹配的多个标签元素
205
+ */
206
+ function selects(element, selector) {
207
+ if (arguments.length == 1) {
208
+ // 仅指定1个参数
209
+ // selects(element/selector);
210
+ if (element.trim) {
211
+ // 仅提供字符串参数
212
+ element = document.querySelectorAll(element);
213
+ if (element.length == 0) {
214
+ return null;
215
+ }
216
+ return Array.from(element);
217
+ } else
218
+ if (element.nodeType) {
219
+ // 仅提供元素参数
220
+ return [element];
221
+ }
222
+ } else
223
+ if (arguments.length == 2) {
224
+ // 指定了2个参数
225
+ // select(element, selector);
226
+ if (element.trim) {
227
+ element = document.querySelectorAll(element);
228
+ if (element.length == 0) {
229
+ return null;
230
+ }
231
+ } else
232
+ if (element.nodeType) {
233
+ element = element.querySelectorAll(selector);
234
+ if (element.length == 0) {
235
+ return null;
236
+ }
237
+ return Array.from(element);
238
+ } else
239
+ if (Array.isArray(element)) {
240
+ if (element.length == 0) {
241
+ return null;
242
+ }
243
+ // element[]
244
+ let nodes, items = new Array();
245
+ for (let i = 0; i < element.length; i++) {
246
+ nodes = element[i].querySelectorAll(selector);
247
+ for (let n = 0; n < nodes.length; n++) {
248
+ items.push(nodes[n]);
249
+ }
250
+ }
251
+ if (items.length == 0) {
252
+ return null;
253
+ }
254
+ return items;
255
+ }
256
+ }
257
+ }
258
+
193
259
  /**
194
260
  * 从文档移除
195
261
  * @param {Element} element 标签元素
@@ -234,16 +300,22 @@ function hide(element, selector) {
234
300
  }
235
301
  if (element) {
236
302
  if (Array.isArray(element)) {
303
+ let e;
237
304
  for (let i = 0; i < element.length; i++) {
238
- element[i].hidden = true;
239
- element[i].__DISPLAY = element[i].style.display
240
- element[i].style.display = "none";
305
+ e = element[i];
306
+ if (e.hidden) {} else {
307
+ e.hidden = true;
308
+ e.__DISPLAY = e.style.display
309
+ e.style.display = "none";
310
+ }
241
311
  }
242
312
  } else {
243
- element.hidden = true;
244
- element.__DISPLAY = element.style.display
245
- // display:flex 导致 hidden 属性失效而不会隐藏
246
- element.style.display = "none";
313
+ if (element.hidden) {} else {
314
+ element.hidden = true;
315
+ element.__DISPLAY = element.style.display;
316
+ // display:flex 导致 hidden 属性失效而不会隐藏
317
+ element.style.display = "none";
318
+ }
247
319
  }
248
320
  }
249
321
  return element;
@@ -266,11 +338,16 @@ function show(element, selector) {
266
338
  }
267
339
  if (element) {
268
340
  if (Array.isArray(element)) {
341
+ let e;
269
342
  for (let i = 0; i < element.length; i++) {
270
- element[i].hidden = false;
271
- element[i].style.display = element[i].__DISPLAY;
343
+ e = element[i];
344
+ if (e.hidden) {
345
+ e.hidden = false;
346
+ e.style.display = e.__DISPLAY;
347
+ }
272
348
  }
273
- } else {
349
+ } else
350
+ if (element.hidden) {
274
351
  element.hidden = false;
275
352
  element.style.display = element.__DISPLAY;
276
353
  }
@@ -283,32 +360,41 @@ function show(element, selector) {
283
360
  * 如果指定样式类名,则当前原始添加样式类,其余元素移除样式类
284
361
  * @param {Element} element 标签元素
285
362
  * @param {String} selector 筛选字符
286
- * @param {String} className 类名称
363
+ * @param {String} applyClass 添加类名称,必须同时提供otherClass参数
364
+ * @param {String} otherClass 移除类名称,必须同时提供applyClass参数
287
365
  * @return {Element} 显示的单个/多个标签元素
288
366
  */
289
- function toggle(element, selector, className) {
367
+ function toggle(element, selector, applyClass, otherClass) {
290
368
  if (arguments.length == 1) {
291
- // toggle(element)
369
+ // toggle(element)
292
370
  element = select(element);
293
371
  } else
294
372
  if (arguments.length == 2) {
295
373
  // toggle(element,selector)
296
- // toggle(element,className)
297
374
  element = select(element, selector);
298
375
  } else
299
376
  if (arguments.length == 3) {
300
- // toggle(element,selector,className)
377
+ // toggle(element,applyClass,otherClass)
378
+ element = select(element);
379
+ otherClass = applyClass;
380
+ applyClass = selector;
381
+ } else
382
+ if (arguments.length == 4) {
383
+ // toggle(element,selector,applyClass,otherClass)
301
384
  element = select(element, selector);
302
385
  } else {
303
386
  return;
304
387
  }
305
388
  if (element) {
306
389
  const parent = element.parentElement;
307
- if (className) {
390
+ if (applyClass) {
308
391
  for (let i = 0; i < parent.children.length; i++) {
309
- parent.children[i].classList.remove(className);
310
392
  if (element == parent.children[i]) {
311
- parent.children[i].classList.add(className);
393
+ parent.children[i].classList.remove(otherClass);
394
+ parent.children[i].classList.add(applyClass);
395
+ } else {
396
+ parent.children[i].classList.remove(applyClass);
397
+ parent.children[i].classList.add(otherClass);
312
398
  }
313
399
  }
314
400
  } else {
@@ -337,6 +423,7 @@ function defaultConverter(element, parameter, name) {}
337
423
  function gets(element, selector, converter = defaultConverter) {
338
424
  if (arguments.length == 1) {
339
425
  // gets(element)
426
+ // gets(selector)
340
427
  element = select(element);
341
428
  } else
342
429
  if (arguments.length == 2) {
@@ -386,6 +473,7 @@ function gets(element, selector, converter = defaultConverter) {
386
473
  function sets(element, selector, parameter, converter = defaultConverter) {
387
474
  if (arguments.length == 2) {
388
475
  // sets(element,parameter)
476
+ // sets(selector,parameter)
389
477
  element = select(element);
390
478
  parameter = selector;
391
479
  } else
@@ -409,71 +497,71 @@ function sets(element, selector, parameter, converter = defaultConverter) {
409
497
  if (element) {
410
498
  if (parameter) {
411
499
  if (Array.isArray(parameter)) {
500
+ // Object[] -> Element.children
412
501
  let i = 0;
413
502
  // 利用ENO_SET记录并判定是否首次
414
- if (element.ENO_SETS) {
415
- element.ENO_SETS = element.ENO_SETS + 1;
416
- } else {
417
- element.ENO_SETS = 1;
418
- // ...<template>...
419
- for (; i < element.children.length; i++) {
420
- // 只有<template>模板具有content属性
503
+ if (element.__ENO_SETS) {} else {
504
+ element.__ENO_SETS = {};
505
+ // before...<template>...after
506
+ // 只有<template>模板具有content属性
507
+ // 记录模板前后已有标签元素数量
508
+ // before数量包括模板本身
509
+ for (; i < element.childElementCount; i++) {
421
510
  if (element.children[i].content) {
422
- element.template = element.children[i];
423
- element.a = ++i;
424
- element.b = element.children.length - i;
511
+ element.__ENO_SETS.template = element.children[i];
512
+ element.__ENO_SETS.before = ++i;
513
+ element.__ENO_SETS.after = element.childElementCount - i;
425
514
  break;
426
515
  }
427
516
  }
428
517
  }
429
518
 
430
- if (element.template) {
519
+ if (element.__ENO_SETS.template) {
431
520
  // 已定义模板
432
- if (parameter.length) { // [a,b]
521
+ if (parameter.length) {
433
522
  let node, n;
434
523
  // 构造填充元素
435
524
  for (i = 0; i < parameter.length; i++) {
436
- if (element.a + i < element.children.length - element.b) {
525
+ if (element.__ENO_SETS.before + i < element.childElementCount - element.__ENO_SETS.after) {
437
526
  // 重用已有元素
438
- for (n = 0; n < element.template.content.childElementCount; n++) {
439
- node = element.children[element.a + i + n];
440
- node.userData = parameter[i];
527
+ for (n = 0; n < element.__ENO_SETS.template.content.childElementCount; n++) {
528
+ node = element.children[element.__ENO_SETS.before + i + n];
441
529
  set(node, parameter[i], converter);
442
- node.hidden = false;
530
+ node.userData = parameter[i];
443
531
  }
444
532
  } else {
445
533
  // 克隆新的元素(DocumentFragment)
446
- node = element.template.content.cloneNode(true);
534
+ // node = element.template.content.cloneNode(true);
535
+ node = document.importNode(element.__ENO_SETS.template.content, true);
447
536
  for (n = 0; n < node.childElementCount; n++) {
448
- node.children.item(n).userData = parameter[i];
449
537
  set(node.children.item(n), parameter[i], converter);
450
- node.children.item(n).hidden = false;
538
+ node.children.item(n).userData = parameter[i];
451
539
  }
452
- element.insertBefore(node, element.children[element.a + i * node.childElementCount]);
540
+ element.insertBefore(node, element.children[element.__ENO_SETS.before + i * node.childElementCount]);
453
541
  }
454
542
  }
455
543
  // 移除多余元素
456
- n = i * element.template.content.childElementCount;
457
- i = element.a + element.b;
458
- while (element.children.length > i + n) {
459
- element.children[element.a + n].remove();
544
+ n = i * element.__ENO_SETS.template.content.childElementCount;
545
+ i = element.__ENO_SETS.before + element.__ENO_SETS.after;
546
+ while (element.childElementCount > i + n) {
547
+ element.children[element.__ENO_SETS.before + n].remove();
460
548
  }
461
549
  return element;
462
- } else { // []
550
+ } else {
463
551
  // 移除多余元素
464
- i = element.a + element.b;
465
- while (element.length > i) {
466
- element[element.a + 1].remove();
552
+ i = element.__ENO_SETS.before + element.__ENO_SETS.after;
553
+ while (element.childElementCount > i) {
554
+ element.children[element.childElementCount - element.__ENO_SETS.after - 1].remove();
467
555
  }
468
556
  return element;
469
557
  }
470
558
  } else {
471
559
  // 未使用模板
472
- if (parameter.length) { // [a,b]
560
+ if (parameter.length) {
473
561
  let node;
474
562
  // 构造填充元素
475
563
  for (i = 0; i < parameter.length; i++) {
476
- if (i < element.children.length) {
564
+ if (i < element.childElementCount) {
477
565
  // 重用已有元素
478
566
  node = element.children[i];
479
567
  } else if (node) {
@@ -481,59 +569,68 @@ function sets(element, selector, parameter, converter = defaultConverter) {
481
569
  node = element.appendChild(node.cloneNode(true));
482
570
  } else {
483
571
  // 干不了
572
+ // 此情形出现于没有任何子标签元素
484
573
  continue;
485
574
  }
486
- node.userData = parameter[i];
487
575
  set(node, parameter[i], converter);
576
+ node.userData = parameter[i];
488
577
  node.hidden = false;
489
578
  }
490
579
  // 移除多余元素
491
- while (element.children.length > i) {
580
+ while (element.childElementCount > i) {
492
581
  element.children[i].remove();
493
582
  }
494
583
  return element;
495
- } else { // []
496
- if (element.children.length) {
497
- // 保留模板
498
- element.children[0].hidden = true;
499
- // 移除多余元素
500
- while (element.children.length > 1) {
501
- element.children[1].remove();
502
- }
584
+ } else {
585
+ // 移除多余元素,保留模板
586
+ element.children[0].userData = null;
587
+ element.children[0].hidden = true;
588
+ while (element.childElementCount > 1) {
589
+ element.children[1].remove();
503
590
  }
504
591
  return element;
505
592
  }
506
593
  }
507
- } else { // Object
508
- if (element.nodeType) {
509
- element.userData = parameter;
510
- set(element, parameter, converter);
511
- return element;
512
- }
513
- if (element.length) {
514
- for (let node, i = 0; i < element.length; i++) {
515
- node = element[i];
516
- node.userData = parameter;
517
- set(node, parameter, converter);
594
+ } else {
595
+ // Object -> Element
596
+ if (Array.isArray(element)) {
597
+ for (let i = 0; i < element.length; i++) {
598
+ set(element[i], parameter, converter);
599
+ element[i].userData = parameter;
518
600
  }
519
- return element;
601
+ } else {
602
+ set(element, parameter, converter);
603
+ element.userData = parameter;
520
604
  }
521
- }
522
- } else { // null / undefine
523
- if (element.nodeType) {
524
- element.userData = null;
525
- set(element, null, converter);
526
605
  return element;
527
606
  }
528
- if (element.length) {
529
- // 保留模板
530
- element[0].hidden = true;
531
- // 移除多余元素
532
- while (element.length > 1) {
533
- element[1].remove();
607
+ } else {
608
+ // null / undefine -> Element
609
+ if (element.__ENO_SETS) {
610
+ if (element.__ENO_SETS.template) {
611
+ const i = element.__ENO_SETS.before + element.__ENO_SETS.after;
612
+ while (element.childElementCount > i) {
613
+ element.children[element.childElementCount - element.__ENO_SETS.after - 1].remove();
614
+ }
615
+ } else {
616
+ element.children[0].userData = null;
617
+ element.children[0].hidden = true;
618
+ while (element.childElementCount > 1) {
619
+ element.children[1].remove();
620
+ }
621
+ }
622
+ } else {
623
+ if (Array.isArray(element)) {
624
+ for (let i = 0; i < element.length; i++) {
625
+ set(element[i], null, converter);
626
+ element[i].userData = null;
627
+ }
628
+ } else {
629
+ set(element, null, converter);
630
+ element.userData = null;
534
631
  }
535
- return element;
536
632
  }
633
+ return element;
537
634
  }
538
635
  }
539
636
  }
@@ -582,7 +679,7 @@ function set(element, parameter, converter) {
582
679
  }
583
680
  name = element.getAttribute("name");
584
681
  if (name && name.length) {
585
- if (element.form) {
682
+ if (element.type) {
586
683
  element.value = text(vale(parameter, name));
587
684
  } else
588
685
  if (element.src) {
@@ -733,29 +830,6 @@ function entity(e, selector) {
733
830
  return null;
734
831
  }
735
832
 
736
- /**
737
- * 根据事件或元素获取属性指定的动作
738
- * @param {Event} e
739
- * @param {String} a
740
- */
741
- function action(e, a) {
742
- if (e.target) {
743
- e = e.target;
744
- } else
745
- if (e.srcElement) {
746
- e = e.srcElement;
747
- }
748
-
749
- while (e) {
750
- if (e.hasAttribute(a)) {
751
- return true;
752
- } else {
753
- e = e.parentElement;
754
- }
755
- }
756
- return false;
757
- }
758
-
759
833
  /**
760
834
  * 根据事件获取绑定实体的元素
761
835
  * @param {Event} e
@@ -785,16 +859,30 @@ function element(e) {
785
859
  * @return {String} 参数值
786
860
  */
787
861
  function query(url, name) {
788
- if (arguments.length == 1) {
789
- // getQueryString(name)
790
- name = url;
862
+ if (arguments.length == 0) {
863
+ // query()
791
864
  // window.location.search 返回从问号?开始的URL查询部分
792
- // ?name1=value1&name2=value2
793
865
  url = window.location.search;
794
- }
866
+ } else
867
+ if (arguments.length == 1) {
868
+ // query(url)
869
+ // query(name)
870
+ if (url.startsWith("http://") || url.startsWith("https://")) {
871
+ let index = url.indexOf("?");
872
+ if (index > 0) {
873
+ url = url.substring(index);
874
+ } else {
875
+ return null;
876
+ }
877
+ } else {
878
+ name = url;
879
+ // window.location.search 返回从问号?开始的URL查询部分
880
+ url = window.location.search;
881
+ }
882
+ } else
795
883
  if (arguments.length == 2) {
796
- // getQueryString(url, name)
797
- let index = url.indexof("?");
884
+ // query(url, name)
885
+ let index = url.indexOf("?");
798
886
  if (index > 0) {
799
887
  url = url.substring(index);
800
888
  } else {
@@ -803,18 +891,68 @@ function query(url, name) {
803
891
  }
804
892
 
805
893
  if (url) {
806
- let start = url.indexOf(name);
807
- if (start >= 0) {
808
- start += name.length;
809
- if (url.charAt(start) == '=') {
810
- start++;
811
- let end = url.indexOf('&', start);
812
- if (end >= 0) {
813
- return url.substring(start, end);
894
+ if (name) {
895
+ let start = url.indexOf(name);
896
+ if (start >= 0) {
897
+ start += name.length;
898
+ if (url.charAt(start) == '=') {
899
+ start++;
900
+ let end = url.indexOf('&', start);
901
+ if (end >= 0) {
902
+ return url.substring(start, end);
903
+ }
904
+ return url.substring(start);
905
+ }
906
+ }
907
+ } else {
908
+ // ?name1=value1&name2=value2
909
+ let start = 1;
910
+ let index = 1;
911
+ let name, parameter = {};
912
+ while (index >= 0 && index < url.length) {
913
+ start = url.indexOf("=", index);
914
+ if (start >= 0) {
915
+ name = url.substring(start, index);
916
+ start = ++index;
917
+
918
+ index = url.indexOf("&", index);
919
+ if (index >= 0) {
920
+ parameter[name] = url.substring(start, index);
921
+ start = ++index;
922
+ } else {
923
+ parameter[name] = url.substring(start);
924
+ break;
925
+ }
926
+ } else {
927
+ break;
814
928
  }
815
- return url.substring(start);
816
929
  }
930
+ return parameter;
817
931
  }
818
932
  }
819
933
  return null;
934
+ }
935
+
936
+ /**
937
+ * 根据事件或元素获取属性指定的动作
938
+ * @param {Event} e
939
+ * @param {String} a
940
+ * @deprecated 1.1.3
941
+ */
942
+ function action(e, a) {
943
+ if (e.target) {
944
+ e = e.target;
945
+ } else
946
+ if (e.srcElement) {
947
+ e = e.srcElement;
948
+ }
949
+
950
+ while (e) {
951
+ if (e.hasAttribute(a)) {
952
+ return true;
953
+ } else {
954
+ e = e.parentElement;
955
+ }
956
+ }
957
+ return false;
820
958
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joyzl/eno",
3
- "version": "1.1.2",
3
+ "version": "1.1.5",
4
4
  "description": "Easy Node Object",
5
5
  "main": "index.js",
6
6
  "scripts": {