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 +15 -0
- data/README.md +6 -0
- data/vendor/assets/javascripts/xooie/carousel.js +5 -5
- data/vendor/assets/javascripts/xooie/event_handler.js +83 -0
- data/vendor/assets/javascripts/xooie/helpers.js +61 -0
- data/vendor/assets/javascripts/xooie/keyboard_navigation.js +216 -0
- data/vendor/assets/javascripts/xooie/shared.js +193 -0
- data/vendor/assets/javascripts/xooie/widgets/accordion.js +32 -0
- data/vendor/assets/javascripts/xooie/widgets/base.js +628 -0
- data/vendor/assets/javascripts/xooie/widgets/carousel.js +769 -0
- data/vendor/assets/javascripts/xooie/widgets/dialog.js +132 -0
- data/vendor/assets/javascripts/xooie/widgets/dropdown.js +283 -0
- data/vendor/assets/javascripts/xooie/widgets/tab.js +355 -0
- data/vendor/assets/javascripts/xooie/xooie.js +282 -0
- metadata +33 -10
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
|
+
});
|