1 |
efrain |
1 |
YUI.add('attribute-observable', function (Y, NAME) {
|
|
|
2 |
|
|
|
3 |
/*For log lines*/
|
|
|
4 |
/*jshint maxlen:200*/
|
|
|
5 |
|
|
|
6 |
|
|
|
7 |
/**
|
|
|
8 |
* The attribute module provides an augmentable Attribute implementation, which
|
|
|
9 |
* adds configurable attributes and attribute change events to the class being
|
|
|
10 |
* augmented. It also provides a State class, which is used internally by Attribute,
|
|
|
11 |
* but can also be used independently to provide a name/property/value data structure to
|
|
|
12 |
* store state.
|
|
|
13 |
*
|
|
|
14 |
* @module attribute
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/**
|
|
|
18 |
* The `attribute-observable` submodule provides augmentable attribute change event support
|
|
|
19 |
* for AttributeCore based implementations.
|
|
|
20 |
*
|
|
|
21 |
* @module attribute
|
|
|
22 |
* @submodule attribute-observable
|
|
|
23 |
*/
|
|
|
24 |
var EventTarget = Y.EventTarget,
|
|
|
25 |
|
|
|
26 |
CHANGE = "Change",
|
|
|
27 |
BROADCAST = "broadcast";
|
|
|
28 |
|
|
|
29 |
/**
|
|
|
30 |
* Provides an augmentable implementation of attribute change events for
|
|
|
31 |
* AttributeCore.
|
|
|
32 |
*
|
|
|
33 |
* @class AttributeObservable
|
|
|
34 |
* @extensionfor AttributeCore
|
|
|
35 |
* @uses EventTarget
|
|
|
36 |
*/
|
|
|
37 |
function AttributeObservable() {
|
|
|
38 |
// Perf tweak - avoid creating event literals if not required.
|
|
|
39 |
this._ATTR_E_FACADE = {};
|
|
|
40 |
|
|
|
41 |
EventTarget.call(this, {emitFacade:true});
|
|
|
42 |
}
|
|
|
43 |
|
|
|
44 |
AttributeObservable._ATTR_CFG = [BROADCAST];
|
|
|
45 |
|
|
|
46 |
AttributeObservable.prototype = {
|
|
|
47 |
|
|
|
48 |
/**
|
|
|
49 |
* Sets the value of an attribute.
|
|
|
50 |
*
|
|
|
51 |
* @method set
|
|
|
52 |
* @chainable
|
|
|
53 |
*
|
|
|
54 |
* @param {String} name The name of the attribute. If the
|
|
|
55 |
* current value of the attribute is an Object, dot notation can be used
|
|
|
56 |
* to set the value of a property within the object (e.g. <code>set("x.y.z", 5)</code>).
|
|
|
57 |
*
|
|
|
58 |
* @param {Any} value The value to set the attribute to.
|
|
|
59 |
*
|
|
|
60 |
* @param {Object} opts (Optional) Optional event data to be mixed into
|
|
|
61 |
* the event facade passed to subscribers of the attribute's change event. This
|
|
|
62 |
* can be used as a flexible way to identify the source of a call to set, allowing
|
|
|
63 |
* the developer to distinguish between set called internally by the host, vs.
|
|
|
64 |
* set called externally by the application developer.
|
|
|
65 |
*
|
|
|
66 |
* @return {Object} A reference to the host object.
|
|
|
67 |
*/
|
|
|
68 |
set : function(name, val, opts) {
|
|
|
69 |
return this._setAttr(name, val, opts);
|
|
|
70 |
},
|
|
|
71 |
|
|
|
72 |
/**
|
|
|
73 |
* Allows setting of readOnly/writeOnce attributes. See <a href="#method_set">set</a> for argument details.
|
|
|
74 |
*
|
|
|
75 |
* @method _set
|
|
|
76 |
* @protected
|
|
|
77 |
* @chainable
|
|
|
78 |
*
|
|
|
79 |
* @param {String} name The name of the attribute.
|
|
|
80 |
* @param {Any} val The value to set the attribute to.
|
|
|
81 |
* @param {Object} opts (Optional) Optional event data to be mixed into
|
|
|
82 |
* the event facade passed to subscribers of the attribute's change event.
|
|
|
83 |
* @return {Object} A reference to the host object.
|
|
|
84 |
*/
|
|
|
85 |
_set : function(name, val, opts) {
|
|
|
86 |
return this._setAttr(name, val, opts, true);
|
|
|
87 |
},
|
|
|
88 |
|
|
|
89 |
/**
|
|
|
90 |
* Sets multiple attribute values.
|
|
|
91 |
*
|
|
|
92 |
* @method setAttrs
|
|
|
93 |
* @param {Object} attrs An object with attributes name/value pairs.
|
|
|
94 |
* @param {Object} opts Properties to mix into the event payload. These are shared and mixed into each set
|
|
|
95 |
* @return {Object} A reference to the host object.
|
|
|
96 |
* @chainable
|
|
|
97 |
*/
|
|
|
98 |
setAttrs : function(attrs, opts) {
|
|
|
99 |
return this._setAttrs(attrs, opts);
|
|
|
100 |
},
|
|
|
101 |
|
|
|
102 |
/**
|
|
|
103 |
* Implementation behind the public setAttrs method, to set multiple attribute values.
|
|
|
104 |
*
|
|
|
105 |
* @method _setAttrs
|
|
|
106 |
* @protected
|
|
|
107 |
* @param {Object} attrs An object with attributes name/value pairs.
|
|
|
108 |
* @param {Object} opts Properties to mix into the event payload. These are shared and mixed into each set
|
|
|
109 |
* @return {Object} A reference to the host object.
|
|
|
110 |
* @chainable
|
|
|
111 |
*/
|
|
|
112 |
_setAttrs : function(attrs, opts) {
|
|
|
113 |
var attr;
|
|
|
114 |
for (attr in attrs) {
|
|
|
115 |
if ( attrs.hasOwnProperty(attr) ) {
|
|
|
116 |
this.set(attr, attrs[attr], opts);
|
|
|
117 |
}
|
|
|
118 |
}
|
|
|
119 |
return this;
|
|
|
120 |
},
|
|
|
121 |
|
|
|
122 |
/**
|
|
|
123 |
* Utility method to help setup the event payload and fire the attribute change event.
|
|
|
124 |
*
|
|
|
125 |
* @method _fireAttrChange
|
|
|
126 |
* @private
|
|
|
127 |
* @param {String} attrName The name of the attribute
|
|
|
128 |
* @param {String} subAttrName The full path of the property being changed,
|
|
|
129 |
* if this is a sub-attribute value being change. Otherwise null.
|
|
|
130 |
* @param {Any} currVal The current value of the attribute
|
|
|
131 |
* @param {Any} newVal The new value of the attribute
|
|
|
132 |
* @param {Object} opts Any additional event data to mix into the attribute change event's event facade.
|
|
|
133 |
* @param {Object} [cfg] The attribute config stored in State, if already available.
|
|
|
134 |
*/
|
|
|
135 |
_fireAttrChange : function(attrName, subAttrName, currVal, newVal, opts, cfg) {
|
|
|
136 |
var host = this,
|
|
|
137 |
eventName = this._getFullType(attrName + CHANGE),
|
|
|
138 |
state = host._state,
|
|
|
139 |
facade,
|
|
|
140 |
broadcast,
|
|
|
141 |
e;
|
|
|
142 |
|
|
|
143 |
if (!cfg) {
|
|
|
144 |
cfg = state.data[attrName] || {};
|
|
|
145 |
}
|
|
|
146 |
|
|
|
147 |
if (!cfg.published) {
|
|
|
148 |
|
|
|
149 |
// PERF: Using lower level _publish() for
|
|
|
150 |
// critical path performance
|
|
|
151 |
e = host._publish(eventName);
|
|
|
152 |
|
|
|
153 |
e.emitFacade = true;
|
|
|
154 |
e.defaultTargetOnly = true;
|
|
|
155 |
e.defaultFn = host._defAttrChangeFn;
|
|
|
156 |
|
|
|
157 |
broadcast = cfg.broadcast;
|
|
|
158 |
if (broadcast !== undefined) {
|
|
|
159 |
e.broadcast = broadcast;
|
|
|
160 |
}
|
|
|
161 |
|
|
|
162 |
cfg.published = true;
|
|
|
163 |
}
|
|
|
164 |
|
|
|
165 |
if (opts) {
|
|
|
166 |
facade = Y.merge(opts);
|
|
|
167 |
facade._attrOpts = opts;
|
|
|
168 |
} else {
|
|
|
169 |
facade = host._ATTR_E_FACADE;
|
|
|
170 |
}
|
|
|
171 |
|
|
|
172 |
// Not using the single object signature for fire({type:..., newVal:...}), since
|
|
|
173 |
// we don't want to override type. Changed to the fire(type, {newVal:...}) signature.
|
|
|
174 |
|
|
|
175 |
facade.attrName = attrName;
|
|
|
176 |
facade.subAttrName = subAttrName;
|
|
|
177 |
facade.prevVal = currVal;
|
|
|
178 |
facade.newVal = newVal;
|
|
|
179 |
|
|
|
180 |
if (host._hasPotentialSubscribers(eventName)) {
|
|
|
181 |
host.fire(eventName, facade);
|
|
|
182 |
} else {
|
|
|
183 |
this._setAttrVal(attrName, subAttrName, currVal, newVal, opts, cfg);
|
|
|
184 |
}
|
|
|
185 |
},
|
|
|
186 |
|
|
|
187 |
/**
|
|
|
188 |
* Default function for attribute change events.
|
|
|
189 |
*
|
|
|
190 |
* @private
|
|
|
191 |
* @method _defAttrChangeFn
|
|
|
192 |
* @param {EventFacade} e The event object for attribute change events.
|
|
|
193 |
* @param {boolean} eventFastPath Whether or not we're using this as a fast path in the case of no listeners or not
|
|
|
194 |
*/
|
|
|
195 |
_defAttrChangeFn : function(e, eventFastPath) {
|
|
|
196 |
|
|
|
197 |
var opts = e._attrOpts;
|
|
|
198 |
if (opts) {
|
|
|
199 |
delete e._attrOpts;
|
|
|
200 |
}
|
|
|
201 |
|
|
|
202 |
if (!this._setAttrVal(e.attrName, e.subAttrName, e.prevVal, e.newVal, opts)) {
|
|
|
203 |
|
|
|
204 |
Y.log('State not updated and stopImmediatePropagation called for attribute: ' + e.attrName + ' , value:' + e.newVal, 'warn', 'attribute');
|
|
|
205 |
|
|
|
206 |
if (!eventFastPath) {
|
|
|
207 |
// Prevent "after" listeners from being invoked since nothing changed.
|
|
|
208 |
e.stopImmediatePropagation();
|
|
|
209 |
}
|
|
|
210 |
|
|
|
211 |
} else {
|
|
|
212 |
if (!eventFastPath) {
|
|
|
213 |
e.newVal = this.get(e.attrName);
|
|
|
214 |
}
|
|
|
215 |
}
|
|
|
216 |
}
|
|
|
217 |
};
|
|
|
218 |
|
|
|
219 |
// Basic prototype augment - no lazy constructor invocation.
|
|
|
220 |
Y.mix(AttributeObservable, EventTarget, false, null, 1);
|
|
|
221 |
|
|
|
222 |
Y.AttributeObservable = AttributeObservable;
|
|
|
223 |
|
|
|
224 |
/**
|
|
|
225 |
The `AttributeEvents` class extension was deprecated in YUI 3.8.0 and is now
|
|
|
226 |
an alias for the `AttributeObservable` class extension. Use that class
|
|
|
227 |
extnesion instead. This alias will be removed in a future version of YUI.
|
|
|
228 |
|
|
|
229 |
@class AttributeEvents
|
|
|
230 |
@uses EventTarget
|
|
|
231 |
@deprecated Use `AttributeObservable` instead.
|
|
|
232 |
@see AttributeObservable
|
|
|
233 |
**/
|
|
|
234 |
Y.AttributeEvents = AttributeObservable;
|
|
|
235 |
|
|
|
236 |
|
|
|
237 |
}, '3.18.1', {"requires": ["event-custom"]});
|