vendor/assets/javascripts/xooie/widgets/carousel.js in xooie-1.0.4 vs vendor/assets/javascripts/xooie/widgets/carousel.js in xooie-1.0.5
- old
+ new
@@ -24,11 +24,12 @@
* scroll content.
* Keyboard-only users will also be able to navigate from item to item using the tab, left or right keys.
* Screen reader users will percieve the carousel as a [list](http://www.w3.org/TR/wai-aria/roles#list) of items.
* For most devices, the native scrollbar is hidden in favor of the directional controls and native scrolling.
**/
-define('xooie/widgets/carousel', ['jquery', 'xooie/helpers', 'xooie/widgets/base', 'xooie/event_handler'], function($, helpers, Base, EventHandler) {
+define('xooie/widgets/carousel', ['jquery', 'xooie/helpers', 'xooie/widgets/base', 'xooie/event_handler'], function ($, helpers, Base, EventHandler) {
+ 'use strict';
var Carousel, timers;
/**
* Xooie.Carousel@xooie-carousel-resize(event)
* - event (Event): A jQuery event object
@@ -39,18 +40,18 @@
timers = {
resize: null
};
- $(window).on('resize', function() {
+ $(window).on('resize', function () {
if (timers.resize !== null) {
clearTimeout(timers.resize);
timers.resize = null;
}
if (Carousel._cache.length > 0) {
// TODO: make this delay adjustable
- timers.resize = setTimeout(function() {
+ timers.resize = setTimeout(function () {
Carousel._cache.trigger(Carousel.prototype.resizeEvent());
}, 100);
}
});
@@ -64,13 +65,13 @@
* [right, undefined, continuous].
**/
function parseCtrlStr(ctrlStr) {
ctrlStr = ctrlStr.toLowerCase();
- var ptrnMatch = ctrlStr.match(/^control:(left|right|goto)\s(\d+)(?:st|nd|rd|th)?\s(.*)$/);
-
- if(ptrnMatch === null) {
+ var ptrnMatch = ctrlStr.match(/^control:(left|right|goto)\s(\d+)(?:st|nd|rd|th)?\s([\w\W]*?)$/);
+
+ if (ptrnMatch === null) {
ptrnMatch = ctrlStr.match(/^control:(left|right)()\s(continuous)$/);
}
if (ptrnMatch !== null) {
return ptrnMatch.slice(1);
@@ -86,11 +87,11 @@
* [[Xooie.Carousel#_controlEvents]], [[Xooie.Carousel#_wrapperEvents]], and [[Xooie.Carousel#cropStyle]].
* Events are bound to the [[Xooie.Widget#root]] to call [[Xooie.Carousel#updateDimensions]] on [[Xooie.Widget@xooie-init]],
* [[Xooie.Widget@xooie-refresh]] and [[Xooie.Carousel@xooie-carousel-resize]].
* Carousel instances are tracked in the [[Xooie.Carousel._cache]] collection.
**/
- Carousel = Base.extend(function() {
+ Carousel = Base.extend(function () {
var self = this;
/** internal
* Xooie.Carousel#_timers -> Object
*
@@ -119,11 +120,11 @@
* - **pixels**(direction, quantity): alias of **pixel**
* - **px**(direction, quantity): alias of **pixel**
**/
this._positioners = {
- item: function(direction, quantity) {
+ item: function (direction, quantity) {
var items, pos, i;
items = this.items();
quantity = helpers.toInt(quantity);
@@ -131,15 +132,11 @@
if (isNaN(quantity)) {
return;
}
if (direction === 'goto' && quantity > 1 && quantity <= items.length) {
- pos = Math.round(items.eq(quantity - 1).position().left);
-
- if (pos === 0) {
- return;
- }
+ pos = Math.round(items.eq(quantity - 1).position().left) - this.contents().position().left;
} else {
i = this.currentItem(direction === 'right');
direction = direction === 'left' ? -1 : 1;
@@ -149,15 +146,15 @@
}
this.scrollTo(pos);
},
- items: function() {
+ items: function () {
return this._positioners.item.apply(this, arguments);
},
- pixel: function(direction, quantity) {
+ pixel: function (direction, quantity) {
var pos;
quantity = helpers.toInt(quantity);
if (isNaN(quantity)) {
@@ -173,15 +170,15 @@
}
this.scrollTo(pos);
},
- pixels: function() {
+ pixels: function () {
return this._positioners.pixel.apply(this, arguments);
},
- px: function() {
+ px: function () {
return this._positioners.pixel.apply(this, arguments);
}
};
/** internal
@@ -190,11 +187,11 @@
* - direction (String): The direction of the scroll. Can be `left` or `right`.
**/
function continuousScroll(ctrl, direction) {
clearInterval(self._timers.continuous);
- self._timers.continuous = setInterval(function(dir) {
+ self._timers.continuous = setInterval(function (dir) {
if (ctrl.is(':disabled')) {
self._timers.continuous = clearInterval(self._timers.continuous);
}
//TODO: Need some way of setting rate
@@ -209,26 +206,26 @@
* [[Xooie.Carousel#controls]].
**/
this._controlEvents = new EventHandler(this.namespace());
this._controlEvents.add({
- keydown: function(event) {
- var ctrl, args;
+ keydown: function (event) {
+ var ctrl, args;
- if ([13,32].indexOf(event.which) !== -1) {
- ctrl = $(this);
- args = parseCtrlStr(ctrl.attr('data-x-role'));
+ if ([13, 32].indexOf(event.which) !== -1) {
+ ctrl = $(this);
+ args = parseCtrlStr(ctrl.attr('data-x-role'));
- if (args[2] === 'continuous' && !ctrl.is(':disabled')) {
- continuousScroll(ctrl, args[0]);
+ if (args[2] === 'continuous' && !ctrl.is(':disabled')) {
+ continuousScroll(ctrl, args[0]);
- event.preventDefault();
- }
+ event.preventDefault();
}
+ }
},
- mousedown: function(event) {
+ mousedown: function (event) {
var ctrl, args;
ctrl = $(this);
args = parseCtrlStr(ctrl.attr('data-x-role'));
@@ -237,29 +234,29 @@
event.preventDefault();
}
},
- keyup: function(event) {
+ keyup: function (event) {
self._timers.continuous = clearInterval(self._timers.continuous);
if ($(this).is(':disabled')) {
return;
}
- if ([13,32].indexOf(event.which) !== -1) {
+ if ([13, 32].indexOf(event.which) !== -1) {
var args = parseCtrlStr($(this).attr('data-x-role'));
if (helpers.isFunction(self._positioners[args[2]])) {
self._positioners[args[2]].apply(self, args);
}
event.preventDefault();
}
},
- mouseup: function(event) {
+ mouseup: function (event) {
self._timers.continuous = clearInterval(self._timers.continuous);
if ($(this).is(':disabled')) {
return;
}
@@ -271,15 +268,15 @@
}
event.preventDefault();
},
- mouseleave: function(event) {
+ mouseleave: function () {
self._timers.continuous = clearInterval(self._timers.continuous);
},
- blur: function(event) {
+ blur: function () {
self._timers.continuous = clearInterval(self._timers.continuous);
}
});
function scrollComplete() {
@@ -294,21 +291,21 @@
* An instance of [[Xooie.EventHandler]] that manages event handlers to be bound to the
* [[Xooie.Carousel#wrappers]].
**/
this._wrapperEvents = new EventHandler(this.namespace());
- this._wrapperEvents.add('scroll', function(event){
+ this._wrapperEvents.add('scroll', function () {
if (self._timers.scroll) {
- self._timers.scroll = clearTimeout(self._timers.scroll);
- } else {
- self.root().removeClass(self.leftClass() + ' ' + self.rightClass());
-
- self.controls().prop('disabled', false);
- }
+ self._timers.scroll = clearTimeout(self._timers.scroll);
+ } else {
+ self.root().removeClass(self.leftClass() + ' ' + self.rightClass());
- // TODO: make this delay adjustable
- self._timers.scroll = setTimeout(scrollComplete, 250);
+ self.controls().prop('disabled', false);
+ }
+
+ // TODO: make this delay adjustable
+ self._timers.scroll = setTimeout(scrollComplete, 250);
});
this.cropStyle(Carousel.createStyleRule('.' + this.instanceClass() + ' .' + this.cropClass() + ', .' + this.instanceClass() + '.' + this.cropClass()));
// TODO: add functionality to remove from cache
@@ -316,13 +313,13 @@
this.root().on([
this.get('initEvent'),
this.get('refreshEvent'),
this.get('resizeEvent')].join(' '),
- function(){
- self.updateDimensions();
- });
+ function () {
+ self.updateDimensions();
+ });
});
/** internal
* Xooie.Carousel._cache -> jQuery
@@ -515,86 +512,82 @@
'font-size': '0px',
'transition': 'left 0.5s'
});
Carousel.createStyleRule('ul.' + Carousel.prototype.contentClass(), {
- 'list-style': 'none',
- 'padding': 0,
- 'margin': 0
+ 'list-style': 'none',
+ 'padding': 0,
+ 'margin': 0
});
Carousel.createStyleRule('.' + Carousel.prototype.contentClass() + ' > *', {
display: 'inline-block',
zoom: '1',
'*display': 'inline',
'font-size': '1em'
});
- Carousel.createStyleRule('.' + Carousel.prototype.leftClass() + '.' + Carousel.prototype.rightClass() + ' [data-x-role^="control:left"]' +
- ', .' + Carousel.prototype.leftClass() + '.' + Carousel.prototype.rightClass() + ' [data-x-role^="control:right"]', {
+ Carousel.createStyleRule('.' + Carousel.prototype.leftClass() + '.' + Carousel.prototype.rightClass() + ' [data-x-role^="control:left"]' + ', .' + Carousel.prototype.leftClass() + '.' + Carousel.prototype.rightClass() + ' [data-x-role^="control:right"]', {
display: 'none'
});
/**
* Xooie.Carousel#currentItem(biasRight) -> Integer
* - biasRight (Boolean): If true, calculates the current item from the right side of the carousel.
*
* Returns the index of the first visible item. The value of [[Xooie.Carousel#visibleThreshold]] determines what
* percentage of the item must be showing to be considered visible.
**/
- Carousel.prototype.currentItem = function(biasRight) {
- var content, items,
- position, itemWidth,
- i;
+ Carousel.prototype.currentItem = function (biasRight) {
+ var content, items, position, itemWidth, i;
- content = this.contents();
- items = this.items();
+ content = this.contents();
+ items = this.items();
- if (biasRight) {
- position = content.outerWidth(true) + content.position().left;
+ if (biasRight) {
+ position = content.outerWidth(true) + content.position().left;
- for (i = items.length - 1; i > 0; i -= 1) {
- itemWidth = items.eq(i).outerWidth(true);
- position -= itemWidth;
+ for (i = items.length - 1; i > 0; i -= 1) {
+ itemWidth = items.eq(i).outerWidth(true);
+ position -= itemWidth;
- if (i > 0 && position <= this.visibleThreshold() * itemWidth) {
- return i;
- }
+ if (i > 0 && position <= this.visibleThreshold() * itemWidth) {
+ return i;
}
- return 0;
- } else {
- position = content.position().left;
+ }
+ return 0;
+ }
- for (i = 0; i < items.length - 1; i++) {
- itemWidth = items.eq(i).outerWidth(true);
+ position = content.position().left;
- if (position + this.visibleThreshold() * itemWidth >= 0){
- return i;
- } else {
- position += itemWidth;
- }
- }
+ for (i = 0; i < items.length - 1; i += 1) {
+ itemWidth = items.eq(i).outerWidth(true);
- return items.length - 1;
+ if (position + this.visibleThreshold() * itemWidth >= 0) {
+ return i;
}
+ position += itemWidth;
+ }
+
+ return items.length - 1;
};
/**
* Xooie.Carousel#isLeft() -> Boolean
*
* Indicates if the carousel is scrolled completely to the left.
**/
- Carousel.prototype.isLeft = function() {
+ Carousel.prototype.isLeft = function () {
return this.wrappers().scrollLeft() === 0;
};
/**
* Xooie.Carousel#isRight() -> Boolean
*
* Indicates if the carousel is scrolled completely to the right.
**/
- Carousel.prototype.isRight = function() {
+ Carousel.prototype.isRight = function () {
var lastItem, position;
try {
lastItem = this.items().filter(':visible:last');
position = lastItem.position();
@@ -614,14 +607,14 @@
*
* Updates the height of the carousel based on the height of the tallest visible item in the carousel.
* The new height is applied to the [[Xooie.Carousel#cropStyle]] rule rather than the cropping element
* itself. This allows developers to use cascade rules to override the height if they so choose.
**/
- Carousel.prototype.updateDimensions = function() {
+ Carousel.prototype.updateDimensions = function () {
var height = 0;
- this.items().each(function(){
+ this.items().each(function () {
height = Math.max(height, $(this).outerHeight(true));
});
//set the height of the wrapper's parent (or cropping element) to ensure we hide the scrollbar
this.cropStyle().style.height = height + 'px';
@@ -636,61 +629,62 @@
* If the carousel is scrolled completely to the left then the [[Xooie.Carousel#leftClass]] is applied to the
* [[Xooie.Widget#root]] and the left [[Xooie.Carousel#controls]] is disabled. If the carousel is scrolled
* completely to the left then the [[Xooie.Carousel#rightClass]] is applied to the [[Xooie.Widget#root]] and the
* right [[Xooie.Carousel#controls]] is disabled.
**/
- Carousel.prototype.updateLimits = function() {
- var isLeft = this.isLeft(),
- isRight = this.isRight();
+ Carousel.prototype.updateLimits = function () {
+ var isLeft, isRight;
- this.root().toggleClass(this.leftClass(), isLeft);
- this.controls().filter('[data-x-role^="control:left"]')
- .prop('disabled', isLeft);
+ isLeft = this.isLeft();
+ isRight = this.isRight();
- this.root().toggleClass(this.rightClass(), isRight);
- this.controls().filter('[data-x-role^="control:right"]')
- .prop('disabled', isRight);
+ this.root().toggleClass(this.leftClass(), isLeft);
+ this.controls().filter('[data-x-role^="control:left"]')
+ .prop('disabled', isLeft);
+
+ this.root().toggleClass(this.rightClass(), isRight);
+ this.controls().filter('[data-x-role^="control:right"]')
+ .prop('disabled', isRight);
};
/**
* Xooie.Carousel#scrollTo(pos, cb)
* - pos (Integer): The position to which the carousel will be scrolled.
* - cb (Function): A callback function that is called when the animation is complete.
*
* Uses the jQuery animate functionality to scroll the carousel to the designated position.
**/
- Carousel.prototype.scrollTo = function(pos, cb) {
+ Carousel.prototype.scrollTo = function (pos, cb) {
var self = this;
pos = Math.floor(pos);
if (this.isScrolling) {
- this.wrappers().stop(true,true);
+ this.wrappers().stop(true, true);
}
this.isScrolling = true;
// TODO: make the scroll timer configurable
this.wrappers().animate({ scrollLeft: pos }, 200,
- function(){
+ function () {
self.isScrolling = false;
if (helpers.isFunction(cb)) {
cb();
}
- }
- );
+ });
};
/** internal
* Xooie.Carousel#_process_role_content(content) -> Element
* - content (Element): A jQuery-selected collection of [[Xooie.Carousel#contents]]
*
* This method processes the element that has been designated as a [[Xooie.Carousel#contents]].
* In addition to applying the [[Xooie.Carousel#contentClass]] the content is also given the
* aria role [list](http://www.w3.org/TR/wai-aria/roles#list) if it is neither a `ul` or `ol` element.
**/
- Carousel.prototype._process_role_content = function(content) {
+ Carousel.prototype._process_role_content = function (content) {
content.addClass(this.contentClass());
if (!content.is('ul,ol')) {
content.attr('role', 'list');
}
@@ -703,11 +697,11 @@
*
* Renders a `div` tag that is wrapped around the [[Xooie.Carousel#contents]]. This element is
* rendered only if no other [[Xooie.Carousel#wrappers]] is present as a decendant of the root of this
* widget.
**/
- Carousel.prototype._render_role_wrapper = function() {
+ Carousel.prototype._render_role_wrapper = function () {
var wrapper = $('<div data-x-role="wrapper" />');
this.contents().wrap(wrapper);
return this.contents().parent();
@@ -719,11 +713,11 @@
*
* This method processes the element that has been designated as a [[Xooie.Carousel#wrappers]].
* The [[Xooie.Carousel#wrapperClass]] is added and the [[Xooie.Carousel#_wrapperEvents]] handlers are
* bound. Also, the [[Xooie.Carousel#cropClass]] is added to this element's parent.
**/
- Carousel.prototype._process_role_wrapper = function(wrapper) {
+ Carousel.prototype._process_role_wrapper = function (wrapper) {
wrapper.addClass(this.wrapperClass())
.on(this._wrapperEvents.handlers)
.parent().addClass(this.cropClass());
return wrapper;
@@ -732,28 +726,28 @@
/** internal
* Xooie.Carousel#_get_role_item() -> Element
*
* Gets all children of [[Xooie.Carousel#contents]].
**/
- Carousel.prototype._get_role_item = function() {
+ Carousel.prototype._get_role_item = function () {
return this.contents().children();
};
/** internal
* Xooie.Carousel#_get_role_control() -> Element
*
* TODO: Test and document
**/
- Carousel.prototype._get_role_control = function(){
+ Carousel.prototype._get_role_control = function () {
return this.root().find('[data-x-role^="control"]');
};
/** internal
* Xooie.Carousel#_process_role_control() -> Element
*
**/
- Carousel.prototype._process_role_control = function(controls) {
+ Carousel.prototype._process_role_control = function (controls) {
controls.on(this._controlEvents.handlers);
controls.attr('aria-hidden', true)
.addClass(this.controlClass());
@@ -763,10 +757,10 @@
/** internal
* Xooie.Carousel#_process_resizeEvent() -> String
*
* Adds the [[Xooie.Widget#namespace]] to the `resizeEvent` string.
**/
- Carousel.prototype._process_resizeEvent = function(resizeEvent) {
+ Carousel.prototype._process_resizeEvent = function (resizeEvent) {
return this.namespace() === '' ? resizeEvent : resizeEvent + '.' + this.namespace();
};
return Carousel;
});
\ No newline at end of file