forked from dojo/dijit-oldmirror
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path_AttachMixin.js
194 lines (169 loc) · 6.67 KB
/
_AttachMixin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
define([
"require",
"dojo/_base/array", // array.forEach
"dojo/_base/declare", // declare
"dojo/_base/lang", // lang.getObject
"dojo/mouse",
"dojo/on",
"dojo/touch",
"./_WidgetBase"
], function(require, array, declare, lang, mouse, on, touch, _WidgetBase){
// module:
// dijit/_AttachMixin
// Map from string name like "mouseenter" to synthetic event like mouse.enter
var synthEvents = lang.delegate(touch, {
"mouseenter": mouse.enter,
"mouseleave": mouse.leave
});
// To be lightweight, _AttachMixin doesn't require() dijit/a11yclick.
// If the subclass has a template using "ondijitclick", it must load dijit/a11yclick itself.
// In that case, the a11yclick variable below will get set to point to that synthetic event.
var a11yclick;
var _AttachMixin = declare("dijit._AttachMixin", null, {
// summary:
// Mixin for widgets to attach to dom nodes and setup events via
// convenient data-dojo-attach-point and data-dojo-attach-event DOM attributes.
//
// Superclass of _TemplatedMixin, and can also be used standalone when templates are pre-rendered on the
// server.
//
// Does not [yet] handle widgets like ContentPane with this.containerNode set. It should skip
// scanning for data-dojo-attach-point and data-dojo-attach-event inside this.containerNode, but it
// doesn't.
/*=====
// _attachPoints: [private] String[]
// List of widget attribute names associated with data-dojo-attach-point=... in the
// template, ex: ["containerNode", "labelNode"]
_attachPoints: [],
// _attachEvents: [private] Handle[]
// List of connections associated with data-dojo-attach-event=... in the
// template
_attachEvents: [],
// attachScope: [public] Object
// Object to which attach points and events will be scoped. Defaults
// to 'this'.
attachScope: undefined,
=====*/
constructor: function(/*===== params, srcNodeRef =====*/){
// summary:
// Create the widget.
// params: Object|null
// Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
// and functions, typically callbacks like onClick.
// The hash can contain any of the widget's properties, excluding read-only properties.
// srcNodeRef: DOMNode|String?
// If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree.
this._attachPoints = [];
this._attachEvents = [];
},
buildRendering: function(){
// summary:
// Attach to DOM nodes marked with special attributes.
// tags:
// protected
this.inherited(arguments);
// recurse through the node, looking for, and attaching to, our
// attachment points and events, which should be defined on the template node.
this._attachTemplateNodes(this.domNode, function(n,p){ return n.getAttribute(p); });
this._beforeFillContent(); // hook for _WidgetsInTemplateMixin
},
_beforeFillContent: function(){
},
_attachTemplateNodes: function(rootNode, getAttrFunc){
// summary:
// Iterate through the dom nodes and attach functions and nodes accordingly.
// Alternately, if rootNode is an array of widgets, then will process data-dojo-attach-point
// etc. for those widgets.
// description:
// Map widget properties and functions to the handlers specified in
// the dom node and it's descendants. This function iterates over all
// nodes and looks for these properties:
//
// - dojoAttachPoint/data-dojo-attach-point
// - dojoAttachEvent/data-dojo-attach-event
// rootNode: DomNode|Widget[]
// the node to search for properties. All children will be searched.
// getAttrFunc: Function
// a function which will be used to obtain property for a given
// DomNode/Widget
// tags:
// private
var nodes = lang.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*")),
_attachScope = this.attachScope || this;
var x = lang.isArray(rootNode) ? 0 : -1;
for(; x < 0 || nodes[x]; x++){ // don't access nodes.length on IE, see #14346
var baseNode = (x == -1) ? rootNode : nodes[x];
if(this.widgetsInTemplate && (getAttrFunc(baseNode, "dojoType") || getAttrFunc(baseNode, "data-dojo-type"))){
continue;
}
// Process data-dojo-attach-point
var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint") || getAttrFunc(baseNode, "data-dojo-attach-point");
if(attachPoint){
var point, points = attachPoint.split(/\s*,\s*/);
while((point = points.shift())){
if(lang.isArray(_attachScope[point])){
_attachScope[point].push(baseNode);
}else{
_attachScope[point]=baseNode;
}
this._attachPoints.push(point);
}
}
// Process data-dojo-attach-event
var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent") || getAttrFunc(baseNode, "data-dojo-attach-event");
if(attachEvent){
// NOTE: we want to support attributes that have the form
// "domEvent: nativeEvent; ..."
var event, events = attachEvent.split(/\s*,\s*/);
var trim = lang.trim;
while((event = events.shift())){
if(event){
var thisFunc = null;
if(event.indexOf(":") != -1){
// oh, if only JS had tuple assignment
var funcNameArr = event.split(":");
event = trim(funcNameArr[0]);
thisFunc = trim(funcNameArr[1]);
}else{
event = trim(event);
}
if(!thisFunc){
thisFunc = event;
}
// Map special type names like "mouseenter" to synthetic events.
// Subclasses are responsible to require() dijit/a11yclick if they want to use it.
event = event.replace(/^on/, "").toLowerCase();
if(event == "dijitclick"){
event = a11yclick || (a11yclick = require("./a11yclick"));
}else{
event = synthEvents[event] || event;
}
this._attachEvents.push(this.own(on(baseNode, event, lang.hitch(_attachScope, thisFunc)))[0]);
}
}
}
}
},
destroyRendering: function(){
// Delete all attach points to prevent IE6 memory leaks.
var _attachScope = this.attachScope || this;
array.forEach(this._attachPoints, function(point){
delete _attachScope[point];
});
this._attachPoints = [];
// And same for event handlers
array.forEach(this._attachEvents, this.disconnect, this);
this._attachEvents = [];
this.inherited(arguments);
}
});
// These arguments can be specified for widgets which are used in templates.
// Since any widget can be specified as sub widgets in template, mix it
// into the base widget class. (This is a hack, but it's effective.).
// Remove for 2.0. Also, hide from API doc parser.
lang.extend(_WidgetBase, /*===== {} || =====*/ {
dojoAttachEvent: "",
dojoAttachPoint: ""
});
return _AttachMixin;
});