/*
 * Version: 2.0.20
 * Build time: Tue Feb 28 2017 19:19:39 GMT+0800 (中国标准时间)
 * Copyright 2016, Alibaba
*/

/******/ (function(modules) { // webpackBootstrap
    /******/ 	// The module cache
    /******/ 	var installedModules = {};

    /******/ 	// The require function
    /******/ 	function __webpack_require__(moduleId) {

        /******/ 		// Check if module is in cache
        /******/ 		if(installedModules[moduleId])
        /******/ 			return installedModules[moduleId].exports;

        /******/ 		// Create a new module (and put it into the cache)
        /******/ 		var module = installedModules[moduleId] = {
            /******/ 			exports: {},
            /******/ 			id: moduleId,
            /******/ 			loaded: false
            /******/ 		};

        /******/ 		// Execute the module function
        /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

        /******/ 		// Flag the module as loaded
        /******/ 		module.loaded = true;

        /******/ 		// Return the exports of the module
        /******/ 		return module.exports;
        /******/ 	}


    /******/ 	// expose the modules object (__webpack_modules__)
    /******/ 	__webpack_require__.m = modules;

    /******/ 	// expose the module cache
    /******/ 	__webpack_require__.c = installedModules;

    /******/ 	// __webpack_public_path__
    /******/ 	__webpack_require__.p = "";

    /******/ 	// Load entry module and return exports
    /******/ 	return __webpack_require__(0);
    /******/ })
/************************************************************************/
/******/ ([
    /* 0 */
    /***/ function(module, exports, __webpack_require__) {

        // webpack入口，用于打包标签引用的build文件，引入页面后会创建全局的FocusEngine对象。



        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

        var _libEngineJs = __webpack_require__(1);

        var _libEngineJs2 = _interopRequireDefault(_libEngineJs);

        if (!window.FocusEngine) {
            window.FocusEngine = _libEngineJs2['default'];
        }

        /***/ },
    /* 1 */
    /***/ function(module, exports, __webpack_require__) {



        Object.defineProperty(exports, '__esModule', {
            value: true
        });

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

        var _event = __webpack_require__(2);

        var _event2 = _interopRequireDefault(_event);

        var _widget = __webpack_require__(3);

        var _widget2 = _interopRequireDefault(_widget);

        var _switch = __webpack_require__(4);

        var _switch2 = _interopRequireDefault(_switch);

        var _scroll = __webpack_require__(5);

        var _scroll2 = _interopRequireDefault(_scroll);

        var _grid = __webpack_require__(8);

        var _grid2 = _interopRequireDefault(_grid);

        var _grille = __webpack_require__(9);

        var _grille2 = _interopRequireDefault(_grille);

        var Engine = {
            Event: _event2['default'],
            Widget: _widget2['default'],
            Switch: _switch2['default'],
            Scroll: _scroll2['default'],
            Grid: _grid2['default'],
            Grille: _grille2['default'],
            roles: ['Widget', 'Switch', 'Scroll', 'Grid', 'Grille'],
            render: function render(dom, noPreventDefault) {
                if (dom === undefined) dom = document.body;

                var domRole = dom.getAttribute('fe-role');
                // 如果fe-role错误，抛出
                if (domRole && this.roles.indexOf(domRole) === -1) {
                    console.error(dom);
                    console.error('[FocusEngine_Error](' + domRole + ')不是支持的fe-role类型，只支持以下类型：' + this.roles.join('、'));
                    return;
                }
                // 默认Widget
                if (!domRole) {
                    dom.setAttribute('fe-role', 'Widget');
                }
                // 如果该页面已经有组件树，那么只需要reRender该组件树即可
                if (window.$FocusEngineGlobalRoot) {
                    window.$FocusEngineGlobalRoot.reRender();
                    return window.$FocusEngineGlobalRoot.getWidgetById(dom.id);
                }
                // 如果该页面还没有组件树，那么需要从body渲染页面组件树，然后返回dom对应的组件
                var bodyRole = document.body.getAttribute('fe-role');
                // 如果fe-role错误，抛出
                if (bodyRole && this.roles.indexOf(bodyRole) === -1) {
                    console.error('[FocusEngine_Error](' + bodyRole + ')不是支持的fe-role类型，只支持以下类型：' + this.roles.join('、'));
                    return;
                }
                // 默认Widget
                if (!bodyRole) {
                    document.body.setAttribute('fe-role', 'Widget');
                    bodyRole = 'Widget';
                }
                window.$FocusEngineGlobalRoot = new this[bodyRole](document.body);
                window.$FocusEngineGlobalRoot.focus();
                window.$FocusEngineGlobalRoot.handleRootEvent(noPreventDefault);
                return window.$FocusEngineGlobalRoot.getWidgetById(dom.id);
            },

            // 通过dom节点创建一个widget并递归创建dom的内部widget
            createWidget: function createWidget(dom) {
                var domRole = dom.getAttribute('fe-role');
                // 如果fe-role错误，抛出
                if (domRole && this.roles.indexOf(domRole) === -1) {
                    console.error(dom);
                    console.error('[FocusEngine_Error](' + domRole + ')不是支持的fe-role类型，只支持以下类型：' + this.roles.join('、'));
                    return;
                }
                // 默认Widget
                if (!domRole) {
                    dom.setAttribute('fe-role', 'Widget');
                }
                return new this[domRole](dom);
            },

            appendWidget: function appendWidget(dom) {
                var widget = this.createWidget(dom);
                while (dom.parentNode) {
                    dom = dom.parentNode;
                    if (!dom.getAttribute('fe-role')) {
                        continue;
                    }
                    var id = dom.id;
                    this.getWidgetById(id).addChildWidget(widget);
                    return;
                }
            },

            // 获取整个页面组件树的根组件
            getRoot: function getRoot() {
                return window.$FocusEngineGlobalRoot;
            },

            getWidgetById: function getWidgetById(id) {
                if (window.$FocusEngineGlobalRoot) {
                    return window.$FocusEngineGlobalRoot.getWidgetById(id);
                } else {
                    return null;
                }
            },

            getFocusedLeaf: function getFocusedLeaf() {
                if (window.$FocusEngineGlobalRoot) {
                    return window.$FocusEngineGlobalRoot.getFocusedLeaf();
                } else {
                    return null;
                }
            },

            freeze: function freeze(blur) {
                window.$FocusEngineGlobalRoot && window.$FocusEngineGlobalRoot.freeze(blur);
            },

            activate: function activate() {
                window.$FocusEngineGlobalRoot && window.$FocusEngineGlobalRoot.activate();
            },

            disableClick: function disableClick() {
                window.$FocusEngineGlobalRoot && window.$FocusEngineGlobalRoot.disableClick();
            },

            enableClick: function enableClick() {
                window.$FocusEngineGlobalRoot && window.$FocusEngineGlobalRoot.enableClick();
            }
        };

        exports['default'] = Engine;
        module.exports = exports['default'];

        /***/ },
    /* 2 */
    /***/ function(module, exports) {


        Object.defineProperty(exports, "__esModule", {
            value: true
        });

        var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var Event = (function () {

            /**
             * type：事件类型
             * target：触发事件的组件
             * data：其他事件属性，如{keyCode: 13}
             */

            function Event(type, target, data) {
                _classCallCheck(this, Event);

                this.type = type;
                this._propagationStopped = false;
                this._defaultPrevented = false;
                this._listenerPrevented = false;
                if (target) {
                    this.target = target;
                }
                if (data) {
                    for (var pro in data) {
                        this[pro] = data[pro];
                    }
                }
            }

            // 停止冒泡

            Event.prototype.stopPropagation = function stopPropagation() {
                this._propagationStopped = true;
            };

            // 该事件是否已经停止冒泡

            Event.prototype.isPropagationStopped = function isPropagationStopped() {
                return this._propagationStopped;
            };

            // 禁止默认事件

            Event.prototype.preventDefault = function preventDefault() {
                this._defaultPrevented = true;
            };

            // 是否已经禁止默认事件

            Event.prototype.isDefaultPrevented = function isDefaultPrevented() {
                return this._defaultPrevented;
            };

            // 禁止触发通过on添加的listener

            Event.prototype.preventListener = function preventListener() {
                this._listenerPrevented = true;
            };

            // 是否已经禁止Listener

            Event.prototype.isListenerPrevented = function isListenerPrevented() {
                return this._listenerPrevented;
            };

            _createClass(Event, null, [{
                key: "VK_ENTER",
                get: function get() {
                    return 13;
                }
            }, {
                key: "VK_LEFT",
                get: function get() {
                    return 37;
                }
            }, {
                key: "VK_UP",
                get: function get() {
                    return 38;
                }
            }, {
                key: "VK_RIGHT",
                get: function get() {
                    return 39;
                }
            }, {
                key: "VK_DOWN",
                get: function get() {
                    return 40;
                }
            }]);

            return Event;
        })();

        exports["default"] = Event;
        module.exports = exports["default"];

        /***/ },
    /* 3 */
    /***/ function(module, exports, __webpack_require__) {



        Object.defineProperty(exports, '__esModule', {
            value: true
        });

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

        var _event = __webpack_require__(2);

        var _event2 = _interopRequireDefault(_event);

        var _engine = __webpack_require__(1);

        var _engine2 = _interopRequireDefault(_engine);

        var Widget = (function () {

            /**
             * @param container {HTMLElement} 组件的容器dom元素
             */

            function Widget(container) {
                _classCallCheck(this, Widget);

                if (!container) {
                    console.error('[FocusEngine_Error]创建组件必须传入相应的容器元素。');
                    return;
                }
                this.con = container;

                if (this.con.id) {
                    this.id = this.con.id;
                    if (document.querySelector('#' + this.id) !== this.con) {
                        console.error('[FocusEngine_Error]页面元素有重复的id(' + this.id + ')，请检查！');
                    }
                } else {
                    // 生成随机ID
                    var randomId = Math.random().toString().slice(2, 12);
                    var confirmed = false;
                    while (!confirmed) {
                        if (document.getElementById('fe-' + randomId)) {
                            randomId = Math.random().toString().slice(2, 12);
                        } else {
                            confirmed = true;
                        }
                    }
                    this.id = 'fe-' + randomId;
                    this.con.id = this.id;
                }
                this.options = this._getOptions(container);
                this.parentWidget = null;
                this.focusedChildWidget = null;
                this.cachedChildWidget = null;
                this.active = true;
                this.disabled = this.options.cfg.disable === 'yes';
                this.noClick = this.options.cfg.disable_click === 'yes';
                if (this.disabled) {
                    this.addClass('fe-disable');
                }
                this.eventListeners = [];
                this._initChildWidgets();
                this._getOriginalRect();
            }

            /**
             * 当widget对应的dom结构发生改变时，进行重新渲染。
             * 渲染会根据变动的dom来针对性的进行，如果某个widget的直接子widget没有变化，那么不进行rerender
             */

            Widget.prototype.reRender = function reRender() {
                if (!document.querySelector('#' + this.id)) {
                    return;
                }
                this.con = document.querySelector('#' + this.id);
                this.options = this._getOptions(this.con);
                this._reRenderChildWidget();
                this._getOriginalRect();
            };

            Widget.prototype._getOriginalRect = function _getOriginalRect() {
                this.originalRect = this.getWidgetRect();
            };

            Widget.prototype.getFutureRect = function getFutureRect() {
                var widget = this;
                var rect = widget.getWidgetRect();
                var originalRect = widget.originalRect;
                while (widget.getParentWidget()) {
                    var _parent = widget.getParentWidget();
                    if (_parent instanceof _engine2['default'].Scroll) {
                        if (_parent.dir === 'v') {
                            rect.top = originalRect.top + _parent.futureOffset;
                            rect.bottom = originalRect.bottom + _parent.futureOffset;
                            rect.centerY = originalRect.centerY + _parent.futureOffset;
                        } else if (_parent.dir === 'h') {
                            rect.left = originalRect.left + _parent.futureOffset;
                            rect.right = originalRect.right + _parent.futureOffset;
                            rect.centerX = originalRect.centerX + _parent.futureOffset;
                        }
                    }
                    if (_parent instanceof _engine2['default'].Grid) {
                        if (_parent.horizontal) {
                            rect.left = originalRect.left + widget.futureOffset;
                            rect.right = originalRect.right + widget.futureOffset;
                            rect.centerX = originalRect.centerX + widget.futureOffset;
                        } else {
                            rect.top = originalRect.top + widget.futureOffset;
                            rect.bottom = originalRect.bottom + widget.futureOffset;
                            rect.centerY = originalRect.centerY + widget.futureOffset;
                        }
                    }
                    widget = _parent;
                }
                return rect;
            };

            Widget.prototype._reRenderChildWidget = function _reRenderChildWidget() {
                var descendantNodes = Array.prototype.slice.call(this.con.querySelectorAll('[fe-role]'));
                // 排除掉深层次的可初始化为组件的dom，
                // 只保留遍历到的首层dom
                for (var i = 0; i < descendantNodes.length; i++) {
                    var descd = descendantNodes[i];
                    var role = descd.getAttribute('fe-role');
                    if (_engine2['default'].roles.indexOf(role) === -1) {
                        console.error(descd);
                        console.error('[FocusEngine_Error](' + role + ')不是支持的fe-role类型，只支持以下类型：' + _engine2['default'].roles.join('、'));
                        continue;
                    }
                    descendantNodes = this._filterArray(descendantNodes, Array.prototype.slice.call(descendantNodes[i].querySelectorAll('[fe-role]')));
                }

                // 首先删除容器已经被删除的子组件
                for (var i = 0; i < this.childWidgets.length; i++) {
                    if (descendantNodes.indexOf(this.childWidgets[i].getDOMNode()) === -1) {
                        this.removeChildWidget(i);
                        i--;
                        continue;
                    }
                    var tempRole = this.childWidgets[i].getDOMNode().getAttribute('fe-role');
                    if (_engine2['default'].roles.indexOf(tempRole) === -1 || !(this.childWidgets[i] instanceof _engine2['default'][tempRole])) {
                        this.removeChildWidget(i);
                        i--;
                    }
                }

                // 其次递归遍历需要保持（容器还存在）的子组件
                for (var i = 0; i < this.childWidgets.length; i++) {
                    this.childWidgets[i].reRender();
                }

                // 最后创建新增加的组件，并添加到子组件中
                for (var i = 0; i < descendantNodes.length && descendantNodes.length > this.childWidgets.length; i++) {
                    var tempNode = descendantNodes[i];
                    var alreadyHas = false;
                    for (var j = 0; j < this.childWidgets.length; j++) {
                        var tempWidget = this.childWidgets[j];
                        if (tempWidget.getDOMNode() === tempNode) {
                            alreadyHas = true;
                        }
                    }
                    if (!alreadyHas) {
                        var role = tempNode.getAttribute('fe-role');
                        if (_engine2['default'].roles.indexOf(role) !== -1) {
                            var newWidget = new _engine2['default'][role](tempNode);
                            this.addChildWidget(newWidget, i);
                        }
                    }
                }

                if (this.focused) {
                    this.focus(true, true);
                }
            };

            // 获取整个页面组件树的根组件

            Widget.prototype.getRoot = function getRoot() {
                return window.$FocusEngineGlobalRoot;
            };

            /**
             * 挂起组件树。
             * @param blur {Boolean} 是否在挂起后清空焦点链路。
             */

            Widget.prototype.freeze = function freeze(blur) {
                var root = this.getRoot();
                if (!root) {
                    return this;
                }
                root.active = false;
                if (blur) {
                    // 若清空焦点，记录挂起前处于焦点状态的叶子节点
                    root.focusedLeafBeforeFreeze = root.getFocusedLeaf();
                    root.blur();
                }
                return this;
            };

            // 激活组件同时还原焦点链路（若挂起时清空）

            Widget.prototype.activate = function activate() {
                var root = this.getRoot();
                if (!root) {
                    return this;
                }
                root.active = true;
                // 若挂起的时候有缓存焦点，激活的时候要还原缓存的焦点
                if (root.focusedLeafBeforeFreeze) {
                    if (document.querySelector('#' + root.focusedLeafBeforeFreeze.id) === root.focusedLeafBeforeFreeze.getDOMNode()) {
                        root.focusedLeafBeforeFreeze.focus();
                    } else {
                        root.focus();
                    }
                    root.focusedLeafBeforeFreeze = null;
                }
                return this;
            };

            Widget.prototype.disable = function disable() {
                this.disabled = true;
                this.addClass('fe-disable');
                return this;
            };

            Widget.prototype.enable = function enable() {
                this.disabled = false;
                this.removeClass('fe-disable');
                return this;
            };

            Widget.prototype._getOptions = function _getOptions(node) {
                var options = {};
                this.feCfg = this._removeSpaces(node.getAttribute('fe-cfg'));
                var cfg = {};
                if (this.feCfg) {
                    var cfgArr = this.feCfg.split(/,|;/);
                    cfgArr.forEach(function (c) {
                        var tmpArr = c.split(':');
                        if (tmpArr.length < 2) return false;
                        tmpArr[0] = tmpArr[0].replace(/switch_|scroll_|grid_/g, '');
                        cfg[tmpArr[0]] = tmpArr[1];
                    });
                }
                options.cfg = cfg;
                var dataDir = this._removeSpaces(node.getAttribute('fe-goto'));
                var dir = {};
                if (dataDir) {
                    var dirArr = dataDir.split(';');
                    if (dirArr[0]) dir.up = dirArr[0];
                    if (dirArr[1]) dir.right = dirArr[1];
                    if (dirArr[2]) dir.down = dirArr[2];
                    if (dirArr[3]) dir.left = dirArr[3];
                }
                options.dir = dir;
                options.tab = this._removeSpaces(node.getAttribute('fe-index'));
                return options;
            };

            // 遍历dom树，自动映射为组件树

            Widget.prototype._initChildWidgets = function _initChildWidgets() {
                this.childWidgets = [];
                this.childMap = {};
                var descendantNodes = Array.prototype.slice.call(this.con.querySelectorAll('[fe-role]'));
                // 排除掉深层次的可初始化为组件的dom，
                // 只保留遍历到的首层dom
                for (var i = 0; i < descendantNodes.length; i++) {
                    var descd = descendantNodes[i];
                    var role = descd.getAttribute('fe-role');
                    if (_engine2['default'].roles.indexOf(role) === -1) {
                        console.error(descd);
                        console.error('[FocusEngine_Error](' + role + ')不是支持的fe-role类型，只支持以下类型：' + _engine2['default'].roles.join('、'));
                        continue;
                    }
                    descendantNodes = this._filterArray(descendantNodes, Array.prototype.slice.call(descendantNodes[i].querySelectorAll('[fe-role]')));
                }

                var node = undefined,
                    w = undefined;
                for (var i = 0, j = descendantNodes.length; i < j; i++) {
                    node = descendantNodes[i];
                    // 如果fe-role为可以初始化的组件名，则初始化子组件
                    var role = node.getAttribute('fe-role');
                    if (_engine2['default'].roles.indexOf(role) !== -1) {
                        // 子组件不需要focus，但需要继续递归初始化
                        w = new _engine2['default'][role](node);
                        this.addChildWidget(w);
                    }
                }
            };

            Widget.prototype.handleRootEvent = function handleRootEvent(noPreventDefault) {
                var _this = this;

                document.addEventListener('keydown', function (e) {
                    if (!_this.active) {
                        return;
                    }
                    e = e || window.event;

                    var k = e.keyCode,
                        l = _this.getFocusedLeaf();
                    if (k) {
                        l.fire(new _event2['default']('keydown', l, { keyCode: k }));
                        // moye默认ok事件， ---王洋注
                        if (l && k === _event2['default'].VK_ENTER) {
                            l.fire(new _event2['default']('okdown', l, { keyCode: k }));
                        }
                        /**
                         * 阻止默认事件，会影响键盘输入，暂时注释
                        * */
                        // if (!noPreventDefault) {
                        //     e.preventDefault();
                        // }
                    }
                });

                document.addEventListener('keyup', function (e) {
                    if (!_this.active) {
                        return;
                    }
                    e = e || window.event;

                    var k = e.keyCode,
                        l = _this.getFocusedLeaf();

                    if (k) {
                        l && l.fire(new _event2['default']('keyup', l, { keyCode: k }));
                        if (l && k === _event2['default'].VK_ENTER) {
                            l.fire(new _event2['default']('ok', l, { keyCode: k }));
                        }
                        /**
                         * 阻止默认事件，会影响键盘输入，暂时注释
                         * */
                        // if (!noPreventDefault) {
                        //     e.preventDefault();
                        // }
                    }
                });

                document.addEventListener('click', function (e) {
                    if (!_this.active) {
                        return;
                    }
                    e = e || window.event;

                    var t = e.target;
                    var w = null;
                    while (t && t !== document) {
                        // 自下向上找到第一个组件容器
                        if (_engine2['default'].roles.indexOf(t.getAttribute('fe-role')) !== -1) {
                            w = _this.getWidgetById(t.id);
                            // 如果是叶子组件的容器，那么触发click事件并focus
                            if (w && w.isLeafWidget()) {
                                var p = w;
                                while (p) {
                                    if (p.noClick) {
                                        return;
                                    }
                                    p = p.parentWidget;
                                }
                                w && w.fire(new _event2['default']('click', w));
                                if (!noPreventDefault) {
                                    e.preventDefault();
                                }
                                if (!w.disabled && w.getDOMNode().style.visibility != 'hidden') {
                                    if (w.focused) {
                                        w.fire(new _event2['default']('ok', w, { isClick: true }));
                                    } else {
                                        var canFocus = w.getDOMNode().getAttribute('can-focus');
                                        if (canFocus != 'no') {
                                            w.focus();
                                        }
                                    }
                                }
                                return;
                                // 如果找到的第一个组件不是叶子组件，则不进行操作
                            } else {
                                return;
                            }
                            // 不是组件容器，继续向上查询
                        } else {
                            t = t.parentNode;
                        }
                    }
                });
            };

            /**
             * 获取当前选中的叶子节点
             * @return {Widget | null} 组件实例
             */

            Widget.prototype.getFocusedLeaf = function getFocusedLeaf() {
                if (this.isLeafWidget()) {
                    return this;
                } else if (!this.getFocusedChildWidget()) {
                    return null;
                } else {
                    return this.getFocusedChildWidget().getFocusedLeaf();
                }
            };

            /**
             * 为widget的容器添加类名
             * @param className {String} 待添加的类名
             */

            Widget.prototype.addClass = function addClass(className) {
                this.con.classList.add(className);
            };

            /**
             * 为widget的容器删除类名
             * @param className {String} 待删除的类名
             */

            Widget.prototype.removeClass = function removeClass(className) {
                this.con.classList.remove(className);
            };

            /**
             * 判断widget的容器是否有类名
             * @param className {String} 待判断的类名
             * @return {Boolean} 是否包含类名
             */

            Widget.prototype.hasClass = function hasClass(className) {
                return this.con.classList.contains(className);
            };

            /**
             * 显示组件
             */

            Widget.prototype.show = function show() {
                this.con.style.display = 'block';
            };

            /**
             * 隐藏组件
             */

            Widget.prototype.hide = function hide() {
                this.con.style.display = 'none';
            };

            /**
             * 选中当前组件，并递归选中
             * @param {Boolean} 是否强制执行focus
             */

            Widget.prototype.focus = function focus(force, preventListener) {
                if (!force && this.focused) {
                    return this;
                }
                // 如果不是叶子节点，找到默认的叶子节点，触发focus事件
                var willFocusedLeaf = this;
                while (!willFocusedLeaf.isLeafWidget()) {
                    var cache = willFocusedLeaf.getCachedChildWidget();
                    if (cache && willFocusedLeaf.options.cfg.disable_child_cache !== 'yes') {
                        willFocusedLeaf = cache;
                        continue;
                    }
                    var defaul = willFocusedLeaf.getDefaultFocusedChildWidget();
                    if (defaul) {
                        willFocusedLeaf = defaul;
                        continue;
                    }
                    var first = willFocusedLeaf.getFirstFocusableChildWidget();
                    if (first) {
                        willFocusedLeaf = first;
                        continue;
                    }
                    break;
                }
                var focusEvent = new _event2['default']('focus', willFocusedLeaf, { force: force });
                if (preventListener) {
                    focusEvent.preventListener();
                }
                willFocusedLeaf.fire(focusEvent);
                return this;
            };

            // focus时的默认处理

            Widget.prototype.focusDefault = function focusDefault(e) {
                if (this.focused && !e.force) {
                    return;
                }
                var parent = this.getParentWidget();
                if (parent) {
                    var oldFocusedChildWidget = parent.getFocusedChildWidget();
                    if (oldFocusedChildWidget && oldFocusedChildWidget !== this) {
                        if (oldFocusedChildWidget.isLeafWidget()) {
                            e.blurLeaf = oldFocusedChildWidget;
                        } else if (oldFocusedChildWidget.getFocusedLeaf()) {
                            e.blurLeaf = oldFocusedChildWidget.getFocusedLeaf();
                        }
                        oldFocusedChildWidget.blur();
                    }
                    parent.setFocusedChildWidget(this);
                }
                this.addClass('fe-focus');
                this.focused = true;
                this.cache();
            };

            Widget.prototype.blur = function blur() {
                if (!this.focused) {
                    return this;
                }
                var parent = this.getParentWidget();
                parent && parent.setFocusedChildWidget(null);
                this.removeClass('fe-focus');
                this.focused = false;
                var focusedChildWidget = this.getFocusedChildWidget();
                if (focusedChildWidget) {
                    focusedChildWidget.blur();
                }
                this.fire(new _event2['default']('blur', this));
                return this;
            };

            Widget.prototype.cache = function cache() {
                if (this.cached) {
                    return this;
                }
                var parent = this.getParentWidget();
                if (parent) {
                    var oldCacheChildWidget = parent.getCachedChildWidget();
                    if (oldCacheChildWidget) {
                        oldCacheChildWidget.removeClass('fe-cache');
                        oldCacheChildWidget.cached = false;
                    }
                    parent.setCachedChildWidget(this);
                }
                this.addClass('fe-cache');
                this.cached = true;
                return this;
            };

            /**
             * 当前组件是否为叶子节点
             * @return {Boolean} 是否为叶子节点
             */

            Widget.prototype.isLeafWidget = function isLeafWidget() {
                return !this.getFirstFocusableChildWidget();
            };

            /**
             * 获取父组件
             * @return {Widget} 返回widget实例
             */

            Widget.prototype.getParentWidget = function getParentWidget() {
                return this.parentWidget;
            };

            /**
             * 获取当前选中的子组件
             * @return {Widget} 返回widget实例
             */

            Widget.prototype.getFocusedChildWidget = function getFocusedChildWidget() {
                if (!this.focusedChildWidget) {
                    return null;
                }
                if (this.childWidgets.indexOf(this.focusedChildWidget) === -1) {
                    var widgetById = this.getWidgetById(this.focusedChildWidget.id);
                    if (this.childWidgets.indexOf(widgetById) !== -1) {
                        return widgetById;
                    }
                    return null;
                }
                return this.focusedChildWidget;
            };

            Widget.prototype.setFocusedChildWidget = function setFocusedChildWidget(widget) {
                if (widget && this.childWidgets.indexOf(widget) === -1) {
                    return;
                }
                this.focusedChildWidget = widget;
            };

            Widget.prototype.getCachedChildWidget = function getCachedChildWidget() {
                // 没有缓存
                if (!this.cachedChildWidget) {
                    return null;
                }
                // 缓存的子组件已经删除
                if (this.childWidgets.indexOf(this.cachedChildWidget) === -1) {
                    return null;
                }
                // 缓存的子组件disable
                if (this.cachedChildWidget.disabled) {
                    return null;
                }
                return this.cachedChildWidget;
            };

            Widget.prototype.setCachedChildWidget = function setCachedChildWidget(widget) {
                if (widget && this.childWidgets.indexOf(widget) === -1) {
                    return;
                }
                this.cachedChildWidget = widget;
            };

            Widget.prototype.getDefaultFocusedChildWidget = function getDefaultFocusedChildWidget() {
                if (!this.defaultFocusedChildWidget) {
                    return null;
                }
                // 默认子组件已经删除
                if (this.childWidgets.indexOf(this.defaultFocusedChildWidget) === -1) {
                    return null;
                }
                // 默认子组件disable
                if (this.defaultFocusedChildWidget.disabled) {
                    return null;
                }
                return this.defaultFocusedChildWidget;
            };

            Widget.prototype.getFirstFocusableChildWidget = function getFirstFocusableChildWidget() {
                for (var i = 0; i < this.childWidgets.length; i++) {
                    var tempWidget = this.childWidgets[i];
                    // 子组件disable
                    if (tempWidget.disabled) {
                        continue;
                    }
                    return tempWidget;
                }
                return null;
            };

            Widget.prototype.setDefaultFocusedChildWidget = function setDefaultFocusedChildWidget(widget) {
                if (widget && this.childWidgets.indexOf(widget) === -1) {
                    return;
                }
                this.defaultFocusedChildWidget = widget;
            };

            /**
             * 根据id获取组件实例
             * @param id {Number} 组件id
             */

            Widget.prototype.getWidgetById = function getWidgetById(id) {
                if (this.id === id) {
                    return this;
                }
                if (this.childMap[id]) {
                    return this.childMap[id];
                }
                for (var i = 0, j = this.childWidgets.length; i < j; i++) {
                    var w = this.childWidgets[i].getWidgetById(id);
                    if (w) {
                        return w;
                    }
                }
                return null;
            };

            /**
             * 在子组件数组的特定位置添加一个新的子组件
             * @param widget {Widget} 组件实例，可以是继承自Widget的任意组件实例
             * @param index {Number} 组件在组件列表的索引位置，从0开始，如果不传，默认在最后面添加
             */

            Widget.prototype.addChildWidget = function addChildWidget(widget, index) {
                if (!index && index !== 0) index = this.childWidgets.length;
                this.childWidgets.splice(index, 0, widget);
                // 为查询效率，增加childMap
                this.childMap[widget.id] = widget;
                widget.parentWidget = this;
                if (widget.options.cfg.default_focus === 'yes') {
                    this.setDefaultFocusedChildWidget(widget);
                }
            };

            /**
             * 判断widget是否在子组件中
             * @param widget {Widget} 组件实例，可以是继承自Widget的任意组件实例
             */

            Widget.prototype.hasChildWidget = function hasChildWidget(widget) {
                return this.childWidgets.indexOf(widget) !== -1;
            };

            /**
             * 删除子组件数组特定位置的子组件
             * @param widgetOrIndex {Number} 组件本身，或组件在组件列表的索引位置（从0开始）
             * @return widget {Number} 被删除的组件
             */

            Widget.prototype.removeChildWidget = function removeChildWidget(widgetOrIndex) {
                var removeArr = undefined;
                // 如果是Widget，则查询index
                if (widgetOrIndex instanceof Widget) {
                    widgetOrIndex = this.childWidgets.indexOf(widgetOrIndex);
                }
                if (widgetOrIndex < 0) {
                    return;
                }
                removeArr = this.childWidgets.splice(widgetOrIndex, 1);
                var removedWidget = removeArr.length ? removeArr[0] : null;
                if (!removedWidget) {
                    return;
                }
                // 从map中删除
                delete this.childMap[removedWidget.id];
                // 如果删除的正好是当前选中的子组件
                if (removedWidget === this.getFocusedChildWidget()) {
                    var willFocusedWidget = this.getDefaultFocusedChildWidget() === removedWidget ? this.childWidgets[0] : this.getDefaultFocusedChildWidget();
                    willFocusedWidget.focus();
                }
                // 如果删除的是缓存的子组件
                if (removedWidget === this.getCachedChildWidget()) {
                    this.cachedChildWidget = null;
                }
                return removedWidget;
            };

            /**
             * 获取容器dom节点
             * @return {HTMLElement}
             */

            Widget.prototype.getDOMNode = function getDOMNode() {
                return this.con;
            };

            // 得到dom的上下左右宽高中心位置信息

            Widget.prototype.getWidgetRect = function getWidgetRect(cache) {
                if (cache && this.rect) {
                    return this.rect;
                }
                var el = this.getDOMNode();
                var elRect = el.getBoundingClientRect();
                this.rect = {
                    top: elRect.top,
                    bottom: elRect.bottom,
                    right: elRect.right,
                    left: elRect.left,
                    width: elRect.width,
                    height: elRect.height,
                    centerX: elRect.width / 2 + elRect.left,
                    centerY: elRect.height / 2 + elRect.top
                };
                return this.rect;
            };

            Widget.prototype.getWidgetRectAsync = function getWidgetRectAsync(cb) {
                var _this2 = this;

                window.requestAnimationFrame(function () {
                    var el = _this2.getDOMNode();
                    var elRect = el.getBoundingClientRect();
                    var rect = {
                        top: elRect.top,
                        bottom: elRect.bottom,
                        right: elRect.right,
                        left: elRect.left,
                        width: elRect.width,
                        height: elRect.height,
                        centerX: elRect.width / 2 + elRect.left,
                        centerY: elRect.height / 2 + elRect.top
                    };
                    _this2.rect || (_this2.rect = rect);
                    cb && cb(rect);
                });
            };

            /**
             * 增加事件监听
             * @param type {String} 事件类型
             * @param cb {Function} 事件回调函数
             * @param ctx {Object} 回调函数执行上下文
             * @param after {Bollean} 监听在默认操作之后执行
             * @return index {Number} 返回该监听的index，可以用来解绑
             */

            Widget.prototype.on = function on(type, cb, ctx, after) {
                if (type.constructor !== String) {
                    console.warn('[FocusEngine] 事件type类型必须是String');
                    return -1;
                }
                if (cb.constructor !== Function) {
                    console.warn('[FocusEngine] 事件监听类型必须是Function');
                    return -1;
                }
                type = type.toLowerCase();
                this.eventListeners.push({
                    type: type,
                    cb: cb,
                    ctx: ctx || null,
                    after: !!after
                });
                return this.eventListeners.length - 1;
            };

            /**
             * 移除事件监听
             * @param index {Number} 事件index，即on方法的返回
             */

            Widget.prototype.off = function off(index) {
                if (index < 0) {
                    return;
                }
                this.eventListeners[index] = null;
            };

            /**
             * 解除事件绑定
             * @param type {String} 事件类型
             * @param cb {Function} 绑定事件的回调函数
             */

            Widget.prototype.detach = function detach(type, cb) {
                console.warn('[FocusEngine] detach方法不再推荐使用，请使用off方法');
                type = type.toLowerCase();
                for (var i = 0, l = this.eventListeners.length; i < l; i++) {
                    var listener = this.eventListeners[i];
                    if (listener.type === type && listener.cb === cb) {
                        this.eventListeners[i] = null;
                    }
                }
            };

            /**
             * 触发事件，支持冒泡和捕获
             * @param type {Event} 事件对象
             * @param data {Object} 事件额外参数
             */

            Widget.prototype.fire = function fire(e) {
                this.exeEventListeners(e);
                this.exeEventDefault(e);
                this.exeEventListeners(e, true);
                var widget = this;
                while (widget.parentWidget && !e.isPropagationStopped()) {
                    widget = widget.parentWidget;
                    widget.exeEventListeners(e);
                    widget.exeEventDefault(e);
                    widget.exeEventListeners(e, true);
                }
                return this;
            };

            // 执行自定义的事件监听

            Widget.prototype.exeEventListeners = function exeEventListeners(e, after) {
                // 如果阻止了Listener，那么禁止执行
                if (e.isListenerPrevented()) {
                    return;
                }
                e.type = e.type.toLowerCase();
                for (var i = 0, l = this.eventListeners.length; i < l; i++) {
                    var listener = this.eventListeners[i];
                    if (!listener) {
                        continue;
                    }
                    if (listener.type === e.type && listener.after === !!after) {
                        listener.cb.call(listener.ctx, e);
                    }
                }
            };

            // 执行默认的事件处理

            Widget.prototype.exeEventDefault = function exeEventDefault(e) {
                // 统一管理所有的默认事件处理，任何继承Widget的组件想处理某个事件只需要增加相应的处理函数即可：
                // 如：scrollend事件的处理函数是 scrollendDefault。
                var eventDefaultHandler = e.type + 'Default';
                this[eventDefaultHandler] && this[eventDefaultHandler](e);
            };

            /**
             * 销毁组件及其子组件
             * @param isClearDom {Boolean} 销毁组件的时候是否把dom架构连带销毁
             */

            Widget.prototype.destroy = function destroy(isClearDom) {
                for (var i = 0; i < this.childWidgets.length; i++) {
                    this.childWidgets[i].destroy(isClearDom);
                }
                if (this.getParentWidget()) {
                    this.getParentWidget().removeChildWidget(this);
                }
                delete this.eventListeners;
                if (isClearDom) {
                    this.con.parentNode.removeChild(this.con);
                }
            };

            Widget.prototype._filterArray = function _filterArray(arr1, arr2) {
                return arr1.filter(function (el, i, arr) {
                    return arr2.indexOf(el) === -1;
                });
            };

            Widget.prototype._removeSpaces = function _removeSpaces(str) {
                if (!str) {
                    return '';
                }
                return str.replace(/\s+/g, '');
            };

            Widget.prototype.parseDom = function parseDom(html) {
                var tmp = document.createElement('div');
                tmp.innerHTML = html;
                return tmp.children;
            };

            Widget.prototype.disableClick = function disableClick() {
                this.noClick = true;
            };

            Widget.prototype.enableClick = function enableClick() {
                this.noClick = false;
            };

            // 得到组件会触发的所有事件类型

            Widget.prototype.getEvents = function getEvents() {
                return ['keydown', 'keyup', 'ok', 'okdown', 'click', 'focus', 'blur'];
            };

            return Widget;
        })();

        exports['default'] = Widget;
        module.exports = exports['default'];

        /***/ },
    /* 4 */
    /***/ function(module, exports, __webpack_require__) {



        Object.defineProperty(exports, '__esModule', {
            value: true
        });

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

        function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _widget = __webpack_require__(3);

        var _widget2 = _interopRequireDefault(_widget);

        var _event = __webpack_require__(2);

        var _event2 = _interopRequireDefault(_event);

        var Switch = (function (_Widget) {
            _inherits(Switch, _Widget);

            /**
             * @param container {HTMLElement} 组件的容器dom元素
             */

            function Switch(container) {
                _classCallCheck(this, Switch);

                _Widget.call(this, container);
                this.minInterval = this.options.cfg.interval > 0 ? this.options.cfg.interval * 1000 : 0;
                // 配置：是否禁用区域算法
                this.disableArea = this.options.cfg.disable_area === 'yes';
                // 配置：是否禁用算法
                this.disableShadow = this.options.cfg.disable_shadow === 'yes';
                this.useLeafRect = this.options.cfg.use_leaf_rect === 'yes';
                this.cacheRect = this.options.cfg.disable_cache_rect === 'yes' ? false : true;
            }

            /**
             * 删除子组件数组特定位置的子组件，由于Switch需要处理方向缓存，增加Widget没有的逻辑
             * @param widgetOrIndex {Number} 组件本身，或组件在组件列表的索引位置（从0开始）
             * @return widget {Number} 被删除的组件
             */

            Switch.prototype.removeChildWidget = function removeChildWidget(widgetOrIndex) {
                var removedWidget = _Widget.prototype.removeChildWidget.call(this, widgetOrIndex);
                // 如果删除的是逆方向缓存的子组件
                if (removedWidget === this.lastFocusedChildWidget) {
                    this.lastFocusedChildWidget = null;
                }
                return removedWidget;
            };

            Switch.prototype.keydownDefault = function keydownDefault(e) {
                if (this.isLeafWidget()) {
                    this.fire(new _event2['default']('switchend', this, { keyCode: e.keyCode }));
                    return;
                }
                // 如果keydown是方向键，而且没有被阻止默认处理，则进行switch操作
                if (!e.isDefaultPrevented() && e.target && [_event2['default'].VK_LEFT, _event2['default'].VK_RIGHT, _event2['default'].VK_UP, _event2['default'].VK_DOWN].indexOf(e.keyCode) !== -1) {
                    this.doSwitch(e);
                }
            };

            // 进行switch操作

            Switch.prototype.doSwitch = function doSwitch(e) {
                // 如果小于设置的最低间隔时间，取消这次switch
                var currentTime = new Date().getTime();
                if (currentTime - this.lastKeydownTime < this.minInterval) {
                    e.preventDefault();
                    return;
                }

                this.lastKeydownTime = currentTime;
                var fChildWidget = this.getFocusedChildWidget();
                var optionDir = fChildWidget.options.dir;
                var newFocusChildWidget = null;

                var oppositeVK = undefined;
                var dirName = undefined;
                if (e.keyCode === _event2['default'].VK_LEFT) {
                    oppositeVK = _event2['default'].VK_RIGHT;
                    dirName = 'left';
                } else if (e.keyCode === _event2['default'].VK_UP) {
                    oppositeVK = _event2['default'].VK_DOWN;
                    dirName = 'up';
                } else if (e.keyCode === _event2['default'].VK_RIGHT) {
                    oppositeVK = _event2['default'].VK_LEFT;
                    dirName = 'right';
                } else if (e.keyCode === _event2['default'].VK_DOWN) {
                    oppositeVK = _event2['default'].VK_UP;
                    dirName = 'down';
                }

                // 第一优先级：缓存
                if (this.options.cfg.disable_cache_pre !== 'yes' && this.lastKeyCode === oppositeVK && this.lastFocusedChildWidget && !this.lastFocusedChildWidget.disabled) {
                    newFocusChildWidget = this.lastFocusedChildWidget;
                }

                // 第二优先级：配置
                if (!newFocusChildWidget && optionDir && optionDir[dirName]) {
                    newFocusChildWidget = this._queryWidgetByCfg(fChildWidget, optionDir[dirName]);
                }

                // 第三优先级：阴影算法
                if (!newFocusChildWidget && !this.disableShadow && fChildWidget.options.cfg.disable_self_shadow !== 'yes') {
                    newFocusChildWidget = this._queryWidgetByShadowAlgorithm(fChildWidget, dirName, e);
                }

                // 第四优先级：区域算法
                if (!newFocusChildWidget && !this.disableArea && fChildWidget.options.cfg.disable_self_area !== 'yes') {
                    newFocusChildWidget = this._queryWidgetByAreaAlgorithm(fChildWidget, dirName, e);
                }

                if (!newFocusChildWidget) {
                    this.fire(new _event2['default']('switchend', this, { keyCode: e.keyCode }));
                    return;
                }

                newFocusChildWidget.focus();
                // 如果没有配置disable_cache_pre，记录上次的焦点及按键
                if (this.options.cfg.disable_cache_pre !== 'yes') {
                    this.lastFocusedChildWidget = fChildWidget;
                    this.lastKeyCode = e.keyCode;
                }

                // 不再执行后续的默认事件处理，但是会继续冒泡。
                e.preventDefault();
            };

            Switch.prototype._queryWidgetByCfg = function _queryWidgetByCfg(widget, tabIndex) {
                if (tabIndex == -1) return widget;
                for (var i = 0, j = this.childWidgets.length; i < j; i++) {
                    var tempChild = this.childWidgets[i];
                    if (tempChild === widget) {
                        continue;
                    }
                    if (tempChild.disabled) {
                        continue;
                    }
                    if (tempChild.options.tab === tabIndex && tempChild.getDOMNode().style.display !== 'none') {
                        return this.childWidgets[i];
                    }
                }
                return null;
            };

            Switch.prototype._queryWidgetByShadowAlgorithm = function _queryWidgetByShadowAlgorithm(widget, dir, e) {
                var currentRect = widget.getWidgetRect(this.cacheRect);
                if ((this.useLeafRect || widget.options.cfg.use_self_leaf_rect === 'yes') && e) {
                    currentRect = e.target.getWidgetRect(this.cacheRect);
                }
                var resultWidget = null;
                var dis = Infinity;
                for (var i = 0; i < this.childWidgets.length; i++) {
                    var tempWidget = this.childWidgets[i];
                    if (tempWidget === widget) {
                        continue;
                    }
                    if (tempWidget.disabled) {
                        continue;
                    }
                    var tempWidgetRect = tempWidget.getWidgetRect(this.cacheRect);
                    if (dir === 'left' && tempWidgetRect.right < currentRect.right && tempWidgetRect.left < currentRect.left && tempWidgetRect.top < currentRect.bottom && tempWidgetRect.bottom > currentRect.top && currentRect.right - tempWidgetRect.right < dis) {
                        resultWidget = tempWidget;
                        dis = currentRect.right - tempWidgetRect.right;
                    } else if (dir === 'right' && tempWidgetRect.left > currentRect.left && tempWidgetRect.right > currentRect.right && tempWidgetRect.top < currentRect.bottom && tempWidgetRect.bottom > currentRect.top && tempWidgetRect.left - currentRect.left < dis) {
                        resultWidget = tempWidget;
                        dis = tempWidgetRect.left - currentRect.left;
                    } else if (dir === 'up' && tempWidgetRect.bottom < currentRect.bottom && tempWidgetRect.top < currentRect.top && tempWidgetRect.left < currentRect.right && tempWidgetRect.right > currentRect.left && currentRect.bottom - tempWidgetRect.bottom < dis) {
                        resultWidget = tempWidget;
                        dis = currentRect.bottom - tempWidgetRect.bottom;
                    } else if (dir === 'down' && tempWidgetRect.top > currentRect.top && tempWidgetRect.bottom > currentRect.bottom && tempWidgetRect.left < currentRect.right && tempWidgetRect.right > currentRect.left && tempWidgetRect.top - currentRect.top < dis) {
                        resultWidget = tempWidget;
                        dis = tempWidgetRect.top - currentRect.top;
                    }
                }
                return resultWidget;
            };

            Switch.prototype._queryWidgetByAreaAlgorithm = function _queryWidgetByAreaAlgorithm(widget, dir, e) {
                var currentRect = widget.getWidgetRect(this.cacheRect);
                if ((this.useLeafRect || widget.options.cfg.use_self_leaf_rect === 'yes') && e) {
                    currentRect = e.target.getWidgetRect(this.cacheRect);
                }
                var resultWidget = null;
                var dis = Infinity;
                for (var i = 0; i < this.childWidgets.length; i++) {
                    var tempWidget = this.childWidgets[i];
                    if (tempWidget === widget) {
                        continue;
                    }
                    if (tempWidget.disabled) {
                        continue;
                    }
                    var tempWidgetRect = tempWidget.getWidgetRect(this.cacheRect);
                    if (dir === 'left' && tempWidgetRect.right <= currentRect.left) {
                        var tempDis = Infinity;
                        if (tempWidgetRect.bottom < currentRect.top) {
                            tempDis = Math.sqrt(Math.pow(currentRect.left - tempWidgetRect.right, 2) + Math.pow(currentRect.top - tempWidgetRect.bottom, 2));
                        } else if (tempWidgetRect.top > currentRect.bottom) {
                            tempDis = Math.sqrt(Math.pow(currentRect.left - tempWidgetRect.right, 2) + Math.pow(tempWidgetRect.top - currentRect.bottom, 2));
                        } else {
                            tempDis = currentRect.left - tempWidgetRect.right;
                        }
                        if (tempDis < dis) {
                            resultWidget = tempWidget;
                            dis = tempDis;
                        }
                    } else if (dir === 'right' && tempWidgetRect.left >= currentRect.right) {
                        var tempDis = Infinity;
                        if (tempWidgetRect.bottom < currentRect.top) {
                            tempDis = Math.sqrt(Math.pow(tempWidgetRect.left - currentRect.right, 2) + Math.pow(currentRect.top - tempWidgetRect.bottom, 2));
                        } else if (tempWidgetRect.top > currentRect.bottom) {
                            tempDis = Math.sqrt(Math.pow(tempWidgetRect.left - currentRect.right, 2) + Math.pow(tempWidgetRect.top - currentRect.bottom, 2));
                        } else {
                            tempDis = tempWidgetRect.left - currentRect.right;
                        }
                        if (tempDis < dis) {
                            resultWidget = tempWidget;
                            dis = tempDis;
                        }
                    } else if (dir === 'up' && tempWidgetRect.bottom <= currentRect.top) {
                        var tempDis = Infinity;
                        if (tempWidgetRect.right < currentRect.left) {
                            tempDis = Math.sqrt(Math.pow(currentRect.top - tempWidgetRect.bottom, 2) + Math.pow(currentRect.left - tempWidgetRect.right, 2));
                        } else if (tempWidgetRect.left > currentRect.right) {
                            tempDis = Math.sqrt(Math.pow(currentRect.top - tempWidgetRect.bottom, 2) + Math.pow(tempWidgetRect.left - currentRect.right, 2));
                        } else {
                            tempDis = currentRect.top - tempWidgetRect.bottom;
                        }
                        if (tempDis < dis) {
                            resultWidget = tempWidget;
                            dis = tempDis;
                        }
                    } else if (dir === 'down' && tempWidgetRect.top >= currentRect.bottom) {
                        var tempDis = Infinity;
                        if (tempWidgetRect.right < currentRect.left) {
                            tempDis = Math.sqrt(Math.pow(tempWidgetRect.top - currentRect.bottom, 2) + Math.pow(currentRect.left - tempWidgetRect.right, 2));
                        } else if (tempWidgetRect.left > currentRect.right) {
                            tempDis = Math.sqrt(Math.pow(tempWidgetRect.top - currentRect.bottom, 2) + Math.pow(tempWidgetRect.left - currentRect.right, 2));
                        } else {
                            tempDis = tempWidgetRect.top - currentRect.bottom;
                        }
                        if (tempDis < dis) {
                            resultWidget = tempWidget;
                            dis = tempDis;
                        }
                    }
                }
                return resultWidget;
            };

            Switch.prototype.getEvents = function getEvents() {
                return _Widget.prototype.getEvents.call(this).concat(['switchend']);
            };

            return Switch;
        })(_widget2['default']);

        exports['default'] = Switch;
        module.exports = exports['default'];

        /***/ },
    /* 5 */
    /***/ function(module, exports, __webpack_require__) {



        Object.defineProperty(exports, '__esModule', {
            value: true
        });

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

        function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _switch = __webpack_require__(4);

        var _switch2 = _interopRequireDefault(_switch);

        var _event = __webpack_require__(2);

        var _event2 = _interopRequireDefault(_event);

        var _animate = __webpack_require__(6);

        var _animate2 = _interopRequireDefault(_animate);

        var Scroll = (function (_Switch) {
            _inherits(Scroll, _Switch);

            /**
             * @param container {HTMLElement} 组件的容器dom元素
             */

            function Scroll(container) {
                var _this = this;

                _classCallCheck(this, Scroll);

                _Switch.call(this, container);
                this.cacheRect = false;
                this.dir = this.options.cfg.dir === 'h' ? this.options.cfg.dir : 'v';
                this.centerDOM = this.options.cfg.center === 'document' ? this.options.cfg.center : 'con';
                this.duration = this.options.cfg.duration ? parseFloat(this.options.cfg.duration) : 0.3;
                this.speedup = this.options.cfg.speedup ? parseFloat(this.options.cfg.speedup) : 0.6;
                this.easing = this.options.cfg.easing ? this.options.cfg.easing : 'ease-out';
                this.speedupEasing = this.options.cfg.speedup_easing ? this.options.cfg.speedup_easing : 'linear';
                this.useRAF = this.options.cfg.use_ram === 'yes' || this.options.cfg.use_raf === 'yes';
                this.lazyload = this.options.cfg.disable_lazyload !== 'yes';
                this.lazyloadDelay = this.options.cfg.lazyload_delay !== undefined ? parseFloat(this.options.cfg.lazyload_delay) : 0.1;
                this.autoListWidth = this.options.cfg.auto_list_width === 'yes';
                this.conList = this.con.querySelector('.scroll-list');
                this.offset = 0;
                this.desArr = [];
                if (!this.conList) {
                    console.error('[FocusEngine_Error]Scroll组件必须含有一个类名为scroll-list的子元素。');
                    return;
                }
                var listStyles = getComputedStyle(this.conList);

                if (listStyles.left !== 'auto' && parseInt(listStyles.left) !== 0 && this.dir === 'h') {
                    console.error('[FocusEngine_Error]横向Scroll容器的.scroll-list子元素不可设置left值');
                }

                if (listStyles.top !== 'auto' && parseInt(listStyles.top) !== 0 && this.dir === 'v') {
                    console.error('[FocusEngine_Error]纵向Scroll容器的.scroll-list子元素不可设置top值');
                }

                if (listStyles.position === 'static') {
                    this.conList.style.position = 'relative';
                }
                this._render();
                if (this.autoListWidth) {
                    this._setAutoListWidth();
                }
                var defaultFocusedChild = this.getDefaultFocusedChildWidget();
                if (defaultFocusedChild) {
                    this.scrollToWidget(defaultFocusedChild, 0);
                }
                if (this.lazyload) {
                    setTimeout(function () {
                        _this.loadVisibleImage();
                    }, 10);
                }
            }

            // 计算容器和list的宽高

            Scroll.prototype._computeScrollRect = function _computeScrollRect() {
                this.conRect = this.getWidgetRect();
                this.conWidth = this.conRect.width;
                this.conHeight = this.conRect.height;
                this.listRect = this.conList.getBoundingClientRect();
                this.listWidth = this.listRect.width;
                this.listHeight = this.listRect.height;
                if (this.centerDOM === 'document') {
                    var docRect = document.documentElement.getBoundingClientRect();
                    if (this.dir === 'v') {
                        this.center = docRect.height / 2;
                    } else {
                        this.center = docRect.width / 2;
                    }
                } else {
                    if (this.dir === 'v') {
                        this.center = this.conRect.height / 2;
                    } else {
                        this.center = this.conRect.width / 2;
                    }
                }
            };

            // 自动设置横向列表的宽度

            Scroll.prototype._setAutoListWidth = function _setAutoListWidth() {
                this.rightPaddingWithUnit = this.options.cfg.right_padding;
                this.rightPadding = 0;
                if (this.rightPaddingWithUnit) {
                    if (this.rightPaddingWithUnit.indexOf('rem') !== -1) {
                        this.rightPadding = parseFloat(this.rightPaddingWithUnit) * parseFloat(document.querySelector('html').style.fontSize);
                    } else {
                        this.rightPadding = parseFloat(this.rightPaddingWithUnit);
                    }
                }
                this.conList.style.width = '99999px';
                for (var i = 0, _length = this.childWidgets.length; i < _length; i++) {
                    var right = this.childWidgets[i].getWidgetRect().right;
                    var width = right - this.listRect.left + this.rightPadding;
                    if (width > this.listWidth) {
                        this.listWidth = width;
                    }
                }
                this.conList.style.width = this.listWidth + 'px';
            };

            Scroll.prototype.reRender = function reRender() {
                var _this2 = this;

                if (!document.querySelector('#' + this.id)) {
                    return;
                }
                this.con = document.querySelector('#' + this.id);
                this.conList = this.con.querySelector('.scroll-list');
                if (!this.conList) {
                    console.error('[FocusEngine_Error]Scroll组件必须含有一个类名为scroll-list的子元素。');
                    return;
                }
                var listStyles = getComputedStyle(this.conList);

                if (listStyles.position === 'static') {
                    this.conList.style.position = 'relative';
                }

                this.options = this._getOptions(this.con);
                this.dir = this.options.cfg.dir === 'h' ? this.options.cfg.dir : 'v';
                this.centerDOM = this.options.cfg.center === 'ducoment' ? this.options.cfg.center : 'con';
                this.duration = this.options.cfg.duration ? parseFloat(this.options.cfg.duration) : 0.3;
                this.easing = this.options.cfg.easing ? this.options.cfg.easing : 'linear';
                this.useRAF = this.options.cfg.use_ram === 'yes' || this.options.cfg.use_raf === 'yes';
                this._render(true);
                this._reRenderChildWidget();
                if (this.autoListWidth) {
                    this._setAutoListWidth();
                }
                if (this.lazyload) {
                    setTimeout(function () {
                        _this2.loadVisibleImage();
                    }, 10);
                }
            };

            Scroll.prototype._render = function _render(isReRender) {
                var _this3 = this;

                this._computeScrollRect();
                if (!isReRender) {
                    if (this.dir === 'v') {
                        this.conList.style.top = '0px';
                    } else {
                        this.conList.style.left = '0px';
                    }
                }
                if (!this.useRAF) {
                    if (this.dir === 'v') {
                        this.conList.style.transition = 'top ' + this.duration + 's ' + this.easing;
                        this.conList.style.webkitTransition = 'top ' + this.duration + 's ' + this.easing;
                    } else {
                        this.conList.style.transition = 'left ' + this.duration + 's ' + this.easing;
                        this.conList.style.webkitTransition = 'left ' + this.duration + 's ' + this.easing;
                    }
                    if (!isReRender) {
                        // 避免首次render后也会触发scrollend事件
                        this.rendered = false;
                        this.conList.addEventListener('webkitTransitionEnd', function (e) {
                            if (e.target !== _this3.conList) {
                                return;
                            }
                            if (_this3.rendered) {
                                _this3.fire(new _event2['default']('scrollend', _this3));
                            }
                            _this3.rendered = true;
                        });
                        this.conList.addEventListener('transitionend', function (e) {
                            if (e.target !== _this3.conList) {
                                return;
                            }
                            if (_this3.rendered) {
                                _this3.fire(new _event2['default']('scrollend', _this3));
                            }
                            _this3.rendered = true;
                        });
                    }
                }
            };

            Scroll.prototype.focusDefault = function focusDefault(e) {
                _Switch.prototype.focusDefault.call(this, e);
                if (!this.getFirstFocusableChildWidget()) {
                    return;
                }
                if (!e.isDefaultPrevented()) {
                    // 如果这些值都是0，那么说明在focus之前是display:none的，因此focus时重新计算这些值
                    if (!this.conWidth && !this.conHeight && !this.listWidth && !this.listHeight && !this.center) {
                        this._computeScrollRect();
                        if (this.autoListWidth) {
                            this._setAutoListWidth();
                        }
                        var defaultFocusedChild = this.getDefaultFocusedChildWidget();
                        if (defaultFocusedChild) {
                            this.scrollToWidget(defaultFocusedChild, 0);
                            return;
                        }
                    }
                    this.doScroll(e);
                }
            };

            Scroll.prototype.scrollstartDefault = function scrollstartDefault(e) {
                this.loadImageTimeout && clearTimeout(this.loadImageTimeout);
            };

            Scroll.prototype.scrollendDefault = function scrollendDefault(e) {
                var _this4 = this;

                if (this.lazyload && e.target === this) {
                    this.loadImageTimeout = setTimeout(function () {
                        _this4.loadVisibleImage();
                    }, this.lazyloadDelay * 1000);
                }
            };

            Scroll.prototype.doSwitch = function doSwitch(e) {
                _Switch.prototype.doSwitch.call(this, e);
            };

            // 进行scroll操作

            Scroll.prototype.doScroll = function doScroll(e) {
                var fWidget = this.getFocusedChildWidget();
                // this.scrollToWidget(fWidget, this.duration, e);
            };

            /**
             * 将scrolllist滚动到某个widget获取焦点时应该在的位置，但是并不会focus该widget
             * @Param {Widget} widget 目标Widget
             * @Param {Event} e 事件
             */

            Scroll.prototype.scrollToWidget = function scrollToWidget(widget, duration, e) {
                var offset = this.computeOffsetByWidget(widget);
                if (duration === undefined) {
                    duration = this.duration;
                }
                // this.scrollListTo(offset, duration, e);
                return this;
            };

            /**
             * 计算滚动到某个widget时list的offset值
             * @Param   {Widget} widget 目标Widget
             * @Returns {Number} offset值
             */

            Scroll.prototype.computeOffsetByWidget = function computeOffsetByWidget(widget) {
                if (widget.options.cfg.to_start === 'yes') {
                    return 0;
                }
                if (widget.options.cfg.to_end === 'yes') {
                    return this.dir === 'v' ? this.conHeight - this.listHeight : this.conWidth - this.listWidth;
                }
                this._computeScrollRect();
                var dis = this.center - this._getExpectCenter(widget);
                if (this.dir === 'v') {
                    if (dis < 0) {
                        // 如果向上滚动时下边界偏出，设置成最向上的位置，如果上次滚动已经达到顶，返回。
                        if (this.offset + dis < this.conHeight - this.listHeight) {
                            dis = this.conHeight - this.listHeight - this.offset;
                            if (dis > 0) {
                                return this.offset;
                            }
                        }
                    } else if (dis > 0) {
                        // 同上，防止上边界偏出。
                        if (this.offset * -1 < dis) {
                            dis = this.offset * -1;
                            if (dis < 0) {
                                return this.offset;
                            }
                        }
                    } else {
                        return this.offset;
                    }
                    return this.offset + dis;
                }
                // horizontal
                if (dis < 0) {
                    // 如果向左滚动时下边界偏出，设置成最向左的位置，如果上次滚动已经达到顶，返回。
                    if (this.offset + dis < this.conWidth - this.listWidth) {
                        dis = this.conWidth - this.listWidth - this.offset;
                        if (dis > 0) {
                            return this.offset;
                        }
                    }
                } else if (dis > 0) {
                    // 同上，防止向右边界偏出
                    if (this.offset * -1 < dis) {
                        dis = this.offset * -1;
                        if (dis < 0) {
                            return this.offset;
                        }
                    }
                } else {
                    return this.offset;
                }
                return this.offset + dis;
            };

            /**
             * 滚动scroll-list到一个位置，des是目的地位置；e是事件
             * @Param {Number} des 目标offset值
             * @Param {Event} e 事件
             */

            Scroll.prototype.scrollListTo = function scrollListTo(des, duration, e) {
                var _this5 = this;

                if (duration === undefined) {
                    duration = this.duration;
                }
                this.fire(new _event2['default']('scrollstart', this));
                if (this.useRAF) {
                    if (this.desArr.length > 0 && des === this.desArr[this.desArr.length - 1]) {
                        return;
                    }
                    if (e && e.type === 'focus') {
                        this.futureOffset = des;
                    }
                    this.desArr.push(des);
                    if (this.desArr.length === 1) {
                        // this.doAnimate(duration, this.easing);
                    }
                } else {
                    this.offset = des;
                    if (this.dir === 'v') {
                        this.conList.style.transition = 'top ' + duration + 's ' + this.easing;
                        this.conList.style.webkitTransition = 'top ' + duration + 's ' + this.easing;
                    } else {
                        this.conList.style.transition = 'left ' + duration + 's ' + this.easing;
                        this.conList.style.webkitTransition = 'left ' + duration + 's ' + this.easing;
                    }
                    setTimeout(function () {
                        if (_this5.dir === 'v') {
                            _this5.conList.style.transition = 'top ' + _this5.duration + 's ' + _this5.easing;
                            _this5.conList.style.webkitTransition = 'top ' + _this5.duration + 's ' + _this5.easing;
                        } else {
                            _this5.conList.style.transition = 'left ' + _this5.duration + 's ' + _this5.easing;
                            _this5.conList.style.webkitTransition = 'left ' + _this5.duration + 's ' + _this5.easing;
                        }
                    }, 1);
                    if (this.dir === 'v') {
                        this.conList.style.top = this.offset + 'px';
                    } else {
                        this.conList.style.left = this.offset + 'px';
                    }
                    if (e && e.type === 'focus') {
                        this.futureOffset = this.offset;
                    }
                }
                return this;
            };

            Scroll.prototype.doAnimate = function doAnimate(duration, easing, isSpeedup) {
                var _this6 = this;

                // 如果下次动画offset地跟当前offset相同，取消这次动画
                if (this.desArr[0] === this.offset) {
                    this.desArr.shift();
                    this.doAnimate(duration, easing);
                    return;
                }
                if (this.desArr.length === 0) {
                    this.fire(new _event2['default']('scrollend', this));
                    return;
                }
                var endCb = function endCb() {
                    _this6.scrollEndTimeout && clearTimeout(_this6.scrollEndTimeout);
                    _this6.offset = _this6.desArr.shift();
                    if (_this6.desArr.length > 0) {
                        _this6.doAnimate(duration, easing, true);
                    } else {
                        _this6.scrollEndTimeout = setTimeout(function () {
                            _this6.fire(new _event2['default']('scrollend', _this6));
                        }, 50);
                    }
                };
                (0, _animate2['default'])({
                    dom: this.conList,
                    style: this.dir === 'v' ? 'top' : 'left',
                    start: this.offset,
                    end: this.desArr[0],
                    duration: isSpeedup ? duration * this.speedup : duration,
                    easing: easing,
                    cb: endCb
                });
            };

            /**
             *得到上次滚动结束后，widget中心点相对于con应该所在的位置（水平或垂直）。
             *由于滚动过程中得到的位置是不准确的，而且也不是滚动结束后应该的位置，所以通过设置的offset和相对距离来计算。
             *widgetRect.centerY - listRect.top是widget.center相对于conList的top的距离，由于两者是动画过程中同时获取的，所以动画对相对距离无影响。
             *两者相加即滚动结束后widget.center相对于con的位置。
             **/

            Scroll.prototype._getExpectCenter = function _getExpectCenter(widget) {
                var widgetRect = widget.getWidgetRect();
                if (this.dir === 'v') {
                    return this.offset + widgetRect.centerY - this.listRect.top;
                } else {
                    return this.offset + widgetRect.centerX - this.listRect.left;
                }
            };

            Scroll.prototype.getListNode = function getListNode() {
                return this.conList;
            };

            Scroll.prototype.loadVisibleImage = function loadVisibleImage() {
                var conRect = this.getWidgetRect();
                var conLeft = conRect.left;
                var conTop = conRect.top;
                var conRight = conRect.right;
                var conBottom = conRect.bottom;
                var lazyImages = this.con.querySelectorAll('.fe-lazyload');

                var _loop = function (i) {
                    var tempImage = lazyImages[i];
                    var dataSrc = tempImage.getAttribute('fe-src');
                    var rect = tempImage.getBoundingClientRect();
                    // 未加载过，而且在viewport之内，加载图片
                    if (tempImage.src !== dataSrc && !(rect.left <= conLeft && rect.right <= conLeft || rect.left >= conRight && rect.right >= conRight || rect.top >= conBottom && rect.bottom >= conBottom || rect.top <= conTop && rect.bottom <= conTop)) {
                        var hiddenImage = new Image();
                        hiddenImage.src = dataSrc;
                        hiddenImage.onload = function () {
                            tempImage.src = dataSrc;
                        };
                    }
                };

                for (var i = 0; i < lazyImages.length; i++) {
                    _loop(i);
                }
            };

            Scroll.prototype.getEvents = function getEvents() {
                return _Switch.prototype.getEvents.call(this).concat(['scrollstart', 'scrollend']);
            };

            return Scroll;
        })(_switch2['default']);

        exports['default'] = Scroll;
        module.exports = exports['default'];

        /***/ },
    /* 6 */
    /***/ function(module, exports, __webpack_require__) {

        // requestAnimationFrame shim for Blitz


        Object.defineProperty(exports, '__esModule', {
            value: true
        });

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

        // Easing functions refer to 'http://greweb.me/2012/02/bezier-curve-based-easing-functions-from-concept-to-implementation/'

        var _bezierEasing = __webpack_require__(7);

        var _bezierEasing2 = _interopRequireDefault(_bezierEasing);

        window.requestAnimationFrame = window.requestAnimationFrame || function (operation) {
            setTimeout(operation, 0);
        };
        var Easing = {
            // Blitz 不支持改语法的babel翻译，用下方的实现
            // 'ease-in': BezierEasing(0.42, 0.0, 1.00, 1.0),
            // 'ease-out': BezierEasing(0.00, 0.0, 0.58, 1.0),
            // 'ease-in-out': BezierEasing(0.42, 0.0, 0.58, 1.0),

            // CSS3 Easing Functions: http://www.w3schools.com/cssref/css3_pr_transition-timing-function.asp
            linear: function linear(t) {
                return t;
            },
            'ease': _bezierEasing2['default'].apply(null, [0.25, 0.1, 0.25, 1]),
            'ease-in': _bezierEasing2['default'].apply(null, [0.42, 0.0, 1.00, 1.0]),
            'ease-out': _bezierEasing2['default'].apply(null, [0.00, 0.0, 0.58, 1.0]),
            'ease-in-out': _bezierEasing2['default'].apply(null, [0.42, 0.0, 0.58, 1.0]),
            /**
             *自定义Bezier曲线
             *@param arr {Array} 是四个Bezier曲线的定义值
             **/
            custom: function custom(arr) {
                return _bezierEasing2['default'].apply(null, arr);
            }
            // 去掉下方的曲线，只用css默认支持的方式及自定义曲线
            // easeInQuad(t) { return t*t;},
            // easeOutQuad(t) { return t*(2-t);},
            // easeInOutQuad(t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t;},
            // easeInCubic(t) { return t*t*t;},
            // easeOutCubic(t) { return (--t)*t*t+1;},
            // easeInOutCubic(t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1;},
            // easeInQuart(t) { return t*t*t*t;},
            // easeOutQuart(t) { return 1-(--t)*t*t*t;},
            // easeInOutQuart(t) { return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t;},
            // easeInQuint(t) { return t*t*t*t*t;},
            // easeOutQuint(t) { return 1+(--t)*t*t*t*t;},
            // easeInOutQuint(t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t;},
        };

        // let frameTime = window.yunos ? 16 : 10;
        // let a = Date.now();
        // const setFrameTime = () => {
        //   const b = Date.now();
        //   frameTime = b - a;
        //   console.log(frameTime);
        //   a = b;
        //   window.requestAnimationFrame(setFrameTime);
        // };
        // window.requestAnimationFrame(setFrameTime);

        /**
         * DOM动画函数，
         * 暂仅支持以数字加单位为值的属性，如top、width等，不支持transform类似的属性。
         * 暂仅支持一次缓动一个属性。
         * @Param {Object} cfg 具体动画配置;
         * @Param {HTMLElement} cfg.dom DOM对象；
         * @Param {String} cfg.style style属性；
         * @Param {String} cfg.transitionType 使用何种方式实现动画，目前支持'css'和'js'两种，默认'js'；
         * @Param {Number} cfg.start 起始值；
         * @Param {Number} cfg.end 结束值；
         * @Param {String} [cfg.unit] 单位，默认px；
         * @Param {Number} [cfg.duration] 执行动画需要的时间，以秒为单位，默认1；
         * @Param {String} [cfg.easing] 缓动函数，目前支持：'ease'（默认）、'ease-out'、'ease-in'、'linear'；
         * @Param {Function} [cfg.cb] 动画结束后的回调函数；
         */
        function animate(cfg) {
            if (!(cfg && cfg.dom && cfg.style && cfg.end !== undefined)) {
                console.error('[FocusEngine_Error]animate方法的cfg参数：dom、style、end必需！');
                return;
            }
            var dom = cfg.dom;
            var style = cfg.style;
            var transitionType = cfg.transitionType === 'css' ? 'css' : 'js';
            var start = cfg.start;
            if (start === undefined) {
                var computedValue = parseFloat(getComputedStyle(dom)[style]);
                start = isNaN(computedValue) ? computedValue : 0;
            }
            var end = cfg.end;
            var duration = cfg.duration !== undefined ? parseFloat(cfg.duration) : 0.3;
            var milliDuration = duration * 1000;
            var easing = cfg.easing || 'ease-out';
            var unit = cfg.unit || 'px';
            var cb = cfg.cb || null;

            // 如果使用css的方式执行动画
            if (transitionType === 'css') {
                var _ret = (function () {
                    var easingFunction = '';
                    if (easing.constructor === Array) {
                        easingFunction = 'cubic-bezier(' + easing.join(',') + ')';
                    } else if (easing.constructor === String) {
                        easingFunction = easing;
                    }
                    var transitionendFunc = function transitionendFunc(e) {
                        if (e.target === dom) {
                            dom.style.transition = '';
                            dom.removeEventListener('transitionend', transitionendFunc);
                            cb && cb();
                        }
                    };
                    dom.addEventListener('transitionend', transitionendFunc);
                    dom.style.transition = style + ' ' + duration + 's ' + easingFunction;
                    dom.style[style] = end + unit;
                    return {
                        v: undefined
                    };
                })();

                if (typeof _ret === 'object') return _ret.v;
            }

            // 如果使用js的方式执行动画，默认
            var easingFunction = null;
            if (easing.constructor === Array) {
                easingFunction = Easing.custom(easing);
            } else if (easing.constructor === String) {
                easingFunction = Easing[easing];
            }
            // 最后权衡：使用requestAnimationFrame／依赖帧的方式
            var allFrames = milliDuration / 14;
            var currentFrame = 1;
            // const startTime = Date.now();
            var doAnimate = function doAnimate() {
                // 每帧都获取时间在Blitz上对动画性能影响较大，因此还是按照帧数来动画
                // const now = Date.now();
                if (currentFrame > allFrames) {
                    dom.style[style] = end + unit;
                    cb && cb();
                } else {
                    var percent = easingFunction(currentFrame / allFrames);
                    var currentValue = start + percent * (end - start);
                    dom.style[style] = currentValue + unit;
                    currentFrame++;
                    window.requestAnimationFrame(doAnimate);
                }
            };
            window.requestAnimationFrame(doAnimate);

            /*
	  每个动画使用单一setInterval的方式
	  const minInterval = window.yunos ? 0 : 14;
	  const interval = setInterval(() => {
	    if (currentFrame >= allFrames) {
	      clearInterval(interval);
	      dom.style[style] = end + unit;
	      cb && cb();
	    } else {
	      const percent = easingFunction(currentFrame / allFrames);
	      const currentValue = start + percent * (end - start);
	      dom.style[style] = currentValue + unit;
	      currentFrame++;
	    }
	  }, minInterval);
	  */

            /*
	  全局单一interval的方式
	  aniArr.push({
	    easingFunction,
	    dom,
	    style,
	    unit,
	    start,
	    end,
	    change: end - start,
	    milliDuration,
	    cb,
	    startTime: Date.now()
	  });
	   if (!aniInterval) {
	    aniInterval = setInterval(() => {
	      const now = Date.now();
	      let aniLen = aniArr.length;
	      let index = 0;
	      while(index < aniLen) {
	        const tempAni = aniArr[index];
	        const past = now - tempAni.startTime;
	        if (past < tempAni.milliDuration) {
	          const percent = tempAni.easingFunction(past / tempAni.milliDuration);
	          tempAni.dom.style[tempAni.style] = tempAni.start + (percent * tempAni.change) + tempAni.unit;
	          index++;
	          continue;
	        }
	        tempAni.dom.style[tempAni.style] = tempAni.end + tempAni.unit;
	        setTimeout(() => {
	          tempAni.cb && tempAni.cb();
	        }, 0);
	        aniArr.splice(index, 1);
	        aniLen--;
	        if (aniLen === 0) {
	          clearInterval(aniInterval);
	          aniInterval = null;
	        }
	      }
	    }, window.yonos ? 0 : 10);
	  }
	  */
        }
        window.animate = animate;

        exports['default'] = animate;
        module.exports = exports['default'];

        /***/ },
    /* 7 */
    /***/ function(module, exports) {

        /**
         * https://github.com/gre/bezier-easing
         * BezierEasing - use bezier curve for transition easing function
         * by Gaëtan Renaudeau 2014 - 2015 – MIT License
         */

            // These values are established by empiricism with tests (tradeoff: performance VS precision)


        var NEWTON_ITERATIONS = 4;
        var NEWTON_MIN_SLOPE = 0.001;
        var SUBDIVISION_PRECISION = 0.0000001;
        var SUBDIVISION_MAX_ITERATIONS = 10;

        var kSplineTableSize = 11;
        var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);

        var float32ArraySupported = typeof Float32Array === 'function';

        function A(aA1, aA2) {
            return 1.0 - 3.0 * aA2 + 3.0 * aA1;
        }
        function B(aA1, aA2) {
            return 3.0 * aA2 - 6.0 * aA1;
        }
        function C(aA1) {
            return 3.0 * aA1;
        }

        // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
        function calcBezier(aT, aA1, aA2) {
            return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
        }

        // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
        function getSlope(aT, aA1, aA2) {
            return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
        }

        function binarySubdivide(aX, aA, aB, mX1, mX2) {
            var currentX,
                currentT,
                i = 0;
            do {
                currentT = aA + (aB - aA) / 2.0;
                currentX = calcBezier(currentT, mX1, mX2) - aX;
                if (currentX > 0.0) {
                    aB = currentT;
                } else {
                    aA = currentT;
                }
            } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
            return currentT;
        }

        function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {
            for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
                var currentSlope = getSlope(aGuessT, mX1, mX2);
                if (currentSlope === 0.0) {
                    return aGuessT;
                }
                var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
                aGuessT -= currentX / currentSlope;
            }
            return aGuessT;
        }

        module.exports = function bezier(mX1, mY1, mX2, mY2) {
            if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) {
                throw new Error('bezier x values must be in [0, 1] range');
            }

            // Precompute samples table
            var sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
            if (mX1 !== mY1 || mX2 !== mY2) {
                for (var i = 0; i < kSplineTableSize; ++i) {
                    sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
                }
            }

            function getTForX(aX) {
                var intervalStart = 0.0;
                var currentSample = 1;
                var lastSample = kSplineTableSize - 1;

                for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
                    intervalStart += kSampleStepSize;
                }
                --currentSample;

                // Interpolate to provide an initial guess for t
                var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
                var guessForT = intervalStart + dist * kSampleStepSize;

                var initialSlope = getSlope(guessForT, mX1, mX2);
                if (initialSlope >= NEWTON_MIN_SLOPE) {
                    return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
                } else if (initialSlope === 0.0) {
                    return guessForT;
                } else {
                    return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
                }
            }

            return function BezierEasing(x) {
                if (mX1 === mY1 && mX2 === mY2) {
                    return x; // linear
                }
                // Because JavaScript number are imprecise, we should guarantee the extremes are right.
                if (x === 0) {
                    return 0;
                }
                if (x === 1) {
                    return 1;
                }
                return calcBezier(getTForX(x), mY1, mY2);
            };
        };

        /***/ },
    /* 8 */
    /***/ function(module, exports, __webpack_require__) {



        Object.defineProperty(exports, '__esModule', {
            value: true
        });

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

        function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _widget = __webpack_require__(3);

        var _widget2 = _interopRequireDefault(_widget);

        var _event = __webpack_require__(2);

        var _event2 = _interopRequireDefault(_event);

        var _animate = __webpack_require__(6);

        var _animate2 = _interopRequireDefault(_animate);

        var Grid = (function (_Widget) {
            _inherits(Grid, _Widget);

            function Grid(container) {
                _classCallCheck(this, Grid);

                _Widget.call(this, container);
                this._init();
                this._writeGridInnerHTML();
                // 初始化子组件
                _Widget.prototype._initChildWidgets.call(this);
                this['_checkWidgets_' + this.dir]();
            }

            Grid.prototype._initChildWidgets = function _initChildWidgets() {
                return;
            };

            // 判断grid是否需要reRender比较特殊，需要特殊处理

            Grid.prototype.reRender = function reRender() {}
            // if (!document.querySelector('#' + this.id)) {
            //   return;
            // }
            // this.con = document.querySelector('#' + this.id);
            // const firstChildWidget = this.childWidgets[0];
            // const firstChildNode = this.getDOMNode().children[0];
            // let needReRender = false;
            // // 判断第一个子dom是否还是原来的dom，如果是，则用原来的templateHTML，如果不是，用新的templateHTML
            // if (firstChildNode !== firstChildWidget.getDOMNode()) {
            //   this.templateHTML = firstChildNode.outerHTML;
            //   needReRender = true;
            // }
            // // 比较fe-cfg的几个属性，如果有改变，则需要reRender
            // const options = this._getOptions(this.con);
            // if (this.options.cfg.dir !== options.cfg.dir ||
            //     this.options.cfg.row !== options.cfg.row ||
            //     this.options.cfg.col !== options.cfg.col
            // ) {
            //   this.options = options;
            //   needReRender = true;
            // }
            // if (!needReRender) {
            //   return;
            // }
            // this.setCachedChildWidget(null);
            // this.setFocusedChildWidget(null);
            // this._init();
            // this._writeGridInnerHTML();
            // super._initChildWidgets();
            // this[`_checkWidgets_${this.dir}`]();
            // if (this.focused) {
            //   this.focus(true);
            // }

            // 设置用户配置内容并初始化Grid
            ;

            Grid.prototype._init = function _init() {
                this.dir = this.options.cfg.dir === 'h' ? 'h' : 'v';
                this.style = this.options.cfg.dir === 'h' ? 'left' : 'top';
                // Grid初始化
                if (isNaN(this.options.cfg.row) || isNaN(this.options.cfg.col)) {
                    console.error('[FocusEngine_Error]Grid组件必须设置行和列！行列数为视口内可见的最多行列数。');
                    return;
                }
                this.duration = this.options.cfg.duration !== undefined ? parseFloat(this.options.cfg.duration) : 0.3;
                this.speedupDuration = this.options.cfg.speedup_duration !== undefined ? parseFloat(this.options.cfg.speedup_duration) : this.duration * 0.6;
                this.easing = this.options.cfg.easing ? this.options.cfg.easing : 'ease-out';
                this.speedupEasing = this.options.cfg.speedup_easing ? this.options.cfg.speedup_easing : 'linear';
                this.delay = this.options.cfg.delay !== undefined ? parseFloat(this.options.cfg.delay) : 0;
                this.noEmpty = this.options.cfg.no_empty === 'yes';
                if (this.delay > 0 && this.delay < 0.05) {
                    // 限制最小delay
                    this.delay = 0.05;
                }
                this.delayStyle = this.options.cfg.delay_style === '1' ? 1 : 0;
                // grid对应的列表数据
                this.data = this.data || [];
                // 内容的渲染器
                this.itemRender = this.itemRender || null;
                // 是否正在滚动中
                this.scrolling = false;
                // 居中原点数，如果是1，则每次都居中对齐，如果是2，则两排对齐。
                this.originSize = this.options.cfg.origin_size ? parseInt(this.options.cfg.origin_size) : 1;
                this.origin = 0;
                // 当前widget对应的数据
                this.dataIndex = 0;
                this['_init_more_' + this.dir]();
            };

            Grid.prototype._init_more_v = function _init_more_v() {
                this.row = parseInt(this.options.cfg.row) + 2;
                this.col = parseInt(this.options.cfg.col);
                // 如果是设置居中原点数，那么行数必须等于排数，强制相等
                if (this.originSize > 1) {
                    this.row = this.originSize + 2;
                    // 如果是居中对齐，则行数必须是奇数才可，强制设置为奇数
                } else if (this.row % 2 === 0) {
                    this.row++;
                }
                this.upRow = 0;
                this.downRow = this.row - 1;
            };

            Grid.prototype._init_more_h = function _init_more_h() {
                this.row = parseInt(this.options.cfg.row);
                this.col = parseInt(this.options.cfg.col) + 2;
                // 如果是设置居中原点数，那么行数必须等于排数，强制相等
                if (this.originSize > 1) {
                    this.col = this.originSize + 2;
                    // 如果是居中对齐，则列数必须是奇数才可，强制设置为奇数
                } else if (this.col % 2 === 0) {
                    this.col++;
                }
                this.lefCol = 0;
                this.rightCol = this.col - 1;
            };

            // 根据第一个子元素来写grid的子组件html

            Grid.prototype._writeGridInnerHTML = function _writeGridInnerHTML() {
                var templateDOM = this.con.children[0];
                templateDOM.id = '';
                this.templateHTML = templateDOM.outerHTML;
                this.con.innerHTML = '';
                this['_writeGridInnerHTML_' + this.dir]();
            };

            Grid.prototype._writeGridInnerHTML_v = function _writeGridInnerHTML_v() {
                var rowHTML = '';
                for (var i = 0; i < this.col; i++) {
                    rowHTML += this.templateHTML;
                }
                rowHTML += '<div style="clear:both;"></div>';
                for (var i = 0; i < this.row; i++) {
                    var rowDom = document.createElement('div');
                    rowDom.innerHTML = rowHTML;
                    rowDom.style.position = 'relative';
                    // 先设置隐藏，等setData后再显示
                    // rowDom.style.opacity = 0;
                    this.con.appendChild(rowDom);
                }
            };

            Grid.prototype._writeGridInnerHTML_h = function _writeGridInnerHTML_h() {
                var colHTML = '';
                for (var i = 0; i < this.row; i++) {
                    colHTML += this.templateHTML + '<div style="clear:both;"></div>';
                }
                var listDom = document.createElement('div');
                listDom.style.width = '99999px';
                listDom.style.height = '100%';
                for (var i = 0; i < this.col; i++) {
                    var colDom = document.createElement('div');
                    colDom.innerHTML = colHTML;
                    colDom.style.position = 'relative';
                    colDom.style.float = 'left';
                    // 先设置隐藏，等setData后再显示
                    // colDom.style.opacity = 0;
                    listDom.appendChild(colDom);
                }
                listDom.appendChild(this.parseDom('<div style="clear:both;"></div>')[0]);
                this.con.appendChild(listDom);
            };

            // 渲染并检查子组件

            Grid.prototype._checkWidgets_v = function _checkWidgets_v() {
                // chidWidgets的二维数组
                this.widgetArr = [];
                var j = 0;
                for (var i = 0, l = this.childWidgets.length; i < l; i += this.col) {
                    var rowArr = this.childWidgets.slice(i, i + this.col);
                    rowArr = rowArr.map(function (v, k) {
                        v.row = j;
                        v.col = k;
                        return v;
                    });
                    this.widgetArr.push(rowArr);
                    j++;
                }
                var conRect = this.getWidgetRect();
                // 容器的高度
                this.conHeight = conRect.height;
                // grid子组件行高，即上下两个组件中心点之间的纵向距离
                this.rowHeight = this.childWidgets[0].con.parentNode.getBoundingClientRect().height;
                // 选中的组件的排列位置数组，如果是1，那么都是以中心居中排列，如果是2，则两行排列
                this.originArr = [];
                if (this.originSize === 1) {
                    this.originArr.push(this.conHeight / 2);
                } else {
                    for (var i = 0, halfHeight = this.rowHeight / 2; i < this.originSize; i++) {
                        this.originArr.push(halfHeight + i * this.rowHeight);
                    }
                }
                // 当前widget
                this.curWid = this.childWidgets[0];
                // 检查子组件
                for (var i = 0; i < this.childWidgets.length; i++) {
                    var widget = this.childWidgets[i];
                    var styles = getComputedStyle(widget.getDOMNode());
                    // 初始时该widget的中心点距顶部距离
                    widget.oriOffsetCY = widget.getWidgetRect().centerY - conRect.top;
                    widget.oriCenteY = widget.oriOffsetCY;
                    // 纪录当前offset
                    widget.offset = 0;
                    widget.animationArr = [];
                    widget.isEmpty = true;
                    // 相对于当前中的子组件，组件的行数，负代表在上方，正代表在下方
                    widget.offsetRow = widget.row;
                    widget.whichData = i;
                }
            };

            // 渲染并检查子组件

            Grid.prototype._checkWidgets_h = function _checkWidgets_h() {
                // chidWidgets的二维数组
                this.widgetArr = [];
                var j = 0;
                for (var i = 0, l = this.childWidgets.length; i < l; i += this.row) {
                    var rowArr = this.childWidgets.slice(i, i + this.row);
                    rowArr = rowArr.map(function (v, k) {
                        v.col = j;
                        v.row = k;
                        return v;
                    });
                    this.widgetArr.push(rowArr);
                    j++;
                }
                var conRect = this.getWidgetRect();
                // 容器的宽度
                this.conWidth = conRect.width;
                // grid子组件列宽，即左右两个组件中心点之间的横向距离
                this.colWidth = this.childWidgets[0].con.parentNode.getBoundingClientRect().width;
                // 选中的组件的排列位置数组，如果是1，那么都是以中心居中排列，如果是2，则两行排列
                this.originArr = [];
                if (this.originSize === 1) {
                    this.originArr.push(this.conWidth / 2);
                } else {
                    for (var i = 0, halfWidth = this.colWidth / 2; i < this.originSize; i++) {
                        this.originArr.push(halfWidth + i * this.colWidth);
                    }
                }
                // 当前widget
                this.curWid = this.childWidgets[0];
                // 检查子组件
                for (var i = 0; i < this.childWidgets.length; i++) {
                    var widget = this.childWidgets[i];
                    var styles = getComputedStyle(widget.getDOMNode());
                    // 初始时该widget的中心点距左侧距离
                    widget.oriOffsetCX = widget.getWidgetRect().centerX - conRect.left;
                    widget.oriCenteX = widget.oriOffsetCX;
                    // 纪录当前offset
                    widget.offset = 0;
                    widget.animationArr = [];
                    widget.isEmpty = true;
                    // 相对于当前中的子组件，组件的列数，负代表在左侧，正代表在右侧
                    widget.offsetCol = widget.col;
                    widget.whichData = i;
                }
            };

            Grid.prototype.keydownDefault = function keydownDefault(e) {
                if (this.stopSwitch) {
                    e.preventDefault();
                    return;
                }
                if (e.isDefaultPrevented()) {
                    return;
                }
                this['_keydownDefault_' + this.dir](e);
            };

            Grid.prototype._keydownDefault_v = function _keydownDefault_v(e) {
                var nexIndex = this._getNextDataIndex_v(e.keyCode);
                if (nexIndex !== -1) {
                    e.preventDefault();
                    var nexFocWid = this.childWidgets[Math.floor(nexIndex / this.col) % this.row * this.col + nexIndex % this.col];
                    nexFocWid.focus();
                }
            };

            Grid.prototype._keydownDefault_h = function _keydownDefault_h(e) {
                var nexIndex = this._getNextDataIndex_h(e.keyCode);
                if (nexIndex !== -1) {
                    e.preventDefault();
                    var nexFocWid = this.childWidgets[Math.floor(nexIndex / this.row) % this.col * this.row + nexIndex % this.row];
                    nexFocWid.focus();
                }
            };

            Grid.prototype._getNextDataIndex_v = function _getNextDataIndex_v(keyCode) {
                var nexIndex = this.dataIndex;
                // 向左
                if (keyCode === _event2['default'].VK_LEFT) {
                    if (nexIndex % this.col !== 0) {
                        return --nexIndex;
                    }
                    return -1;
                }
                if (keyCode === _event2['default'].VK_RIGHT) {
                    if (nexIndex % this.col !== this.col - 1 && nexIndex + 1 < this.data.length) {
                        return ++nexIndex;
                    }
                    return -1;
                }
                if (keyCode === _event2['default'].VK_UP) {
                    if (nexIndex >= this.col) {
                        return nexIndex -= this.col;
                    }
                    return -1;
                }
                if (keyCode === _event2['default'].VK_DOWN) {
                    if (nexIndex + this.col < this.data.length) {
                        return nexIndex += this.col;
                    }
                    if (nexIndex + this.col >= this.data.length && Math.floor(nexIndex / this.col) < Math.floor((this.data.length - 1) / this.col)) {
                        return this.data.length - 1;
                    }
                    this.fire(new _event2['default']('reachend', this));
                    return -1;
                }
                return -1;
            };

            Grid.prototype._getNextDataIndex_h = function _getNextDataIndex_h(keyCode) {
                var nexIndex = this.dataIndex;
                // 向左
                if (keyCode === _event2['default'].VK_LEFT) {
                    if (nexIndex >= this.row) {
                        return nexIndex -= this.row;
                    }
                    return -1;
                }
                if (keyCode === _event2['default'].VK_RIGHT) {
                    if (nexIndex + this.row < this.data.length) {
                        return nexIndex += this.row;
                    }
                    if (nexIndex + this.row >= this.data.length && Math.floor(nexIndex / this.row) < Math.floor((this.data.length - 1) / this.row)) {
                        return this.data.length - 1;
                    }
                    this.fire(new _event2['default']('reachend', this));
                    return -1;
                }
                if (keyCode === _event2['default'].VK_UP) {
                    if (nexIndex % this.row !== 0) {
                        return --nexIndex;
                    }
                    return -1;
                }
                if (keyCode === _event2['default'].VK_DOWN) {
                    if (nexIndex % this.row !== this.row - 1 && nexIndex + 1 < this.data.length) {
                        return ++nexIndex;
                    }
                    return -1;
                }
                return -1;
            };

            Grid.prototype.focusDefault = function focusDefault(e) {
                _Widget.prototype.focusDefault.call(this, e);
                // 如果是setData调用，那么只需要更改focus状态，无需移动
                if (this.isSetData) {
                    return;
                }
                // focus时监测一次容器宽高，如果都是0，说明focus前是display:none，需要重新_checkWidgets
                if (!this.conHeight && !this.conWidth) {
                    this['_checkWidgets_' + this.dir]();
                }
                this['_focusDefault_' + this.dir](e);
            };

            Grid.prototype._focusDefault_v = function _focusDefault_v(e) {
                var nexWid = this.getFocusedChildWidget();
                this.dataIndex = nexWid.whichData;
                this.curWid = nexWid;
                // 如果左右切换，则不滚动
                if (nexWid.offsetRow === 0) {
                    return;
                }
                this._computeGridStatus_v(nexWid);
                this._computeAllWidgetStatus_v(nexWid);
                this._triggerWidgetsAnimation_v(nexWid);
            };

            Grid.prototype._focusDefault_h = function _focusDefault_h(e) {
                var nexWid = this.getFocusedChildWidget();
                this.dataIndex = nexWid.whichData;
                this.curWid = nexWid;
                // 如果上下切换，则不滚动
                if (nexWid.offsetCol === 0) {
                    return;
                }
                this._computeGridStatus_h(nexWid);
                this._computeAllWidgetStatus_h(nexWid);
                this._triggerWidgetsAnimation_h(nexWid);
            };

            // 根据焦点widget计算纵向Grid滚动的一些状态：
            // 1. 是向上还是向下滚动；2. 滚动结束后上下各有多少行；3. 焦点组件的位置

            Grid.prototype._computeGridStatus_v = function _computeGridStatus_v(curWid) {
                // 如果是setData调用，那么一些属性不需要再次计算
                if (!this.isSetData) {
                    // 确定是向上还是向下滚动
                    this.isUp = curWid.offsetRow < 0;
                    // 确定下次focus子组件的origin
                    if (this.isUp && this.origin > 0) {
                        this.origin--;
                    } else if (!this.isUp && this.origin < this.originArr.length - 1) {
                        this.origin++;
                    }
                }

                // 选中的组件的中心点应在的位置
                this.focsedCY = this.originArr[this.origin];
                // 确定滚动结束后当前选中的行上下各应该有多少行
                // 没有设置originSize的情况
                if (this.originSize === 1) {
                    this.upRow = Math.floor(this.row / 2);
                    this.downRow = Math.floor(this.row / 2);
                    var curDataRow = Math.floor(this.dataIndex / this.col);
                    var lastDataRow = Math.floor((this.data.length - 1) / this.col);
                    var tempFocsedCY = this.focsedCY;
                    // 到达底部的情况
                    var downOffset = (lastDataRow - curDataRow) * this.rowHeight + this.rowHeight / 2;
                    if (downOffset < tempFocsedCY) {
                        this.focsedCY = this.conHeight - downOffset;
                        this.downRow = lastDataRow - curDataRow;
                        this.upRow = this.row - 1 - this.downRow;
                    }
                    // 到达顶部的情况，如果同时到达顶部和底部，则按顶部算
                    var upOffset = curDataRow * this.rowHeight + this.rowHeight / 2;
                    var listHeight = (lastDataRow + 1) * this.rowHeight;
                    if (upOffset < tempFocsedCY || listHeight < this.conHeight) {
                        this.focsedCY = upOffset;
                        this.upRow = curDataRow;
                        this.downRow = this.row - 1 - this.upRow;
                        return;
                    }
                    // 设置originSize的情况
                } else {
                    this.upRow = this.origin + 1;
                    this.downRow = this.originSize - this.origin;
                    // 到达顶部的情况
                    if (Math.floor(this.dataIndex / this.col) === 0) {
                        this.upRow = 0;
                        this.downRow = this.row - 1;
                        return;
                    }
                    // 到达底部的情况
                    if (Math.floor(this.dataIndex / this.col) === Math.floor((this.data.length - 1) / this.col)) {
                        this.upRow = this.row - 1;
                        this.downRow = 0;
                    }
                }
            };

            // 根据焦点widget计算横向Grid滚动的一些状态：
            // 1. 是向左还是向右滚动；2. 滚动结束后左右各有多少列；3. 焦点组件的位置

            Grid.prototype._computeGridStatus_h = function _computeGridStatus_h(curWid) {
                // 如果是setData调用，那么一些属性不需要再次计算
                if (!this.isSetData) {
                    // 确定是向上还是向下滚动
                    this.isLeft = curWid.offsetCol < 0;
                    // 确定下次focus子组件的origin
                    if (this.isLeft && this.origin > 0) {
                        this.origin--;
                    } else if (!this.isLeft && this.origin < this.originArr.length - 1) {
                        this.origin++;
                    }
                }

                // 选中的组件的中心点应在的位置
                this.focsedCX = this.originArr[this.origin];
                // 确定滚动结束后当前选中的行左右各应该有多少列
                // 没有设置originSize的情况
                if (this.originSize === 1) {
                    this.leftCol = Math.floor(this.col / 2);
                    this.rightCol = Math.floor(this.col / 2);
                    var curDataCol = Math.floor(this.dataIndex / this.row);
                    var lastDataCol = Math.floor((this.data.length - 1) / this.row);
                    var tempFocsedCX = this.focsedCX;
                    // 到达右部的情况
                    var rightOffset = (lastDataCol - curDataCol) * this.colWidth + this.colWidth / 2;
                    if (rightOffset < tempFocsedCX) {
                        this.focsedCX = this.conWidth - rightOffset;
                        this.rightCol = lastDataCol - curDataCol;
                        this.leftCol = this.col - 1 - this.rightCol;
                    }
                    // 到达左部的情况，如果同时到达左部和右部，则按左部算
                    var leftOffset = curDataCol * this.colWidth + this.colWidth / 2;
                    var listWidth = (lastDataCol + 1) * this.colWidth;
                    if (leftOffset < tempFocsedCX || listWidth < this.conWidth) {
                        this.focsedCX = leftOffset;
                        this.leftCol = curDataCol;
                        this.rightCol = this.col - 1 - this.leftCol;
                        return;
                    }
                    // 设置originSize的情况
                } else {
                    this.leftCol = this.origin + 1;
                    this.rightCol = this.originSize - this.origin;
                    // 到达左部的情况
                    if (this.dataIndex < this.row) {
                        this.leftCol = 0;
                        this.rightCol = this.col - 1;
                        return;
                    }
                    // 到达右部的情况
                    if (Math.floor(this.dataIndex / this.row) === Math.floor((this.data.length - 1) / this.row)) {
                        this.leftCol = this.col - 1;
                        this.rightCol = 0;
                    }
                }
            };

            // 根据Grid的状态计算每个widget自身的状态
            // curWid：当前焦点子组件
            // 纵向Grid使用

            Grid.prototype._computeAllWidgetStatus_v = function _computeAllWidgetStatus_v(curWid) {
                var curWidRow = curWid.row;
                var curDataRow = Math.floor(this.dataIndex / this.col);
                this._computeRowWidgetStatus_v(curWidRow, curDataRow, 0);
                for (var i = -1; i >= -this.upRow; i--) {
                    this._computeRowWidgetStatus_v(curWidRow, curDataRow, i);
                }
                for (var i = 1; i <= this.downRow; i++) {
                    this._computeRowWidgetStatus_v(curWidRow, curDataRow, i);
                }
            };

            // 横向Grid使用

            Grid.prototype._computeAllWidgetStatus_h = function _computeAllWidgetStatus_h(curWid) {
                var curWidCol = curWid.col;
                var curDataCol = Math.floor(this.dataIndex / this.row);
                this._computeColWidgetStatus_h(curWidCol, curDataCol, 0);
                for (var i = -1; i >= -this.leftCol; i--) {
                    this._computeColWidgetStatus_h(curWidCol, curDataCol, i);
                }
                for (var i = 1; i <= this.rightCol; i++) {
                    this._computeColWidgetStatus_h(curWidCol, curDataCol, i);
                }
            };

            // 设置某行widget的状态，纵向Grid使用
            // 如：动画、位置、whichData等

            Grid.prototype._computeRowWidgetStatus_v = function _computeRowWidgetStatus_v(curWidRow, curDataRow, offsetRow) {
                var widRow = (curWidRow + offsetRow + this.row) % this.row;
                var dataRow = curDataRow + offsetRow;
                for (var i = 0; i < this.col; i++) {
                    var widget = this.childWidgets[this.col * widRow + i];
                    var whichData = this.col * dataRow + i;
                    var opacityAfterAnimation = 1;
                    if (whichData >= this.data.length || whichData < 0) {
                        opacityAfterAnimation = 0;
                    }
                    widget.whichData = whichData;
                    widget.whichDataRow = dataRow;
                    if (this.isSetData) {
                        widget.offset = this.focsedCY + offsetRow * this.rowHeight - widget.oriCenteY;
                        widget.con.parentNode.style.top = widget.offset + 'px';
                        widget.con.style.opacity = opacityAfterAnimation;
                        widget.offsetRow = offsetRow;
                    } else {
                        var nexOffset = this.focsedCY + offsetRow * this.rowHeight - widget.oriCenteY;
                        widget.futureOffset = nexOffset;
                        widget.animationArr.push({
                            offset: nexOffset,
                            jump: widget.offsetRow * offsetRow < 0,
                            opacity: opacityAfterAnimation
                        });
                        widget.offsetRow = offsetRow;
                    }
                }
            };

            // 设置某行widget的状态，横向Grid使用
            // 如：动画、位置、whichData等

            Grid.prototype._computeColWidgetStatus_h = function _computeColWidgetStatus_h(curWidCol, curDataCol, offsetCol) {
                var widCol = (curWidCol + offsetCol + this.col) % this.col;
                var dataCol = curDataCol + offsetCol;
                for (var i = 0; i < this.row; i++) {
                    var widget = this.childWidgets[this.row * widCol + i];
                    var whichData = dataCol * this.row + i;
                    var opacityAfterAnimation = 1;
                    if (whichData >= this.data.length || whichData < 0) {
                        opacityAfterAnimation = 0;
                    }
                    widget.whichData = whichData;
                    widget.whichDataCol = dataCol;
                    if (this.isSetData) {
                        widget.offset = this.focsedCX + offsetCol * this.colWidth - widget.oriCenteX;
                        widget.con.parentNode.style.left = widget.offset + 'px';
                        widget.con.style.opacity = opacityAfterAnimation;
                        widget.offsetCol = offsetCol;
                    } else {
                        var nexOffset = this.focsedCX + offsetCol * this.colWidth - widget.oriCenteX;
                        widget.futureOffset = nexOffset;
                        widget.animationArr.push({
                            offset: nexOffset,
                            jump: widget.offsetCol * offsetCol < 0,
                            opacity: opacityAfterAnimation
                        });
                        widget.offsetCol = offsetCol;
                    }
                }
            };

            // 如果是还未开始动画，计算动画延迟且触发动画

            Grid.prototype._triggerWidgetsAnimation_v = function _triggerWidgetsAnimation_v() {
                for (var i = 0; i < this.row; i++) {
                    var widget = this.widgetArr[i][0];
                    if (widget.animationArr.length !== 1) {
                        return;
                    }
                    this['_startScroll_' + this.dir](widget);
                }
            };

            // 如果是还未开始动画，计算动画延迟且触发动画

            Grid.prototype._triggerWidgetsAnimation_h = function _triggerWidgetsAnimation_h() {
                for (var i = 0; i < this.col; i++) {
                    var widget = this.widgetArr[i][0];
                    if (widget.animationArr.length !== 1) {
                        return;
                    }
                    this['_startScroll_' + this.dir](widget);
                }
            };

            Grid.prototype._startScroll_v = function _startScroll_v(widget, speedup) {
                var _this = this;

                var rowWidgets = this.widgetArr[widget.row];
                for (var i = 0, l = rowWidgets.length; i < l; i++) {
                    var tempWidget = rowWidgets[i];
                    var _animation = tempWidget.animationArr[0];
                    if (_animation.jump) {
                        if (this.noEmpty) {
                            var item = this.data[tempWidget.whichData];
                            if (item) {
                                this.itemRender(tempWidget.getDOMNode(), item);
                                tempWidget.isEmpty = false;
                            }
                        } else if (!tempWidget.isEmpty) {
                            this.itemRender(tempWidget.getDOMNode());
                            tempWidget.isEmpty = true;
                        }
                    }
                }
                var endCb = function endCb() {
                    for (var i = 0, l = rowWidgets.length; i < l; i++) {
                        var tempWidget = rowWidgets[i];
                        var preAnimation = tempWidget.animationArr.shift();
                        tempWidget.offset = preAnimation.offset;
                        tempWidget.con.style.opacity = preAnimation.opacity;
                    }
                    if (widget.animationArr.length > 0) {
                        _this._startScroll_v(widget, true);
                    } else {
                        if (_this.scrolling && widget.row === 0) {
                            _this.scrolling = false;
                            _this.fire(new _event2['default']('scrollend', _this));
                        }
                    }
                };
                this.stopSwitch = widget.animationArr.length >= 2;
                var animation = widget.animationArr[0];
                if (animation.offset !== widget.offset && !animation.jump) {
                    if (!this.scrolling) {
                        this.scrolling = true;
                        this.fire(new _event2['default']('scrollstart', this, { distance: animation.offset - widget.offset }));
                    }
                }
                (0, _animate2['default'])({
                    dom: widget.con.parentNode,
                    style: this.style,
                    start: animation.jump ? animation.offset : widget.offset,
                    end: animation.offset,
                    duration: speedup ? this.speedupDuration : this.duration,
                    easing: speedup ? this.speedupEasing : this.easing,
                    cb: endCb
                });
            };

            Grid.prototype._startScroll_h = function _startScroll_h(widget, speedup) {
                var _this2 = this;

                var colWidgets = this.widgetArr[widget.col];
                for (var i = 0, l = colWidgets.length; i < l; i++) {
                    var tempWidget = colWidgets[i];
                    var _animation2 = tempWidget.animationArr[0];
                    if (_animation2.jump) {
                        if (this.noEmpty) {
                            var item = this.data[tempWidget.whichData];
                            if (item) {
                                this.itemRender(tempWidget.getDOMNode(), item);
                                tempWidget.isEmpty = false;
                            }
                        } else if (!tempWidget.isEmpty) {
                            this.itemRender(tempWidget.getDOMNode());
                            tempWidget.isEmpty = true;
                        }
                    }
                }
                var endCb = function endCb() {
                    for (var i = 0, l = colWidgets.length; i < l; i++) {
                        var tempWidget = colWidgets[i];
                        var preAnimation = tempWidget.animationArr.shift();
                        tempWidget.offset = preAnimation.offset;
                        tempWidget.con.style.opacity = preAnimation.opacity;
                    }
                    if (widget.animationArr.length > 0) {
                        _this2._startScroll_h(widget, true);
                    } else {
                        if (_this2.scrolling && widget.col === 0) {
                            _this2.scrolling = false;
                            _this2.fire(new _event2['default']('scrollend', _this2));
                        }
                    }
                };
                this.stopSwitch = widget.animationArr.length >= 2;
                var animation = widget.animationArr[0];
                if (animation.offset !== widget.offset && !animation.jump) {
                    if (!this.scrolling) {
                        this.scrolling = true;
                        this.fire(new _event2['default']('scrollstart', this, { distance: animation.offset - widget.offset }));
                    }
                }
                (0, _animate2['default'])({
                    dom: widget.con.parentNode,
                    style: this.style,
                    start: animation.jump ? animation.offset : widget.offset,
                    end: animation.offset,
                    duration: speedup ? this.speedupDuration : this.duration,
                    easing: speedup ? this.speedupEasing : this.easing,
                    cb: endCb
                });
            };

            Grid.prototype.scrollendDefault = function scrollendDefault(e) {
                if (e.isDefaultPrevented()) {
                    return;
                }
                if (this.scrolling) {
                    return;
                }
                this['_toggleDelay_' + this.dir](0);
            };

            Grid.prototype.scrollstartDefault = function scrollstartDefault(e) {
                if (e.isDefaultPrevented()) {
                    return;
                }
                this['_toggleDelay_' + this.dir](e.distance);
                this.loadContentTimeout && clearTimeout(this.loadContentTimeout);
                // Blitz内核提供的禁止图片加载的方法，优化动画
                window.stopImgLoading && window.stopImgLoading();
            };

            // 开始或者结束delay状态
            // @param {Number} moveDistance 此次焦点滚动的距离，根据改距离确定delay幅度

            Grid.prototype._toggleDelay_v = function _toggleDelay_v() {
                var _this3 = this;

                var moveDistance = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];

                var focusedWidget = this.getFocusedChildWidget() || this.getCachedChildWidget();
                if (!focusedWidget) {
                    return;
                }
                var focusCol = focusedWidget.col;
                for (var i = 0; i < this.col; i++) {
                    for (var j = 0; j < this.row; j++) {
                        var widget = this.widgetArr[j][i];
                        var delayOffset = -(moveDistance * this.delay * Math.abs(widget.col - focusCol * this.delayStyle));
                        var aniEndCb = null;
                        if (delayOffset === 0 && i === 0 && j === 0) {
                            aniEndCb = function () {
                                _this3.loadContent();
                            };
                        }
                        (0, _animate2['default'])({
                            dom: widget.con,
                            style: this.style,
                            start: widget.delayOffset || 0,
                            end: delayOffset,
                            duration: this.duration,
                            easing: 'ease-out',
                            cb: aniEndCb
                        });
                        widget.delayOffset = delayOffset;
                    }
                }
            };

            // 开始或者结束delay状态
            // @param {Number} moveDistance 此次焦点滚动的距离，根据改距离确定delay幅度

            Grid.prototype._toggleDelay_h = function _toggleDelay_h() {
                var _this4 = this;

                var moveDistance = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];

                var focusedWidget = this.getFocusedChildWidget() || this.getCachedChildWidget();
                if (!focusedWidget) {
                    return;
                }
                var focusRow = focusedWidget.row;
                for (var i = 0; i < this.row; i++) {
                    for (var j = 0; j < this.col; j++) {
                        var widget = this.widgetArr[j][i];
                        var delayOffset = -(moveDistance * this.delay * Math.abs(widget.row - focusRow * this.delayStyle));
                        var aniEndCb = null;
                        if (delayOffset === 0 && i === 0 && j === 0) {
                            aniEndCb = function () {
                                _this4.loadContent();
                            };
                        }
                        (0, _animate2['default'])({
                            dom: widget.con,
                            style: this.style,
                            start: widget.delayOffset || 0,
                            end: delayOffset,
                            duration: this.duration,
                            easing: 'ease-out',
                            cb: aniEndCb
                        });
                        widget.delayOffset = delayOffset;
                    }
                }
            };

            Grid.prototype.setItemRender = function setItemRender(fun) {
                this.itemRender = function (dom, item) {
                    if (!item) {
                        dom.setAttribute('can-focus', 'no');
                    } else {
                        dom.removeAttribute('can-focus');
                    }
                    fun(dom, item);
                    // Blitz提供的加载文字的方法，用于避免滚动过程中文字加载不全的问题
                    dom.createTextGraphics && dom.createTextGraphics();
                };
                return this;
            };

            Grid.prototype.addData = function addData(data) {
                if (!Array.isArray(data)) {
                    return;
                }
                var newData = this.data.concat(data);
                var dataIndex = this.focused ? this.getFocusedChildWidget().whichData : this.dataIndex;
                this.setData(newData, dataIndex, this.origin);
                return this;
            };

            Grid.prototype.setData = function setData(data, index, origin) {
                if (Array.isArray(data)) {
                    this.data = data.concat([]);
                }
                this.isSetData = true;
                this.allDataCol = Math.floor(this.data.length / this.row);
                this.allDataRow = Math.floor(this.data.length / this.col);
                if (index !== undefined && index < this.data.length) {
                    this.dataIndex = index;
                } else {
                    this.dataIndex = 0;
                }
                this.origin = this['_getSetDataOrigin_' + this.dir](this.data.length, this.dataIndex, origin);
                var nexWid = this['_getWidgetByDataIndex_' + this.dir](this.dataIndex);
                this['_computeGridStatus_' + this.dir](nexWid);
                this['_computeAllWidgetStatus_' + this.dir](nexWid);
                nexWid.dataIndex = this.dataIndex;
                if (this.focused) {
                    nexWid.focus(true, true);
                } else {
                    nexWid.cache();
                }
                this.curWid = nexWid;
                this.loadContent();
                this.isSetData = false;
                return this;
            };

            // 根据dataIndex获取当前对应的是哪个widget

            Grid.prototype._getWidgetByDataIndex_v = function _getWidgetByDataIndex_v(dataIndex) {
                return this.childWidgets[Math.floor(dataIndex / this.col) % this.row * this.col + dataIndex % this.col];
            };

            // 根据dataIndex获取当前对应的是哪个widget

            Grid.prototype._getWidgetByDataIndex_h = function _getWidgetByDataIndex_h(dataIndex) {
                return this.childWidgets[Math.floor(dataIndex / this.row) % this.col * this.row + dataIndex % this.row];
            };

            // 根据数据长度，当前setData的index及origin返回合适的origin

            Grid.prototype._getSetDataOrigin_v = function _getSetDataOrigin_v(dataLength, index, origin) {
                if (origin === undefined || origin > this.originSize) {
                    origin = 0;
                }
                var row = Math.floor(this.dataIndex / this.col);
                var lastRow = Math.floor((this.data.length - 1) / this.col);
                // 最后的几行item有最小的origin限制
                if (lastRow - row < this.originSize) {
                    var minOrigin = row + this.originSize - lastRow - 1;
                    if (minOrigin >= 0 && origin < minOrigin) {
                        origin = minOrigin;
                    }
                }
                // 最前的几个item的origin有最大的origin限制
                if (row < this.originSize) {
                    var maxOrigin = row;
                    if (origin > maxOrigin) {
                        origin = maxOrigin;
                    }
                }
                return origin;
            };

            // 根据数据长度，当前setData的index及origin返回合适的origin

            Grid.prototype._getSetDataOrigin_h = function _getSetDataOrigin_h(dataLength, index, origin) {
                if (origin === undefined || origin > this.originSize) {
                    origin = 0;
                }
                var col = Math.floor(this.dataIndex / this.row);
                var lastCol = Math.floor((this.data.length - 1) / this.row);
                // 最后的几列item有最小的origin限制
                if (lastCol - col < this.originSize) {
                    var minOrigin = col + this.originSize - lastCol - 1;
                    if (minOrigin >= 0 && origin < minOrigin) {
                        origin = minOrigin;
                    }
                }
                // 最前的几个item的origin有最大的origin限制
                if (col < this.originSize) {
                    var maxOrigin = col;
                    if (origin > maxOrigin) {
                        origin = maxOrigin;
                    }
                }
                return origin;
            };

            // 加载内容

            Grid.prototype.loadContent = function loadContent() {
                if (this.scrolling) {
                    return;
                }
                for (var i = 0, _length = this.childWidgets.length; i < _length; i++) {
                    var widget = this.childWidgets[i];
                    // 如果是setData调用，那么需要强制重新渲染item
                    if (widget.isEmpty || this.isSetData) {
                        var item = this.data[widget.whichData];
                        this.itemRender && this.itemRender(widget.getDOMNode(), item);
                        widget.isEmpty = false;
                    }
                }
                // Blitz内核提供的恢复图片加载的方法
                window.resumeImgLoading && window.resumeImgLoading();
                this.fire(new _event2['default']('contentloaded', this));
            };

            // 更改Grid的内容
            // 参数同数组的splice

            Grid.prototype.splice = function splice() {
                Array.prototype.splice.apply(this.data, arguments);
                this.isSetData = true;
                this.loadContent();
                this.isSetData = false;
            };

            Grid.prototype.getEvents = function getEvents() {
                return _Widget.prototype.getEvents.call(this).concat(['reachend', 'contentloaded']);
            };

            return Grid;
        })(_widget2['default']);

        exports['default'] = Grid;
        module.exports = exports['default'];

        /***/ },
    /* 9 */
    /***/ function(module, exports, __webpack_require__) {



        Object.defineProperty(exports, '__esModule', {
            value: true
        });

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

        function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _engine = __webpack_require__(1);

        var _engine2 = _interopRequireDefault(_engine);

        var _widget = __webpack_require__(3);

        var _widget2 = _interopRequireDefault(_widget);

        var _event = __webpack_require__(2);

        var _event2 = _interopRequireDefault(_event);

        var _animate = __webpack_require__(6);

        var _animate2 = _interopRequireDefault(_animate);

        // TODO:补充注释

        var Grille = (function (_Widget) {
            _inherits(Grille, _Widget);

            function Grille(container) {
                _classCallCheck(this, Grille);

                _Widget.call(this, container);
                this._init();
            }

            Grille.prototype._init = function _init() {
                var _this = this;

                // this.horizontal = this.options.cfg.dir === 'h';
                // 创建内部的list
                this.listDom = document.createElement('div');
                this.listDom.style.position = 'relative';
                this.listDom.style.width = '100%';
                this.con.innerHTML = '';
                this.con.appendChild(this.listDom);
                this.duration = this.options.cfg.duration !== undefined ? parseFloat(this.options.cfg.duration) : 0.3;
                this.delay = this.options.cfg.delay !== undefined ? parseFloat(this.options.cfg.delay) : 0.1;
                this.easing = this.options.cfg.easing ? this.options.cfg.easing : 'ease-out';
                this.bottomPadding = this.options.cfg.bottom_padding !== undefined ? parseFloat(this.options.cfg.bottom_padding) : 0;
                this.visibleRow = this.options.cfg.visible_row !== undefined ? parseInt(this.options.cfg.visible_row) : 5;
                this.listDom.style.transition = 'transform ' + this.duration + 's ' + this.easing;
                this.listDom.addEventListener('transitionend', function (e) {
                    if (e.target === _this.listDom) {
                        _this.fire(new _event2['default']('scrollend', _this));
                    }
                });
                this.getWidgetRect();
                this.align = this.rect.height / 2;
                this.offset = 0;
                this._reset();
            };

            Grille.prototype._reset = function _reset() {
                // 记录最后一个item是第几行第几列
                this.lastWidgetRow = 0;
                this.lastWidgetCol = 0;
                this.lastWidgetCenter = 0;
                this.listHeight = 0;
                // 用二维数组记录子widget，便于查找
                this.childrenArr = [];
                // 只记录子Widget
                this.childWidgets = [];
                // 记录所有类型的子代
                this.childItems = [];
                this.focusPos = {
                    row: 0,
                    col: 0
                };
            };

            Grille.prototype.setData = function setData(data, index) {
                var _this2 = this;

                this.isSetData = true;
                if (this.childItems.length == 0) {
                    this.listDom.innerHTML = '';
                    this._reset();
                    this.dataIndex = index !== undefined ? index : 0;
                    this.data = [].concat(data);
                    this._renderChildren();
                    return;
                }
                var transitionEndSetted = false;
                for (var i = 0; i < this.childItems.length; i++) {
                    var item = this.childItems[i];
                    if (item.con && item.visible) {
                        item.con.style.transform = 'scale3d(0.3,0.3,0.3)';
                        if (!transitionEndSetted) {
                            transitionEndSetted = true;
                            item.con.addEventListener('transitionend', function (e) {
                                _this2.listDom.innerHTML = '';
                                _this2._reset();
                                _this2.dataIndex = index !== undefined ? index : 0;
                                _this2.data = [].concat(data);
                                _this2._renderChildren();
                            });
                        }
                    }
                }
            };

            Grille.prototype.addData = function addData(data) {
                this.data = this.data.concat(data);
                this._renderChildren();
            };

            Grille.prototype.setItemRender = function setItemRender(itemRender) {
                this.itemRender = itemRender;
            };

            Grille.prototype._renderChildren = function _renderChildren() {
                var _this3 = this;

                // renderChildren时需要同时有data且有itemRender
                if (!this.data || !this.itemRender) {
                    return;
                }
                this.isSetData && (this.listDom.style.visibility = 'hidden');

                var _loop = function (i) {
                    var tempData = _this3.data[i];
                    var dom = _this3.itemRender(tempData);
                    // 如果render返回的是string，那么将string parse成dom对象
                    if (typeof dom === 'string') {
                        var children = _this3.parseDom(dom);
                        if (children.length > 1) {
                            console.error('[FocusEngine_Error]Grille组件的itemRender返回的字符串必须是可解析成一个dom对象。');
                            return 'continue';
                        }
                        dom = children[0];
                    }
                    var lazyDom = dom.querySelector('.grille-lazyload');
                    lazyDom && dom.removeChild(lazyDom);
                    _this3.listDom.appendChild(dom);
                    if (!dom.getAttribute('fe-role')) {
                        _this3.childItems.push(dom);
                        return 'continue';
                    }
                    var widget = _engine2['default'].createWidget(dom);
                    _this3.addChildWidget(widget);
                    _this3.childItems.push(widget);
                    widget.data = tempData;
                    widget.index = i;
                    widget.lazyDom = lazyDom;
                    widget.getWidgetRectAsync(function (widgetRect) {
                        // 计算正常情况下，该widget获取焦点时整个列表的偏移量
                        // 初始情况下，组件中心点距离容器top的距离
                        widget.oriOffset = widgetRect.centerY - _this3.rect.top - _this3.offset;
                        if (_this3.listHeight < widgetRect.bottom - _this3.rect.top - _this3.offset + _this3.bottomPadding) {
                            _this3.listHeight = widgetRect.bottom - _this3.rect.top - _this3.offset + _this3.bottomPadding;
                        }
                        if (!_this3.lastWidgetCenter) {
                            // 第一个widget时
                            widget.row = _this3.lastWidgetRow;
                            widget.col = _this3.lastWidgetCol;
                            _this3.lastWidgetCenter = widgetRect.centerY;
                            _this3.childrenArr[_this3.lastWidgetRow] = [widget];
                        } else if (widgetRect.centerY - _this3.offset === _this3.lastWidgetCenter) {
                            // 同一行的情况
                            widget.row = _this3.lastWidgetRow;
                            _this3.lastWidgetCol++;
                            widget.col = _this3.lastWidgetCol;
                            _this3.childrenArr[_this3.lastWidgetRow].push(widget);
                        } else if (widgetRect.centerY - _this3.offset > _this3.lastWidgetCenter) {
                            // 换行的情况
                            _this3.lastWidgetRow++;
                            widget.row = _this3.lastWidgetRow;
                            _this3.lastWidgetCol = 0;
                            widget.col = _this3.lastWidgetCol;
                            _this3.lastWidgetCenter = widgetRect.centerY - _this3.offset;
                            _this3.childrenArr[_this3.lastWidgetRow] = [widget];
                        }
                        if (widget.row <= _this3.visibleRow) {
                            widget.visible = true;
                            widget.con.style.transition = 'transform ' + _this3.duration * 0.8 + 's ' + _this3.easing;
                        }
                        if (i === _this3.data.length - 1) {
                            _this3.focused && _this3.childItems[_this3.dataIndex].focus();
                            if (_this3.isSetData) {
                                _this3.listDom.style.visibility = 'visible';
                                var setWidget = _this3.childItems[_this3.dataIndex];
                                _this3.loadContent();
                                _this3._doScroll(setWidget);
                                _this3.setCachedChildWidget(setWidget);
                            }
                        }
                    });
                };

                for (var i = this.childItems.length; i < this.data.length; i++) {
                    var _ret = _loop(i);

                    if (_ret === 'continue') continue;
                }
            };

            Grille.prototype.focusDefault = function focusDefault(e) {
                _Widget.prototype.focusDefault.call(this, e);
                if (e.target === this) {
                    return;
                }
                if (this.isSetData) {
                    return;
                }
                this.dataIndex = e.target.index;
                this._doScroll(e.target);
            };

            Grille.prototype._doScroll = function _doScroll(curWidget) {
                var _this4 = this;

                this.focusPos.row = curWidget.row;
                this.focusPos.col = curWidget.col;
                // 如果列表高度小于容器高度，不滚动
                if (this.listHeight < this.rect.height) {
                    return;
                }
                var offset = this.align - curWidget.oriOffset;
                // 到达顶部的情况
                if (offset > 0) {
                    offset = 0;
                }
                // 到达底部的情况
                if (this.listHeight - curWidget.oriOffset < this.rect.height - this.align) {
                    offset = this.rect.height - this.listHeight;
                }
                // 配置位置的情况
                if (curWidget.data.align !== undefined) {
                    offset = this.align - curWidget.oriOffset;
                }
                // 如果同一行，不滚动
                if (this.offset === offset && !this.isSetData) {
                    return;
                }
                if (this.isSetData) {
                    this.listDom.style.transition = '';
//	      this.listDom.style.transform = 'translateY(' + (offset + this.rect.height) + 'px)';
                    this.offset = offset + this.rect.height;
                    setTimeout(function () {
                        _this4.listDom.style.transition = 'transform ' + _this4.duration + 's ' + _this4.easing;
//	        _this4.listDom.style.transform = 'translateY(' + offset + 'px)';
                        var des = -_this4.rect.height / 3;
                        _this4.offset = offset;
                        !_this4.isScrolling && _this4.fire(new _event2['default']('scrollstart', _this4, { des: des }));
                        _this4.isSetData = false;
                    }, 300);
                } else {
                    this.listDom.style.transition = 'transform ' + this.duration + 's ' + this.easing;
//	      this.listDom.style.transform = 'translateY(' + offset + 'px)';
                    var des = offset - this.offset;
                    this.offset = offset;
                    !this.isScrolling && this.fire(new _event2['default']('scrollstart', this, { des: des }));
                }
            };

            Grille.prototype.keydownDefault = function keydownDefault(e) {
                var curRow = this.focusPos.row;
                var curCol = this.focusPos.col;
                if (e.keyCode === _event2['default'].VK_UP && curRow > 0) {
                    curRow--;
                    if (curCol >= this.childrenArr[curRow].length) {
                        curCol = this.childrenArr[curRow].length - 1;
                    }
                    e.preventDefault();
                }
                if (e.keyCode === _event2['default'].VK_DOWN && curRow == this.lastWidgetRow - 1) {
                    this.fire(new _event2['default']('reachend', this));
                }
                if (e.keyCode === _event2['default'].VK_DOWN && curRow < this.lastWidgetRow) {
                    curRow++;
                    if (curCol >= this.childrenArr[curRow].length) {
                        curCol = this.childrenArr[curRow].length - 1;
                    }
                    e.preventDefault();
                }
                if (e.keyCode === _event2['default'].VK_LEFT && curCol > 0) {
                    curCol--;
                    e.preventDefault();
                }
                if (e.keyCode === _event2['default'].VK_RIGHT && curCol < this.childrenArr[curRow].length - 1) {
                    curCol++;
                    e.preventDefault();
                }
                if (curRow === this.focusPos.row && curCol === this.focusPos.col) {
                    return;
                } else {
                    this.focusPos.row = curRow;
                    this.focusPos.col = curCol;
                    var tempWidget = this.childrenArr[curRow][curCol];
                    tempWidget.focus();
                }
            };

            Grille.prototype.scrollstartDefault = function scrollstartDefault(e) {
                this.isScrolling = true;
                // Blitz内核提供的禁止图片加载的方法，优化动画
                window.stopImgLoading && window.stopImgLoading();
                clearTimeout(this.loadContentTimeout);
                var curWidget = this.childItems[this.dataIndex];
                for (var i = 0; i < this.childWidgets.length; i++) {
                    var widget = this.childWidgets[i];
                    var delay = -Math.abs(widget.col - curWidget.col) * e.des * this.delay;
//	      widget.con.style.transform = 'translateY(' + delay + 'px)';
                }
            };

            Grille.prototype.scrollendDefault = function scrollendDefault(e) {
                var _this5 = this;

                this.isScrolling = false;
                var curWidget = this.childItems[this.dataIndex];
                for (var i = 0; i < this.childWidgets.length; i++) {
                    var widget = this.childWidgets[i];
                    var loadRowMax = Math.floor(this.visibleRow / 2);
                    if (Math.abs(widget.row - curWidget.row) <= loadRowMax) {
                        widget.con.style.transition = 'transform ' + this.duration * 0.8 + 's ' + this.easing;
                        widget.visible = true;
                    } else if (widget.visible) {
                        widget.con.style.transition = '';
                        widget.visible = false;
                    }
                    widget.con.style.transform = '';
                }
                this.loadContentTimeout = setTimeout(function () {
                    _this5.loadContent();
                }, 500);
            };

            Grille.prototype.loadContent = function loadContent() {
                for (var i = 0; i < this.childWidgets.length; i++) {
                    var widget = this.childWidgets[i];
                    if (widget.lazyDom && widget.visible && !widget.lazyLoaded) {
                        widget.con.appendChild(widget.lazyDom);
                        widget.lazyLoaded = true;
                    } else if (widget.lazyDom && !widget.visible && widget.lazyLoaded) {
                        widget.con.removeChild(widget.lazyDom);
                        widget.lazyLoaded = false;
                    }
                }
                // Blitz内核提供的恢复图片加载的方法
                window.resumeImgLoading && window.resumeImgLoading();
                this.fire(new _event2['default']('contentloaded', this));
            };

            Grille.prototype.getEvents = function getEvents() {
                return _Widget.prototype.getEvents.call(this).concat(['scrollstart', 'scrollend', 'contentloaded', 'reachend']);
            };

            return Grille;
        })(_widget2['default']);

        exports['default'] = Grille;
        module.exports = exports['default'];

        /***/ }
    /******/ ]);