codice:
/**
* Slider Simulator
*
*/
if (typeof(AC) == "undefined") AC = {};
AC.Slider = Class.create();
AC.Slider.prototype = {
orientation: 'horizontal',
container: null,
items: null,
currentPage: 1,
itemsPerPage: null,
totalPages: null,
maskInnerDimension: null,
isAnimating: false,
initialize: function(containerId, sliderElements) {
this.items = new Array();
this.container = $(containerId);
this.populate(sliderElements);
},
populate: function() {
this.container.innerHTML = 'The slider requires population with data. You need to call this.render(itemsPerList) from your custom this.populate() function.';
// ????? throw new TypeError('The slider requires population with data. You need to call this.render(itemsPerList) from your custom this.populate() function.');
},
render: function(itemsPerList) {
this.container.innerHTML = '';
// TODO figure out the itemsPerList when it's not specified
this.itemsPerPage = itemsPerList;
this.list = Builder.node('ul', this.renderItems() );
var mask = Builder.node('div', { 'class':'ACSliderMaskDiv' }, [this.list]);
this.container.appendChild(mask);
this.totalPages = Math.ceil(this.items.length/this.itemsPerPage);
if (this.items.length > this.itemsPerPage) {
this.positionWithinMask(mask);
this.createArrows();
this.createDots();
}
},
positionWithinMask: function(mask) {
if (this.orientation == 'horizontal') {
this.maskInnerDimension = Element.getInnerDimensions(mask).width;
this.list.style.left = -this.maskInnerDimension*this.currentPage +'px';
} else {
this.maskInnerDimension = Element.getInnerDimensions(mask).height;
this.list.style.top = -this.maskInnerDimension*this.currentPage +'px';
}
},
renderItems: function() {
var list = [];
var lastPageStart = this.items.length-this.items.length%this.itemsPerPage;
if (lastPageStart==this.items.length) lastPageStart = this.items.length-this.itemsPerPage;
var overflowAmount = this.itemsPerPage-this.items.length%this.itemsPerPage;
if (overflowAmount==this.itemsPerPage) overflowAmount = 0;
var multiplePages = this.items.length > this.itemsPerPage;
// copy the last page before the first page
if (multiplePages) {
list.push(this.renderPlaceholderItems(lastPageStart, this.items.length));
// empty nodes as space filler before the all the pages
for (var i=0; i<overflowAmount; i++) {
var listItem = Builder.node('li', {'class': 'empty'});
list.push(listItem);
}
}
// create all the pages
for (var i=0; i<this.items.length; i++) {
var listItem = this.items[i].render().cloneNode(true);
list.push(listItem);
}
if (multiplePages) {
// empty nodes as space filler before the copy of the first page
for (var i=0; i<overflowAmount; i++) {
var listItem = Builder.node('li', {'class': 'empty'});
list.push(listItem);
}
// copy the first page after the last page
list.push(this.renderPlaceholderItems(0, this.itemsPerPage));
}
return list;
},
renderPlaceholderItems: function(start, finish) {
var list = [];
for (var i=start; i<finish; i++) {
var listItem = this.items[i].render().cloneNode(true);
// try and retain unique ids
if (listItem.id) listItem.removeAttribute('id');
for (var j=0, child; child=listItem.childNodes[j]; j++) {
if (child.getAttribute('id')) child.removeAttribute('id');
}
$(listItem).addClassName('cloned');
list.push(listItem);
}
return list;
},
createArrows: function() {
// previous arrow
var prevArrow = Builder.node('a', { 'class':'ACSliderPreviousArrow' }, '<');
$(prevArrow).observe('click', function(evt) {
Event.stop(evt);
this.getPrevious();
}.bind(this));
this.container.appendChild(prevArrow);
// next arrow
var nextArrow = Builder.node('a', { 'class':'ACSliderNextArrow' }, '>');
$(nextArrow).observe('click', function(evt) {
Event.stop(evt);
this.getNext();
}.bind(this));
this.container.appendChild(nextArrow);
},
createDots: function() {
this.pageNav = Builder.node('ul', { 'class':'ACSliderPageNav' });
for (var i=1; i<=this.totalPages; i++) {
var navListItemAnchor = (i==this.currentPage) ? Builder.node('a', { 'class':'active' }, i) : Builder.node('a', i);
$(navListItemAnchor).observe('click', function(evt, pageNumber) {
Event.stop(evt);
this.scrolltoPageNumber(pageNumber);
}.bindAsEventListener(this, i));
var navListItem = Builder.node('li', [navListItemAnchor]);
this.pageNav.appendChild(navListItem);
}
this.container.appendChild(this.pageNav);
},
getPrevious: function() {
var previousPageIndex = this.currentPage - 1;
this.scrolltoPageNumber(previousPageIndex, 1);
},
getNext: function() {
var nextPageIndex = this.currentPage + 1;
this.scrolltoPageNumber(nextPageIndex, -1);
},
scrolltoPageNumber: function(toPageNumber, direction) {
// if we're not going to the current page & we're not already doing something ...
if (this.currentPage != toPageNumber && !this.isAnimating) {
// if we don't know the direction, figure it out (-1 is next, 1 is previous)
if (!direction) var direction = this.currentPage-toPageNumber;
this.isAnimating = true;
// set the current page to the one we're going to
this.currentPage = toPageNumber;
// and fix the number if we're going to before the first page or page after the last page
this.resetPages();
// remove the 'active' class on the page nav items
var pageNavAnchors = this.pageNav.getElementsByTagName('a');
for (var i=0, anchor; anchor=pageNavAnchors[i]; i++) {
if (Element.hasClassName(anchor, 'active')) Element.removeClassName(anchor, 'active');
if (anchor.innerHTML==this.currentPage) Element.addClassName(anchor, 'active');
}
// try {console.debug(this.list,"Scrolling to page", toPageNumber);} catch(e) {}
// do the scroll
var options = {
duration: 0.5,
queue: { position:'end', scope:'sliderQueue', limit:1 },
afterFinish: this.afterScroll.bind(this)
};
// TODO slider needs to be reworked, pretty inflexible
//may not always have the mask dimensions prior to this point.
//probably need to maintain a reference to the mask itself to
//recalculate the dimendions if necessary. Only recalculating
//if it's 0 right now but could do it more often to aid in
//flexibile resizing
if (!this.maskInnerDimension) {
this.positionWithinMask(this.container);
}
if (this.orientation == 'horizontal') {
// try {console.debug("X: ", this.maskInnerDimension*direction);} catch(e) {}
new Effect.MoveBy(this.list, 0, this.maskInnerDimension*direction, options);
} else {
new Effect.MoveBy(this.list, this.maskInnerDimension*direction, 0, options);
}
}
},
jumptoPageNumber: function(toPageNumber) {
// if we're not going to the current page & we're not already doing something ...
if (this.currentPage != toPageNumber && !this.isAnimating) {
// figure out the direction (-1 is next, 1 is previous)
var direction = this.currentPage-toPageNumber;
// set the current page to the one we're going to
this.currentPage = toPageNumber;
// and fix the number if we're going to before the first page or page after the last page
this.resetPages();
// remove the 'active' class on the page nav items
var pageNavAnchors = this.pageNav.getElementsByTagName('a');
for (var i=0, anchor; anchor=pageNavAnchors[i]; i++) {
if (Element.hasClassName(anchor, 'active')) Element.removeClassName(anchor, 'active');
if (anchor.innerHTML==this.currentPage) Element.addClassName(anchor, 'active');
}
var options = {
duration: 0.0};
// do the scroll
if (this.orientation == 'horizontal') {
new Effect.MoveBy(this.list, 0, this.maskInnerDimension*direction, options);
} else {
new Effect.MoveBy(this.list, this.maskInnerDimension*direction, 0, options);
}
}
},
resetPages: function() {
if (this.currentPage == 0) {
this.currentPage = this.totalPages;
this.positionOffset = -this.maskInnerDimension*this.totalPages +'px';
} else if (this.currentPage == this.totalPages+1) {
this.currentPage = 1;
this.positionOffset = -this.maskInnerDimension+'px';
} else {
this.positionOffset = false;
}
},
afterScroll: function() {
// set the position of the list to the actual page number position value
if (this.positionOffset) {
if (this.orientation == 'horizontal') {
this.list.style.left = this.positionOffset;
} else {
this.list.style.top = this.positionOffset;
}
}
// reset the animating flag
this.isAnimating = false;
},
jumpToPage: function(toPageNumber) {
}
};
AC.SliderItem = Class.create();
AC.SliderItem.prototype = {
html: 'List items must be populated with data; it can be an HTML object or HTML as a string.',
initialize: function(input) {
if (input) this.html = input;
// ???? else throw new TypeError(this.html);
},
render: function() {
if (typeof(this.html) == 'string') {
var li = Builder.node('li');
li.innerHTML = this.html;
} else {
var li = Builder.node('li', [this.html]);
}
return li;
}
};
non ho tempo per studiarlo... veditelo, poi quando posso ci butto un'occhiata anch'io