xooie 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,214 +0,0 @@
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/base', ['jquery', 'xooie', 'xooie/stylesheet'], function($, $X, Stylesheet) {
18
- $.event.special['xooie-init'] = {
19
- add: function(handleObj) {
20
- var control = $(this).data(handleObj.namespace + '-instance');
21
- if (control) {
22
- var event = $.Event('xooie-init');
23
- event.namespace = handleObj.namespace;
24
- event.data = handleObj.data;
25
-
26
- handleObj.handler.call(this, event);
27
- }
28
- }
29
- };
30
-
31
- var Base = function(name, constructor) {
32
- var instances, defaultOptions, instanceCounter, initEvent, instanceName, cssRules, stylesInstance, className, Xooie;
33
-
34
- instances = [];
35
-
36
- defaultOptions = {};
37
-
38
- name = name.toLowerCase();
39
- initEvent = 'xooie-init.' + name;
40
- refreshEvent = 'xooie-refresh.' + name;
41
- instanceName = name + '-instance';
42
- instanceCounter = 0;
43
- className = 'is-' + name + '-instantiated';
44
-
45
- cssRules = {};
46
- stylesInstance = new Stylesheet('Xooie');
47
-
48
- Xooie = function(root) {
49
- this.root = $(root);
50
- this._name = name;
51
-
52
- if (this.root.data(instanceName)) {
53
- this.root.trigger(refreshEvent);
54
- return instances[this.root.data(instanceName)];
55
- }
56
- instanceCounter+=1;
57
- instances[instanceCounter] = this;
58
- this.root.data(instanceName, instanceCounter);
59
-
60
- this.instanceClass = this._name + '-' + instanceCounter;
61
- this.root.addClass(this.instanceClass);
62
-
63
- this.options = $.extend({}, Xooie.getDefaultOptions(), this.root.data());
64
-
65
- //expose the stylesheet for this widget to each instance
66
- this.stylesheet = stylesInstance;
67
-
68
- //expose the common css rules
69
- this.cssRules = $.extend({}, cssRules);
70
-
71
- var addons, i, self = this;
72
-
73
- constructor.apply(this, arguments);
74
-
75
- this.root.addClass(className);
76
-
77
- if(this.options.addons) {
78
- addons = this.options.addons.split(' ');
79
-
80
- for (i = 0; i < addons.length; i += 1) {
81
- this.loadAddon(addons[i]);
82
- }
83
- }
84
-
85
- this.root.trigger(initEvent);
86
- };
87
-
88
- Xooie.prototype = {
89
- loadAddon: function(addon){
90
- var self = this,
91
- addon_name = $X.mapName(addon, 'addons', 'xooie/addons/');
92
-
93
- if (typeof this.addons === 'undefined') {
94
- this.addons = {};
95
- }
96
-
97
- try {
98
- $X._requireShim(addon_name, function(Addon){
99
- if (typeof Addon === 'function') {
100
- new Addon(self);
101
- }
102
- });
103
- } catch (e) {
104
- //need to determine how to handle missing addons
105
- }
106
- },
107
-
108
- render: function(template, view) {
109
- var language = template.data('templateLanguage') || Base.default_template_language,
110
- result = Base.render[language](template, view);
111
-
112
- if (result === false) {
113
- return $('<span>Error rendering template</span>');
114
- } else {
115
- return result;
116
- }
117
- },
118
-
119
- cleanup: function() {
120
- var name;
121
-
122
- for (name in this.addons) {
123
- if (this.addons.hasOwnProperty(name)) {
124
- this.addons[name].cleanup();
125
- }
126
- }
127
-
128
- this.root.removeClass(className);
129
- this.root.removeClass(this.instanceClass);
130
- this.root.data(instanceName, false);
131
- }
132
-
133
- };
134
-
135
- Xooie.setCSSRules = function(rules){
136
- var rule;
137
-
138
- if(typeof stylesInstance.addRule === 'undefined'){
139
- return;
140
- }
141
-
142
- for (rule in rules){
143
- cssRules[rule] = stylesInstance.addRule(rule, rules[rule]);
144
- }
145
- };
146
-
147
- Xooie.getDefaultOptions = function(){
148
- return defaultOptions || {};
149
- };
150
-
151
- Xooie.setDefaultOptions = function(options) {
152
- if (typeof options !== 'undefined') {
153
- $.extend(defaultOptions, options);
154
- }
155
- };
156
-
157
- Xooie.garbageCollect = function() {
158
- var id, instance;
159
-
160
- for (id in instances) {
161
- if (instances.hasOwnProperty(id)) {
162
- instance = instances[id];
163
-
164
- if (instance.root.parents('body').length === 0) {
165
- instance.cleanup();
166
- delete instances[id];
167
- }
168
- }
169
- }
170
- };
171
-
172
- $X.registeredClasses.push(Xooie);
173
-
174
- return Xooie;
175
- };
176
-
177
- Base.default_template_language = 'micro_template';
178
-
179
- Base.render = {
180
- 'micro_template': function(template, view) {
181
- if (typeof template.micro_render !== 'undefined') {
182
- return $(template.micro_render(view));
183
- } else {
184
- return false;
185
- }
186
- },
187
-
188
- 'mustache': function(template, view) {
189
- if (typeof Mustache !== 'undefined' && typeof Mustache.render !== 'undefined') {
190
- return $(Mustache.render(template.html(), view));
191
- } else {
192
- return false;
193
- }
194
- },
195
-
196
- 'jsrender': function(template, view) {
197
- if (typeof template.render !== 'undefined') {
198
- return $(template.render(view));
199
- } else {
200
- return false;
201
- }
202
- },
203
-
204
- 'underscore': function(template, view) {
205
- if (typeof _ !== 'undefined' && typeof _.template !== 'undefined') {
206
- return $(_.template(template.html())(view).trim());
207
- } else {
208
- return false;
209
- }
210
- }
211
- };
212
-
213
- return Base;
214
- });
@@ -1,400 +0,0 @@
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/carousel', ['jquery', 'xooie/base'], function($, Base) {
18
-
19
- var resizeTimer = null,
20
- carouselElements = $(),
21
- clickQueue = [],
22
- cssRules = {},
23
- cache;
24
-
25
- $(window).on('resize', function() {
26
- if (resizeTimer) {
27
- clearTimeout(resizeTimer);
28
- resizeTimer = null;
29
- }
30
- if (carouselElements) {
31
- resizeTimer = setTimeout(function() {
32
- carouselElements.trigger('carouselResize');
33
- }, 100);
34
- }
35
- });
36
-
37
- var Carousel = Base('carousel', function() {
38
- var self = this,
39
- scrollTimer,
40
- onClick, onScroll, onScrollComplete;
41
-
42
- this.isScrolling = false;
43
-
44
- //Define the dispatch tables for various functionality:
45
- this.positionUpdaters = {
46
-
47
- "item": function(quantity, direction) {
48
- var items = self.content.children(),
49
- bias, offset,
50
- position = self.wrapper.scrollLeft(),
51
- i;
52
-
53
- if (typeof direction === 'undefined') {
54
- if (quantity > 0 && quantity <= items.length) {
55
- offset = Math.round(items.eq(quantity - 1).position().left);
56
- }
57
- } else {
58
- direction = direction === -1 ? -1 : 1;
59
-
60
- bias = -direction;
61
-
62
- if (!quantity || typeof quantity !== 'number') {
63
- quantity = 1;
64
- }
65
-
66
- i = self.currentItem(bias) + direction * quantity;
67
- i = Math.max(0, Math.min(items.length - 1, i));
68
- offset = Math.round(items.eq(i).position().left);
69
- }
70
-
71
- return position + offset;
72
- },
73
-
74
- "px": function(quantity, direction) {
75
- var position;
76
-
77
- if (typeof direction === 'undefined') {
78
- position = 0;
79
- direction = 1;
80
- } else {
81
- position = self.wrapper.scrollLeft();
82
- }
83
- return position + direction * quantity;
84
- }
85
-
86
- };
87
-
88
- this.snapMethods = {
89
-
90
- "item": function(){
91
- var items = self.content.children(),
92
- offset, p1, p2,
93
- i = self.currentItem();
94
-
95
- p1 = items.eq(i).position().left;
96
- if (Math.abs(p1) < 1) {
97
- p1 = p1 < 0 ? Math.ceil(p1) : Math.floor(p1);
98
- } else {
99
- p1 = Math.round(p1);
100
- }
101
-
102
- if (p1 !== 0 && i > 0) {
103
- p2 = items.eq(i - 1).position().left;
104
- if (Math.abs(p2) < 1) {
105
- p2 = p2 < 0 ? Math.ceil(p2) : Math.floor(p2);
106
- } else {
107
- p2 = Math.round(p2);
108
- }
109
-
110
- if (Math.abs(p1) < Math.abs(p2)) {
111
- offset = p1 + self.wrapper.scrollLeft();
112
- } else {
113
- offset = p2 + self.wrapper.scrollLeft();
114
- }
115
-
116
- self.wrapper.animate({ scrollLeft: offset });
117
- }
118
-
119
- }
120
-
121
- };
122
-
123
- this.displayMethods = {
124
- "item": function(container, template){
125
- var element, item, items, lastVisible, rightPosition, i;
126
-
127
- items = self.content.children();
128
- currentItem = self.currentItem();
129
- rightPosition = items.eq(currentItem).position().left + self.wrapper.innerWidth();
130
- lastVisible = items.length;
131
-
132
- for (i = currentItem; i < items.length; i += 1) {
133
- item = items.eq(i);
134
- if (Math.floor(item.position().left) + item.outerWidth() * self.options.visibleThreshold >= rightPosition) {
135
- lastVisible = i;
136
- break;
137
- }
138
- }
139
-
140
- element = self.render(template, {
141
- current_item: currentItem + 1,
142
- last_visible_item: lastVisible,
143
- total_items: items.length
144
- });
145
-
146
- container.append(element);
147
- }
148
- };
149
-
150
- //select the content area and wrap it in a container
151
- this.content = this.root.find(this.options.contentSelector);
152
- this.content.wrap('<div/>');
153
-
154
- this.wrapper = this.content.parent();
155
- this.wrapper.addClass('xooie-carousel-wrapper');
156
-
157
- //setting the wrapper's parent to overflow-y=hidden allows us to hide the horizontal scrollbar
158
- this.wrapper.parent().addClass('xooie-carousel-crop');
159
-
160
- this.cssRules.heightAdjust = this.stylesheet.addRule('.carousel-' + this.root.data('carousel-instance') + ' .xooie-carousel-crop');
161
-
162
- this.content.addClass('xooie-carousel-content');
163
-
164
- this.content.children().addClass('xooie-carousel-item');
165
-
166
- this.root.find(this.options.controlSelector)
167
- .on('click', function(event){
168
- event.preventDefault();
169
-
170
- self.updatePosition($(this).data('scroll'));
171
- });
172
-
173
- onScrollComplete = function() {
174
- self.snap();
175
- self.root.trigger('carouselScrollComplete');
176
- };
177
-
178
- onScroll = function(){
179
- if (scrollTimer) {
180
- scrollTimer = clearTimeout(scrollTimer);
181
- } else {
182
- self.root.removeClass('is-carousel-leftmost is-carousel-rightmost');
183
- }
184
-
185
- scrollTimer = setTimeout(onScrollComplete, 250);
186
- };
187
-
188
- this.wrapper.on('scroll', onScroll);
189
-
190
- this.root.on({
191
- carouselScrollComplete: function(){
192
- self.updateDisplay();
193
- self.updateLimits();
194
- },
195
- carouselInit: this.updateDimensions.bind(this),
196
- carouselResize: this.updateDimensions.bind(this)
197
- });
198
-
199
- //It is possible that images may load after the carousel has instantiated/
200
- //Also, this can be used for lazy-loading images
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));
203
-
204
- carouselElements = carouselElements.add(this.root);
205
- });
206
-
207
- Carousel.setDefaultOptions({
208
- contentSelector: '[data-role="carousel-content"]',
209
- controlSelector: '[data-role="carousel-control"]',
210
-
211
- displayMode: 'none',
212
- displaySelector: '[data-role="carousel-display"]',
213
- displayTemplateSelector: '[data-role="carousel-display-template"]',
214
-
215
- snapMode: 'none',
216
- visibleThreshold: 0.50
217
- });
218
-
219
- //Set css rules for all carousels
220
- Carousel.setCSSRules({
221
- '.xooie-carousel-wrapper': {
222
- 'overflow-x': 'scroll',
223
- 'overflow-y': 'hidden'
224
- },
225
- '.xooie-carousel-crop': {
226
- 'overflow-y': 'hidden'
227
- },
228
- '.xooie-carousel-content': {
229
- display: 'table-cell',
230
- 'white-space': 'nowrap',
231
- 'font-size': '0px'
232
- },
233
- '.xooie-carousel-item': {
234
- display: 'inline-block',
235
- zoom: '1',
236
- '*display': 'inline',
237
- 'font-size': '1em'
238
- }
239
- });
240
-
241
- cache = {
242
- currentItem: 0,
243
- lastItem: 0
244
- };
245
-
246
- Carousel.prototype.currentItem = function(bias) {
247
- var i, items = this.content.children(),
248
- position, itemWidth;
249
-
250
- if (typeof bias === 'undefined') {
251
- bias = 1;
252
- }
253
-
254
- if (bias === 1) {
255
- position = this.content.position().left;
256
-
257
- for (i = 0; i < items.length - 1; i++) {
258
- itemWidth = items.eq(i).outerWidth(true);
259
-
260
- if (position + this.options.visibleThreshold * itemWidth >= 0){
261
- return i;
262
- } else {
263
- position += itemWidth;
264
- }
265
- }
266
- return items.length - 1;
267
- } else {
268
- position = this.content.outerWidth(true) + this.content.position().left;
269
-
270
- for (i = items.length - 1; i > 0; i -= 1) {
271
- itemWidth = items.eq(i).outerWidth(true);
272
- position -= itemWidth;
273
-
274
- if (i > 0 && position <= this.options.visibleThreshold * itemWidth) {
275
- return i;
276
- }
277
- }
278
- return 0;
279
- }
280
- };
281
-
282
- Carousel.prototype.getRightLimit = function(){
283
- try {
284
- var lastItem = this.content.children(':last'),
285
- position = lastItem.position();
286
-
287
- if (position && typeof position.left !== 'undefined') {
288
- return Math.floor(position.left) + lastItem.outerWidth(true);
289
- }
290
- } catch (e) {
291
- return;
292
- }
293
- };
294
-
295
- Carousel.prototype.updateDimensions = function() {
296
- var items = this.content.children(),
297
- height = 0;
298
-
299
- items.each(function() {
300
- var node = $(this);
301
- height = Math.max(height, node.outerHeight(true));
302
- });
303
-
304
- //set the height of the wrapper's parent (or cropping element) to ensure we hide the scrollbar
305
- this.cssRules.heightAdjust.style.height = height + 'px';
306
-
307
- this.updateLimits();
308
- this.updateDisplay();
309
- this.snap();
310
-
311
- this.root.trigger('carouselUpdated');
312
- };
313
-
314
- Carousel.prototype.updateLimits = function() {
315
- this.root.toggleClass('is-carousel-leftmost', this.wrapper.scrollLeft() === 0);
316
- this.root.toggleClass('is-carousel-rightmost', this.getRightLimit() <= this.wrapper.innerWidth());
317
- };
318
-
319
- Carousel.prototype.updatePosition = function(amount, cb) {
320
- var match = (amount + '').match(/^([+\-]?)(\d+)(.*)$/),
321
- callback,
322
- self = this;
323
-
324
- if (!match) {
325
- if (typeof cb === 'function') {
326
- cb();
327
- }
328
-
329
- return;
330
- }
331
-
332
- callback = function(){
333
- var direction, quantity, units, offset;
334
-
335
- if (match[1] !== '') {
336
- direction = (match[1] === '-') ? -1 : 1;
337
- }
338
-
339
- quantity = parseInt(match[2], 10);
340
- units = match[3];
341
-
342
- if (units === '') {
343
- units = 'px';
344
- }
345
-
346
- if (typeof self.positionUpdaters[units] === 'function') {
347
- offset = self.positionUpdaters[units](quantity, direction);
348
- } else {
349
- offset = 0;
350
- }
351
-
352
- self.isScrolling = true;
353
-
354
- self.root.trigger('carouselMove', offset);
355
-
356
- self.wrapper.animate({ scrollLeft: offset }, 200,
357
- function(){
358
- self.isScrolling = false;
359
- if (typeof cb === 'function') {
360
- cb();
361
- }
362
- }
363
- );
364
- };
365
-
366
- if (this.isScrolling) {
367
- self.wrapper.stop(true,true);
368
- }
369
-
370
- callback();
371
-
372
- };
373
-
374
- Carousel.prototype.updateDisplay = function(){
375
- if (this.options.displayMode === 'none') {
376
- return;
377
- }
378
-
379
- var container = this.root.find(this.options.displaySelector),
380
- template = this.root.find(this.options.displayTemplateSelector);
381
-
382
- if (container.length === 0 || template.length === 0) {
383
- return;
384
- }
385
-
386
- container.html('');
387
-
388
- if (typeof this.displayMethods[this.options.displayMode] === 'function') {
389
- this.displayMethods[this.options.displayMode](container, template);
390
- }
391
- };
392
-
393
- Carousel.prototype.snap = function(){
394
- if (this.getRightLimit() > this.wrapper.innerWidth() && typeof this.snapMethods[this.options.snapMode] === 'function') {
395
- this.snapMethods[this.options.snapMode]();
396
- }
397
- };
398
-
399
- return Carousel;
400
- });