| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- define(function(require, exports, module) {
- "use strict";
- var Util = require('../util');
- var Base = require('../base');
- //transform
- var transform = Util.prefixStyle("transform");
- // default render function for position:sticky elements
- var defaultStickyRenderFunc = function(e) {
- var stickyElement = e.stickyElement;
- var curStickyElement = e.curStickyElement;
- var xscroll = e.xscroll;
- var _ = e._;
- var infinite = xscroll.getPlugin("infinite");
- if (infinite) {
- infinite.userConfig.renderHook.call(self, stickyElement, curStickyElement);
- stickyElement.setAttribute("xs-guid", curStickyElement.guid);
- Util.addClass(stickyElement, curStickyElement.className);
- for (var attrName in curStickyElement.style) {
- if (attrName != "display" && attrName != "position") {
- //copy styles
- stickyElement.style[attrName] = attrName == _.height ? curStickyElement.style[attrName] + 'px' : curStickyElement.style[attrName];
- }
- }
- } else {
- var style = curStickyElement.getAttribute("style");
- stickyElement.innerHTML = curStickyElement.innerHTML;
- stickyElement.className = curStickyElement.className;
- style && stickyElement.setAttribute("style", style);
- }
- }
- var Sticky = function(cfg) {
- Sticky.superclass.constructor.call(this, cfg);
- this.userConfig = Util.mix({
- stickyRenderTo: undefined,
- forceSticky: true,
- prefix: "xs-sticky-container",
- stickyRenderFunc: defaultStickyRenderFunc,
- zoomType: "y"
- }, cfg);
- this.init();
- }
- Util.extend(Sticky, Base, {
- init: function() {
- var self = this,
- userConfig = self.userConfig,
- xscroll = self.xscroll = userConfig.xscroll;
- var isY = self.isY = !!(userConfig.zoomType == "y");
- self._ = {
- top: self.isY ? "top" : "left",
- left: self.isY ? "left" : "bottom",
- right: self.isY ? "right" : "top",
- height: self.isY ? "height" : "width",
- width: self.isY ? "width" : "height"
- };
- self.stickyRenderTo = Util.getNode(userConfig.stickyRenderTo);
- self._handlers = [];
- return self;
- },
- getStickiesPos: function() {
- var self = this;
- var xscroll = self.xscroll;
- var isInfinite = self.isInfinite;
- var isY = self.isY;
- var _ = self._;
- var stickiesPos = [];
- var getPos = function(sticky) {
- var pos = {};
- if (isInfinite) {
- pos[_.top] = isY ? sticky._top : sticky._left;
- pos[_.height] = isY ? sticky._height : sticky._width;
- } else {
- pos[_.top] = self.isY ? Util.getOffsetTop(sticky) : Util.getOffsetLeft(sticky);
- pos[_.height] = self.isY ? sticky.offsetHeight : sticky.offsetWidth;
- }
- return pos;
- }
- for (var i = 0; i < self.stickiesNum; i++) {
- var pos = getPos(self.stickyElements[i]);
- self._handlers[i] = self._handlers[i] || self.createStickyEl();
- pos.el = self._handlers[i];
- pos.isRender = false;
- stickiesPos.push(pos);
- }
- return stickiesPos
- },
- getStickyElements: function() {
- var self = this;
- var xscroll = self.xscroll;
- var userConfig = self.userConfig;
- var isInfinite = self.isInfinite;
- var infinite = xscroll.getPlugin("infinite");
- if (infinite) {
- var stickyElements = [],
- serializedData = infinite.__serializedData;
- for (var i in serializedData) {
- var rowData = serializedData[i];
- if (rowData && rowData.style && "sticky" == rowData.style.position) {
- stickyElements.push(rowData);
- }
- }
- return stickyElements;
- } else {
- return Util.getNodes(xscroll.userConfig.stickyElements, xscroll.content);
- }
- },
- render: function(force) {
- var self = this;
- var userConfig = self.userConfig;
- var xscroll = self.xscroll;
- self.isInfinite = !!xscroll.getPlugin("infinite");
- var _ = self._;
- self.stickyElements = self.getStickyElements();
- self.stickiesNum = self.stickyElements && self.stickyElements.length;
- if (!self.stickiesNum) return;
- if (!self.stickyRenderTo) {
- self.stickyRenderTo = document.createElement('div');
- xscroll.renderTo.appendChild(self.stickyRenderTo);
- }
- self.stickiesPos = self.getStickiesPos();
- var stickyRenderTo = self.stickyRenderTo;
- stickyRenderTo.style[_.top] = 0;
- stickyRenderTo.style[_.left] = 0;
- stickyRenderTo.style[_.right] = 0;
- stickyRenderTo.style.position = xscroll.userConfig.useOriginScroll ? "fixed" : "absolute";
- Util.addClass(self.stickyRenderTo, userConfig.prefix);
- self.stickyHandler(force);
- self._bindEvt();
- },
- createStickyEl: function() {
- var self = this;
- var el = document.createElement('div');
- el.style.display = "none";
- Util.addClass(el, "xs-sticky-handler");
- self.stickyRenderTo.appendChild(el);
- return el;
- },
- _bindEvt: function() {
- var self = this,
- xscroll = self.xscroll;
- xscroll.on("scroll", self.stickyHandler, self);
- },
- stickyHandler: function(force) {
- var self = this;
- var xscroll = self.xscroll;
- var userConfig = self.userConfig;
- var scrollTop = self.isY ? xscroll.getScrollTop() : xscroll.getScrollLeft();
- var stickiesPos = self.stickiesPos;
- var _ = self._;
- var indexes = [];
- for (var i = 0, l = stickiesPos.length; i < l; i++) {
- var top = stickiesPos[i][_.top];
- if (scrollTop > top) {
- indexes.push(i);
- }
- }
- if (!indexes.length) {
- if (self.stickyElement) {
- self.stickyElement.style.display = "none";
- }
- self.curStickyIndex = undefined;
- return;
- }
- var curStickyIndex = Math.max.apply(null, indexes);
- if (self.curStickyIndex != curStickyIndex || force) {
- var prevStickyIndex = self.curStickyIndex;
- self.curStickyIndex = curStickyIndex;
- self.curStickyElement = self.stickyElements[curStickyIndex];
- self.curStickyPos = stickiesPos[curStickyIndex];
- self.stickyElement = self.curStickyPos.el;
- for (var i = 0, l = stickiesPos.length; i < l; i++) {
- stickiesPos[i].el.style.display = "none";
- }
- var eventsObj = {
- stickyElement: self.stickyElement,
- curStickyIndex: self.curStickyIndex,
- prevStickyIndex: prevStickyIndex,
- curStickyPos: self.curStickyPos,
- isRender: self.curStickyPos.isRender
- };
- xscroll.trigger("beforestickychange", eventsObj);
- self._stickyRenderFunc(self);
- xscroll.trigger("stickychange", eventsObj);
- }
- var trans = 0;
- if (self.stickiesPos[self.curStickyIndex + 1]) {
- var cur = self.stickiesPos[self.curStickyIndex];
- var next = self.stickiesPos[self.curStickyIndex + 1];
- if (scrollTop + cur[_.height] > next[_.top] && scrollTop + cur[_.height] < next[_.top] + cur[_.height]) {
- trans = cur[_.height] + scrollTop - next[_.top];
- } else {
- trans = 0;
- }
- }
- self.stickyElement.style[transform] = self.isY ? "translateY(-" + (trans) + "px) translateZ(0)" : "translateX(-" + (trans) + "px) translateZ(0)";
- },
- _stickyRenderFunc: function(e) {
- var self = this;
- var _ = self._;
- var stickyRenderFunc = self.userConfig.stickyRenderFunc;
- var el = self.curStickyPos.el;
- if (!self.curStickyPos.isRender) {
- el.style[_.left] = 0;
- el.style[_.right] = 0;
- stickyRenderFunc && stickyRenderFunc.call(self, e);
- }
- el.style.display = "block";
- self.curStickyPos.isRender = true;
- },
- destroy: function() {
- var self = this;
- self.stickyElements = undefined;
- self.stickiesNum = undefined;
- self.stickiesPos = undefined;
- Util.remove(self.stickyElement);
- self.stickyElement = undefined;
- }
- });
- if (typeof module == 'object' && module.exports) {
- module.exports = Sticky;
- }
- /** ignored by jsdoc **/
- else {
- return Sticky;
- }
- });
|