slideheader
Version:
A JavaScript plugin to display or hide headerbar with a sliding motion
231 lines (230 loc) • 10.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var slideheader_model_1 = require("./slideheader.model");
var SlideHeader = /** @class */ (function () {
/**
* インスタンスを生成する
* @param element
* @param options
*/
function SlideHeader(element, options) {
/** メソッドタイプ */
this.methodType = slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_DOWN;
/** ヘッダバーのスライドの方向 */
this.slideDirection = slideheader_model_1.SlideHeaderModel.SlideType.UP;
/** オプション設定 */
this.config = {};
if (!element) {
throw new Error('element must not be null.');
}
this.element = document.querySelector(element);
if (this.element instanceof HTMLElement === false) {
throw new Error('querySelector does not find appropriate element.');
}
this.options = options;
this.defaults = {
headerBarHeight: this.element.clientHeight,
headerBarWidth: '100%',
header2SelectorName: '.cb-header2',
zIndex: 9999,
boxShadow: 'none',
opacity: 1,
slidePoint: 0,
slideDownDuration: '500ms',
slideUpDuration: '500ms',
slideDownTiming: slideheader_model_1.SlideHeaderModel.SlideTiming.EASE,
slideUpTiming: slideheader_model_1.SlideHeaderModel.SlideTiming.EASE,
slideDownCallback: function () { },
slideUpCallback: function () { },
cloneHeader: false,
fullscreenView: false,
headroom: false,
};
}
Object.defineProperty(SlideHeader.prototype, "isHeadroom", {
/** headroomオプジョンが有効かどうか */
get: function () {
if (this.config.headroom === undefined || this.config.headroom === null) {
return false;
}
return this.methodType === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_UP && this.config.headroom;
},
enumerable: true,
configurable: true
});
/**
* ヘッダーバーのアニメーションを制御する
* @param top
* @param slideType
*/
SlideHeader.prototype.controlHeaderAnimations = function (slideType, top) {
var slideDuration = this.config["slide" + slideType + "Duration"];
var slideTiming = this.config["slide" + slideType + "Timing"];
this.element.style.transition = "transform " + slideDuration + " " + slideTiming;
this.element.style.transform = "translate3d(0, " + top + ", 0)";
this.slideDirection = this.slideDirection === slideheader_model_1.SlideHeaderModel.SlideType.UP ? slideheader_model_1.SlideHeaderModel.SlideType.DOWN : slideheader_model_1.SlideHeaderModel.SlideType.UP;
};
/**
* ブラウザをスクロールした時に呼び出される処理
* @param currentScrollTop
* @param startingScrollTop
* @param slideType
*/
SlideHeader.prototype.handleScroll = function (currentScrollTop, startingScrollTop, slideType) {
if (this.config.slidePoint === undefined || this.config.slidePoint === null) {
throw new Error('slidePoint must not to be undefined.');
}
var top1 = this.methodType === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_DOWN ? 0 : "-" + this.config.headerBarHeight + "px";
var top2 = this.methodType === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_DOWN ? "-" + this.config.headerBarHeight + "px" : 0;
if (currentScrollTop > this.config.slidePoint && currentScrollTop > startingScrollTop) {
if (this.slideDirection === slideheader_model_1.SlideHeaderModel.SlideType.UP) {
this.controlHeaderAnimations(slideType, top1);
}
}
else {
if (this.slideDirection === slideheader_model_1.SlideHeaderModel.SlideType.DOWN) {
this.controlHeaderAnimations(slideType, top2);
}
}
};
/**
* scrollイベントを監視する
* @param slideType1
* @param slideType2
*/
SlideHeader.prototype.listenScroll = function (slideType1, slideType2) {
var _this = this;
var startingScrollTop = 0; // スライドの開始位置
var currentScrollTop = 0; // 現在のスクロールの位置
window.addEventListener('scroll', function () {
var frameId = 0;
cancelAnimationFrame(frameId);
frameId = requestAnimationFrame(function () {
currentScrollTop = window.scrollY;
var slideType = _this.slideDirection === slideheader_model_1.SlideHeaderModel.SlideType.UP ? slideType1 : slideType2;
_this.handleScroll(currentScrollTop, startingScrollTop, slideType);
if (_this.isHeadroom) {
startingScrollTop = currentScrollTop;
}
});
}, false);
};
/**
* ヘッダーバーのアニメーションが終わった時に呼び出される処理
* @param slideType
* @param style
*/
SlideHeader.prototype.handleTransitionend = function (slideType, style) {
this.element.style.boxShadow = style;
if (typeof this.config["slide" + slideType + "Callback"] === 'function') {
this.config["slide" + slideType + "Callback"]();
}
};
/**
* TransitionEndイベントを監視する
* @param slideType1
* @param slideType2
*/
SlideHeader.prototype.listenTransitionEnd = function (slideType1, slideType2) {
var _this = this;
var boxShadowStyle1 = "" + this.config.boxShadow;
var boxShadowStyle2 = 'none';
var boxShadow1 = this.methodType === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_DOWN ? boxShadowStyle1 : boxShadowStyle2;
var boxShadow2 = this.methodType === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_DOWN ? boxShadowStyle2 : boxShadowStyle1;
window.addEventListener('transitionend', function () {
var slideType = _this.slideDirection === slideheader_model_1.SlideHeaderModel.SlideType.UP ? slideType1 : slideType2;
var boxShadow = _this.slideDirection === slideheader_model_1.SlideHeaderModel.SlideType.UP ? boxShadow1 : boxShadow2;
_this.handleTransitionend(slideType, boxShadow);
}, false);
};
/**
* SlideHeaderのメイン処理
*/
SlideHeader.prototype.excuteSlideHeader = function () {
var slideType1 = this.methodType === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_DOWN ? slideheader_model_1.SlideHeaderModel.SlideType.DOWN : slideheader_model_1.SlideHeaderModel.SlideType.UP;
var slideType2 = this.methodType === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_DOWN ? slideheader_model_1.SlideHeaderModel.SlideType.UP : slideheader_model_1.SlideHeaderModel.SlideType.DOWN;
this.listenScroll(slideType1, slideType2);
this.listenTransitionEnd(slideType1, slideType2);
};
/**
* ヘッダーバーの初期スタイルを適用する
*/
SlideHeader.prototype.applyDefaultHeaderStyles = function () {
var top = this.methodType === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_DOWN ? "-" + this.config.headerBarHeight + "px" : 0;
this.element.style.transform = "translate3d(0, " + top + ", 0)";
this.element.style.visibility = 'visible';
this.element.style.opacity = "" + this.config.opacity;
this.element.style.width = "" + this.config.headerBarWidth;
this.element.style.zIndex = "" + this.config.zIndex;
};
/**
* ヘッダーバーを複製する
* cloneHeaderがtrueの時のみ呼び出される
*/
SlideHeader.prototype.cloneHeader = function () {
if (!this.element.parentNode) {
throw new Error('parentNode does not be found.');
}
var clonedElement = this.element.cloneNode(true);
this.element.parentNode.insertBefore(clonedElement, this.element.nextElementSibling);
clonedElement.removeAttribute('class');
clonedElement.setAttribute('class', 'cb-header1');
clonedElement.style.zIndex = '10000';
};
/**
* フルスクリーン要素(header2)の高さを適用する
* fullscreenViewがtrueの時のみ呼び出される
*/
SlideHeader.prototype.applyHeader2Styles = function () {
if (!this.config.header2SelectorName) {
throw new Error('header2SelectorName must not be undefined.');
}
var header2 = document.querySelector(this.config.header2SelectorName);
if (header2 instanceof HTMLElement === false) {
throw new Error('querySelector does not find appropriate element.');
}
var headerBarHeight = this.element.clientHeight;
var headerHeight = headerBarHeight + header2.clientHeight;
var windowHeight = window.outerHeight;
if (windowHeight > headerHeight) {
var padding = this.config.cloneHeader
? (windowHeight - headerHeight) / 2
: (windowHeight - headerHeight + headerBarHeight) / 2;
header2.style.paddingTop = padding + "px";
header2.style.paddingBottom = padding + "px";
this.config.slidePoint = windowHeight;
}
else {
this.config.slidePoint = this.config.cloneHeader ? headerHeight : headerHeight - headerBarHeight;
}
};
/**
* オプションをマージする
* @param defaults
* @param options
*/
SlideHeader.prototype.mergeOptions = function (defaults, options) {
return Object.assign({}, defaults, options);
};
/**
* インスタンスを初期化する
* @param type
*/
SlideHeader.prototype.init = function (type) {
if (!(type && (type === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_UP || type === slideheader_model_1.SlideHeaderModel.MethodType.SLIDE_DOWN))) {
throw new Error('type does not found and is not type of MethodType.');
}
this.methodType = type;
this.config = this.mergeOptions(this.defaults, this.options);
if (this.config.cloneHeader) {
this.cloneHeader();
}
this.applyDefaultHeaderStyles();
if (this.config.fullscreenView) {
this.applyHeader2Styles();
}
this.excuteSlideHeader();
};
return SlideHeader;
}());
exports.default = SlideHeader;