晓风博客

一片荒芜的地方

基于HTML5 localStorage的便利贴

放寒假了,整日昏昏欲睡,实在无聊。今天看了一会书,忽然发现一个让自己感兴趣的玩意——HTML5 localStorage,于是花了一下午加半晚上的时间完成了这个应用。

很多该说的,该写的已经在源码里了。相信大家都和我一样,喜欢看源码。源码来的直接一点。遂奉上源码,当然还有整个项目的百度网盘地址,由于只使用了3张很小的图片,遂整个应用显的很苗条,压缩之后只剩下156KB了。

应用地址:http://liyaodong.sinaapp.com/localStorage/

Tip:源码下来后直接是看不到效果的,localStorage需要服务器的支持。wamp搭建个临时的吧。

技术难点分析:

首先就是localStorage了,localStorage就是一个基于客户端的数据库吧,可以这么说。但是这个数据库只能放点不是很重要的玩意,如果你放进去账号密码。那么再删除浏览器或者更换浏览器或者清空缓存或者重装系统之后,恭喜你,你就杯具了。localStorage允许我们在客户端,即浏览器内存储5MB的数据。神马?才5MB?太小气了吧。起初我也这么认为,但是当我支持Cookies只支持4K之后我突然觉得HTML5已经很大方了。毕竟是客户端嘛,相对于Cookies来说,localStorage有更大的空间,更长的生命周期。可以存储更多的东西,这会使你的应用看起来更像应用一点。不是吗?

那么localStorage到底怎么看呢?打开你的Chrome,不要给我说你还在用IE6,请使用支持HTML5的浏览器,例如Chrome、Safari、猎豹、360急速、搜狗等国产浏览器的急速模式。也就是webkit,因为我没有针对火狐和IE这2B做优化。所以应该是看不了的,推荐使用webkit内核的浏览器查看。如果你确定是webkit内核了,请按F12,打开审查元素,点击Resources看左侧的Local Storage,选中你查看的网站的域就可以了。需要注意的是localStorage需要有服务器的支持,没有服务器的亲可以下载wamp或者phpnow之类的。

如果你在即时贴中输入数据就可以看到localStorage中有数据了。

难点二就是让颜色随机的很好看了,这个是通过控制HSL颜色模式中的H来达到目的的,HSL和RGB、HSB一样都是一种颜色模式,而且CSS原生支持HSL,起初我还在为RGB转HSB的公式而头疼,我这人不喜欢数学。但是RGB转HSB的公式让我想起了我蛋疼的高数。正在沮丧之时我看到CSS的手册中颜色模式有HSL,就差一个B,估计也2不到哪去。然后研究了一下发现HSL和HSB很像,但只是很像,具体区别请找度娘。

难点三呢就是没有了,其他的CSS、响应式WEB都不算难点,因为写JS是最花时间和脑细胞的。看起来就会觉得头疼。不是吗?

下面不废话了,奉上源码,给不能再百度网盘下载源码的亲们,希望大家寒假都能有所收获:

HTML源码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!doctype html>
<html lang="zh_cn">
<head>
	<title>HTML5 localStorage 便利贴</title>
	<meta charset="UTF-8" />
	<meta name="author" content="晓风东东" />
	<meta name="keywords" content="HTML5,locaStorage,HSL,便利贴,即时贴" />
	<meta name="description" content="一个基于HTML5和CSS3技术的便利贴应用,你可以写入一些待办事项。这些东西会完整的保存在你的浏览器里,除非你清空缓存。" />
	<link rel="stylesheet" href="css/style.css">
	<!--[if lt IE 9]>
		<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
	<![endif]-->
	<script type="text/javascript" src="js/jquery.min.js"></script>
	<script type="text/javascript" src="js/js.js"></script>
</head>
	<body>
		<section id="shell">
			<form id="ctrl_form">
				<div id="title">HTML5 localStorage 便利贴</div>
				<label for="note_color">颜色:</label>
				<select id="note_color">
					<option>随机</option>
					<option>科技蓝</option>
					<option>淡雅黄</option>
					<option>清新绿</option>
					<option>暧昧粉</option>
					<option>高贵紫</option>
				</select>
				<input type="text" id="note_text" />
				<input type="button" id="add_btn" value="增加" />
			</form>
			<section id="note_display">
				<ul id="note_display_ul">
				</ul>
			</section><!--note_display end-->
		</section><!--shell end-->
	</body>

</html>

CSS源码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
html,body {
	background:url(../images/bg.png);
	font-family:&quot;微软雅黑&quot;;
}
#ctrl_form {
	background:-webkit-gradient(linear, 0 0, 0 100%, from(#2c2f36), to(#16181c));
	width:60%;
	border-radius:5px;
	margin:0 auto;
	margin-top:5%;
	text-align:center;
	padding:1%;
	color:#fff;
}
#title {
	font-size:200%;
	padding-bottom:10px;
	margin-bottom:10px;
	border-bottom:2px dashed #888;
	text-shadow:2px 1px 2px #888;
}
#note_display {
	width:90%;
	margin:0 auto;
	text-align:center;
	margin-top:5%;
}
#note_display ul li {
	width:10%;
	background:hsl(110,53%,60%);
	background-image:url(../images/wangge.png);
	height:150px;
	float:left;
	border:1px solid #aeaeae;
	color:#222;
	font-size:150%;
	padding:1%;
	margin:1%;
	cursor:pointer;
	overflow:hidden;
	box-shadow: 2px 2px 8px #222;
}
#note_display ul li:hover {
	opacity:.8;
}
#add_btn,#note_text,#note_color,label {
	font-family:&quot;微软雅黑&quot;;
	font-size:150%;
	padding:.5%;
}
#note_color {
	padding:.4%;
}
#add_btn {
	background:-webkit-gradient(linear, 0 0, 0 100%, from(#aeaeae), to(#888));
	border:1px solid #aeaeae;
	color:#000;
}
#add_btn:hover {
	background:-webkit-gradient(linear, 0 0, 0 100%, from(#888), to(#aeaeae));
}
#note_text {
	width:30%;
}
/*响应式web设计的核心,为不同设备屏幕写出独立的CSS,同时尽量避免使用PX作为宽度的单位,更多的使用相对单位。*/
@media screen and (max-width:720px) {
	#note_display ul li {
		width:20%;
	}
}
@media screen and (max-width:480px) {
	#note_display ul li {
		width:40%;
		font-size:120%;
	}
}

终于要到了最头疼的JS源码了,不过也是最有技术含量的部分:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
$(document).ready(function(){
	//给增加按钮绑定事件,并设置在点击增加后输入框内清空
	$(&quot;#add_btn&quot;).click(function(){
		var note_text_val = $(&quot;#note_text&quot;).val();
		if (note_text_val == &quot;&quot;){
			alert(&quot;你还没有填写任何内容喔&quot;);
		}
		else {
			createSticky();
			$(&quot;#note_text&quot;).val(&quot;&quot;);
		}
	});
	//遍历便利贴数组,同时传递值给其他函数
	//JSON.parse是个非常神奇的函数,可以给你把数组或者对象的内容转化为字符串。就像JSON那样,很棒!这使的我可以在Cookies或者localStore中存储更多的数据
	var stickiesArray = getStickiesArray();
	for(var i= 0 ; i &lt; stickiesArray.length;  i++){
		var key = stickiesArray[i];
		var value = JSON.parse(localStorage[key]);
		addStickyToDOM(key, value);
	}
});
//创建stickiesArray,存放一个类似电话本的键,并且对localStorage中的stickiesArray这个“母键”初始化
function getStickiesArray() {
	var stickiesArray = localStorage[&quot;stickiesArray&quot;];
	if(!stickiesArray) {
		stickiesArray = [];
		localStorage.setItem(&quot;stickiesArray&quot;, JSON.stringify(stickiesArray));
	}
	else {
		stickiesArray = JSON.parse(stickiesArray);
	}
	return stickiesArray;
}
//创建其他键值,并且从用户界面得到所选颜色值,并且转换为HSL值,写入localStorage
//stickyObj是一个对象,不同于数组了。对象是个很抽象的玩意,Everything is an object
function createSticky (){
	var stickiesArray = getStickiesArray();
	var currentDate = new Date();//按照时间获得一个随机数,保证键值不重复
	var colorSelectObj = document.getElementById(&quot;note_color&quot;);
	var index = colorSelectObj.selectedIndex;
	var colorName = colorSelectObj[index].value;
	var colorHSL = colorNameToHSL(colorName);
	var value = $(&quot;#note_text&quot;).val();
	var key = &quot;sticky_&quot; + currentDate.getTime();
	var stickyObj = {
		&quot;value&quot;: value,
		&quot;colorHSL&quot;: colorHSL
	}
	//将对象写入localStorage
	localStorage.setItem(key, JSON.stringify(stickyObj));
	//将键名添加到哪个神奇的母键的最后一项
	stickiesArray.push(key);
	localStorage.setItem(&quot;stickiesArray&quot;, JSON.stringify(stickiesArray));
	//添加便贴到DOM
	addStickyToDOM(key, stickyObj);
}
//添加便贴到DOM的具体步骤,stickyObj是一个对象,要用.来访问子元素
function addStickyToDOM (key, stickyObj){
	var sticky = document.createElement(&quot;li&quot;);
	sticky.setAttribute(&quot;id&quot;, key);
	sticky.setAttribute(&quot;style&quot;, &quot;background-color:hsl(&quot; + stickyObj.colorHSL +&quot;, 56%, 60%);&quot;);//HSL中的色相保持随机,其他的固定上。保证颜色的饱和度和亮度
	var span = document.createElement(&quot;span&quot;);
	span.setAttribute(&quot;class&quot;, &quot;sticky&quot;);
	span.innerHTML = stickyObj.value;
	sticky.appendChild(span);
	$(&quot;#note_display_ul&quot;).append(sticky);
	sticky.onclick = deleteSticky;
}
//删除即时贴的函数,做了一个判断,判断点击对象并确保为ul下的li元素,而不是span
//同时还要更新删除过后的stickiesArray数组
function deleteSticky (e){
	if(confirm(&quot;你确定要删除这个即时贴吗&quot;)){
		var key = e.target.id;
		if(e.target.tagName.toLowerCase() == &quot;span&quot;) {
			key = e.target.parentNode.id;
		}
		localStorage.removeItem(key);
		var stickiesArray = getStickiesArray();
		if(stickiesArray) {
			for (var i = 0; i&lt; stickiesArray.length; i++) {
				if(key == stickiesArray[i]){
					stickiesArray.splice(i,1);
				}
			}
			localStorage.setItem(&quot;stickiesArray&quot;, JSON.stringify(stickiesArray));
			removeStickyFromDom(key);
		}
	}
}
//从DOM中删除已经删除的便贴
function removeStickyFromDom(key) {
	var sticky = document.getElementById(key);
	sticky.parentNode.removeChild(sticky);
}
//将colorName根据HSL的颜色值进行分析并返回
function colorNameToHSL(colorName) {
	if(colorName == &quot;科技蓝&quot;) {
		return 200;
	}
	else if (colorName == &quot;淡雅黄&quot;){
		return 60;
	}
	else if (colorName == &quot;清新绿&quot;){
		return 100;
	}
	else if (colorName == &quot;暧昧粉&quot;){
		return 325;
	}
	else if (colorName == &quot;高贵紫&quot;){
		return 250;
	}
	else{
		var random_num = Math.floor(Math.random()*359+1);
		return random_num;
	}
}