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