Source: plugins/pullup.js

"use strict";
var Util = require('../util');
var Base = require('../base');
var clsPrefix;
var containerCls;
var loadingContent = "Loading...";
var upContent = "Pull Up To Refresh";
var downContent = "Release To Refresh";
var PULL_UP_HEIGHT = 60;
var HEIGHT = 40;
/**
 * A pullup to load plugin for xscroll.
 * @constructor
 * @param {object} cfg
 * @param {number} cfg.height
 * @param {string} cfg.downContent
 * @param {string} cfg.upContent
 * @param {string} cfg.loadingContent
 * @param {string} cfg.clsPrefix  class prefix which default value is "xs-plugin-pullup-"
 * @param {number} cfg.bufferHeight preload data before scrolling to the bottom of the boundry
 * @extends {Base}
 */
var PullUp = function(cfg) {
	PullUp.superclass.constructor.call(this);
	this.userConfig = Util.mix({
		upContent: upContent,
		downContent: downContent,
		pullUpHeight: PULL_UP_HEIGHT,
		height: HEIGHT,
		loadingContent: loadingContent,
		bufferHeight: 0,
		clsPrefix: "xs-plugin-pullup-"
	}, cfg);
}
Util.extend(PullUp, Base, {
	/**
	 * a pluginId
	 * @memberOf PullUp
	 * @type {string}
	 */
	pluginId: "pullup",
	/**
	 * plugin initializer
	 * @memberOf PullUp
	 * @override Base
	 * @return {PullUp}
	 */
	pluginInitializer: function(xscroll) {
		var self = this;
		self.xscroll = xscroll.render();
		clsPrefix = self.userConfig.clsPrefix;
		self.render();
		return self;
	},
	/**
	 * detroy the plugin
	 * @memberOf PullUp
	 * @override Base
	 * @return {PullUp}
	 */
	pluginDestructor: function() {
		var self = this;
		Util.remove(self.pullup);		
		self.xscroll.off("scrollend", self._scrollEndHandler, self);
		self.xscroll.off("scroll", self._scrollHandler, self);
		self.xscroll.off("pan", self._panHandler, self);
		self.xscroll.boundry.resetBottom();
		self.__isRender = false;
		self._evtBinded = false;
	},
	/**
	 * render pullup plugin
	 * @memberOf PullUp
	 * @return {PullUp}
	 */
	render: function() {
		var self = this;
		if (self.__isRender) return;
		self.__isRender = true;
		var containerCls = clsPrefix + "container";
		var height = self.userConfig.height;
		var pullup = self.pullup = document.createElement("div");
		pullup.className = containerCls;
		pullup.style.position = "absolute";
		pullup.style.width = "100%";
		pullup.style.height = height + "px";
		pullup.style.bottom = -height + "px";
		self.xscroll.container.appendChild(pullup);
		self.xscroll.boundry.expandBottom(self.userConfig.height);
		self.status = 'up';
		Util.addClass(pullup, clsPrefix + self.status);
		pullup.innerHTML = self.userConfig[self.status + "Content"] || self.userConfig.content;
		self._bindEvt();
		return self;
	},
	_bindEvt: function() {
		var self = this;
		if (self._evtBinded) return;
		self._evtBinded = true;
		var pullup = self.pullup;
		var xscroll = self.xscroll;
		xscroll.on("pan", self._panHandler, self);
		//load width a buffer
		if (self.userConfig.bufferHeight > 0) {
			xscroll.on("scroll", self._scrollHandler, self);
		}
		//bounce bottom
		xscroll.on("scrollend", self._scrollEndHandler, self);
		return self;
	},
	_scrollEndHandler: function(e) {
		var self = this,
			xscroll = self.xscroll,
			scrollTop = xscroll.getScrollTop();
		if (scrollTop == xscroll.containerHeight - xscroll.height + self.userConfig.height) {
			self._changeStatus("loading");
		}
		return self;
	},
	_scrollHandler: function(e) {
		var self = this,
			xscroll = self.xscroll;
		if (!self.isLoading && Math.abs(e.scrollTop) + xscroll.height + self.userConfig.height + self.userConfig.bufferHeight >= xscroll.containerHeight + xscroll.boundry._xtop + xscroll.boundry._xbottom) {
			self._changeStatus("loading");
		}
		return self;
	},
	_panHandler: function(e) {
		var self = this;
		var xscroll = self.xscroll;
		var offsetTop = -xscroll.getScrollTop();
		if (offsetTop < xscroll.height - xscroll.containerHeight - self.userConfig.pullUpHeight) {
			self._changeStatus("down")
		} else {
			self._changeStatus("up");
		}
		return self;
	},
	_changeStatus: function(status) {
		if (status != "loading" && this.isLoading) return;
		var prevVal = this.status;
		this.status = status;
		Util.removeClass(this.pullup, clsPrefix + prevVal)
		Util.addClass(this.pullup, clsPrefix + status);
		this.pullup.innerHTML = this.userConfig[status + "Content"];
		if (prevVal != status) {
			this.trigger("statuschange", {
				prevVal: prevVal,
				newVal: status
			});
			if (status == "loading") {
				this.isLoading = true;
				this.trigger("loading");
			}
		}
		return this;
	},
	/**
	 * notify pullup plugin to complete state after a remote data request
	 * @memberOf PullUp
	 * @return {PullUp}
	 */
	complete: function() {
		var self = this;
		var xscroll = self.xscroll;
		self.isLoading = false;
		self._changeStatus("up");
		return self;
	}
});

if (typeof module == 'object' && module.exports) {
	module.exports = PullUp;
}