embd/bower_components/gumby/js/libs/ui/gumby.skiplink.js

158 lines
3.6 KiB
JavaScript

/**
* Gumby SkipLink
*/
!function($) {
'use strict';
function SkipLink($el) {
Gumby.debug('Initializing Skiplink', $el);
this.$el = $el;
this.targetPos = 0;
this.duration = 0;
this.offset = false;
this.easing = '';
this.update = false;
// set up module based on attributes
this.setup();
var scope = this;
// skip to target element on click or trigger of gumby.skipTo event
this.$el.on(Gumby.click+' gumby.skip', function(e) {
e.preventDefault();
if(e.namespace === 'skip') {
Gumby.debug('Skip event triggered', scope.$el);
}
// calculate target on each click if update var set to true
if(scope.update) {
scope.calculateTarget(scope.skipTo);
// skip straight to target
} else {
scope.skipTo();
}
}).on('gumby.initialize', function() {
Gumby.debug('Re-initializing Skiplink', scope.$el);
scope.setup();
});
}
// set up module based on attributes
SkipLink.prototype.setup = function() {
this.duration = Number(Gumby.selectAttr.apply(this.$el, ['duration'])) || 200;
this.offset = Gumby.selectAttr.apply(this.$el, ['offset']) || false;
this.easing = Gumby.selectAttr.apply(this.$el, ['easing']) || 'swing';
this.update = Gumby.selectAttr.apply(this.$el, ['update']) ? true : false;
this.calculateTarget();
};
// calculate target px point to skip to
SkipLink.prototype.calculateTarget = function(cb) {
var scope = this,
target = Gumby.selectAttr.apply(this.$el, ['goto']),
$target;
// 'top' specified so target is 0px
if(target == 'top') {
this.targetPos = 0;
// px point specified
} else if($.isNumeric(target)) {
this.targetPos = Number(target);
} else {
// check for element with target as selector
$target = $(target);
// target does not exist, we need a target
if(!$target.length) {
Gumby.error('Cannot find skiplink target: '+target);
return false;
}
this.targetPos = $target.offset().top;
}
if(cb) {
cb.apply(this);
}
};
// animate body, html scrollTop value to target px point
SkipLink.prototype.skipTo = function() {
Gumby.debug('Skipping to target', this.$el);
var scope = this;
// slide to position of target
$('html,body').animate({
'scrollTop' : this.calculateOffset()
}, this.duration, this.easing).promise().done(function() {
Gumby.debug('Triggering onComplete event', scope.$el);
scope.$el.trigger('gumby.onComplete');
});
};
// calculate offset with current target point
SkipLink.prototype.calculateOffset = function() {
// no offset so return target here
if(!this.offset) {
return this.targetPos;
}
// negative / positive
var op = this.offset.substr(0, 1),
off = Number(this.offset.substr(1, this.offset.length));
// subtract offset from target position
if(op === '-') {
return this.targetPos - off;
// add offset to target position
} else if(op === '+') {
return this.targetPos + off;
}
};
// add initialisation
Gumby.addInitalisation('skiplink', function(all) {
$('.skiplink > a, .skip').each(function() {
var $this = $(this);
// this element has already been initialized
// and we're only initializing new modules
if($this.data('isSkipLink') && !all) {
return true;
// this element has already been initialized
// and we need to reinitialize it
} else if($this.data('isSkipLink') && all) {
$this.trigger('gumby.initialize');
return true;
}
// mark element as initialized
$this.data('isSkipLink', true);
new SkipLink($this);
});
});
// register UI module
Gumby.UIModule({
module: 'skiplink',
events: ['initialize', 'onComplete', 'skip'],
init: function() {
Gumby.initialize('skiplink');
}
});
}(jQuery);