JS新增標籤效果
在豆瓣網上新增自己的標籤是一種常見的效果,今天也就做了一個簡單的demo。由於時間的問題 我不多原理,大家可以試著操作幾遍就能明白其中的原理了。
JSFiddle的效果如下:
依賴於HTML結構如下:
<div class="j-container"> <div class="mb-meta"> <div class="btn mb-add-button">Add</div> </div> <ul class="mb-list"></ul> </div>
所有的JS程式碼如下:
/** * JS文字標籤 * @time 2014-4-10 * @author tugenhua */ function AddTag(options) { this.config = { containerCls : '.j-container', // 最外層容器 buttonCls : '.mb-add-button', // add按鈕 btnContainer : '.mb-meta', // add按鈕最近的父容器 listItemCls : '.mb-list', // 新增標籤到當前的容器裡 isInput : true // add按鈕前是否需要input輸入框 }; this.cache = { arrs : [] } this.init(options); } AddTag.prototype = { constructor: AddTag, init: function(options){ this.config = $.extend(this.config,options || {}); var self = this, _config = self.config, _cache = self.cache; if(_config.isInput) { $(_config.btnContainer).each(function(){ $(this).prepend('<input placeholder="Enter tags here" class="mb-input">'); }); } self._bindEnv(); }, /* * 繫結事件 * @method _bindEnv * keycode 13->enter鍵 */ _bindEnv: function(){ var self = this, _config = self.config, _cache = self.cache; // input enter鍵 事件 if($('.mb-input').length > 0) { $('.mb-input').each(function(){ $(this).unbind('keyup').bind('keyup',function(e){ var keyCode = e.keyCode, curValue = $.trim($(this).val()), tparent = $(this).closest(_config.containerCls); if(keyCode == 13) { self._renderHTML(curValue,tparent); } }); }); } // 點選add按鈕 觸發事件 $(_config.buttonCls).each(function(){ $(this).unbind('click').bind('click',function(){ var container = $(this).closest(_config.containerCls); if($('.mb-input',container).length > 0) { var inputVal = $.trim($('.mb-input',container).val()); self._renderHTML(inputVal,container); }else { var $thisParent = $(this).closest(_config.btnContainer), $container = $(this).closest(_config.containerCls); // 否則的話 直接把按鈕變成input輸入框 $($thisParent).prepend('<input placeholder="Enter tags here" class="mb-input">'); !$(this).hasClass('hidden') && $(this).addClass('hidden'); $('.mb-input',$container).focus(); // 失去焦點時候 觸發事件 self._blurEnv($('.mb-input'),$(this),$container); } }); }); }, /* * 新增html標籤 * @method _renderHTML * @param {curValue,tparent} 當前值 當前最外層容器 */ _renderHTML: function(curValue,tparent){ var self = this, _config = self.config, _cache = self.cache; var html = '<li class="mb-tag" data-tag="'+curValue+'">'+ '<div class="mb-tag-content">'+ '<span class="mb-tag-text">'+curValue+'</span>'+ '<a class="mb-tag-remove"></a>'+ '</div>'+ '</li>'; if($('.mb-tag',_config.listItemCls).length > 0) { $('.mb-tag',_config.listItemCls).each(function(){ var dataTag = $(this).attr('data-tag'); _cache.arrs.push(dataTag); _cache.arrs = self.unique(_cache.arrs); }); } var curIndex = self._indexOf(curValue,_cache.arrs); if(curIndex < 0) { $(tparent).find(_config.listItemCls).append(html); }else { alert('重複項,請重新輸入'); return true; } // 關閉事件 self._closedEnv(); }, /* * 失去焦點時候觸發 * @method _blurEnv * @param {target,$btn,$container}當前輸入框目標元素 按鈕 當前最外層容器 */ _blurEnv: function(target,$btn,$container){ var self = this, _config = self.config, _cache = self.cache; $(target).unbind('blur').bind('blur',function(e){ var tagVal = $.trim($(this).val()); blur($(this),tagVal); }); function blur($this,tagVal){ if(tagVal == '') { return; }else { self._renderHTML(tagVal,$container); var curIndex = self._indexOf(tagVal,_cache.arrs); if(curIndex < 0) { $(target).remove(); self._removeItem(tagVal,_cache.arrs); _cache.arrs = self.unique(_cache.arrs); $($btn).removeClass('hidden'); } } } // ENTER鍵 if($(target).length > 0) { $(target).each(function(){ $(this).unbind('keyup').bind('keyup',function(e){ e.preventDefault(); var keyCode = e.keyCode, curValue = $.trim($(this).val()), tparent = $(this).closest(_config.containerCls); if(keyCode == 13) { // 先清空值 呼叫 _renderHTML方法 目地使按enter鍵下時候 不觸發blur事件 $(this).val(''); var istrue = self._renderHTML(curValue,tparent); if(istrue) { $(this).val(curValue); return; } $(this).remove(); $($btn).removeClass('hidden'); } }); }); } }, /* * 關閉事件 */ _closedEnv: function(){ var self = this, _config = self.config, _cache = self.cache; // 關閉X按鈕事件 if($('.mb-tag-remove',_config.listItemCls).length > 0) { $('.mb-tag-remove',_config.listItemCls).each(function(){ $(this).unbind('click').bind('click',function(){ var liparent = $(this).closest('li'), tagVal = $.trim($(liparent).attr('data-tag')); self._removeItem(tagVal,_cache.arrs); _cache.arrs = self.unique(_cache.arrs); $(liparent).remove(); }); }); } }, /* * 從陣列裡面刪除一項 * @method _removeItem * @param {item,arr} 當前的項 陣列 * @return 返回新陣列 */ _removeItem: function(item,arr){ var self = this, index = self._indexOf(item,arr); if(index > -1) { arr.splice(index, 1); } }, /* * 索引 jquery1.8 indexof 會重新排序 所以沒有用jquery indexof */ _indexOf: function(item,arr) { if(Array.prototype.indexOf) { return arr.indexOf(item); }else { for(var i = 0, ilen = arr.length; i < ilen; i+=1) { if(arr[i] == item) { return i; }else { return -1; } } } }, /* * 去掉陣列重複項 * @method unique * @param array * @return newArray */ unique: function(arr){ arr = arr || []; var obj = {}, ret = []; for(var i = 0, ilen = arr.length; i < ilen; i+=1) { var curItem = arr[i], curItemType = typeof(curItem) + curItem; if(obj[curItemType] !== 1) { ret.push(curItem); obj[curItemType] = 1; } } return ret; } };
由於時間問題 先晚安 如果有問題的話,請留言!ok!