Created
June 2, 2015 03:34
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! Metro -v0.2.7 - 2015-05-29 */ | |
!function() { | |
function template(filename, content) { | |
return (/string|function/.test(typeof content) ? compile : renderFile)(filename, content); | |
} | |
function toString(value, type) { | |
return "string" != typeof value && (type = typeof value, "number" === type ? value += "" : value = "function" === type ? toString(value.call(value)) : ""), | |
value; | |
} | |
function escapeFn(s) { | |
return escapeMap[s]; | |
} | |
function escapeHTML(content) { | |
return toString(content).replace(/&(?![\w#]+;)|[<>"']/g, escapeFn); | |
} | |
function each(data, callback) { | |
if (isArray(data)) for (var i = 0, len = data.length; len > i; i++) callback.call(data, data[i], i, data); else for (i in data) callback.call(data, data[i], i); | |
} | |
function resolve(from, to) { | |
var DOUBLE_DOT_RE = /(\/)[^/]+\1\.\.\1/, dirname = ("./" + from).replace(/[^/]+$/, ""), filename = dirname + to; | |
for (filename = filename.replace(/\/\.\//g, "/"); filename.match(DOUBLE_DOT_RE); ) filename = filename.replace(DOUBLE_DOT_RE, "/"); | |
return filename; | |
} | |
function renderFile(filename, data) { | |
var fn = template.get(filename) || showDebugInfo({ | |
filename: filename, | |
name: "Render Error", | |
message: "Template not found" | |
}); | |
return data ? fn(data) : fn; | |
} | |
function compile(filename, fn) { | |
if ("string" == typeof fn) { | |
var string = fn; | |
fn = function() { | |
return new String(string); | |
}; | |
} | |
var render = cache[filename] = function(data) { | |
try { | |
return new fn(data, filename) + ""; | |
} catch (e) { | |
return showDebugInfo(e)(); | |
} | |
}; | |
return render.prototype = fn.prototype = utils, render.toString = function() { | |
return fn + ""; | |
}, render; | |
} | |
function showDebugInfo(e) { | |
var type = "{Template Error}", message = e.stack || ""; | |
if (message) message = message.split("\n").slice(0, 2).join("\n"); else for (var name in e) message += "<" + name + ">\n" + e[name] + "\n\n"; | |
return function() { | |
return "object" == typeof console && console.error(type + "\n\n" + message), type; | |
}; | |
} | |
var cache = template.cache = {}, String = this.String, escapeMap = { | |
"<": "<", | |
">": ">", | |
'"': """, | |
"'": "'", | |
"&": "&" | |
}, isArray = Array.isArray || function(obj) { | |
return "[object Array]" === {}.toString.call(obj); | |
}, utils = template.utils = { | |
$helpers: {}, | |
$include: function(filename, data, from) { | |
return filename = resolve(from, filename), renderFile(filename, data); | |
}, | |
$string: toString, | |
$escape: escapeHTML, | |
$each: each | |
}, helpers = template.helpers = utils.$helpers; | |
template.get = function(filename) { | |
return cache[filename.replace(/^\.\//, "")]; | |
}, template.helper = function(name, helper) { | |
helpers[name] = helper; | |
}, "function" == typeof define ? define("Components/Metro/template", function() { | |
return template; | |
}) : "undefined" != typeof exports ? module.exports = template : this.templateMetro = template, | |
template.helper("dateFormat", function(date, format) { | |
date = new Date(+date); | |
var map = { | |
M: date.getMonth() + 1, | |
d: date.getDate(), | |
h: date.getHours(), | |
m: date.getMinutes(), | |
s: date.getSeconds(), | |
q: Math.floor((date.getMonth() + 3) / 3), | |
S: date.getMilliseconds() | |
}; | |
return format = format.replace(/([yMdhmsqS])+/g, function(all, t) { | |
var v = map[t]; | |
return void 0 !== v ? (all.length > 1 && (v = "0" + v, v = v.substr(v.length - 2)), | |
v) : "y" === t ? (date.getFullYear() + "").substr(4 - all.length) : all; | |
}); | |
}), template.helper("parseInt", function(a, b) { | |
return parseInt(a, b || 10); | |
}), template.helper("min", function(a, b) { | |
return Math.min(a, b); | |
}), template.helper("max", function(a, b) { | |
return Math.max(a, b); | |
}), template.helper("stripImages", function(c) { | |
return c.replace(/<img[^>]*\/?>/g, ""); | |
}), template.helper("escape", function(c) { | |
return escape(c); | |
}), template.helper("firstImg", function(s) { | |
return s ? s.split("||")[0].split("/^/^")[0] : ""; | |
}), template.helper("serialize", function(o) { | |
return JSON.stringify(o); | |
}), template.helper("unserialize", function(o) { | |
return JSON.parse(o); | |
}), template.helper("split", function(s) { | |
return s.split(","); | |
}), template.helper("head", function(arr, amount) { | |
return "[object Array]" !== Object.prototype.toString.call(arr) ? -1 : 1 === (amount = +amount || 1) ? arr[0] : arr.slice(0, amount); | |
}), template.helper("eq", function(arr, which) { | |
return "[object Array]" !== Object.prototype.toString.call(arr) ? -1 : arr[which || 0]; | |
}), template.helper("realPx", function(val, baseOn) { | |
return -1 !== val.indexOf("%") ? baseOn * parseInt(val, 10) / 100 + "px" : (val = parseInt(val, 10), | |
isNaN(val) ? "350px" : val + "px"); | |
}), /*v:1*/ | |
template("Components/Metro/expand", ""), /*v:55*/ | |
template("Components/Metro/group", function($data) { | |
"use strict"; | |
var $utils = this, $helpers = $utils.$helpers, $escape = $utils.$escape, group = $data.group, screenWidth = $data.screenWidth, containerHeight = $data.containerHeight, $out = ""; | |
return $out += '<div class="tile-group" data-code="', $out += $escape(group.code), | |
$out += '" style="left: 0px; width: ', $out += $escape($helpers.realPx($helpers.head($helpers.split(group.rect)), screenWidth)), | |
$out += "; height: ", $out += $escape($helpers.realPx($helpers.eq($helpers.split(group.rect), 1), containerHeight)), | |
$out += ';"> <div class="tile-group-banner"> <span class="tile-group-banner-item tile-group-title">', | |
$out += $escape(group.name), $out += '</span> <i class="tile-group-banner-item icons-Metro icons-Metro-right-a" data-class-click="icons-Metro-right-click" data-class-hover="icons-Metro-right-hover"></i> <i class="tile-group-banner-item icons-Metro icons-Metro-left-a" data-class-click="icons-Metro-left-click" data-class-hover="icons-Metro-left-hover"></i> </div> <div class="tile-container"></div> </div> ', | |
new String($out); | |
}), /*v:15*/ | |
template("Components/Metro/groups", function($data, $filename) { | |
"use strict"; | |
var $utils = this, $each = ($utils.$helpers, $utils.$each), groups = $data.groups, groupData = ($data.group, | |
$data.gi, $data.groupData), screenWidth = $data.screenWidth, screenHeight = $data.screenHeight, containerWidth = $data.containerWidth, containerHeight = $data.containerHeight, include = function(filename, data) { | |
data = data || $data; | |
var text = $utils.$include(filename, data, $filename); | |
return $out += text; | |
}, $out = ""; | |
return $out += '<i class="component-metro-mask component-metro-mask-left"></i> <i class="component-metro-mask component-metro-mask-right"></i> <div class="component-metro-slider"></div> <div class="component-metro"> <div class="groups-wrapper animate"> ', | |
$each(groups, function(group) { | |
$out += " ", groupData = { | |
group: group, | |
screenWidth: screenWidth, | |
screenHeight: screenHeight, | |
containerWidth: containerWidth, | |
containerHeight: containerHeight | |
}, $out += " ", include("./group", groupData), $out += " "; | |
}), $out += " </div> </div> ", new String($out); | |
}); | |
}(); | |
;;(function(global) { | |
'use strict'; | |
// @const UNDEFINED | |
// @const STRING | |
// @const NUMBER | |
var | |
UNDEFINED = typeof undefined, | |
STRING = typeof '', | |
NUMBER = typeof 0, | |
GROUP_GHOST = 150, // 当打开一个组时,旁边的组所应该留下的残影 | |
AVAILABLE_COLORS = [ // 可用的颜色 | |
"ypapi_color1", | |
"ypapi_color2", | |
"ypapi_color3", | |
"ypapi_color4", | |
"ypapi_color5", | |
"ypapi_color6" | |
]; | |
// 定义依赖模块名 | |
var | |
deps = { | |
jQuery: undefined, | |
mouseWheel: undefined, | |
template: undefined, | |
YPAPI: undefined, | |
manSlider: undefined, | |
Hammer: undefined, | |
LocalEvent: undefined | |
}; | |
// 共享变量 | |
// @var {Number} 屏幕的宽度 | |
// @var {Number} 屏幕的高度 | |
var | |
screenWidth, | |
screenHeight; | |
// 辅助函数,防止一个函数被高频调用 | |
function debounce(idle, action){ | |
var last; | |
return function(){ | |
var ctx = this, args = arguments; | |
clearTimeout(last); | |
last = setTimeout(function(){ | |
action.apply(ctx, args); | |
}, idle); | |
}; | |
} | |
/* | |
* 绑定Metro的事件 | |
* | |
* @method bindEvents | |
* @access private | |
* @param {Object} $wrapper 一个绑定事件的目标容器 | |
* @return {Void} | |
*/ | |
function bindEvents($wrapper) { | |
var self = this, | |
panStartAt, panMoveMax; | |
$wrapper.off('.metro'); // 清除已绑定事件的重要性 | |
$wrapper.on('click.metro', '.tile-group-banner-item', function(ev) { | |
ev.stopPropagation(); | |
self.openGroup($(this).parent().parent().data('code')); | |
}); | |
$wrapper.on('mouseover.metro', '.icons-Metro', function(ev) { | |
var $this = $(this); | |
$this.addClass($this.data('class-hover')); | |
}); | |
$wrapper.on('mouseout.metro', '.icons-Metro', function(ev) { | |
var $this = $(this); | |
$this.removeClass($this.data('class-hover')); | |
}); | |
this.__$metro.on('mousedown.metro', function(ev) { | |
self.__realClickEvent = true; | |
}); | |
this.__hammer.on('panstart', function(ev) { | |
if (!self.__activeGroupCode) { | |
panStartAt = self.__slider.get(); | |
panMoveMax = self.__slider.getMax(); | |
} | |
}); | |
this.__hammer.on('panmove', function(ev) { | |
var stopAt; | |
self.__$groupsWrapper.removeClass('animate'); | |
if (!self.__activeGroupCode) { | |
stopAt = panStartAt - ev.deltaX; | |
stopAt = Math.max(0, stopAt); | |
stopAt = Math.min(panMoveMax, stopAt); | |
self.__$groupsWrapper.css('left', -stopAt + 'px'); | |
self.__slider.set(stopAt); | |
} | |
}); | |
this.__hammer.on('panend', function(ev) { | |
self.__realClickEvent = false; | |
panStartAt = null; | |
panMoveMax = null; | |
self.__$groupsWrapper.addClass('animate'); | |
}); | |
this.__hammer.on('swipe', function(ev) { | |
var stopAt; | |
self.__$groupsWrapper.addClass('animate').hasClass('animate'); // 使用hasClass 让浏览器立即写入animate类 | |
if (self.__activeGroupCode) { | |
if (ev.deltaX > 0) { | |
self.__groups[self.__activeGroupCode].RunPrev(); | |
} | |
else { | |
self.__groups[self.__activeGroupCode].RunNext(); | |
} | |
} | |
else { | |
stopAt = self.__slider.get() + ev.velocityX * 45; | |
stopAt = Math.max(0, stopAt); | |
stopAt = Math.min(stopAt, panMoveMax); | |
self.__$groupsWrapper.css('left', -stopAt + 'px'); | |
self.__slider.set(stopAt); | |
} | |
}); | |
} | |
/* | |
* 绑定鼠标滚动事件 | |
* | |
* @method bindMouseWheelEvent | |
* @access private | |
* @return {Void} | |
*/ | |
function bindMouseWheelEvent() { | |
var self = this; | |
$(document).on('mousewheel.metro', function(ev) { | |
var offset; | |
if (!self.__activeGroupCode) { | |
offset = self.__slider.get() + ev.deltaY * 20; | |
offset = Math.max(0, offset); | |
offset = Math.min(offset, self.__slider.getMax()); | |
self.__slider.set(offset); | |
self.__$groupsWrapper.css('left', -offset + 'px'); | |
} | |
else { | |
if (ev.deltaY > 0) { | |
self.__groups[self.__activeGroupCode].RunNext(); | |
} | |
else { | |
self.__groups[self.__activeGroupCode].RunPrev(); | |
} | |
} | |
}); | |
} | |
/* | |
* 解绑鼠标滚动事件 | |
* | |
* @method unBindMouseWheelEvent | |
* @access private | |
* @return {Void} | |
*/ | |
function unBindMouseWheelEvent() { | |
$(document).off('mousewheel.metro'); | |
} | |
/* | |
* 填充一个迷你group | |
* | |
* @method produceMiniGroup | |
* @access private | |
* @param {Object} $group group所处的容器 | |
* @return {Void} | |
*/ | |
function produceMiniGroup($group) { | |
var self = this, | |
$tileContainer = $group.find('.tile-container'), | |
code = $group.data('code'), | |
rect = this.__tileGroupsData[code].rect.split(','); | |
this.__groups[code] = null; | |
this.__groups[code] = new deps.YPAPI({ | |
mediaSpeed: 5000, | |
isIntro: true, | |
introHeight: 40, | |
rows: rect[2], | |
cols: rect[3], | |
rowMargin: 2.8, | |
colMargin: 4, | |
style: 1, | |
colors: AVAILABLE_COLORS, | |
showPage: 1, | |
"doevents": { | |
"click": this.__clickEvent | |
} | |
}); | |
this.__groups[code].Show($tileContainer[0], this.__tileGroupsData[code].grids); | |
} | |
/* | |
* 填充一个展开的group | |
* | |
* @method produceExpandGroup | |
* @access private | |
* @param {Object} $group group所处的容器 | |
* @param {Object} grids [optional] 使用指定的块块数据,忽略原有数据 | |
* @param {Number|String} row [optional] 使用指定的行数,忽略原有数据 | |
* @param {Number|String} col [optional] 使用指定的列数,忽略原有数据 | |
* @return {Void} | |
*/ | |
function produceExpandGroup($group, grids, row, col) { | |
var self = this, | |
$tileContainer = $group.find('.tile-container'), | |
code = $group.data('code'), | |
rect = this.__tileGroupsData[code].rect.split(','), | |
currentWidth = $group.width(), | |
suitableColNumber = Math.floor(rect[3] * currentWidth / parseInt($group.data('width'), 10)); // cannot use rec[0], cause it may be a percentage | |
if (isNaN(+row) || 0 === row) { | |
row = rect[2]; | |
} | |
if (isNaN(+col) || 0 === col) { | |
col = suitableColNumber; | |
} | |
this.__groups[code] = null; | |
this.__groups[code] = new deps.YPAPI({ | |
mediaSpeed: 5000, | |
isIntro: true, | |
introHeight: 40, | |
rows: row, | |
cols: col, | |
rowMargin: 3, | |
colMargin: 1, | |
style: 1, | |
colors: AVAILABLE_COLORS, | |
showPage: 2, | |
"doevents": { | |
"click": this.__clickEvent | |
} | |
}); | |
this.__groups[code].Show($tileContainer[0], grids || this.__tileGroupsData[code].grids); | |
} | |
/* | |
* 渲染一个当所有组收起来时的滑块 | |
* | |
* @method produceTileSlider | |
* @access private | |
* @return {Void} | |
*/ | |
function produceTileSlider() { | |
var self = this, timeout; | |
if (this.__slider) { | |
this.__slider.destory(); | |
this.__slider = null; | |
} | |
this.__slider = this.__$slider.manSlider({ | |
theme: 'kitkat', | |
min: 0, | |
max: this.__groupWrapperWidth - this.__$metro.width(), | |
change: function(val) { | |
clearTimeout(timeout); | |
self.__$groupsWrapper.removeClass('animate').hasClass('animate'); // 使用hasClass 让浏览器立即写入animate类 | |
self.__$groupsWrapper.css('left', -val + 'px'); | |
timeout = setTimeout(function() { | |
self.__$groupsWrapper.addClass('animate'); | |
}, 80); | |
} | |
}); | |
} | |
/* | |
* 渲染针对单个组展开时用来翻页的滑块 | |
* | |
* @method produceGroupSlider | |
* @access private | |
* @return {Void} | |
*/ | |
function produceGroupSlider() { | |
var self = this; | |
if (this.__slider) { | |
this.__slider.destory(); | |
this.__slider = null; | |
} | |
if (2 > this.__groups[this.__activeGroupCode].GetPages()) { | |
// 小于等于1页的话不需要滑块 | |
return; | |
} | |
this.__slider = this.__$slider.manSlider({ | |
theme: 'kitkat', | |
step: 1, | |
min: 1, | |
max: this.__groups[this.__activeGroupCode].GetPages(), | |
change: function(val) { | |
self.__groups[self.__activeGroupCode].RunPage(val); | |
} | |
}); | |
} | |
/* | |
* 渲染dom | |
* | |
* @method render | |
* @access private | |
* @return {Void} | |
*/ | |
function render() { | |
var $group, groupData, code; | |
screenWidth = $(window).width(); | |
screenHeight = $(window).height(); | |
this.__$container | |
.css({ | |
//position: 'absolute', | |
overflow: 'hidden' | |
}) | |
.html(deps.template('Components/Metro/groups', { | |
groups: this.__tileGroupsData, | |
screenWidth: screenWidth, | |
screenHeight: screenHeight, | |
containerWidth: this.__$container.innerWidth(), | |
containerHeight: this.__$container.innerHeight() | |
})); | |
this.__$masks = this.__$container.find('>.component-metro-mask'); | |
this.__$slider = this.__$container.find('>.component-metro-slider'); | |
this.__$metro = this.__$container.find('>.component-metro'); | |
this.__$groupsWrapper = this.__$container.find('.groups-wrapper'); | |
this.__groupWrapperWidth = 0; | |
this.__groups = {}; | |
this.__$groups= {}; | |
this.__$groupsContainer= {}; | |
if (this.__hammer) { | |
this.__hammer.destory && this.__hammer.destory(); | |
this.__hammer = null; | |
} | |
this.__hammer = new deps.Hammer(this.__$metro[0]); | |
for (code in this.__tileGroupsData) { | |
if (!this.__tileGroupsData.hasOwnProperty(code)) { | |
continue; | |
} | |
groupData = this.__tileGroupsData[code]; | |
$group = this.__$container.find('.tile-group[data-code=' + groupData.code + ']'); | |
produceMiniGroup.call(this, $group); | |
$group.find('.tile-container').addClass('fadeIn animated'); | |
this.__$groups[groupData.code] = $group; | |
this.__$groupsContainer[groupData.code] = $group.find('.tile-container'); | |
this.__groupWrapperWidth += $group.outerWidth(true); | |
} | |
produceTileSlider.call(this); | |
bindEvents.call(this, this.__$container); | |
} | |
/* | |
* @class Metro | |
* @constructor | |
* @return {Object} Metro 的实例 | |
*/ | |
var Metro = function() { | |
var localEvent, i; | |
if (!(this instanceof Metro)) { | |
throw new TypeError('Metro is a Class, which cannot be called as an function.'); | |
} | |
// 检查依赖 | |
// jquery | |
if (!deps.jQuery && !(deps.jQuery = global.jQuery)) { | |
throw new TypeError('Metro dependence not met: jQuery'); | |
} | |
// jquery-mousewheel | |
if (!deps.mouseWheel && !$.fn.mousewheel) { | |
throw new TypeError('Metro dependence not met: jquery-mousewheel'); | |
} | |
// jquery | |
if (!deps.manSlider && !$.fn.manSlider) { | |
throw new TypeError('Metro dependence not met: manSlider'); | |
} | |
// 模板 | |
if (!deps.template && !(deps.template = global.templateMetro)) { | |
throw new TypeError('Metro dependence not met: template'); | |
} | |
// Pane控件 | |
if (!deps.YPAPI && !(deps.YPAPI = global.YX && global.YX.Pane)) { | |
throw new TypeError('Metro dependence not met: YPAPI(YX.Pane)'); | |
} | |
// Hammer.js | |
if (!deps.Hammer && !(deps.Hammer = global.Hammer)) { | |
throw new TypeError('Metro dependence not met: Hammer.js'); | |
} | |
// LocalEvent | |
if (!deps.LocalEvent && !(deps.LocalEvent = global.LocalEvent)) { | |
throw new TypeError('Metro dependence not met: LocalEvent.js'); | |
} | |
localEvent = new deps.LocalEvent(); | |
for (i in localEvent) { | |
this[i] = localEvent[i]; | |
} | |
/* | |
* 存储容器 | |
* | |
* @property __$container | |
* @access private | |
* @type {Object} | |
*/ | |
this.__$container; | |
/* | |
* 存储外部传递的数据 | |
* | |
* @property __tileGroupsData | |
* @access private | |
* @type {Object} | |
*/ | |
this.__tileGroupsData; | |
/* | |
* 点击YPAPI内部时触发的事件 | |
* | |
* @property __clickEvent | |
* @access private | |
* @type {Function} | |
*/ | |
this.__clickEvent; | |
/* | |
* 存储YPAPI的实例 | |
* | |
* @property __groups | |
* @access private | |
* @type {Object} | |
*/ | |
this.__groups; | |
/* | |
* 存储YPAPI实例对应的group dom | |
* | |
* @property __$groups | |
* @access private | |
* @type {Object} | |
*/ | |
this.__$groups; | |
/* | |
* 存储YPAPI实例实际使用的容器 | |
* | |
* @property __$groupsContainer | |
* @access private | |
* @type {Object} | |
*/ | |
this.__$groupsContainer; | |
/* | |
* 记录打开某个group之前 groupwrapper向左偏移的距离 | |
* | |
* @property __offsetBeforeOpen | |
* @access private | |
* @type {String} | |
*/ | |
this.__offsetBeforeOpen; | |
/* | |
* 记录当前打开的group code是多少 | |
* 如果没有打开则为undefined | |
* | |
* @property __activeGroupCode | |
* @access private | |
* @type {Number | Undefined} | |
*/ | |
this.__activeGroupCode; | |
/* | |
* 左右遮罩 | |
* 当打开一个group时,当值相邻的group被点击 | |
* | |
* @property __$masks | |
* @access private | |
* @type {Object} | |
*/ | |
this.__$masks | |
/* | |
* 手势库实例 | |
* | |
* @property __hammer | |
* @access private | |
* @type {Object} | |
*/ | |
this.__hammer | |
/* | |
* 是否是一个真实的click事件 | |
* 当pan和panmove事件发生时,需要屏蔽click | |
* | |
* @property __realClickEvent | |
* @access private | |
* @type {Boolean} | |
*/ | |
this.__realClickEvent; | |
}; | |
/* | |
* 根据外部给定的数据初始化 | |
* | |
* @method init | |
* @access public | |
* @param {Object} container 用于存放图书dom结构的容器 | |
* @param {Object} data 用于构造模块的JSON数据 | |
* @param {Function} clickEvent 点击YPAPI内部时触发的事件 | |
* @return {Void} | |
*/ | |
Metro.prototype.init = function(container, data, clickEvent) { | |
var self = this; | |
if ( | |
STRING === typeof container || | |
container instanceof Element || | |
container instanceof $ | |
) { | |
this.__$container = $(container); | |
} | |
if (!this.__$container || 0 === this.__$container.length) { | |
throw new TypeError('The specified container is not accessible: ' + container); | |
} | |
if (1 < this.__$container.length) { | |
throw new TypeError('The specified container matchs multiple target: ' + container); | |
} | |
this.__tileGroupsData = data; | |
this.__clickEvent = function() { | |
if (self.__realClickEvent) { | |
clickEvent.apply(this, arguments); | |
} | |
}; | |
render.call(this); | |
this.responseMouseWheel(true); | |
$(window).on('resize', debounce(100, function(ev) { | |
render.call(self); | |
if (self.__timer) { | |
clearTimeout(self.__timer); | |
self.__timer = null; | |
} | |
self.__timer = setTimeout(function() { | |
var tmp; | |
if (tmp = self.__activeGroupCode) { | |
self.__activeGroupCode = undefined; | |
self.openGroup(tmp); | |
} | |
}, 500); | |
})); | |
}; | |
/* | |
* 销毁Metro实例 | |
* | |
* @method destory | |
* @access public | |
* @return {Void} | |
*/ | |
Metro.prototype.destory = function() { | |
if (this.__$container) { | |
this.__$container.html('').off('.metro'); | |
} | |
}; | |
/* | |
* 展开该组,并展现该组的完整内容 | |
* 展开一组的内容,以动画的形式聚焦到目标组后,计算合适的尺寸, | |
* | |
* @method openGroup | |
* @param {String} groupCode 展开哪一组内容 | |
* @return {Void} | |
*/ | |
Metro.prototype.openGroup = function(groupCode) { | |
var self = this, $target, suitableWidth, | |
groupCode = groupCode + ''; | |
function openGroupHandler() { | |
$target = self.__$groups[groupCode]; | |
if (1 === $target.length) { | |
$target.addClass('expanded'); | |
$target.off('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend'); | |
$target.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function animationEndHandler(ev) { | |
self.__$groupsContainer[groupCode].html(''); // ensure dom is empty even if no data is usable | |
if (self._getListenersAsFlat('groupOpen')['groupOpen'].length) { | |
self.trigger('groupOpen', self.__tileGroupsData[self.__activeGroupCode].id, function(data, id, row, col) { | |
if (self.__tileGroupsData[self.__activeGroupCode] && id === self.__tileGroupsData[self.__activeGroupCode].id) { | |
produceExpandGroup.call(self, $target, data, row, col); | |
} | |
}); | |
} | |
else { | |
produceExpandGroup.call(self, $target); | |
} | |
$target.off('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend'); | |
self.__$groupsContainer[groupCode].removeClass('fadeOut').addClass('fadeIn animated'); | |
//produceGroupSlider.call(self); | |
self.__slider.destory(); | |
self.__slider = null; | |
self.__$masks.addClass('shown'); | |
}); | |
self.__activeGroupCode = groupCode; | |
self.__$groupsContainer[groupCode].removeClass('fadeIn').addClass('fadeOut animated'); | |
self.__offsetBeforeOpen = self.__slider.get(); | |
$target.data('width', $target.css('width')); | |
$target.data('height', $target.css('height')); | |
suitableWidth = self.__$metro.width() - 2* GROUP_GHOST; | |
self.__$groupsWrapper.css({ | |
left: (-$target[0].offsetLeft + GROUP_GHOST) + 'px' | |
}); | |
$target.css({ | |
width: suitableWidth + 'px', | |
height: '100%' | |
}); | |
} | |
} | |
// 自然地,我们需要先关闭可能的已经展开的组 | |
if (groupCode === this.__activeGroupCode) { | |
this.foldGroup(); | |
return ; | |
} | |
else if (!this.__activeGroupCode) { | |
openGroupHandler(); | |
} | |
else { | |
self.foldGroup(openGroupHandler); | |
} | |
}; | |
/* | |
* 收起展开的列 | |
* | |
* @method foldGroup | |
* @access public | |
* @return {Void} | |
*/ | |
Metro.prototype.foldGroup = function(callback) { | |
var self = this, rect, $target; | |
$target = this.__$groups[this.__activeGroupCode]; | |
if (1 === $target.length) { | |
$target.removeClass('expanded'); | |
$target.off('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend'); | |
$target.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function animationEndHandler() { | |
produceMiniGroup.call(self, $target); | |
$target.off('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend'); | |
self.__$groupsContainer[self.__activeGroupCode].removeClass('fadeOut').addClass('fadeIn animated'); | |
self.__activeGroupCode = undefined; | |
self.__$masks.removeClass('shown'); | |
callback && callback(); | |
}); | |
this.__$groupsContainer[this.__activeGroupCode].removeClass('fadeIn').addClass('fadeOut animated'); | |
rect = this.__tileGroupsData[this.__activeGroupCode].rect.split(','); | |
$target.css({ | |
//width: rect[0] + 'px' | |
width: $target.data('width'), | |
height: $target.data('height') | |
}); | |
$target.data('width', null); | |
$target.data('height', null); | |
produceTileSlider.call(this); | |
this.__$groupsWrapper.css('left', -this.__offsetBeforeOpen + 'px'); | |
this.__slider.set(this.__offsetBeforeOpen); | |
} | |
}; | |
/* | |
* 返回所有 groups 的 YPAPI 实例和当前处于激活状态的groupId | |
* | |
* @method getGroups | |
* @access public | |
* @return {Array} | |
*/ | |
Metro.prototype.getGroups = function() { | |
return [this.__groups, this.__activeGroupCode]; | |
}; | |
/* | |
* 设定是否响应鼠标滚轮事件 | |
* | |
* @method responseMouseWheel | |
* @access public | |
* @param {Boolean} 是否响应鼠标滚轮事件的布尔值 | |
* @return {Void} | |
*/ | |
Metro.prototype.responseMouseWheel = function(response) { | |
if (!response) { | |
unBindMouseWheelEvent.call(this); | |
} | |
else { | |
bindMouseWheelEvent.call(this); | |
} | |
}; | |
// 定义为一个UMD模块 | |
if (UNDEFINED !== typeof define) { | |
var required_modules = [], | |
namespace2Module = { | |
'jquery': 'jQuery', | |
'jquery-mousewheel': 'mouseWheel', | |
'Components/manSlider/manSlider': 'manSlider', | |
'Components/Pane/Pane': 'YPAPI', | |
'Components/Metro/template': 'template', | |
'Hammer': 'Hammer', | |
'LocalEvent': 'LocalEvent' | |
}; | |
// 使用小写的AMD模块名, @see http://www.tuicool.com/articles/fiuAziA | |
!(deps.jQuery = global.jQuery) && required_modules.push('jquery'); | |
global.jQuery && | |
!(deps.manSlider = global.jQuery.fn.manSlider) && | |
required_modules.push('Components/manSlider/manSlider'); | |
global.jQuery && | |
!(deps.mouseWheel = global.jQuery.fn.mousewheel) && | |
required_modules.push('jquery-mousewheel'); | |
required_modules.push('Components/Metro/template'); | |
if (!global.YX || !(deps.YPAPI = global.YX.Pane)) { | |
required_modules.push('Components/Pane/Pane'); | |
} | |
!(deps.Hammer = global.Hammer) && required_modules.push('Hammer'); | |
!(deps.LocalEvent = global.LocalEvent) && required_modules.push('LocalEvent'); | |
define(required_modules, function() { | |
var i, len; | |
for (i = 0; i < required_modules.length; i++) { | |
deps[namespace2Module[required_modules[i]] || required_modules[i]] = arguments[i]; | |
} | |
return Metro; | |
}); | |
} | |
else if (UNDEFINED !== typeof exports) { | |
module.exports = Metro; | |
} | |
else { | |
deps.jQuery = global.jQuery; | |
deps.mouseWheel = global.jQuery.fn.mousewheel; | |
deps.manSlider = global.jQuery.fn.manSlider; | |
deps.template = global.templateMeteo; | |
deps.YPAPI = global.YX && global.YX.Pane; | |
deps.Hammer = global.Hammer; | |
deps.LocalEvent = global.LocalEvent; | |
if (UNDEFINED === typeof global.YX) { | |
global.YX = {}; | |
} | |
if (UNDEFINED === typeof global.YX.Ui) { | |
global.YX.Ui = {}; | |
} | |
if (UNDEFINED === typeof global.YX.Ui.Components) { | |
global.YX.Ui.Components = {}; | |
} | |
global.YX.Ui.Components.Metro = Metro; | |
} | |
})(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment