/**
* Progress Bar wrapper.
*
* @author Htmlstream
* @version 1.0
* @requires appear.js (v1.0.3)
*
*/
;(function($){
'use strict';
$.HSCore.components.HSProgressBar = {
/**
*
*
* @var Object _baseConfig
*/
_baseConfig : {
bounds: -100,
debounce: 10,
time: 1000,
fps: 60,
rtl: false,
direction: 'horizontal',
useProgressElement: false,
indicatorSelector: 'progress-bar-indicator',
moveElementSelector: false,
moveElementTo: 'currentPosition',
onChange: function(value){},
beforeUpdate: function(){},
afterUpdate: function(){},
onMoveElementChange: function(value){},
beforeMoveElementUpdate: function(){},
afterMoveElementUpdate: function(){}
},
/**
*
*
* @var jQuery _pageCollection
*/
_pageCollection : $(),
/**
* Initialization of Progress Bar wrapper.
*
* @param String selector (optional)
* @param Object config (optional)
*
* @return jQuery currentCollection - collection of initialized items.
*/
init: function(selector, config){
if(!(selector && $(selector).length)) return;
this.extendHorizontalProgressBar();
this.extendVerticalProgressBar();
return this._initProgressBar(selector, config && $.isPlainObject(config) ? $.extend(true, {}, this._baseConfig, config) : this._baseConfig);
},
/**
*
* Initialization of each Progress Bar of the page.
*
* @return undefined
*/
_initProgressBar: function(selector, config) {
var self = this,
currentCollection = $();
appear({
bounds: config['bounds'],
debounce: config['debounce'],
init: function() {
$(selector).each(function(i, el) {
var $this = $(el);
if(config['direction'] === 'horizontal') {
$this.data('ProgressBar', new self.HorizontalProgressBar($this, config));
}
else {
$this.data('ProgressBar', new self.VerticalProgressBar($this, config));
}
currentCollection = currentCollection.add($this);
self._pageCollection = self._pageCollection.add($this);
});
},
elements: function() {
return document.querySelectorAll(selector);
},
appear: function(el) {
// console.log( $(el).data('ProgressBar'), $(el).data('value') );
$(el).data('ProgressBar').update($(el).data('value'));
}
});
return currentCollection;
},
/**
* Constructor Function of Horizontal Progress Bar
*
* @param jQuery element
* @param Object config
*
*/
HorizontalProgressBar: function(element, config) {
this.element = element;
this.indicator = this.element.find( config.indicatorSelector );
this.config = config;
this.moveElement = config['moveElementSelector'] ? element.parent().find(config['moveElementSelector']) : $();
if(this.moveElement.length) {
if(config['rtl']) {
this.moveElement.css({
'left': 'auto',
'right': 0,
'margin-right': this.moveElement.outerWidth() / -2
});
}
else {
this.moveElement.css({
'left': 0,
'margin-left': this.moveElement.outerWidth() / -2
});
}
}
if(this.config.useProgressElement) {
this.element.data( 'value', this.element.attr( 'value' ) );
this.element.attr('value', 0);
}
else {
this.element.data(
'value',
this.indicator.length ? Math.round( this.indicator.outerWidth() / this.element.outerWidth() * 100 ) : 0
);
this.indicator.css('width', '0%');
}
},
/**
* Constructor Function of Vertical Progress Bar
*
* @param jQuery element
* @param Object config
*
*/
VerticalProgressBar: function(element, config) {
this.element = element;
this.config = config;
this.indicator = element.find(config['indicatorSelector']);
if(!this.indicator.length) return;
element.data('value', parseInt(this.indicator.css('height'), 10) / this.indicator.parent().outerHeight() * 100);
this.indicator.css('height', 0);
},
/**
* Extends HorizontalProgressBar.
*
* @return undefined
*/
extendHorizontalProgressBar: function() {
/**
* Sets new value of the Progress Bar.
*
* @param Number value
*
* @return undefined
*/
this.HorizontalProgressBar.prototype.update = function(value) {
var self = this;
if( this.config.useProgressElement ) {
var fps = (this.config['time'] / this.config['fps']),
iterationValue = parseInt(value / fps, 10),
counter = 0,
self = this;
if(iterationValue == 0) iterationValue = 1;
this.config.beforeUpdate.call(this.element);
if(this.moveElement.length) this.config.beforeMoveElementUpdate.call(this.moveElement);
if(self.config.moveElementSelector && self.config['moveElementTo'] == 'end') {
var mCounter = 0,
mIterationValue = parseInt(100 / fps, 10);
if(mIterationValue == 0) mIterationValue = 1;
var mCounterId = setInterval(function() {
self.moveSubElement(mCounter+=mIterationValue);
if(self.moveElement.length) self.config.onMoveElementChange.call(self.moveElement, mCounter+=mIterationValue);
if(mCounter > 100) {
clearInterval(mCounterId);
self.moveSubElement(100);
if(self.moveElement.length) self.config.afterMoveElementUpdate.call(self.moveElement);
}
}, fps);
}
this.element.data('intervalId', setInterval(function(){
var currentValue = counter += iterationValue;
self.element.attr('value', currentValue);
self.config.onChange.call(self.element, currentValue);
if(self.config.moveElementSelector && self.config['moveElementTo'] == 'currentPosition') self.moveSubElement(currentValue);
if(counter > value) {
self.element.attr('value', value);
if(self.config.moveElementSelector && self.config['moveElementTo'] == 'currentPosition') self.moveSubElement(value);
clearInterval(self.element.data('intervalId'));
self.config.afterUpdate.call(self.element);
}
}, fps));
}
else {
if( this.indicator.length ) {
this.indicator.stop().animate({
'width': value + '%'
}, {
duration: self.config.time,
complete: function() {
self.config.afterUpdate.call(self.element);
}
});
}
}
};
/**
*
*
* @param
*
* @return
*/
this.HorizontalProgressBar.prototype.moveSubElement = function(value, duration) {
if(!this.moveElement.length) return;
var self = this;
this.moveElement.css(this.config['rtl'] ? 'right' : 'left', value + '%');
};
},
/**
* Extends VerticalProgressBars.
*
*
* @return undefined
*/
extendVerticalProgressBar: function() {
/**
* Sets new value of the Progress Bar.
*
* @param Number value
*
* @return undefined
*/
this.VerticalProgressBar.prototype.update = function(value) {
this.indicator.stop().animate({
height: value + '%'
});
}
},
/**
* Returns full collection of all initialized progress bars.
*
*
* @return jQuery _pageCollection
*/
get: function() {
return this._pageCollection;
},
/**
* Returns API of the progress bar by index in collection.
*
* @param Number index
*
* @return HorizontalProgressBar | VerticalProgressBar
*/
getAPI: function(index) {
if(this._pageCollection.eq(index).length) return this._pageCollection.eq(index).data('ProgressBar');
return null;
}
};
})(jQuery);