JS添加标签效果
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!
JS添加标签效果的更多相关文章
- JS添加标签
<script> function show(){ $('.add').unbind(); $('.low ...
- 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结
史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...
- 原生JS实现分页效果2.0(新增了上一页和下一页,添加当前元素样式)
虽然写的很烂,但至少全部都是自己写的,因为这个没有固定的顺序,所以就没有封装,如果你技术好的话,可以你写的分享给我,谢谢. <!DOCTYPE html><html lang=&qu ...
- 添加标签2 jquery 和JS
TAG添加标签 做了个方法方便调用 一.JS版本 <!DOCTYPE html> <html lang="en"> <head> <met ...
- 原生js实现一个DIV的碰撞反弹运动,并且添加重力效果
继上一篇... 原生js实现一个DIV的碰撞反弹运动,并且添加重力效果 关键在于边界检测,以及乘以的系数问题,实现代码并不难,如下: <!DOCTYPE html> <html la ...
- js 面向对象 动态添加标签
有点逻辑 上代码 thml布局 点击查看代码 <!DOCTYPE html> <html lang="en"> <head> <meta ...
- BootStrap入门教程 (四) :JQuery类库插件(模态窗口,滚动监控,标签效果,提示效果,“泡芙”效果,警告区域,折叠效果,旋转木马,输入提示)
上讲回顾:Bootstrap组件丰富同时具有良好可扩展性,能够很好地应用在生产环境.这些组件包括按钮(Button),导航(Navigation),缩略图( thumbnails),提醒(Alert) ...
- JS添加节点方法与JQuery添加节点方法的比较及总结
原生JS添加节点方法与JQuery添加节点方法的比较及总结 一.首先构建一个简单布局,来供下边讲解使用 1.HTML部分代码: <div id="div1">div ...
- jQuery输入框回车添加标签特效
效果如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...
随机推荐
- 类(class)相关概念小结
参考在线文档,整理php中类的相关概念如下 $this 在类的内部可以使用伪变量$this,这个伪变量为一个到主叫对象(经个人测试理解这应该是在运行时的真实对象,不是类,运行时绑定)的引用,所以一 ...
- js-权威指南-Web套接字
HTTP是一种无状态的协议,,由客户端请求和服务端响应组成.HTTP实际上是比较特殊的网络协议. 大多数基于因特网的网络连接通常包含长连接和基于TCP套接字的双向消息交换.让不信任的客户端脚本访问底层 ...
- CSS3 鼠标划上图片放大
td img{transition: all 1s}/*鼠标划上,图片1s全部显示完成*/ td img:hover{ transform: scale(5) translateX(50%) tran ...
- 如何用WebSocket实现一个简单的聊天室以及单聊功能
百度百科中这样定义WebSocket:WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端.简单的说,We ...
- Angular调用父Scope的函数
app.directive('toggle', function(){ return { restrict: 'A', template: '<a ng-click="f()" ...
- Java计算大整数
import java.util.*; import java.math.*; //BigInteger类型在这个包里 public class Gcc_test { public static vo ...
- Unity[C#] Reflection Use
Reflection Reflection是C#程序员的一个最有力工具 最常用的例子来说明反射的用处是一个插件系统.假设你正在创建一个 接受用户创建 的扩展程序,有没有办法预先知道哪些方法这个扩展 ...
- Windows10 家庭版没有本地组策略解决方法
windows 家庭版默认是没有本地组策略的, win+R运行gpedit.msc提示不存在 下面的代码保存一个cmdorbat 脚本文件add_gpedit.cmd, 并执行 add_gpedit. ...
- django -- Celery实现异步任务
1. 环境 python==2.7 djang==1.11.2 # 1.8, 1.9, 1.10应该都没问题 celery-with-redis==3.0 # 需要用到redis作为中间人服务(Bro ...
- 记录一次mysql使用load into命令导入csv格式数据的过程
今天从qwiklab实验获取一组数据,大概有5万条,在qwiklab实验室使用的是pgsql数据库,但是今天想把他插入本地的mysql数据库中. 1.首先是查看一下数据内容: 数据中有的是空值,有的是 ...