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 POI excel 导出复合样式(一个单元格两个字体)

    前言:java poi 导出 excel 时,需要设置一个单元格有多个字体样式,有点类似于富文本. 想要达到的效果(一个单元格里): 我使用的 poi 版本是 <dependency> & ...

  2. vue-infinite-loading2.0 中文文档

    简介 这是一个使用在Vue.js中的无限滚动插件,它可以帮助你快速创建一个无限滚动列表. 特点 移动端支持友好 兼容任何一个可以滚动的元素 有不同的旋转器可以作为加载动画 支持加载后显示结果 支持两个 ...

  3. eclipse java web项目经常自动调试进入debug模式

    今天在运行Javaweb项目时,程序运行运行着就自动调试进入ThreadpoolExecutor,看着非常影响心情.最后在网上搜解决方法最后找到原因,解决方法如下. Window——>Prefe ...

  4. 测试sql server服务是否配置正确

    最简单的方法: 新建一个testdb.udl文件,双击可出现测试界面

  5. rdlc里面的textbox怎么赋值

    通过传递参数来实现 当前在rdlc页面,ctrl+alt+d,打开report data侧边栏 点击report data的Parameters文件夹,右键,添加新的参数,命名.定义类型,譬如命名为R ...

  6. Python Django框架笔记(五):模型

    #前言部分来自Django Book (一)    前言 大多数web应用本质上: 1. 每个页面都是将数据库的数据以HTML格式进行展现. 2. 向用户提供修改数据库数据的方法.(例如:注册.发表评 ...

  7. python常用模块之-random模块

    random模块顾名思义就是生成随机数的模块. random模块有以下常见方法: 1,打印0-1之间的任意随机浮点数,不能指定区间. print(random.random()) 2,打印随机符点数, ...

  8. kafka入门1:安装及配置

    1下载 官方下载地址:https://kafka.apache.org/downloads 案例使用版本:kafka_2.11-1.1.0.tgz 2上传服务器 使用ftp工具将压缩包放置到服务器上 ...

  9. win10 安装microsoft.net framework3.5

    转载于:https://www.windows10.pro/win10-net-framework-3-5/ 之前手残不小心把microsoft.net framework3.5删了,结果导致Sql ...

  10. Azure 虚拟机代理概述

    Azure 虚拟机代理(AM 代理)是受保护的轻型过程,用于管理 VM 与 Azure 结构控制器的交互. VM 代理有一个主要角色,目的是启用和执行 Azure 虚拟机扩展. VM 扩展可用于对虚拟 ...