xooie 0.0.17.pre → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,355 @@
1
+ /*
2
+ * Copyright 2012 Comcast
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ /**
18
+ * class Xooie.Tab < Xooie.Widget
19
+ *
20
+ * A widget that associates containers of information with "tabs". The pattern is
21
+ * designed to mimic the real-world concept of a filing cabinet, where content is
22
+ * stored in folders with protruding tabs that label said content.
23
+ *
24
+ * The Tab widget should be used as a way to organize how content is displayed
25
+ * visually. Content is hidden until the associated tab is activated.
26
+ **/
27
+ define('xooie/widgets/tab', ['jquery', 'xooie/helpers', 'xooie/widgets/base', 'xooie/event_handler'], function($, helpers, Base, EventHandler) {
28
+
29
+ function setSelection(widget, selectedTabs) {
30
+ var activeTabs = widget.getActiveTabs();
31
+
32
+ activeTabs.not(selectedTabs).each(function() {
33
+ widget.deactivateTab($(this));
34
+ });
35
+
36
+ selectedTabs.not(activeTabs).each(function() {
37
+ widget.activateTab($(this));
38
+ });
39
+ }
40
+ /**
41
+ * Xooie.Tab@xooie-tab-active(event)
42
+ * - event (Event): A jQuery event object
43
+ *
44
+ * An event that is fired when a tab is activated. Triggers on the `root` element of the widget.
45
+ *
46
+ * ##### Event Properties
47
+ * - **tabId** (String): The id of the tab that was activated.
48
+ **/
49
+
50
+ /**
51
+ * Xooie.Tab@xooie-tab-inactive(event)
52
+ * - event (Event): A jQuery event object
53
+ *
54
+ * An event that is fired when a tab is deactivated. Triggers on the `root` element of the widget.
55
+ *
56
+ * ##### Event Properties
57
+ * - **tabId** (String): The id of the tab that was deactivated.
58
+ **/
59
+
60
+ /**
61
+ * new Xooie.Tab(element[, addons])
62
+ * - element (Element | String): A jQuery-selected element or string selector for the root element of this widget
63
+ * - addons (Array): An optional collection of [[Xooie.Addon]] classes to be instantiated with this widget
64
+ *
65
+ * Instantiates a new Tab instance. See [[Xooie.Widget]] for more functionality.
66
+ **/
67
+ var Tab = Base.extend(function(){
68
+ var self = this;
69
+
70
+ this._tabEvents = new EventHandler(this.namespace());
71
+
72
+ this._tabEvents.add({
73
+ keyup: function(event){
74
+ if ([13,32].indexOf(event.which) !== -1){
75
+ setSelection(self, self.selectTabs(event, $(this)));
76
+
77
+ event.preventDefault();
78
+ }
79
+ },
80
+
81
+ mouseup: function(event){
82
+ setSelection(self, self.selectTabs(event, $(this)));
83
+ },
84
+
85
+ click: function(event){
86
+ event.preventDefault();
87
+ }
88
+ });
89
+
90
+ // TODO: Test and document this. Also, create a property for data-activate
91
+ this.root().on(this.initEvent(), function(){
92
+ self.activateTab(self.tabs().filter('[data-activate="true"]'));
93
+ });
94
+
95
+ });
96
+
97
+ /** internal
98
+ * Xooie.Tab#_namespace -> String
99
+ *
100
+ * See [[Xooie.Widget#_namespace]].
101
+ * Default: `tab`.
102
+ **/
103
+ /**
104
+ * Xooie.Tab#namespace([value]) -> String
105
+ * - value: an optional value to be set.
106
+ *
107
+ * See [[Xooie.Widget#namespace]]
108
+ **/
109
+ Tab.define('namespace', 'tab');
110
+
111
+ /** internal
112
+ * Xooie.Tab#_tabSelector -> String
113
+ *
114
+ * An alternative selector for a [[Xooie.Tab#tabs]]. This allows developers to specify a tab control that may not
115
+ * be a child of the tab widget.
116
+ **/
117
+ /**
118
+ * Xooie.Tab#tabSelector([value]) -> String
119
+ * - value: an optional value to be set.
120
+ *
121
+ * The method for setting or getting [[Xooie.Tab#_tabSelector]]. Returns the current value of
122
+ * [[Xooie.Tab#_tabSelector]] if no value is passed or sets the value.
123
+ **/
124
+ Tab.define('tabSelector');
125
+
126
+ /** internal
127
+ * Xooie.Tab#_activeClass -> String
128
+ *
129
+ * A class string that is applied to active [[Xooie.Tab#tabs]] and [[Xooie.Tab#tabpanels]].
130
+ * Default: `is-tab-active`.
131
+ **/
132
+ /**
133
+ * Xooie.Tab#activeClass([value]) -> String
134
+ * - value: an optional value to be set.
135
+ *
136
+ * The method for setting or getting [[Xooie.Tab#_activeClass]]. Returns the current value of
137
+ * [[Xooie.Tab#_activeClass]] if no value is passed or sets the value.
138
+ **/
139
+ Tab.defineReadOnly('activeClass', 'is-tab-active');
140
+
141
+ /**
142
+ * Xooie.Tab#tabpanels() -> Elements
143
+ *
144
+ * Tabpanels are elements that contain the content that is shown or hidden when the corresponding
145
+ * [[Xooie.Tab#tabs]] is activated.
146
+ * This role maps to the ARIA [tab role](http://www.w3.org/TR/wai-aria/roles#tab)
147
+ **/
148
+ Tab.defineRole('tabpanel');
149
+
150
+ /**
151
+ * Xooie.Tab#tabs() -> Elements
152
+ *
153
+ * Tabs are elements that, when activated, also activate the corresponding [[Xooie.Tab#tabpanels]].
154
+ * This role maps to the ARIA [tabpanel role](http://www.w3.org/TR/wai-aria/roles#tabpanel).
155
+ **/
156
+ Tab.defineRole('tab');
157
+
158
+ /**
159
+ * Xooie.Tab#tablists() -> Elements
160
+ *
161
+ * A tablist is an element that contains all the [[Xooie.Tab#tabs]]. If any tabs are not decendants of
162
+ * the tablist, ownership of the tab is indicated using the `aria-owns` attribute.
163
+ * There should only be one tablist per tab widget.
164
+ * This role maps to the ARIA [tablist role](http://www.w3.org/TR/wai-aria/roles#tablist)
165
+ **/
166
+ Tab.defineRole('tablist');
167
+
168
+ /**
169
+ * Xooie.Tab#activateTab(tab)
170
+ * - tab (Element): One of the [[Xooie.Tab#tabs]] associated with this widget.
171
+ *
172
+ * Activates the [[Xooie.Tab#tabs]] by adding the [[Xooie.Tab#activeClass]] class and setting the `aria-expanded` property to 'true'.
173
+ * The method also activates the [[Xooie.Tab#tabpanels]] that is indicated by the tab's `aria-controls` attribute,
174
+ * adding the [[Xooie.Tab#activeClass]] class and setting `aria-expanded` to 'true'.
175
+ **/
176
+ Tab.prototype.activateTab = function(tab) {
177
+ tab.addClass(this.activeClass())
178
+ .attr('aria-selected', true);
179
+
180
+ $('#' + tab.attr('aria-controls')).addClass(this.activeClass())
181
+ .attr('aria-expanded', true)
182
+ .focus();
183
+
184
+ var e = $.Event('xooie-tab-active');
185
+
186
+ e.tabId = tab.attr('id');
187
+
188
+ this.root().trigger(e);
189
+ };
190
+
191
+ /**
192
+ * Xooie.Tab#deactivateTab(tab)
193
+ * - tab (Element): One of the [[Xooie.Tab#tabs]] associated with this widget.
194
+ *
195
+ * Deactivates the [[Xooie.Tab#tabs]] by removing the [[Xooie.Tab#activeClass]] class and setting the `aria-expanded` property to 'false'.
196
+ * The method also deactivates the [[Xooie.Tab#tabpanels]] that is indicated by the tab's `aria-controls` attribute,
197
+ * removing the [[Xooie.Tab#activeClass]] class and setting `aria-expanded` to 'false'.
198
+ **/
199
+ Tab.prototype.deactivateTab = function(tab) {
200
+ tab.removeClass(this.activeClass())
201
+ .attr('aria-selected', false);
202
+
203
+ $('#' + tab.attr('aria-controls')).removeClass(this.activeClass())
204
+ .attr('aria-expanded', false);
205
+
206
+ var e = $.Event('xooie-tab-inactive');
207
+
208
+ e.tabId = tab.attr('id');
209
+
210
+ this.root().trigger(e);
211
+ };
212
+
213
+ /**
214
+ * Xooie.Tab#selectTabs(event, selectedTab)
215
+ * - event (Event): Browser event that triggered selectTabs call
216
+ * - selectedTab (Element): Tab that was selected by a mouse or keyboard event
217
+ *
218
+ * Only called by mouse/keyboard event handlers to generate the list of
219
+ * currently active tabs. Should return a jQuery collection of tabs that are
220
+ * to be active. Any tabs which are currently active and not in the
221
+ * collection will be deactivated, and likewise any tabs not currently active
222
+ * and in the collection will be activated.
223
+ *
224
+ * Override this method to alter the behavior of the Tab widget.
225
+ **/
226
+ Tab.prototype.selectTabs = function(event, selectedTab) {
227
+ return selectedTab;
228
+ };
229
+
230
+ /**
231
+ * Xooie.Tab#getActiveTabs() -> Elements
232
+ *
233
+ * Returns a jQuery-selected collection of all [[Xooie.Tab#tabs]] that currently have the
234
+ * [[Xooie.Tab#activeClass]] class.
235
+ **/
236
+ Tab.prototype.getActiveTabs = function() {
237
+ return this.tabs().filter('.' + this.activeClass());
238
+ };
239
+
240
+ /** internal
241
+ * Xooie.Tab#_process_role_tab(tabs) -> Element
242
+ * - tabs (Element): A jQuery-selected collection of [[Xooie.Tab#tabs]]
243
+ *
244
+ * This method processes the elements that have been designated as [[Xooie.Tab#tabs]] with
245
+ * the `data-x-role="tab"` attribute. Tabs are given the [`role="tab"`](http://www.w3.org/TR/wai-aria/roles#tab) and [`aria-selected="false"`](http://www.w3.org/TR/wai-aria/states_and_properties#aria-selected)
246
+ * [ARIA](http://www.w3.org/TR/wai-aria/) attributes.
247
+ **/
248
+ Tab.prototype._process_role_tab = function(tabs){
249
+ var tabpanels = this.tabpanels(),
250
+ tab, panelId,
251
+ self = this;
252
+
253
+ tabs.attr('role', 'tab')
254
+ .attr('aria-selected', false);
255
+
256
+ tabs.each(function(index) {
257
+ tab = $(this);
258
+ panelId = tabpanels.eq(index).attr('id');
259
+
260
+ $(this).attr('aria-controls', panelId);
261
+
262
+ if ($(this).is('a')) {
263
+ $(this).attr('href', '#' + panelId);
264
+ }
265
+
266
+ });
267
+
268
+ tabs.on(this._tabEvents.handlers);
269
+
270
+ return tabs;
271
+ };
272
+
273
+ /** internal
274
+ * Xooie.Tab#_get_role_tab() -> Element
275
+ *
276
+ * Internal method used to retrieve the [[Xooie.Tab#tabs]] for this widget. If [[Xooie.Tab#tabSelector]] has been
277
+ * defined then its value will be used to select from the DOM. Otherwise, tabs will be selected from decendants of
278
+ * the root using the `[data-x-role="tab"]` selector.
279
+ **/
280
+ Tab.prototype._get_role_tab = function(){
281
+ if (!helpers.isUndefined(this.tabSelector())) {
282
+ return $(this.tabSelector());
283
+ } else {
284
+ return this.root().find('[data-x-role="tab"]');
285
+ }
286
+ };
287
+
288
+ /** internal
289
+ * Xooie.Tab#_render_role_tab() -> Elements
290
+ *
291
+ * TODO: Create this method to keep parity with the existing tab functionality
292
+ **/
293
+ Tab.prototype._render_role_tab = function(){
294
+
295
+ };
296
+
297
+ /** internal
298
+ * Xooie.Tab#_process_role_tablist(tablist) -> Element
299
+ * - tablist (Element): A jQuery-selected collection of [[Xooie.Tab#tablists]]
300
+ *
301
+ * This method processes the elements that have been designated as [[Xooie.Tab#tablists]] with
302
+ * the `data-x-role="tablist"` attribute. The tablist is given the [`role="tablist"`](http://www.w3.org/TR/wai-aria/roles#tablist)
303
+ * [ARIA](http://www.w3.org/TR/wai-aria/) attributes. If any [[Xooie.Tab#tabs]] are not decendants of the tab list, the ids of those
304
+ * tabs are added to the [`aria-owns`](http://www.w3.org/TR/wai-aria/states_and_properties#aria-owns) attribute.
305
+ **/
306
+ Tab.prototype._process_role_tablist = function(tablist) {
307
+ var tabs = this.tabs();
308
+
309
+ tablist.attr('role', 'tablist');
310
+
311
+ tabs.each(function(index) {
312
+ var owns, id;
313
+ if (tablist.has(this).length === 0) {
314
+ owns = tablist.attr('aria-owns') || '';
315
+
316
+ owns = owns.split(' ');
317
+
318
+ id = $(this).attr('id');
319
+
320
+ if (owns.indexOf(id) === -1) {
321
+ owns.push(id);
322
+ }
323
+
324
+ tablist.attr('aria-owns', owns.join(' '));
325
+ }
326
+ });
327
+
328
+ return tablist;
329
+ };
330
+ /** internal
331
+ * Xooie.Tab#_render_role_tablist() -> Element
332
+ *
333
+ * TODO: Add this method to render the tablist if it is not included.
334
+ **/
335
+ Tab.prototype._render_role_tablist = function(){
336
+ return $('<ul data-x-role="tablist"></ul>');
337
+ };
338
+
339
+ /** internal
340
+ * Xooie.Tab#_process_role_tabpanel(tabpanels) -> Element
341
+ * - tabpanels (Element): A jQuery-selected collection of [[Xooie.Tab#tabpanels]]
342
+ *
343
+ * This method processes the elements that have been designated as [[Xooie.Tab#tabpanels]] with
344
+ * the `data-x-role="tabpanel"` attribute. Tabs are given the [`role="tabpanel"`](http://www.w3.org/TR/wai-aria/roles#tab) and [`aria-expanded="false"`](http://www.w3.org/TR/wai-aria/states_and_properties#aria-selected)
345
+ * [ARIA](http://www.w3.org/TR/wai-aria/) attributes.
346
+ **/
347
+ Tab.prototype._process_role_tabpanel = function(tabpanels) {
348
+ tabpanels.attr('role', 'tabpanel')
349
+ .attr('aria-expanded', false);
350
+
351
+ return tabpanels;
352
+ };
353
+
354
+ return Tab;
355
+ });
@@ -0,0 +1,282 @@
1
+ /*
2
+ * Copyright 2012 Comcast
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ var $X, Xooie;
18
+
19
+ /** alias of: $X
20
+ * Xooie
21
+ *
22
+ * Xooie is a JavaScript UI widget library.
23
+ **/
24
+
25
+ /**
26
+ * $X(element)
27
+ * - element (Element | String): A jQuery collection or string representing the DOM element to be
28
+ * instantiated as a Xooie widget.
29
+ *
30
+ * Traverses the DOM, starting from the element passed to the method, and instantiates a Xooie
31
+ * widget for every element that has a data-widget-type attribute.
32
+ **/
33
+
34
+ $X = Xooie = (function(static_config) {
35
+ var config = {
36
+ widgets: {},
37
+ addons: {}
38
+ },
39
+ obj = function() {
40
+ return false;
41
+ },
42
+ gcTimer = null;
43
+
44
+ function copyObj(dst, src) {
45
+ var name;
46
+
47
+ for (name in src) {
48
+ if (src.hasOwnProperty(name)) {
49
+ dst[name] = src[name];
50
+ }
51
+ }
52
+ }
53
+
54
+ function gcCallback() {
55
+ if (typeof Xooie.cleanup !== 'undefined') {
56
+ Xooie.cleanup();
57
+ }
58
+ }
59
+
60
+ /**
61
+ * $X.config(options)
62
+ * - options (Object): An object that describes the configuration options for Xooie.
63
+ *
64
+ * Defines the url strings for Xooie modules that will be used to require said modules.
65
+ *
66
+ * ##### Options
67
+ *
68
+ * - **root** (String): The location of all Xooie files.
69
+ * Default: `xooie`.
70
+ * - **widgets** (Object): Defines the location of widgets. By default, Xooie will look for widgets in the
71
+ * '/widgets' directory, relative to the `{root}`.
72
+ * - **addons** (Object): Defines the location of addons. By default, Xooie will look for addons in the
73
+ * '/addons' directory, relative to the `{root}`.
74
+ * - **cleanupInterval** (Integer): Defines the interval at which Xooie checks for instantiated widgets that are
75
+ * no longer active in the DOM. A value of '0' means no cleanup occurs.
76
+ * Default: `0`.
77
+ **/
78
+
79
+ obj.config = function(options) {
80
+ var name;
81
+
82
+ for (name in options) {
83
+ if (options.hasOwnProperty(name)) {
84
+ if (name === 'widgets' || name == 'addons') {
85
+ copyObj(config[name], options[name]);
86
+ } else {
87
+ config[name] = options[name];
88
+ }
89
+ }
90
+ }
91
+
92
+ if (typeof options.cleanupInterval !== 'undefined') {
93
+ gcTimer = clearInterval(gcTimer);
94
+
95
+ if (config.cleanupInterval > 0) {
96
+ gcTimer = setInterval(gcCallback, config.cleanupInterval);
97
+ }
98
+ }
99
+ };
100
+
101
+ /** internal
102
+ * $X._mapName(name, type) -> String
103
+ * - name (String): The name of the module, as determeined by the `data-widget-type` or `data-addons` properties.
104
+ * - type (String): The type of module. Can be either `'widget'` or `'addon'`
105
+ *
106
+ * Maps the name of the widget or addon to the correct url string where the module file is located.
107
+ **/
108
+
109
+ obj._mapName = function(name, type) {
110
+ if (typeof config[type][name] === 'undefined') {
111
+ return [config.root, '/', type, '/', name].join('');
112
+ } else {
113
+ return config[type][name];
114
+ }
115
+ };
116
+
117
+ obj.config({
118
+ root: 'xooie',
119
+ cleanupInterval: 0
120
+ });
121
+
122
+ if (static_config) {
123
+ obj.config(static_config);
124
+ }
125
+
126
+ return obj;
127
+ }(Xooie));
128
+
129
+ define('xooie/xooie', ['jquery', 'xooie/helpers', 'xooie/stylesheet'], function($, helpers, Stylesheet){
130
+ var config = Xooie.config,
131
+ _mapName = Xooie._mapName,
132
+ widgetSelector = '[data-widget-type]';
133
+ widgetDataAttr = 'widgetType';
134
+ addonDataAttr = 'addons';
135
+
136
+ $X = Xooie = function(element){
137
+ var nodes, moduleNames, moduleUrls,
138
+ node, url,
139
+ i, j;
140
+
141
+ element = $(element);
142
+
143
+ // Find all elements labeled as widgets:
144
+ nodes = element.find(widgetSelector);
145
+
146
+ // If the element is also tagged, add it to the collection:
147
+ if (element.is(widgetSelector)){
148
+ nodes = nodes.add(element);
149
+ }
150
+
151
+ // This array will be the list of unique modules to load:
152
+ moduleUrls = [];
153
+
154
+ // Iterate through each item in the collection:
155
+ for(i = 0; i < nodes.length; i+=1) {
156
+ node = $(nodes[i]);
157
+
158
+ // Add all of the widget types to the list of modules we need:
159
+ moduleNames = helpers.toAry(node.data(widgetDataAttr));
160
+
161
+ // For each widget we check to see if the url is already in our
162
+ // list of urls to require:
163
+ for (j = 0; j < moduleNames.length; j+=1) {
164
+ url = $X._mapName(moduleNames[j], 'widgets');
165
+
166
+ if (moduleUrls.indexOf(url) === -1) {
167
+ moduleUrls.push(url);
168
+ }
169
+ }
170
+
171
+ // Do the same with each addon name:
172
+ moduleNames = helpers.toAry(node.data(addonDataAttr)) || [];
173
+
174
+ for (j = 0; j < moduleNames.length; j+=1) {
175
+ url = $X._mapName(moduleNames[j], 'addons');
176
+
177
+ if (moduleUrls.indexOf(url) === -1) {
178
+ moduleUrls.push(url);
179
+ }
180
+ }
181
+ }
182
+
183
+ // Now that we have a list of urls to load, let's load them:
184
+ require(moduleUrls, function(){
185
+ var widgets, addons, node,
186
+ addonMods, widgetMod, argIndex,
187
+ i, j, k;
188
+
189
+ // We need to iterate through our collection of nodes again:
190
+ for (i = 0; i < nodes.length; i+=1) {
191
+ node = $(nodes[i]);
192
+
193
+ // This time, we're keeping track of our addons and widges separately:
194
+ widgets = helpers.toAry(node.data(widgetDataAttr));
195
+ addons = helpers.toAry(node.data(addonDataAttr)) || [];
196
+
197
+ // Iterate through each widget type:
198
+ for (j = 0; j < widgets.length; j+=1) {
199
+
200
+ // Get the index of this module from the moduleUrls:
201
+ argIndex = moduleUrls.indexOf($X._mapName(widgets[j], 'widgets'));
202
+
203
+ //Get the widget that we'll be instantiating:
204
+ widgetMod = arguments[argIndex];
205
+
206
+ addonMods = [];
207
+
208
+ // Now get each addon that we'll instantiate with the widget:
209
+ for (k = 0; k < addons.length; k+=1) {
210
+ // Get the index of the addon module from moduleUrls:
211
+ argIndex = moduleUrls.indexOf($X._mapName(addons[k], 'addons'));
212
+
213
+ addonMods.push(arguments[argIndex]);
214
+ }
215
+
216
+ // Instantiate the new instance using the argIndex to find the right module:
217
+ new widgetMod(node, addonMods);
218
+ }
219
+ }
220
+ });
221
+ };
222
+
223
+ Xooie.config = config;
224
+ Xooie._mapName = _mapName;
225
+
226
+ /** internal, read-only
227
+ * $X._stylesheet -> Object
228
+ *
229
+ * An instance of the [[Stylesheet]] class used to manipluate a dynamically created Xooie stylesheet
230
+ **/
231
+ Xooie._stylesheet = new Stylesheet('Xooie');
232
+
233
+ /** internal
234
+ * $X._styleRules -> Object
235
+ *
236
+ * A cache of css rules defined by the [[Xooie.Widget.createStyleRule]] method.
237
+ **/
238
+ Xooie._styleRules = {};
239
+
240
+ /** internal
241
+ * $X._instanceCache -> Array
242
+ *
243
+ * A collection of currently instantiated widgets.
244
+ **/
245
+ Xooie._instanceCache = [];
246
+
247
+ /** internal
248
+ * $X._instanceIndex -> Integer
249
+ *
250
+ * Tracks the next available instance index in the cache. This value also serves as the id of the
251
+ * next instantiated widget.
252
+ **/
253
+ Xooie._instanceIndex = 0;
254
+
255
+ /**
256
+ * $X.cleanup()
257
+ *
258
+ * Checks all instantiated widgets to ensure that the root element is still in the DOM. If the
259
+ * root element is no longer in the DOM, the module is garbage collected.
260
+ **/
261
+
262
+ Xooie.cleanup = function() {
263
+ var i, instance;
264
+
265
+ for (i = 0; i < $X._instanceCache.length; i++) {
266
+ instance = $X._instanceCache[i];
267
+
268
+ if (instance.root() && instance.root().parents('body').length === 0) {
269
+ instance.cleanup();
270
+ delete $X._instanceCache[i];
271
+ }
272
+ }
273
+ };
274
+
275
+ return Xooie;
276
+ });
277
+
278
+ require(['jquery', 'xooie/xooie'], function($, $X){
279
+ $(document).ready(function() {
280
+ $X($(this));
281
+ });
282
+ });