|
1 YUI.add('widget-htmlparser', function (Y, NAME) { |
|
2 |
|
3 /** |
|
4 * Adds HTML Parser support to the base Widget class |
|
5 * |
|
6 * @module widget |
|
7 * @submodule widget-htmlparser |
|
8 * @for Widget |
|
9 */ |
|
10 |
|
11 var Widget = Y.Widget, |
|
12 Node = Y.Node, |
|
13 Lang = Y.Lang, |
|
14 |
|
15 SRC_NODE = "srcNode", |
|
16 CONTENT_BOX = "contentBox"; |
|
17 |
|
18 /** |
|
19 * Object hash, defining how attribute values are to be parsed from |
|
20 * markup contained in the widget's content box. e.g.: |
|
21 * <pre> |
|
22 * { |
|
23 * // Set single Node references using selector syntax |
|
24 * // (selector is run through node.one) |
|
25 * titleNode: "span.yui-title", |
|
26 * // Set NodeList references using selector syntax |
|
27 * // (array indicates selector is to be run through node.all) |
|
28 * listNodes: ["li.yui-item"], |
|
29 * // Set other attribute types, using a parse function. |
|
30 * // Context is set to the widget instance. |
|
31 * label: function(contentBox) { |
|
32 * return contentBox.one("span.title").get("innerHTML"); |
|
33 * } |
|
34 * } |
|
35 * </pre> |
|
36 * |
|
37 * @property HTML_PARSER |
|
38 * @type Object |
|
39 * @static |
|
40 */ |
|
41 Widget.HTML_PARSER = {}; |
|
42 |
|
43 /** |
|
44 * The build configuration for the Widget class. |
|
45 * <p> |
|
46 * Defines the static fields which need to be aggregated, |
|
47 * when this class is used as the main class passed to |
|
48 * the <a href="Base.html#method_build">Base.build</a> method. |
|
49 * </p> |
|
50 * @property _buildCfg |
|
51 * @type Object |
|
52 * @static |
|
53 * @final |
|
54 * @private |
|
55 */ |
|
56 Widget._buildCfg = { |
|
57 aggregates : ["HTML_PARSER"] |
|
58 }; |
|
59 |
|
60 /** |
|
61 * The DOM node to parse for configuration values, passed to the Widget's HTML_PARSER definition |
|
62 * |
|
63 * @attribute srcNode |
|
64 * @type String | Node |
|
65 * @writeOnce |
|
66 */ |
|
67 Widget.ATTRS[SRC_NODE] = { |
|
68 value: null, |
|
69 setter: Node.one, |
|
70 getter: "_getSrcNode", |
|
71 writeOnce: true |
|
72 }; |
|
73 |
|
74 Y.mix(Widget.prototype, { |
|
75 |
|
76 /** |
|
77 * @method _getSrcNode |
|
78 * @protected |
|
79 * @return {Node} The Node to apply HTML_PARSER to |
|
80 */ |
|
81 _getSrcNode : function(val) { |
|
82 return val || this.get(CONTENT_BOX); |
|
83 }, |
|
84 |
|
85 /** |
|
86 * Implement the BaseCore _preAddAttrs method hook, to add |
|
87 * the srcNode and related attributes, so that HTML_PARSER |
|
88 * (which relies on `this.get("srcNode")`) can merge in it's |
|
89 * results before the rest of the attributes are added. |
|
90 * |
|
91 * @method _preAddAttrs |
|
92 * @protected |
|
93 * |
|
94 * @param attrs {Object} The full hash of statically defined ATTRS |
|
95 * attributes being added for this instance |
|
96 * |
|
97 * @param userVals {Object} The hash of user values passed to |
|
98 * the constructor |
|
99 * |
|
100 * @param lazy {boolean} Whether or not to add the attributes lazily |
|
101 */ |
|
102 _preAddAttrs : function(attrs, userVals, lazy) { |
|
103 |
|
104 var preAttrs = { |
|
105 id : attrs.id, |
|
106 boundingBox : attrs.boundingBox, |
|
107 contentBox : attrs.contentBox, |
|
108 srcNode : attrs.srcNode |
|
109 }; |
|
110 |
|
111 this.addAttrs(preAttrs, userVals, lazy); |
|
112 |
|
113 delete attrs.boundingBox; |
|
114 delete attrs.contentBox; |
|
115 delete attrs.srcNode; |
|
116 delete attrs.id; |
|
117 |
|
118 if (this._applyParser) { |
|
119 this._applyParser(userVals); |
|
120 } |
|
121 }, |
|
122 |
|
123 /** |
|
124 * @method _applyParsedConfig |
|
125 * @protected |
|
126 * @return {Object} The merged configuration literal |
|
127 */ |
|
128 _applyParsedConfig : function(node, cfg, parsedCfg) { |
|
129 return (parsedCfg) ? Y.mix(cfg, parsedCfg, false) : cfg; |
|
130 }, |
|
131 |
|
132 /** |
|
133 * Utility method used to apply the <code>HTML_PARSER</code> configuration for the |
|
134 * instance, to retrieve config data values. |
|
135 * |
|
136 * @method _applyParser |
|
137 * @protected |
|
138 * @param config {Object} User configuration object (will be populated with values from Node) |
|
139 */ |
|
140 _applyParser : function(config) { |
|
141 |
|
142 var widget = this, |
|
143 srcNode = this._getNodeToParse(), |
|
144 schema = widget._getHtmlParser(), |
|
145 parsedConfig, |
|
146 val; |
|
147 |
|
148 if (schema && srcNode) { |
|
149 Y.Object.each(schema, function(v, k, o) { |
|
150 val = null; |
|
151 |
|
152 if (Lang.isFunction(v)) { |
|
153 val = v.call(widget, srcNode); |
|
154 } else { |
|
155 if (Lang.isArray(v)) { |
|
156 val = srcNode.all(v[0]); |
|
157 if (val.isEmpty()) { |
|
158 val = null; |
|
159 } |
|
160 } else { |
|
161 val = srcNode.one(v); |
|
162 } |
|
163 } |
|
164 |
|
165 if (val !== null && val !== undefined) { |
|
166 parsedConfig = parsedConfig || {}; |
|
167 parsedConfig[k] = val; |
|
168 } |
|
169 }); |
|
170 } |
|
171 config = widget._applyParsedConfig(srcNode, config, parsedConfig); |
|
172 }, |
|
173 |
|
174 /** |
|
175 * Determines whether we have a node reference which we should try and parse. |
|
176 * |
|
177 * The current implementation does not parse nodes generated from CONTENT_TEMPLATE, |
|
178 * only explicitly set srcNode, or contentBox attributes. |
|
179 * |
|
180 * @method _getNodeToParse |
|
181 * @return {Node} The node reference to apply HTML_PARSER to. |
|
182 * @private |
|
183 */ |
|
184 _getNodeToParse : function() { |
|
185 var srcNode = this.get("srcNode"); |
|
186 return (!this._cbFromTemplate) ? srcNode : null; |
|
187 }, |
|
188 |
|
189 /** |
|
190 * Gets the HTML_PARSER definition for this instance, by merging HTML_PARSER |
|
191 * definitions across the class hierarchy. |
|
192 * |
|
193 * @private |
|
194 * @method _getHtmlParser |
|
195 * @return {Object} HTML_PARSER definition for this instance |
|
196 */ |
|
197 _getHtmlParser : function() { |
|
198 // Removed caching for kweight. This is a private method |
|
199 // and only called once so don't need to cache HTML_PARSER |
|
200 var classes = this._getClasses(), |
|
201 parser = {}, |
|
202 i, p; |
|
203 |
|
204 for (i = classes.length - 1; i >= 0; i--) { |
|
205 p = classes[i].HTML_PARSER; |
|
206 if (p) { |
|
207 Y.mix(parser, p, true); |
|
208 } |
|
209 } |
|
210 return parser; |
|
211 } |
|
212 }); |
|
213 |
|
214 |
|
215 }, '@VERSION@', {"requires": ["widget-base"]}); |