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;
}
};

DEMO下载

由于时间问题 先晚安 如果有问题的话,请留言!ok!

JS添加标签效果的更多相关文章

  1. JS添加标签

    <script>            function show(){                $('.add').unbind();                $('.low ...

  2. 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结

    史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...

  3. 原生JS实现分页效果2.0(新增了上一页和下一页,添加当前元素样式)

    虽然写的很烂,但至少全部都是自己写的,因为这个没有固定的顺序,所以就没有封装,如果你技术好的话,可以你写的分享给我,谢谢. <!DOCTYPE html><html lang=&qu ...

  4. 添加标签2 jquery 和JS

    TAG添加标签 做了个方法方便调用 一.JS版本 <!DOCTYPE html> <html lang="en"> <head> <met ...

  5. 原生js实现一个DIV的碰撞反弹运动,并且添加重力效果

    继上一篇... 原生js实现一个DIV的碰撞反弹运动,并且添加重力效果 关键在于边界检测,以及乘以的系数问题,实现代码并不难,如下: <!DOCTYPE html> <html la ...

  6. js 面向对象 动态添加标签

    有点逻辑 上代码 thml布局 点击查看代码 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  7. BootStrap入门教程 (四) :JQuery类库插件(模态窗口,滚动监控,标签效果,提示效果,“泡芙”效果,警告区域,折叠效果,旋转木马,输入提示)

    上讲回顾:Bootstrap组件丰富同时具有良好可扩展性,能够很好地应用在生产环境.这些组件包括按钮(Button),导航(Navigation),缩略图( thumbnails),提醒(Alert) ...

  8. JS添加节点方法与JQuery添加节点方法的比较及总结

    原生JS添加节点方法与JQuery添加节点方法的比较及总结   一.首先构建一个简单布局,来供下边讲解使用 1.HTML部分代码: <div id="div1">div ...

  9. jQuery输入框回车添加标签特效

    效果如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...

随机推荐

  1. Java - "JUC" CyclicBarrier源码分析

    Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例 CyclicBarrier简介 CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 ...

  2. 函数表达式(JavaScript高程笔记)

    函数声明 特点:函数声明提升(执行代码之前解析器会先读取函数声明,并使其在执行任何代码之前可用,意味着可以把函数声明放在调用语句之后) function functionName(arg0,arg1) ...

  3. Vue.js之路由系统

    Vue.js生态之vue-router vue-router是什么? vue-router是Vue的路由系统,定位资源的,我们可以不进行整页刷新去切换页面内容. vue-router的安装与基本配置 ...

  4. 【java基础】基础小总结

    学习java,将自己的心得或总结写下来吧. Java 标识符 标识符由字母,下划线(_),美元符($)和数字组成. 标识符不能以数字开头. 标识符不能使java关键字. 标识符对大小写敏感. Java ...

  5. 高德地图 JS API - 根据地名实现标记定位

    德地图 JS API 使用前的准备工作请参考官方网站说明: https://lbs.amap.com/api/javascript-api/guide/abc/prepare 根据地名实现地图标记定位 ...

  6. windows10 java环境变量设置

    由于安装的是jdk1.8所以不需要配置classpath了,只需要配置java_home和path即可. 我的电脑 -> 右键属性 -> 高级系统设置 -> 高级 -> 环境变 ...

  7. [基础架构]PeopleSoft Tuxedo 重要文件说明

    我们都知道PeopleSoft是由几个不同的服务组成的,他们在PeopleSoft体系结构中扮演着自己的角色.这些服务具有不同的文件结构并包含重要的可执行文件和配置文件. 以下是Peoplesoft体 ...

  8. 在Android Studio中调用so中的方法

    本节用的so是上节用Android Studio创建的so.想在Android Studio中调用so中的方法,需要先引用so.Android Studio中引用so的方法有二种,下面开始介绍. 一 ...

  9. gulp学习。

    安装gulp 安装gulp之前必须先安装node.js,然后在命令行里输入 $ npm install gulp-cli -g (-g 表示全局安装)然后在输入$ gulp -v ,验证,安装完成后再 ...

  10. Linux 安装MongoDB 并设置防火墙,使用远程客户端访问

    1. 下载 MongoDB 提供了 linux 各发行版本 64 位的安装包  下载地址:https://www.mongodb.com/download-center#community 2. 安装 ...