Created
August 15, 2016 00:26
-
-
Save maolion/36ecf888cb491f381cd1992d1073a26a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var $ = require("jquery"); | |
| var Event = require('common/utils/event.js'); | |
| var Helpers = require('common/utils/helpers.js'); | |
| var DEFAULT_OPTIONS = { | |
| renderLeaf: _renderLeaf, | |
| renderNode: _renderNode, | |
| firstNode: null, | |
| firstLeaf: null, | |
| triggerEventType: "mouseenter" | |
| }; | |
| var ROOT_KEY = 'R'; | |
| var $NOOP_EL = $(null); | |
| function Cascader($el, options) { | |
| Event.call(this); | |
| this._options = $.extend({}, DEFAULT_OPTIONS, options); | |
| this._source = this._options.source || []; | |
| this._sourceIndexMap = {}; | |
| this._rendered = {}; | |
| this._opened = []; | |
| this._$el = $el; | |
| this._currentKey = null; | |
| if (!this._source.length) { | |
| _sourceMaybeFromDOM.call(this); | |
| } | |
| _generateSourceIndexMap.call(this, this._source, ROOT_KEY); | |
| _init.call(this); | |
| _initUIEvent.call(this); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // private methods | |
| function _init() { | |
| this._$el.empty(); | |
| _render.call(this, this._source, this._$el, ROOT_KEY); | |
| } | |
| function _generateSourceIndexMap(list, prefix) { | |
| for (var i = 0, l = list.length; i < l; i++) { | |
| var item = list[i]; | |
| var key = prefix + '_' + i; | |
| item.__cascader_key__ = key; | |
| this._sourceIndexMap[key] = item; | |
| if (item.children && item.children.length) { | |
| _generateSourceIndexMap.call(this, item.children, key); | |
| } | |
| } | |
| } | |
| function _initUIEvent() { | |
| var _this = this; | |
| var map = _this._sourceIndexMap; | |
| this._$el.on(this._options.triggerEventType, '.cascader-node', function() { | |
| var $node = $(this); | |
| var key = $node.attr('data-key'); | |
| if (!map[key]) { | |
| return; | |
| } | |
| var $child = _render.call(_this, map[key].children, $node, key); | |
| var item = [$node[0], $child[0]]; | |
| _this._opened[key] = item; | |
| $(item).addClass('active'); | |
| _clearOpened.call(_this, key); | |
| _this._currentKey = key; | |
| _this.fireEvent('opened', [key, item[0], item[1]]); | |
| }); | |
| } | |
| function _renderNode(item) { | |
| return item.content || item.name || item.label; | |
| } | |
| function _renderLeaf(item) { | |
| return item.content || item.name || item.label; | |
| } | |
| function _generate(list, key) { | |
| var output = '<div class="cascader-panel '+ (key == ROOT_KEY ? 'is-root' : 'is-child') +'" data-key="'+key+'">'; | |
| var nodes = []; | |
| var leafs = []; | |
| if (this._options.firstNode) { | |
| nodes.push( | |
| '<div class="cascader-node is-leaf" data-key="'+key+'">' + | |
| this._options.renderNode.call(this, this._options.firstNode, key) + | |
| '</div>' | |
| ); | |
| } | |
| if (this._options.firstLeaf) { | |
| leafs.push( | |
| '<div class="cascader-leaf" data-key="'+key+'">' + | |
| this._options.renderLeaf.call(this, this._options.firstLeaf, key) + | |
| '</div>' | |
| ); | |
| } | |
| for (var i = 0, l = list.length; i < l; i++) { | |
| var item = list[i]; | |
| var itemKey = item.__cascader_key__; | |
| if (item.children && item.children.length) { | |
| nodes.push( | |
| '<div class="cascader-node" data-key="'+itemKey+'">' + | |
| this._options.renderNode.call(this, item, itemKey) + | |
| '</div>' | |
| ); | |
| } else { | |
| leafs.push( | |
| '<div class="cascader-leaf" data-key="'+itemKey+'">' + | |
| this._options.renderLeaf.call(this, item, itemKey) + | |
| '</div>' | |
| ); | |
| } | |
| } | |
| output += | |
| (nodes.length ? '<div class="cascader-node-list">' + nodes.join('') + '</div>' : '')+ | |
| (leafs.length ? '<div class="cascader-leaf-list">' + leafs.join('') + '</div>' : '')+ | |
| '</div>'; | |
| return output; | |
| } | |
| function _render(list, $parent, key) { | |
| if (list && list.length && this._rendered[key]) { | |
| return this._rendered[key] || $NOOP_EL; | |
| } | |
| var $child = $(_generate.call(this, list, key)) | |
| this._$el.append($child); | |
| this.fireEvent('rendered', [key, $parent, $child]); | |
| return ( | |
| this._rendered[key] = $child | |
| ); | |
| } | |
| function _clearOpened(currentKey) { | |
| for (var key in this._opened) { | |
| if (!this._opened.hasOwnProperty(key)) { | |
| continue; | |
| } | |
| if (currentKey.indexOf(key) != 0) { | |
| var item = this._opened[key]; | |
| $(item).removeClass('active'); | |
| delete this._opened[key]; | |
| this.fireEvent('closed', [key, item[0], item[1]]); | |
| } | |
| } | |
| } | |
| function _sourceMaybeFromDOM() { | |
| var $items = this._$el.find('.cascader-source-item'); | |
| if (!$items.length) { | |
| return; | |
| } | |
| var rootChildrens = this._source; | |
| var map = { | |
| 0: { children: rootChildrens } | |
| }; | |
| for (var i = 0, l = $items.length; i < l; i++) { | |
| var $item = $items.eq(i); | |
| var id = $item.attr('data-id'); | |
| map[id] = { | |
| id: id, | |
| pid: $item.attr('data-pid'), | |
| content: $item.html(), | |
| children: [] | |
| }; | |
| } | |
| for (var id in map) { | |
| if (!map.hasOwnProperty(id)) { | |
| continue; | |
| } | |
| var item = map[id]; | |
| if (map.hasOwnProperty(item.pid)) { | |
| map[item.pid].children.push(item) | |
| } | |
| } | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // public methods | |
| var api = Cascader.prototype = Helpers.create(Event.prototype, Cascader); | |
| api.getItem = function(key) { | |
| return this._sourceIndexMap[key]; | |
| }; | |
| api.getSource = function(key) { | |
| return this._source; | |
| }; | |
| api.getOpened = function() { | |
| return this._opened; | |
| }; | |
| api.getCurrent = function() { | |
| return | |
| }; | |
| api.close = function() { | |
| _clearOpened.call(this, ''); | |
| this.fireEvent('close'); | |
| }; | |
| api.open = function() { | |
| this.fireEvent('open'); | |
| }; | |
| module.exports = Cascader; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment