1+ /*
2+ * @Date : 2020-04-29 10:13:23
3+ * @LastEditors : MemoryShadow
4+ * @LastEditTime : 2021-01-06 20:13:22
5+ * @Effect : 内置类ControlNode,用于控制节点,并包含一些内置的控件,可以快速创建
6+ */
7+
8+ /**
9+ * 节点控制器
10+ */
11+
12+ function ControlNode ( MainNodeID ) {
13+
14+ /**
15+ * 储存对象名称"ID"
16+ */
17+ this . Name ;
18+
19+ /**
20+ * 储存主节点
21+ */
22+ this . MainNodeObject ;
23+
24+ /**
25+ * RegisteredNode自动维护的输入框对象表,用于追踪目标对象
26+ */
27+ this . Node_Data_List = [ ] ;
28+
29+ /**
30+ * 此对象在公共队列中的位置
31+ */
32+ this . thisObjectIndex ;
33+
34+ /**
35+ * 构造器
36+ * @param {string } MainNodeID 指定要作为主节点的ID
37+ */
38+ this . constructor = function ( MainNodeID ) {
39+ this . MainNodeObject = document . getElementById ( MainNodeID ) ;
40+ // 储存自己的名字(ID)
41+ this . Name = MainNodeID ;
42+ // 在添加前储存索引
43+ this . thisObjectIndex = ControlNode . ObjectList . length ;
44+ ControlNode . ObjectList . push ( this ) ;
45+ }
46+
47+ /**
48+ * 向此对象主节点注册指定的节点,使其被应用到页面中
49+ * @param {HTMLElement } NodeObj 节点对象
50+ * @return {void }
51+ */
52+ this . RegisteredNode = function ( NodeObj ) {
53+ var NodeObject = this . MainNodeObject . appendChild ( NodeObj ) ;
54+ this . Node_Data_List . push ( NodeObject ) ;
55+ }
56+
57+ /**
58+ * 获取当前控制节点子节点长度
59+ */
60+ this . length = function ( ) {
61+ return this . Node_Data_List . length ;
62+ }
63+
64+ /**
65+ * 清空所有子节点
66+ */
67+ this . remove = function ( ) {
68+ this . MainNodeObject . remove ( ) ;
69+ }
70+
71+ /**
72+ * 用于索引自动管理的控件
73+ * @param {int } Key 要删除的键
74+ * @return {HTMLElement } 被删除的节点控件
75+ */
76+ this . removeChild = function ( Key ) {
77+ // 判断是数字还是字符串
78+ switch ( typeof Key ) {
79+ case 'number' :
80+ var Del_Node = this . MainNodeObject . removeChild ( this . Node_Data_List [ Key ] ) ;
81+ this . Node_Data_List . splice ( Key , 1 ) ;
82+ return Del_Node ;
83+ case 'string' :
84+ for ( var index = 0 ; index < this . length ( ) ; index ++ ) {
85+ var Node = this . indexOf ( index ) ;
86+ if ( Node . id == Key ) {
87+ var Del_Node = this . MainNodeObject . removeChild ( this . Node_Data_List [ index ] ) ;
88+ this . Node_Data_List . splice ( index , 1 ) ;
89+ return Del_Node ;
90+ }
91+ }
92+ return undefined
93+
94+ default :
95+ return undefined ;
96+ }
97+ }
98+
99+ /**
100+ * 用于索引自动管理的控件
101+ * @param {int } Key 要索引的键
102+ * @return {HTMLElement } 被索引的节点控件
103+ */
104+ this . indexOf = function ( Key ) {
105+ // 判断是数字还是字符串
106+ switch ( typeof Key ) {
107+ case 'number' :
108+ return this . Node_Data_List [ Key ] ;
109+ case 'string' :
110+ for ( var index = 0 ; index < this . length ( ) ; index ++ ) {
111+ var Node = this . Node_Data_List [ index ] ;
112+ if ( Node . id == Key ) {
113+ return Node ;
114+ }
115+ }
116+ return undefined
117+
118+ default :
119+ return undefined ;
120+ }
121+ }
122+
123+ // 初始化
124+ this . constructor ( MainNodeID ) ;
125+ }
126+
127+ /**
128+ * 新增指定类型的节点对象,在注册后将会被应用到页面中
129+ * @param {JSON } NodeDescription 节点描述,以下为特殊的属性(区分大小写)
130+ * [Tag: 标签,Text: 文本内容,Child: 子节点的描述,Checked: 如果是按钮,是否处于选中状态]
131+ * 其他都会被设置到属性上
132+ * @return {HTMLElement } 节点控制对象
133+ */
134+ ControlNode . NewNode = function ( NodeDescription ) {
135+ // 创建当前节点描述
136+ var node = ControlNode . getNode ( NodeDescription . Tag ) ;
137+
138+ // 遍历属性,将其添加到属性中
139+ Object . keys ( NodeDescription ) . forEach ( Attributes_Name => {
140+ // 除非这个属性名在这个列表中
141+ switch ( Attributes_Name ) {
142+ case "Tag" :
143+ case "Child" :
144+ // 这部分是要跳过的属性类型,此部分的内容将在其他位置处理
145+ break ;
146+ case "Text" :
147+ // 处理文本(简称)
148+ node . innerText = NodeDescription [ Attributes_Name ] ;
149+ break ;
150+ case "Checked" :
151+ // 处理选项信息,在这里额外处理
152+ node . checked = NodeDescription [ Attributes_Name ] ;
153+ break ;
154+
155+ default :
156+ var AttributesObject = document . createAttribute ( Attributes_Name ) ;
157+ AttributesObject . value = NodeDescription [ Attributes_Name ] ;
158+ node . setAttributeNode ( AttributesObject ) ;
159+ break ;
160+ }
161+ } ) ;
162+
163+ // 检查是否有下级节点
164+ if ( NodeDescription . Child != undefined ) {
165+ // 如果有,就遍历此节点并添加至自身
166+ NodeDescription . Child . forEach ( Child => {
167+ var Child_node = ControlNode . NewNode ( Child ) ;
168+ // 将子节点添加至自身
169+ node . appendChild ( Child_node ) ;
170+ } ) ;
171+ }
172+
173+ return node ;
174+ }
175+
176+ /**
177+ * 获取一个新的节点对象
178+ * @param {string } NodeType 节点类型
179+ * @return {HTMLElement } 指定的节点类型对象
180+ */
181+ ControlNode . getNode = function ( NodeType ) {
182+ return document . createElement ( NodeType ) ;
183+ }
184+
185+ /**
186+ * 获取一个指定样式的输入框
187+ * @param {String } NodeDataType 节点数据类型,以下是支持的值
188+ * [boolean/switch,Integer,Range,String]
189+ * 当此参数为Range时,必须提供Candidate参数
190+ * @param {* } Value 默认值
191+ * @param {Array } Candidate 待选列表
192+ * @param {boolean } isDisable 是否禁用此输入框的操作(暂未开放)
193+ * @return {JSON } 此输入控件的描述JSON对象
194+ */
195+ ControlNode . getInputNode = function ( NodeDataType , Value , Candidate , isDisable ) {
196+ switch ( NodeDataType ) {
197+ case 'boolean' :
198+ case 'switch' :
199+ return JSON . parse ( JSON . stringify ( {
200+ "Tag" : "input" ,
201+ "type" : "checkbox" ,
202+ "Class" : "switch" ,
203+ "Checked" : Value ,
204+ "InputType" : "Switch"
205+ } ) ) ;
206+ case 'Integer' :
207+ return JSON . parse ( JSON . stringify ( {
208+ "Tag" : "input" ,
209+ "type" : "number" ,
210+ "placeholder" : parseInt ( Value ) ,
211+ "value" : parseInt ( Value ) ,
212+ "InputType" : "Integer"
213+ } ) ) ;
214+ case 'Range' :
215+ return JSON . parse ( JSON . stringify ( {
216+ "Tag" : "div" ,
217+ "InputType" : "Range" ,
218+ "Child" : [
219+ {
220+ "Tag" : "span" ,
221+ "Text" : Value
222+ } ,
223+ {
224+ "Tag" : "input" ,
225+ "type" : "range" ,
226+ "onchange" : "" ,
227+ "value" : parseInt ( Value ) ,
228+ "min" : parseInt ( Candidate [ 0 ] . Value . split ( '..' ) [ 0 ] ) ,
229+ "max" : parseInt ( Candidate [ 0 ] . Value . split ( '..' ) [ 1 ] )
230+ }
231+ ]
232+ } ) ) ;
233+
234+
235+ case 'String' :
236+ return JSON . parse ( JSON . stringify ( {
237+ "Tag" : "input" ,
238+ "placeholder" : Value ,
239+ "value" : Value ,
240+ "InputType" : "String" ,
241+ } ) ) ;
242+
243+ default :
244+ return JSON . parse ( JSON . stringify ( {
245+ "Tag" : "input"
246+ } ) ) ;
247+ }
248+ }
249+
250+ /**
251+ * 获取一个指定样式的输入框
252+ * @param {String } NodeDataType 节点数据类型,以下是支持的值
253+ * [default: 默认形式, link: 链接形式]
254+ * @param {String } Value 按钮的显示内容
255+ * @param {function,String } onClick 点击后产生的效果,随着NodeDataType改变
256+ * [default: {function} 一个回调函数,link: {String} 一个链接地址]
257+ * @param {boolean } isDisable 是否禁用此按钮的操作
258+ * @return {JSON } 此输入控件的描述JSON对象
259+ */
260+ ControlNode . getButtonNode = function ( NodeDataType , Value , onClick , isDisable ) {
261+ switch ( NodeDataType ) {
262+ case 'link' :
263+ return JSON . parse ( JSON . stringify ( {
264+ "Tag" : "a" ,
265+ "Class" : isDisable ? "button disable" : "button enable" ,
266+ "Href" : onClick ,
267+ "Text" : Value
268+ } ) ) ;
269+
270+ default :
271+ return JSON . parse ( JSON . stringify ( {
272+ "Tag" : "button" ,
273+ "Disabled" : isDisable ? "disable" : "" ,
274+ "OnClick" : onClick ,
275+ "Text" : Value
276+ } ) ) ;
277+ }
278+ }
279+
280+ /**
281+ * 索引
282+ * @param {int,String } Key 要用于索引的Key
283+ * @return {ControlNode } 指定的控制对象
284+ */
285+ ControlNode . indexOf = function ( Key ) {
286+ // 判断是数字还是字符串
287+ switch ( typeof Key ) {
288+ case 'number' :
289+ return ControlNode . ObjectList [ Key ] ;
290+ case 'string' :
291+ for ( var index = 0 ; index < ControlNode . ObjectList . length ; index ++ ) {
292+ var controlNode = ControlNode . ObjectList [ index ] ;
293+ if ( controlNode . Name == Key ) {
294+ return controlNode ;
295+ }
296+ }
297+ return undefined
298+
299+ default :
300+ return undefined ;
301+ }
302+ }
303+
304+ /**
305+ * 获取指定节点的控制对象
306+ * @param {string } MainNodeID 指定要作为主节点的ID
307+ * @return {ControlNode } 指定的控制对象
308+ */
309+ ControlNode . valueOf = function ( MainNodeID ) {
310+ // 检查是否存在重复的对象,如果有,就直接返回,没有的情况下才创建新对象
311+ if ( ControlNode . indexOf ( MainNodeID ) == undefined ) {
312+ // 如果没有,就New新的值
313+ return new ControlNode ( MainNodeID ) ;
314+ } else {
315+ // 如果不为空,就返回指定的内容
316+ return ControlNode . indexOf ( MainNodeID ) ;
317+ }
318+ }
319+
320+ /**
321+ * 将指定ID的控制节点转为一个JSON格式的节点描述
322+ * @param {String,Object } NodeID
323+ * @return {JSON_Object } JSON字符串
324+ */
325+ ControlNode . HTMLElement2JSON_NodeDescription = function ( NodeID ) {
326+ // 创建描述
327+ var NodeDescription = Object ( ) ;
328+ // 取得对象
329+ switch ( typeof NodeID ) {
330+ case 'string' :
331+ var NodeObj = document . getElementById ( NodeID ) ;
332+ break ;
333+ case 'object' :
334+ var NodeObj = NodeID ;
335+ break ;
336+ default :
337+ var NodeObj = NodeID ;
338+ break ;
339+ }
340+ // 解析当前节点配置
341+ for ( var Node_index = 0 ; Node_index < NodeObj . attributes . length ; Node_index ++ ) {
342+ var attributeName = NodeObj . attributes [ Node_index ] . name ;
343+ NodeDescription [ attributeName ] = NodeObj . getAttribute ( attributeName ) ;
344+ }
345+ // 解析特殊内容
346+ NodeDescription [ 'Tag' ] = NodeObj . tagName ;
347+ // 检查是否有子节点
348+ if ( NodeObj . childNodes . length > 0 ) {
349+ for ( var Child_index = 0 ; Child_index < NodeObj . childNodes . length ; Child_index ++ ) {
350+ var Child = NodeObj . childNodes [ Child_index ] ;
351+ // 如果无法查到子节点的标签,就说明是文本类型,存入Text中
352+ if ( Child . tagName == undefined ) {
353+ NodeDescription [ "Text" ] = Child . data ;
354+ } else {
355+ if ( NodeDescription . Child == undefined )
356+ NodeDescription . Child = [ ] ;
357+ NodeDescription . Child . push ( ControlNode . HTMLElement2JSON_NodeDescription ( Child ) ) ;
358+ }
359+ }
360+ }
361+ return NodeDescription ;
362+ }
363+
364+ /**
365+ * ControlNodeObject自动维护的输入框对象表,用于追踪操作对象
366+ */
367+ ControlNode . ObjectList = [ ] ;
0 commit comments