~launchpad-pqm/launchpad/devel

13302.1.4 by Jeroen Vermeulen
Adding tests.
1
/* Copyright 2011 Canonical Ltd.  This software is licensed under the
13302.1.2 by Danilo Segan
Move expander to a separate module.
2
 * GNU Affero General Public License version 3 (see the file LICENSE).
3
 *
13302.1.5 by Jeroen Vermeulen
Document and refactory interface; show spinner.
4
 * Expander widget.  Can be used to let the user toggle the visibility of
5
 * existing elements on the page, or to make the page load elements on demand
6
 * as the user expands them.
7
 *
13302.1.13 by Jeroen Vermeulen
Reduced to two connection-point tags, without a surrounding tag.
8
 * Synonyms: collapsible, foldable.
9
 *
13302.1.5 by Jeroen Vermeulen
Document and refactory interface; show spinner.
10
 * Each expander needs two tags as "connection points":
13302.1.15 by Jeroen Vermeulen
Object-style API.
11
 *  * Icon tag, to be marked up with the expander icon.
12
 *  * Content tag, to be exposed by the expander.
13302.1.5 by Jeroen Vermeulen
Document and refactory interface; show spinner.
13
 *
13302.1.12 by Jeroen Vermeulen
Fixes & documentation for initial content.
14
 * Either may have initial contents.  The initial contents of the icon tag
13302.1.15 by Jeroen Vermeulen
Object-style API.
15
 * stays in place, so it could say something like "Details..." that explains
13302.1.12 by Jeroen Vermeulen
Fixes & documentation for initial content.
16
 * what the icon means.  You'll want to hide it using the "unseen" class if
17
 * these contents should only be shown once the expander has been set up.
18
 *
19
 * Any initial contents of the content tag will be revealed when the expander
20
 * is opened; hide them using the "unseen" class if they should not be shown
21
 * when the expander has not been enabled.  An optional loader function may
13302.1.15 by Jeroen Vermeulen
Object-style API.
22
 * produce new contents for this tag when the user first opens the expander.
13302.1.12 by Jeroen Vermeulen
Fixes & documentation for initial content.
23
 *
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
24
 * If you provide a loader function, the expander runs it when the user first
25
 * opens it.  The loader should produce a DOM node or node list(it may do this
26
 * asynchronously) and feed that back to the expander by passing it to the
27
 * expander's "receive" method.  The loader gets a reference to the expander
28
 * as its first argument.
13302.1.2 by Danilo Segan
Move expander to a separate module.
29
 *
13302.1.15 by Jeroen Vermeulen
Object-style API.
30
 * The expander is set up in its collapsed state by default.  If you want it
31
 * created in its expanded state instead, mark your content tag with the
32
 * "expanded" class.
33
 *
13580.1.1 by Ian Booth
Add radio button style support to expanders
34
 * An expander may be created with a group_id. Expanders which belong to the
35
 * same group can only have one instance in the expanded state at any time. If
36
 * a collapsed expander is opened, any other open expander within the same
37
 * group will be closed.
38
 *
13302.1.4 by Jeroen Vermeulen
Adding tests.
39
 * @module lp.app.widgets.expander
13302.1.5 by Jeroen Vermeulen
Document and refactory interface; show spinner.
40
 * @requires node, event
13302.1.2 by Danilo Segan
Move expander to a separate module.
41
 */
42
43
YUI.add('lp.app.widgets.expander', function(Y) {
44
45
var namespace = Y.namespace('lp.app.widgets.expander');
46
13580.1.1 by Ian Booth
Add radio button style support to expanders
47
// Define some constants.
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
48
var EXPANDER_CREATED = 'expander:created',
49
    EXPANDER_DESTROYED = 'expander:destroyed',
50
    EXPANDER_STATE_CHANGED = 'expander:state_changed',
51
    EXPANDED = 'expander:expanded',
52
    COLLAPSED = 'expander:collapsed';
13580.1.1 by Ian Booth
Add radio button style support to expanders
53
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
54
namespace.EXPANDER_CREATED = EXPANDER_CREATED;
55
namespace.EXPANDER_DESTORYED = EXPANDER_DESTROYED;
56
namespace.EXPANDER_STATE_CHANGED = EXPANDER_STATE_CHANGED;
13580.1.1 by Ian Booth
Add radio button style support to expanders
57
namespace.EXPANDED = EXPANDED;
58
namespace.COLLAPSED = COLLAPSED;
59
60
/**
61
 * A single ExpanderRadioController instance is created for this namespace.
62
 * Each expander instance which is created with a group id is registered with
63
 * this controller. The controller ensures that only one expander from each
64
 * group is open at any time.
65
 */
66
function ExpanderRadioController() {
67
    ExpanderRadioController.superclass.constructor.apply(this, arguments);
68
}
69
70
ExpanderRadioController.NAME = "ExpanderRadioController";
71
72
Y.extend(ExpanderRadioController, Y.Base, {
73
74
    initializer: function() {
75
        this.expanders = {};
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
76
        var controller = this;
77
        Y.on(EXPANDER_CREATED, function(group_id, expander) {
78
            controller._registerExpander(group_id, expander);
79
        });
80
        Y.on(EXPANDER_DESTROYED, function(group_id, expander) {
81
            controller._deregisterExpander(group_id, expander);
82
        });
83
        Y.on(EXPANDER_STATE_CHANGED,
84
            function(group_id, new_state, active_expander) {
85
                controller._stateChangeProcessor(
86
                    group_id, new_state, active_expander);
87
            });
13580.1.1 by Ian Booth
Add radio button style support to expanders
88
    },
89
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
90
    _stateChangeProcessor: function(group_id, new_state, active_expander) {
91
        this.expanders[group_id].forEach(function(expander) {
92
            if (new_state === EXPANDED && expander !== active_expander) {
93
                if (expander.isExpanded()) {
94
                    expander.render(false);
13580.1.1 by Ian Booth
Add radio button style support to expanders
95
                }
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
96
            }
97
        }, this);
13580.1.1 by Ian Booth
Add radio button style support to expanders
98
    },
99
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
100
    _registerExpander: function(group_id, expander) {
13580.1.1 by Ian Booth
Add radio button style support to expanders
101
        if (!this.expanders.hasOwnProperty(group_id)) {
102
            this.expanders[group_id] = [];
103
        }
104
        this.expanders[group_id].push(expander);
105
    },
106
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
107
    _deregisterExpander: function(group_id, expander) {
13580.1.1 by Ian Booth
Add radio button style support to expanders
108
        if (this.expanders.hasOwnProperty(group_id)) {
109
            var idx = this.expanders[group_id].indexOf(expander);
110
            if (idx !== -1) {
111
                this.expanders[group_id].splice(idx, 1);
112
            }
113
        }
114
    }
115
});
116
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
117
// Create the controller instance
118
if (namespace.expanderRadioController === undefined) {
119
    namespace.expanderRadioController = new ExpanderRadioController();
120
}
13580.1.1 by Ian Booth
Add radio button style support to expanders
121
13302.1.15 by Jeroen Vermeulen
Object-style API.
122
/*
123
 * Create an expander.
124
 *
125
 * @param icon_node Node to serve as connection point for the expander icon.
126
 * @param content_node Node to serve as connection point for expander content.
127
 * @param config Object with additional parameters.
128
 *     loader: A function that will produce a Node or NodeList to replace the
129
 *         contents of the content tag.  Receives the Expander object
130
 *         "expander" as its argument.  Once the loader has constructed the
131
 *         output Node or NodeList it wants to display ("output"), it calls
132
 *         expander.receive(output) to update the content node.
13453.2.1 by Danilo Segan
Restore expander replacements.
133
 *     animate_node: A node to perform an animation on.  Mostly useful for
134
 *         animating table rows/cells when you want to animate the inner
135
 *         content (eg. a <div>).
136
 *     no_animation: Set to true if no animation should be used.  Useful for
137
 *         when you can't rearrange the nodes so animations apply to them
138
 *         (eg. we want to show a bunch of rows in the same table).
13302.1.15 by Jeroen Vermeulen
Object-style API.
139
 */
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
140
function Expander(icon_node, content_node, config) {
13580.1.1 by Ian Booth
Add radio button style support to expanders
141
    Expander.superclass.constructor.apply(this);
142
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
143
    if (!Y.Lang.isObject(icon_node)) {
144
        throw new Error("No icon node given.");
145
    }
146
    if (!Y.Lang.isObject(content_node)) {
147
        throw new Error("No content node given.");
148
    }
13302.1.15 by Jeroen Vermeulen
Object-style API.
149
    this.icon_node = icon_node;
150
    this.content_node = content_node;
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
151
    if (Y.Lang.isValue(config)) {
152
        this.config = config;
153
    } else {
154
        this.config = {};
155
    }
156
    this.loaded = !Y.Lang.isValue(this.config.loader);
13453.2.1 by Danilo Segan
Restore expander replacements.
157
158
    if (Y.Lang.isValue(this.config.animate_node)) {
159
        this._animate_node = Y.one(this.config.animate_node);
160
    } else {
161
        this._animate_node = this.content_node;
162
    }
163
164
    if (this.config.no_animation !== true) {
165
        this._animation = Y.lazr.effects.reversible_slide_out(
166
            this._animate_node);
167
    } else {
168
        this._animation = undefined;
169
    }
13302.1.15 by Jeroen Vermeulen
Object-style API.
170
13580.1.1 by Ian Booth
Add radio button style support to expanders
171
    if (Y.Lang.isValue(this.config.group_id)) {
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
172
        Y.fire(EXPANDER_CREATED, this.config.group_id, this);
13580.1.1 by Ian Booth
Add radio button style support to expanders
173
    }
174
13302.1.15 by Jeroen Vermeulen
Object-style API.
175
    // Is setup complete?  Skip any animations until it is.
176
    this.fully_set_up = false;
177
}
13580.1.1 by Ian Booth
Add radio button style support to expanders
178
Expander.NAME = "Expander";
13302.1.15 by Jeroen Vermeulen
Object-style API.
179
namespace.Expander = Expander;
180
13580.1.1 by Ian Booth
Add radio button style support to expanders
181
Y.extend(Expander, Y.Base, {
13302.1.15 by Jeroen Vermeulen
Object-style API.
182
    /*
183
     * CSS classes.
184
     */
185
    css_classes: {
186
        expanded: 'expanded',
187
        unseen: 'unseen'
188
    },
189
13580.1.1 by Ian Booth
Add radio button style support to expanders
190
    destructor: function() {
191
        if (Y.Lang.isValue(this.config.group_id)) {
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
192
            Y.fire(EXPANDER_DESTROYED, this.config.group_id, this);
13580.1.1 by Ian Booth
Add radio button style support to expanders
193
        }
194
    },
195
13302.1.15 by Jeroen Vermeulen
Object-style API.
196
    /*
197
     * Return sprite name for given expander state.
198
     */
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
199
    nameSprite: function(expanded) {
13302.1.15 by Jeroen Vermeulen
Object-style API.
200
        if (expanded) {
201
            return 'treeExpanded';
202
        } else {
203
            return 'treeCollapsed';
204
        }
205
    },
206
207
    /*
208
     * Is the content node currently expanded?
209
     */
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
210
    isExpanded: function() {
13302.6.27 by Danilo Segan
Move away from NodeLists which don't animate.
211
        return this.content_node.hasClass(this.css_classes.expanded);
13302.1.15 by Jeroen Vermeulen
Object-style API.
212
    },
213
13302.1.18 by Jeroen Vermeulen
Test createByCSS.
214
    /*
215
     * Either add or remove given CSS class from the content tag.
216
     *
217
     * @param want_class Whether this class is desired for the content tag.
218
     *     If it is, then the function may need to add it; if it isn't, then
219
     *     the function may need to remove it.
220
     * @param class_name CSS class name.
221
     */
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
222
    setContentClassIf: function(want_class, class_name) {
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
223
        if (want_class) {
224
            this.content_node.addClass(class_name);
225
        } else {
226
            this.content_node.removeClass(class_name);
227
        }
228
    },
229
13302.1.15 by Jeroen Vermeulen
Object-style API.
230
    /*
13580.1.1 by Ian Booth
Add radio button style support to expanders
231
     * Record the expanded/collapsed state of the content tag and fire the
232
     * state_changed event.
13302.1.15 by Jeroen Vermeulen
Object-style API.
233
     */
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
234
    setExpanded: function(is_expanded) {
13580.1.1 by Ian Booth
Add radio button style support to expanders
235
        var state_changed = this.isExpanded() !== is_expanded;
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
236
        this.setContentClassIf(is_expanded, this.css_classes.expanded);
13580.1.1 by Ian Booth
Add radio button style support to expanders
237
        if (state_changed && Y.Lang.isValue(this.config.group_id)) {
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
238
            Y.fire(
239
                EXPANDER_STATE_CHANGED,
13580.1.1 by Ian Booth
Add radio button style support to expanders
240
                this.config.group_id,
13580.1.3 by Ian Booth
Fix yui event implementation and add tests
241
                is_expanded?EXPANDED:COLLAPSED, this);
13580.1.1 by Ian Booth
Add radio button style support to expanders
242
        }
13302.1.15 by Jeroen Vermeulen
Object-style API.
243
    },
244
245
    /*
246
     * Hide or reveal the content node (by adding the "unseen" class to it).
247
     *
248
     * @param expand Are we expanding?  If not, we must be collapsing.
13302.2.24 by Danilo Segan
Some basic expander animation tests.
249
     * @param no_animation {Boolean} Whether to short-circuit the animation?
13302.1.15 by Jeroen Vermeulen
Object-style API.
250
     */
13302.2.13 by Danilo Segan
Merge stable.
251
    foldContentNode: function(expand, no_animation) {
13302.2.11 by Danilo Segan
Add animations to expander.
252
        var expander = this;
253
        var has_paused = false;
13453.2.1 by Danilo Segan
Restore expander replacements.
254
        if (no_animation === true || Y.Lang.isUndefined(this._animation)) {
13302.2.30 by Danilo Segan
Minor fix in foldContentNode.
255
            // Make the animation have the proper direction set from
256
            // the start.
13453.2.1 by Danilo Segan
Restore expander replacements.
257
            if (!Y.Lang.isUndefined(this._animation)) {
258
                this._animation.set('reverse', expand);
259
            }
13302.2.11 by Danilo Segan
Add animations to expander.
260
            expander.setContentClassIf(
261
                !expand, expander.css_classes.unseen);
13302.2.18 by Danilo Segan
Clean-up reversing support.
262
        } else {
263
            this._animation.set('reverse', !expand);
13302.2.21 by Danilo Segan
Make sure animation end event is not executed when the direction changes in the meantime.
264
13302.2.11 by Danilo Segan
Add animations to expander.
265
            if (expand) {
13302.2.21 by Danilo Segan
Make sure animation end event is not executed when the direction changes in the meantime.
266
                // Show when expanding.
13302.2.18 by Danilo Segan
Clean-up reversing support.
267
                expander.setContentClassIf(
13302.2.21 by Danilo Segan
Make sure animation end event is not executed when the direction changes in the meantime.
268
                    false, expander.css_classes.unseen);
13302.2.11 by Danilo Segan
Add animations to expander.
269
            } else {
13302.2.21 by Danilo Segan
Make sure animation end event is not executed when the direction changes in the meantime.
270
                // Hide when collapsing but only after
271
                // animation is complete.
13302.2.18 by Danilo Segan
Clean-up reversing support.
272
                this._animation.once('end', function() {
13302.2.21 by Danilo Segan
Make sure animation end event is not executed when the direction changes in the meantime.
273
                    // Only hide if the direction has not been
274
                    // changed in the meantime.
275
                    if (this.get('reverse')) {
276
                        expander.setContentClassIf(
277
                            true, expander.css_classes.unseen);
278
                    }
13302.2.18 by Danilo Segan
Clean-up reversing support.
279
                });
13302.2.11 by Danilo Segan
Add animations to expander.
280
            }
13302.2.21 by Danilo Segan
Make sure animation end event is not executed when the direction changes in the meantime.
281
13302.2.18 by Danilo Segan
Clean-up reversing support.
282
            expander._animation.run();
13302.2.8 by Danilo Segan
Non-working animation.
283
        }
13302.1.15 by Jeroen Vermeulen
Object-style API.
284
    },
13302.2.10 by Danilo Segan
Fix whitespace.
285
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
286
    revealIcon: function() {
13302.1.18 by Jeroen Vermeulen
Test createByCSS.
287
        this.icon_node
13453.2.1 by Danilo Segan
Restore expander replacements.
288
            .addClass('sprite')
13302.1.18 by Jeroen Vermeulen
Test createByCSS.
289
            .removeClass('unseen');
290
    },
291
13302.1.15 by Jeroen Vermeulen
Object-style API.
292
    /*
293
     * Set icon to either the "expanded" or the "collapsed" state.
294
     *
295
     * @param expand Are we expanding?  If not, we must be collapsing.
296
     */
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
297
    setIcon: function(expand) {
13302.1.15 by Jeroen Vermeulen
Object-style API.
298
        this.icon_node
299
            .removeClass(this.nameSprite(!expand))
13453.2.3 by Danilo Segan
Set mouse cursor to a pointer where appropriate.
300
            .addClass(this.nameSprite(expand))
301
            .setStyle('cursor', 'pointer');
13302.1.15 by Jeroen Vermeulen
Object-style API.
302
    },
303
304
    /*
305
     * Process the output node being produced by the loader.  To be invoked
306
     * by a custom loader when it's done.
307
     *
308
     * @param output A Node or NodeList to replace the contents of the content
309
     *     tag with.
13302.2.16 by Danilo Segan
Reload on error.
310
     * @param failed Whether loading has failed and should be retried.
13302.1.15 by Jeroen Vermeulen
Object-style API.
311
     */
13302.2.16 by Danilo Segan
Reload on error.
312
    receive: function(output, failed) {
313
        if (failed === true) {
314
            this.loaded = false;
315
        }
13453.2.1 by Danilo Segan
Restore expander replacements.
316
        var from_height = this._animate_node.getStyle('height');
317
        this._animate_node.setContent(output);
318
        if (Y.Lang.isUndefined(this._animation)) {
319
            return;
320
        }
321
        var to_height = this._animate_node.get('scrollHeight');
13302.2.11 by Danilo Segan
Add animations to expander.
322
        if (this._animation.get('running')) {
323
            this._animation.stop();
324
        }
325
        this._animation.set('to', { height: to_height });
326
        this._animation.set('from', { height: from_height });
327
        this._animation.run();
13302.1.15 by Jeroen Vermeulen
Object-style API.
328
    },
329
330
    /*
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
331
     * Invoke the loader, and record the fact that the loader has been
332
     * started.
13302.1.15 by Jeroen Vermeulen
Object-style API.
333
     */
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
334
    load: function() {
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
335
        this.loaded = true;
13302.1.15 by Jeroen Vermeulen
Object-style API.
336
        this.config.loader(this);
337
    },
338
339
    /*
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
340
     * Set the expander's DOM elements to a consistent, operational state.
341
     *
342
     * @param expanded Whether the expander is to be rendered in its expanded
343
     *     state.  If not, it must be in the collapsed state.
13302.1.15 by Jeroen Vermeulen
Object-style API.
344
     */
13302.2.13 by Danilo Segan
Merge stable.
345
    render: function(expanded, no_animation) {
13302.2.11 by Danilo Segan
Add animations to expander.
346
        this.foldContentNode(expanded, no_animation);
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
347
        this.setIcon(expanded);
13302.1.17 by Jeroen Vermeulen
At last! A working test.
348
        if (expanded && !this.loaded) {
13302.1.15 by Jeroen Vermeulen
Object-style API.
349
            this.load();
350
        }
13302.1.17 by Jeroen Vermeulen
At last! A working test.
351
        this.setExpanded(expanded);
13302.1.15 by Jeroen Vermeulen
Object-style API.
352
    },
353
13453.2.1 by Danilo Segan
Restore expander replacements.
354
    /**
355
     * Wrap node content in an <a> tag and mark it as js-action.
356
     *
357
     * @param node Y.Node object to modify: its content is modified
358
     *     in-place so node events won't be lost, but anything set on
359
     *     the inner content nodes might be.
360
     */
361
    wrapNodeWithLink: function(node) {
362
        var link_node = Y.Node.create('<a></a>')
363
            .addClass('js-action')
364
            .set('href', '#')
365
            .setContent(node.getContent());
366
        node.setContent(link_node);
367
    },
368
13302.1.15 by Jeroen Vermeulen
Object-style API.
369
    /*
370
     * Set up an expander's DOM and event handler.
371
     *
13453.2.1 by Danilo Segan
Restore expander replacements.
372
     * @param linkify {Boolean} Wrap the icon node into an <A> tag with
373
     *     proper CSS classes and content from the icon node.
13302.1.15 by Jeroen Vermeulen
Object-style API.
374
     */
13453.2.1 by Danilo Segan
Restore expander replacements.
375
    setUp: function(linkify) {
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
376
        var expander = this;
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
377
        function click_handler(e) {
13302.2.11 by Danilo Segan
Add animations to expander.
378
            e.halt();
13302.1.16 by Jeroen Vermeulen
If expander is initially expanded, also invoke loader if any.
379
            expander.render(!expander.isExpanded());
13302.1.15 by Jeroen Vermeulen
Object-style API.
380
        }
381
13302.2.11 by Danilo Segan
Add animations to expander.
382
        this.render(this.isExpanded(), true);
13453.2.1 by Danilo Segan
Restore expander replacements.
383
        if (linkify === true) {
384
            this.wrapNodeWithLink(this.icon_node);
385
        }
13302.1.15 by Jeroen Vermeulen
Object-style API.
386
        this.icon_node.on('click', click_handler);
13302.1.18 by Jeroen Vermeulen
Test createByCSS.
387
        this.revealIcon();
13302.1.15 by Jeroen Vermeulen
Object-style API.
388
        this.fully_set_up = true;
13302.1.18 by Jeroen Vermeulen
Test createByCSS.
389
        return this;
13302.1.15 by Jeroen Vermeulen
Object-style API.
390
    }
13580.1.1 by Ian Booth
Add radio button style support to expanders
391
});
13302.1.10 by Jeroen Vermeulen
Flattened code. Added please-wait text to TAL.
392
13302.1.5 by Jeroen Vermeulen
Document and refactory interface; show spinner.
393
/*
13302.1.13 by Jeroen Vermeulen
Reduced to two connection-point tags, without a surrounding tag.
394
 * Initialize expanders based on CSS selectors.
13302.1.5 by Jeroen Vermeulen
Document and refactory interface; show spinner.
395
 *
13302.1.13 by Jeroen Vermeulen
Reduced to two connection-point tags, without a surrounding tag.
396
 * @param widget_select CSS selector to specify each tag that will have an
397
 *     expander created inside it.
398
 * @param icon_select CSS selector for the icon tag inside each tag matched
399
 *     by widget_select.
400
 * @param content_select CSS selector for the content tag inside each tag
401
 *     matched by widget_select.
13302.5.30 by Danilo Segan
Linkify from createByCSS.
402
 * @param linkify Whether to linkify the content in the icon_select node.
13302.1.18 by Jeroen Vermeulen
Test createByCSS.
403
 * @param loader Optional loader function for each expander that is set up.
404
 *     Must take an Expander as its argument, create a Node or NodeList with
405
 *     the output to be displayed, and feed the output to the expander's
406
 *     "receive" method.
13302.1.5 by Jeroen Vermeulen
Document and refactory interface; show spinner.
407
 */
13302.5.30 by Danilo Segan
Linkify from createByCSS.
408
function createByCSS(widget_select, icon_select, content_select, linkify,
409
                     loader) {
13302.1.15 by Jeroen Vermeulen
Object-style API.
410
    var config = {
411
        loader: loader
412
    };
13302.1.23 by Jeroen Vermeulen
Review change: function() instead of function ().
413
    var expander_factory = function(widget) {
13302.1.15 by Jeroen Vermeulen
Object-style API.
414
        var expander = new Expander(
13302.1.18 by Jeroen Vermeulen
Test createByCSS.
415
            widget.one(icon_select), widget.one(content_select), config);
13302.5.30 by Danilo Segan
Linkify from createByCSS.
416
        expander.setUp(linkify);
13302.1.18 by Jeroen Vermeulen
Test createByCSS.
417
    };
418
    Y.all(widget_select).each(expander_factory);
13302.1.2 by Danilo Segan
Move expander to a separate module.
419
}
13302.1.13 by Jeroen Vermeulen
Reduced to two connection-point tags, without a surrounding tag.
420
namespace.createByCSS = createByCSS;
13302.1.2 by Danilo Segan
Move expander to a separate module.
421
13580.1.1 by Ian Booth
Add radio button style support to expanders
422
}, "0.1", {"requires": ["base", "event", "node", "lazr.effects"]});