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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjU5YmQyYzFiMWZjYjExMmE1MTU2YmE2MzJiYTYxMzRmZDBkNjdjYQ==
5
+ data.tar.gz: !binary |-
6
+ MTc0ZGNiYTFlMThmMjkzMTQ0YzZiNjBjYjk4YjQwMzJmNGJkZmZkMA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ M2M2Yjg2OWVlYjYxOTRiZDhjMzdmMGFlMmRhYjAzNzY3ZDYzNzA0MzYxMDA0
10
+ YmNjYWMyOWQ1MDUyZDc4M2RiOGFhNzYyZWZiMzY2Njg5YTMxNzg3OTMxYjVl
11
+ YWQ5MjcwMTNhYTI5MGE4MmViNDUxOWFiZDk0NWM5Y2ZjNzFiM2Y=
12
+ data.tar.gz: !binary |-
13
+ NmJkYTZiMWIxMWQzNDYwZDUwNTBlOGYzNWNkY2VjMjgzYjNkMzQwNjY0NmM2
14
+ YjYxN2U3NjljNDE0NTlhOTRiNjdmMWEyNGUwYjhjMGYzOTcwNzFiNzMzYzMy
15
+ Mjg1OTY4NzVkM2YyNWEzNjcyNmM1MWNlODQwNjlmN2FhOTI4ZmQ=
data/README.md CHANGED
@@ -30,6 +30,12 @@ Xooie will work by just loading xooie.js on your page; all other files will be l
30
30
 
31
31
  Instantiation happens automatically when the page is loaded. All HTML elements tagged with the "data-widget-type" attribute will offer the associated Xooie widget functionality.
32
32
 
33
+ 1.x vs 0.1.x:
34
+ ---
35
+ v1.0 is our official release of Xooie. All new feature development & bug fixes occur on [master](https://github.com/Comcast/Xooie) & are released from a release_1_x branch (e.g. [release_1_1](https://github.com/Comcast/Xooie/tree/release_1_1)). So if you're just getting started with Xooie, be sure to grab the latest 1.x version.
36
+
37
+ If you were already using a pre-1.0 release of Xooie, there is a [release_0_1_x branch](https://github.com/Comcast/Xooie/tree/release_0_1_x) that is updated with bug fixes only. Any 0.1.x release is from the pre-1.0 Xooie development work.
38
+
33
39
  Documentation:
34
40
  ---
35
41
  Carousel
@@ -45,7 +45,7 @@ define('xooie/carousel', ['jquery', 'xooie/base'], function($, Base) {
45
45
  this.positionUpdaters = {
46
46
 
47
47
  "item": function(quantity, direction) {
48
- var items = self.content.children(),
48
+ var items = self.content.children(':visible'),
49
49
  bias, offset,
50
50
  position = self.wrapper.scrollLeft(),
51
51
  i;
@@ -73,7 +73,7 @@ define('xooie/carousel', ['jquery', 'xooie/base'], function($, Base) {
73
73
 
74
74
  "px": function(quantity, direction) {
75
75
  var position;
76
-
76
+
77
77
  if (typeof direction === 'undefined') {
78
78
  position = 0;
79
79
  direction = 1;
@@ -199,7 +199,7 @@ define('xooie/carousel', ['jquery', 'xooie/base'], function($, Base) {
199
199
  //It is possible that images may load after the carousel has instantiated/
200
200
  //Also, this can be used for lazy-loading images
201
201
  //TODO: This can be problematic, since it is triggering update dimensions for each image load
202
- this.content.find('img').on('load', this.updateDimensions.bind(this));
202
+ this.content.find('img').first().on('load', this.updateDimensions.bind(this));
203
203
 
204
204
  carouselElements = carouselElements.add(this.root);
205
205
  });
@@ -244,7 +244,7 @@ define('xooie/carousel', ['jquery', 'xooie/base'], function($, Base) {
244
244
  };
245
245
 
246
246
  Carousel.prototype.currentItem = function(bias) {
247
- var i, items = this.content.children(),
247
+ var i, items = this.content.children(':visible'),
248
248
  position, itemWidth;
249
249
 
250
250
  if (typeof bias === 'undefined') {
@@ -366,7 +366,7 @@ define('xooie/carousel', ['jquery', 'xooie/base'], function($, Base) {
366
366
  if (this.isScrolling) {
367
367
  self.wrapper.stop(true,true);
368
368
  }
369
-
369
+
370
370
  callback();
371
371
 
372
372
  };
@@ -0,0 +1,83 @@
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
+ define('xooie/event_handler', ['jquery', 'xooie/helpers'], function($, helpers) {
18
+
19
+ var EventHandler = function(namespace) {
20
+ this.namespace = namespace;
21
+
22
+ this.handlers = {};
23
+
24
+ this._callbacks = {};
25
+ };
26
+
27
+ function format(type, namespace) {
28
+ if (!namespace) {
29
+ return type;
30
+ } else {
31
+ return type + '.' + namespace;
32
+ }
33
+ }
34
+
35
+ EventHandler.prototype.add = function(type, method) {
36
+ var self = this,
37
+ formattedType, t;
38
+
39
+ if (helpers.isObject(type) && helpers.isUndefined(method)) {
40
+ for(t in type) {
41
+ if (helpers.isFunction(type[t])) {
42
+ this.add(t, type[t]);
43
+ }
44
+ }
45
+
46
+ return;
47
+ }
48
+
49
+ formattedType = format(type, this.namespace);
50
+
51
+ if (helpers.isUndefined(this.handlers[formattedType])) {
52
+ this.handlers[formattedType] = function(e) {
53
+ self.fire(e, this, arguments);
54
+ };
55
+ }
56
+
57
+ if (helpers.isUndefined(this._callbacks[type])) {
58
+ this._callbacks[type] = $.Callbacks('unique');
59
+ }
60
+
61
+ this._callbacks[type].add(method);
62
+ };
63
+
64
+ EventHandler.prototype.clear = function(type) {
65
+ delete(this.handlers[format(type, this.namespace)]);
66
+
67
+ if (!helpers.isUndefined(this._callbacks[type])) {
68
+ this._callbacks[type].empty();
69
+ }
70
+ };
71
+
72
+ EventHandler.prototype.fire = function(event, context, args) {
73
+ if (event.namespace && event.namespace !== this.namespace) {
74
+ return;
75
+ }
76
+
77
+ if (!helpers.isUndefined(this._callbacks[event.type])) {
78
+ this._callbacks[event.type].fireWith(context, args);
79
+ }
80
+ };
81
+
82
+ return EventHandler;
83
+ });
@@ -0,0 +1,61 @@
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.helpers
19
+ *
20
+ * A collection of helper methods used by Xooie modules.
21
+ **/
22
+
23
+ define('xooie/helpers', ['jquery'], function($){
24
+ var helpers = {};
25
+ /**
26
+ * Xooie.helpers.toAry(str) -> Array
27
+ * - str (String | Array): The string to be converted to an array, or an array.
28
+ *
29
+ * Converts a string to an array, or returns the passed argument if it is already an array. Used
30
+ * when parsing data attributes that can be either a space-delineated string or an array.
31
+ **/
32
+ helpers.toAry = function(str) {
33
+ if (typeof str === 'string') {
34
+ return str.split(/\s+/);
35
+ } else if (str instanceof Array) {
36
+ return str;
37
+ }
38
+ };
39
+
40
+ helpers.toInt = function(int) {
41
+ return parseInt(int, 10);
42
+ };
43
+
44
+ helpers.isArray = Array.isArray || function(ary) {
45
+ return Array.prototype.toString(ary) === '[object Array]';
46
+ };
47
+
48
+ helpers.isObject = function(obj) {
49
+ return Object.prototype.toString(obj) === '[object Object]';
50
+ };
51
+
52
+ helpers.isUndefined = function(obj) {
53
+ return obj === void 0;
54
+ };
55
+
56
+ helpers.isFunction = function(func) {
57
+ return typeof func === 'function';
58
+ };
59
+
60
+ return helpers;
61
+ });
@@ -0,0 +1,216 @@
1
+ define('xooie/keyboard_navigation', ['jquery', 'xooie/helpers'], function($, helpers){
2
+ var selectors, keyboardNavigation, keybindings;
3
+
4
+
5
+ keybindings = {
6
+ 37: function(event) {
7
+ moveFocus($(event.target), -1);
8
+
9
+ event.preventDefault();
10
+ },
11
+
12
+ 38: function() {
13
+
14
+ },
15
+
16
+ 39: function(event) {
17
+ moveFocus($(event.target), 1);
18
+
19
+ event.preventDefault();
20
+ },
21
+
22
+ 40: function() {
23
+
24
+ }
25
+ };
26
+
27
+ /** internal
28
+ * Xooie.Widget._moveFocus(direction)
29
+ * - direction (Integer): Determines whether or not to increment or decrement the index. Can be 1 or -1.
30
+ *
31
+ * Moves focus to either the next or previous focusable item, if available. Focus order follows the
32
+ * tab order of the page (items without tabindex or tabindex=0 will be focused before tabindex=1). Focusable
33
+ * items with a tabindex=-1 will not be focused.
34
+ **/
35
+ function moveFocus(current, direction) {
36
+ // TODO: Clean this up. It's a mess
37
+ // TODO: Write tests.
38
+ // TODO: Add detection of new contexts
39
+ // TODO: Add recollection of last focused item
40
+
41
+ var selector, selectors, tabindex, index, target;
42
+
43
+ var tabIndicies= [];
44
+
45
+ selectors = {
46
+ unindexed: ['[data-widget-type] a[href]:visible:not(:disabled):not([tabindex])',
47
+ '[data-widget-type] button:visible:not(:disabled):not([tabindex])',
48
+ '[data-widget-type] input:visible:not(:disabled):not([tabindex])',
49
+ '[data-widget-type] select:visible:not(:disabled):not([tabindex])',
50
+ '[data-widget-type] textarea:visible:not(:disabled):not([tabindex])',
51
+ '[data-widget-type] [tabindex=0]:visible:not(:disabled)'].join(','),
52
+ indexed: function(t) {
53
+ if (t > 0) {
54
+ return '[data-widget-type] [tabindex=' + t + ']:visible:not(:disabled)';
55
+ }
56
+ },
57
+ allIndexed: '[data-widget-type] [tabindex]:visible:not(:disabled)'
58
+ };
59
+
60
+ // jquery select the current item
61
+ current = $(current);
62
+
63
+ // we may not be focused on anything. If that's the case, focus on the first focusable item
64
+ if (!current.is(selectors.unindexed) && !current.is(selectors.allIndexed)) {
65
+ // get the lowest tabindex
66
+ $(selectors.allIndexed).each(function(){
67
+ var i = helpers.toInt($(this).attr('tabindex'));
68
+
69
+ if (tabIndicies.indexOf(i) === -1 && i > 0) {
70
+ tabIndicies.push(i);
71
+ }
72
+ });
73
+
74
+ if (tabIndicies.length > 0) {
75
+ tabIndicies.sort(function(a,b) { return a-b; });
76
+
77
+ target = $(selectors.indexed(tabIndicies[0])).first();
78
+ } else {
79
+ target = $(selectors.unindexed).first();
80
+ }
81
+
82
+ if (target.length > 0) {
83
+ target.focus();
84
+
85
+ return;
86
+ }
87
+ }
88
+
89
+ // get the current tabindex
90
+ tabindex = helpers.toInt(current.attr('tabindex'));
91
+
92
+ // check if tabindex is a number and not 0...
93
+ if (!tabindex) {
94
+ // if it is not, assume we're on an element that has no tab index and select other such elements
95
+ selector = selectors.unindexed;
96
+ } else {
97
+ // otherwise, select all items that are of the same tabindex
98
+ selector = selectors.indexed(tabindex);
99
+ }
100
+
101
+ // find the index of the current item
102
+ index = current.index(selector);
103
+
104
+ if (index + direction >= 0) {
105
+ // get the next/previous item
106
+ target = $(selector).eq(index + direction);
107
+
108
+ // Check to see if we have a valid target...
109
+ if (target.length > 0) {
110
+ // if it is, focus the target and return
111
+ target.focus();
112
+
113
+ return;
114
+ }
115
+ }
116
+
117
+ // if it is not, then we have several possibilities:
118
+
119
+ // If the direction is 1 and tabindex is not a number or 0, then we are at the end of the tab order. Do nothing.
120
+ if (direction === 1 && !tabindex) {
121
+ return;
122
+ // If the direction is 1 and the tabindex is a number, then we need to check for the presence of the next tabindex
123
+ } else if (direction === 1 && !isNaN(tabindex)) {
124
+ // Loop through all elements with a tab index
125
+ $(selectors.allIndexed).each(function() {
126
+ // Build a collection of all tab indicies greater than the current tab index:
127
+ var i = helpers.toInt($(this).attr('tabindex'));
128
+
129
+ if (i > tabindex && tabIndicies.indexOf(i) === -1 && i > 0) {
130
+ tabIndicies.push(i);
131
+ }
132
+ });
133
+
134
+ // If there are tab indicies that are greater than the current one...
135
+ if (tabIndicies.length > 0) {
136
+ // sort our tab indicies ascending
137
+ tabIndicies.sort(function(a, b) { return a-b; });
138
+
139
+ // we now have our new tab index
140
+ tabindex = tabIndicies[0];
141
+
142
+ // Get the first item of the new tab index
143
+ target = $(selectors.indexed(tabindex)).first();
144
+ } else {
145
+ // Otherwise, select the first unindexed item
146
+ target = $(selectors.unindexed).first();
147
+ }
148
+
149
+ } else if (direction === -1 && isNaN(tabindex)) {
150
+ // In this case, we are at the first non-indexed focusable item. We need to find the last indexed item.
151
+ // Loop through all elements with a tab index
152
+ $(selectors.allIndexed).each(function() {
153
+ var i = helpers.toInt($(this).attr('tabindex'));
154
+ // Build a collection of all tab indicies
155
+ if (tabIndicies.indexOf(i) === -1) {
156
+ tabIndicies.push(i);
157
+ }
158
+ });
159
+
160
+ if (tabIndicies.length > 0) {
161
+ // sort our tab indicies descending
162
+ tabIndicies.sort(function(a, b) { return b-a; });
163
+
164
+ // we now have our new tab index
165
+ tabindex = tabIndicies[0];
166
+
167
+ // Select the last indexed item
168
+ target = $(selectors.indexed(tabindex)).last();
169
+ }
170
+ } else if (direction === -1 && !isNaN(tabindex) && tabindex > 0) {
171
+ $(selectors.allIndexed).each(function(){
172
+ var i = helpers.toInt($(this).attr('tabindex'));
173
+
174
+ if (i < tabindex && tabIndicies.indexOf(i) === -1 && i > 0) {
175
+ tabIndicies.push(i);
176
+ }
177
+ });
178
+
179
+ if (tabIndicies.length > 0) {
180
+ // sort our tab indicies asceding
181
+ tabIndicies.sort(function(a, b) { return a-b; });
182
+
183
+ // we now have our new tab index
184
+ tabindex = tabIndicies[0];
185
+
186
+ // Select the last indexed item
187
+ target = $(selectors.indexed(tabindex)).last();
188
+ }
189
+ }
190
+
191
+ if (!helpers.isUndefined(target)) {
192
+ // assuming we have a target, focus it.
193
+ target.focus();
194
+ }
195
+
196
+ }
197
+
198
+ var instantiated;
199
+
200
+ keyboardNavigation = function(){
201
+ if (instantiated) {
202
+ return instantiated;
203
+ }
204
+
205
+ $(document).on('keyup', function(event) {
206
+ if (helpers.isFunction(keybindings[event.which])) {
207
+ keybindings[event.which](event);
208
+ }
209
+ });
210
+
211
+ instantiated = this;
212
+ };
213
+
214
+ return keyboardNavigation;
215
+
216
+ });
@@ -0,0 +1,193 @@
1
+ /**
2
+ * class Xooie.shared
3
+ *
4
+ * A module that contains functionality that is used both by [[Xooie.Widget]] and [[Xooie.Addon]]
5
+ * This module exists to abstract common functionality so that it can be maintained in one place.
6
+ * It is not intended to be used independently.
7
+ **/
8
+ define('xooie/shared', ['jquery'], function($){
9
+
10
+ /** internal
11
+ * Xooie.shared.propertyDetails(name) -> Object
12
+ * - name (String): The name of the property
13
+ *
14
+ * Generates a hash of attributes that will be used in setting and getting the property.
15
+ *
16
+ * ##### Return values
17
+ *
18
+ * - **getter** (String): The name of the internal getter method for this property.
19
+ * `_get_name`
20
+ * - **setter** (String): The name of the internal setter method for this property.
21
+ * `_set_name`
22
+ * - **processor** (String): The name of the internal processor method for this property.
23
+ * `_process_name`
24
+ * - **validator** (String): The name of the internal validator method for this property.
25
+ * `_validate_name`
26
+ * **default** (String): The name of the internally stored default value for this property.
27
+ * `_default_name`
28
+ * - **value** (String): The name of the internally stored value for this property.
29
+ * `_name`
30
+ **/
31
+ function propertyDetails (name) {
32
+ return {
33
+ getter: '_get_' + name,
34
+ setter: '_set_' + name,
35
+ processor: '_process_' + name,
36
+ validator: '_validate_' + name,
37
+ defaultValue: '_default_value_' + name,
38
+ value: '_' + name
39
+ };
40
+ }
41
+
42
+ /** internal
43
+ * Xooie.shared.propertyDispatcher(name, prototype)
44
+ * - name (String): The name of the property
45
+ * - prototype (Object): The prototype of the [[Xooie.Widget]] or [[Xooie.Addon]] for which the property is being set.
46
+ *
47
+ * Gets the [[Xooie.shared.propertyDetails]] for the property, adds the `name` to the list of [[Xooie.Widget#_definedProps]]
48
+ * (or [[Xooie.Addon#_definedProps]]). Adds a method called `name` to the prototype that allows this property to be set or
49
+ * retrieved.
50
+ **/
51
+ function propertyDispatcher (name, prototype) {
52
+ var prop = propertyDetails(name);
53
+
54
+ if (typeof prototype[name] !== 'function') {
55
+ prototype._definedProps.push(name);
56
+
57
+ prototype[name] = function(value) {
58
+ if (typeof value === 'undefined') {
59
+ return this[prop.getter]();
60
+ } else {
61
+ return this[prop.setter](value);
62
+ }
63
+ };
64
+ }
65
+ }
66
+
67
+ var shared = {
68
+ /**
69
+ * Xooie.shared.defineReadOnly(module, name[, defaultValue])
70
+ * - module (Widget | Addon): The module on which this property will be defined.
71
+ * - name (String): The name of the property to define as a read-only property.
72
+ * - defaultValue (Object): An optional default value.
73
+ *
74
+ * Defines a read-only property that can be accessed either by [[Xooie.Widget#get]]/[[Xooie.Addon#get]] or
75
+ * calling the `{{name}}` method on the instance of the module.
76
+ **/
77
+ defineReadOnly: function(module, name, defaultValue){
78
+ var prop = propertyDetails(name);
79
+
80
+ propertyDispatcher(name, module.prototype);
81
+
82
+ //The default value is reset each time this method is called;
83
+ module.prototype[prop.defaultValue] = defaultValue;
84
+
85
+ if (typeof module.prototype[prop.getter] !== 'function') {
86
+ module.prototype[prop.getter] = function() {
87
+ var value = typeof this[prop.value] !== 'undefined' ? this[prop.value] : this[prop.defaultValue];
88
+
89
+ if (typeof this[prop.processor] === 'function') {
90
+ return this[prop.processor](value);
91
+ }
92
+
93
+ return value;
94
+ };
95
+ }
96
+ },
97
+ /**
98
+ * Xooie.shared.defineWriteOnly(module, name)
99
+ * - module (Widget | Addon): The module on which this property will be defined.
100
+ * - name (String): The name of the property to define as a write-only property
101
+ *
102
+ * Defines a write-only property that can be set using [[Xooie.Widget#set]]/[[Xooie.Addon#set]] or by passing
103
+ * a value to the `{{name}}` method on the instance of the module.
104
+ **/
105
+ defineWriteOnly: function(module, name){
106
+ var prop = propertyDetails(name);
107
+
108
+ propertyDispatcher(name, module.prototype);
109
+
110
+ if (typeof module.prototype[prop.setter] !== 'function') {
111
+ module.prototype[prop.setter] = function(value){
112
+ if (typeof this[prop.validator] !== 'function' || this[prop.validator](name)) {
113
+ this[prop.value] = value;
114
+ }
115
+ };
116
+ }
117
+ },
118
+ /**
119
+ * Xooie.shared.extend(constr, _super) -> Widget | Addon
120
+ * - constr (Function): The constructor for the new [[Xooie.Widget]] or [[Xooie.Addon]] class.
121
+ * - _super (Widget | Addon): The module which is to be extended
122
+ *
123
+ * Creates a new Xooie widget/addon class that inherits all properties from the extended class.
124
+ * Constructors for the class are called in order from the top-level constructor to the
125
+ * base constructor.
126
+ **/
127
+ extend: function(constr, module){
128
+ var newModule = (function(){
129
+ return function Child() {
130
+ module.apply(this, arguments);
131
+ constr.apply(this, arguments);
132
+ this._extendCount -= 1;
133
+ };
134
+ })();
135
+
136
+
137
+ $.extend(true, newModule, module);
138
+ $.extend(true, newModule.prototype, module.prototype);
139
+
140
+ newModule.prototype._extendCount = newModule.prototype._extendCount === null ? 1 : newModule.prototype._extendCount += 1;
141
+
142
+ return newModule;
143
+ },
144
+ /**
145
+ * Xooie.shared.get(instance, name) -> object
146
+ * - instance (Widget | Addon): The instance from which the property is to be retrieved.
147
+ * - name (String): The name of the property to be retrieved.
148
+ *
149
+ * Retrieves the value of the property. Returns `undefined` if the property has not been defined.
150
+ **/
151
+ get: function(instance, name){
152
+ var prop = propertyDetails(name);
153
+
154
+ return instance[prop.getter]();
155
+ },
156
+ /**
157
+ * Xooie.shared.set(instance, name, value)
158
+ * - instance (Widget | Addon): The instance where the property is being set.
159
+ * - name (String): The name of the property to be set.
160
+ * - value: The value of the property to be set.
161
+ *
162
+ * Sets a property, so long as that property has been defined.
163
+ **/
164
+ set: function(instance, name, value){
165
+ var prop = propertyDetails(name);
166
+
167
+ if (typeof instance[prop.setter] === 'function') {
168
+ instance[prop.setter](value);
169
+ }
170
+ },
171
+
172
+ /**
173
+ * Xooie.shared.setData(instance, data)
174
+ * - instance (Widget | Addon): The instance to set data on
175
+ * - data (Object): A collection of key/value pairs
176
+ *
177
+ * Sets the properties to the values specified, as long as the property has been defined
178
+ **/
179
+ setData: function(instance, data) {
180
+ var i, prop;
181
+
182
+ for (i = 0; i < instance._definedProps.length; i++) {
183
+ prop = instance._definedProps[i];
184
+ if (typeof data[prop] !== 'undefined') {
185
+ instance.set(prop, data[prop]);
186
+ }
187
+ }
188
+ }
189
+
190
+ };
191
+
192
+ return shared;
193
+ });
@@ -0,0 +1,32 @@
1
+ define('xooie/widgets/accordion', ['jquery', 'xooie/widgets/tab'], function($, Tab){
2
+ var Accordion = Tab.extend(function() {
3
+ });
4
+
5
+ Accordion.define('namespace', 'accordion');
6
+
7
+ /** internal
8
+ * Xooie.Accordion#_process_role_tablist(tablist) -> Element
9
+ * - tablist (Element): A jQuery-selected collection of [[Xooie.Tab#tablists]]
10
+ *
11
+ * Same as [[Xooie.Tab#_process_role_tablist]] and also adds the [`aria-multiselectable="true"`](http://www.w3.org/TR/wai-aria/states_and_properties#aria-multiselectable) attribute.
12
+ **/
13
+ Accordion.prototype._process_role_tablist = function(tablist) {
14
+ Tab.prototype._process_role_tablist.apply(this, arguments);
15
+
16
+ tablist.attr('aria-multiselectable', true);
17
+
18
+ return tablist;
19
+ };
20
+
21
+ Accordion.prototype.selectTabs = function(event, selectedTab) {
22
+ var activeTabs = this.getActiveTabs();
23
+
24
+ if (activeTabs.is(selectedTab)) {
25
+ return activeTabs.not(selectedTab);
26
+ } else {
27
+ return activeTabs.add(selectedTab);
28
+ }
29
+ };
30
+
31
+ return Accordion;
32
+ });