123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- /**
- * IndexedList
- * 类似联系人应用中的联系人列表,可以按首字母分组
- * 右侧的字母定位工具条,可以快速定位列表位置
- * varstion 1.0.0
- * by Houfeng
- * Houfeng@DCloud.io
- **/
- (function($, window, document) {
- var classSelector = function(name) {
- return '.' + $.className(name);
- }
- var IndexedList = $.IndexedList = $.Class.extend({
- /**
- * 通过 element 和 options 构造 IndexedList 实例
- **/
- init: function(holder, options) {
- var self = this;
- self.options = options || {};
- self.box = holder;
- if (!self.box) {
- throw "实例 IndexedList 时需要指定 element";
- }
- self.createDom();
- self.findElements();
- self.caleLayout();
- self.bindEvent();
- },
- createDom: function() {
- var self = this;
- self.el = self.el || {};
- //styleForSearch 用于搜索,此方式能在数据较多时获取很好的性能
- self.el.styleForSearch = document.createElement('style');
- (document.head || document.body).appendChild(self.el.styleForSearch);
- },
- findElements: function() {
- var self = this;
- self.el = self.el || {};
- self.el.search = self.box.querySelector(classSelector('indexed-list-search'));
- self.el.searchInput = self.box.querySelector(classSelector('indexed-list-search-input'));
- self.el.searchClear = self.box.querySelector(classSelector('indexed-list-search') + ' ' + classSelector('icon-clear'));
- self.el.bar = self.box.querySelector(classSelector('indexed-list-bar'));
- self.el.barItems = [].slice.call(self.box.querySelectorAll(classSelector('indexed-list-bar') + ' a'));
- self.el.inner = self.box.querySelector(classSelector('indexed-list-inner'));
- self.el.items = [].slice.call(self.box.querySelectorAll(classSelector('indexed-list-item')));
- self.el.liArray = [].slice.call(self.box.querySelectorAll(classSelector('indexed-list-inner') + ' li'));
- self.el.alert = self.box.querySelector(classSelector('indexed-list-alert'));
- },
- caleLayout: function() {
- var self = this;
- var withoutSearchHeight = (self.box.offsetHeight - self.el.search.offsetHeight) + 'px';
- self.el.bar.style.height = withoutSearchHeight;
- self.el.inner.style.height = withoutSearchHeight;
- var barItemHeight = ((self.el.bar.offsetHeight - 40) / self.el.barItems.length) + 'px';
- self.el.barItems.forEach(function(item) {
- item.style.height = barItemHeight;
- item.style.lineHeight = barItemHeight;
- });
- },
- scrollTo: function(group) {
- var self = this;
- var groupElement = self.el.inner.querySelector('[data-group="' + group + '"]');
- if (!groupElement || (self.hiddenGroups && self.hiddenGroups.indexOf(groupElement) > -1)) {
- return;
- }
- self.el.inner.scrollTop = groupElement.offsetTop;
- },
- bindBarEvent: function() {
- var self = this;
- var pointElement = null;
- var findStart = function(event) {
- if (pointElement) {
- pointElement.classList.remove('active');
- pointElement = null;
- }
- self.el.bar.classList.add('active');
- var point = event.changedTouches ? event.changedTouches[0] : event;
- pointElement = document.elementFromPoint(point.pageX, point.pageY);
- if (pointElement) {
- var group = pointElement.innerText;
- if (group && group.length == 1) {
- pointElement.classList.add('active');
- self.el.alert.innerText = group;
- self.el.alert.classList.add('active');
- self.scrollTo(group);
- }
- }
- event.preventDefault();
- };
- var findEnd = function(event) {
- self.el.alert.classList.remove('active');
- self.el.bar.classList.remove('active');
- if (pointElement) {
- pointElement.classList.remove('active');
- pointElement = null;
- }
- };
- self.el.bar.addEventListener($.EVENT_MOVE, function(event) {
- findStart(event);
- }, false);
- self.el.bar.addEventListener($.EVENT_START, function(event) {
- findStart(event);
- }, false);
- document.body.addEventListener($.EVENT_END, function(event) {
- findEnd(event);
- }, false);
- document.body.addEventListener($.EVENT_CANCEL, function(event) {
- findEnd(event);
- }, false);
- },
- search: function(keyword) {
- var self = this;
- keyword = (keyword || '').toLowerCase();
- var selectorBuffer = [];
- var groupIndex = -1;
- var itemCount = 0;
- var liArray = self.el.liArray;
- var itemTotal = liArray.length;
- self.hiddenGroups = [];
- var checkGroup = function(currentIndex, last) {
- if (itemCount >= currentIndex - groupIndex - (last ? 0 : 1)) {
- selectorBuffer.push(classSelector('indexed-list-inner li') + ':nth-child(' + (groupIndex + 1) + ')');
- self.hiddenGroups.push(liArray[groupIndex]);
- };
- groupIndex = currentIndex;
- itemCount = 0;
- }
- liArray.forEach(function(item) {
- var currentIndex = liArray.indexOf(item);
- if (item.classList.contains($.className('indexed-list-group'))) {
- checkGroup(currentIndex, false);
- } else {
- var text = (item.innerText || '').toLowerCase();
- var value = (item.getAttribute('data-value') || '').toLowerCase();
- var tags = (item.getAttribute('data-tags') || '').toLowerCase();
- if (keyword && text.indexOf(keyword) < 0 &&
- value.indexOf(keyword) < 0 &&
- tags.indexOf(keyword) < 0) {
- selectorBuffer.push(classSelector('indexed-list-inner li') + ':nth-child(' + (currentIndex + 1) + ')');
- itemCount++;
- }
- if (currentIndex >= itemTotal - 1) {
- checkGroup(currentIndex, true);
- }
- }
- });
- if (selectorBuffer.length >= itemTotal) {
- self.el.inner.classList.add('empty');
- } else if (selectorBuffer.length > 0) {
- self.el.inner.classList.remove('empty');
- self.el.styleForSearch.innerText = selectorBuffer.join(', ') + "{display:none;}";
- } else {
- self.el.inner.classList.remove('empty');
- self.el.styleForSearch.innerText = "";
- }
- },
- bindSearchEvent: function() {
- var self = this;
- self.el.searchInput.addEventListener('input', function() {
- var keyword = this.value;
- self.search(keyword);
- }, false);
- $(self.el.search).on('tap', classSelector('icon-clear'), function() {
- self.search('');
- }, false);
- },
- bindEvent: function() {
- var self = this;
- self.bindBarEvent();
- self.bindSearchEvent();
- }
- });
- //mui(selector).indexedList 方式
- $.fn.indexedList = function(options) {
- //遍历选择的元素
- this.each(function(i, element) {
- if (element.indexedList) return;
- element.indexedList = new IndexedList(element, options);
- });
- return this[0] ? this[0].indexedList : null;
- };
- })(mui, window, document);
|