前言

做了差不多一个星期的jquery清单,将所学到的内容整理成笔记,在床上纠结要写这个还是canvas做网页背景,结果还是这个。将有关思路和代码整理如下:

html结构

html代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div class="msg">
<span class="msg-content"></span>
<span class="anchor confirmed">ok</span>
</div>
<div class="container">
<h1>jquery清单</h1>
<div class="add-task">
<form>
<input type="text" name="content" placeholder="hellow" autofocus autocomplete="off">
<button type="submit" class="btn">submit</button>
</form>
</div>
<div class="task-list">
</div>
<div class="task-detail-mask"></div>
<div class="task-detail">
</div>
</div>
<video src="" class="alerter"></video>

其中msg为到时后提醒内容,add-task存放输入框和按钮表单,task-list为清单内容。task-detail-mask为详细框的遮罩,task-detail为详细框

css样式

引用如下代码:

1
<link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/normalize/7.0.0/normalize.min.css">

将浏览器的默认样式清除。其它样式主要按照自己的想法构建,具体可看附录源码

js实现功能

首先,各变量定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var $form_add_task=$('.add-task'),//获取输入的class
task_list={},//存放数据
$delail_task,//获取delail类,渲染html后再获得
$delete_task,//获取delete类,渲染html后再获得
$task_detail=$('.task-detail'),//获取详情类
$task_detail_masks=$('.task-detail-mask')//获取详细的遮罩
current_index,
$upate_form,
$task_detail_content,
$task_detail_content_input,
$checkbox_complete,
$msg=$('.msg'),
$msg_content=$msg.find('.msg-content'),
$msg_confirm=$msg.find('.confirmed'),
$alerter=$('.alerter'),
$body=$('body'),
$window=$(window)
;
  1. 将输入的内容存储,这里使用了store.js来存放,主要使用它的
    store.set() 来存放数据。
    代码如下:
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
//提交表单时触发事件
$form_add_task.on('submit',function(e){
var new_task={};
e.preventDefault();/*禁用default*/
var $input=$(this).find('input[name=content]');
new_task.content = $input.val();
if(!new_task.content) return;
/*存放Task*/
if(add_task(new_task)){
$input.val(null);//将输入框内容清除
}
})
//将数据存入task_list
function add_task(new_task){
/*将taskpush入task_list*/
task_list.push(new_task);
refresh_task_list();
return true;
}
//存放数据在store并渲染html
function refresh_task_list(){
store.set('task_list',task_list);
render_task_list();
}
  1. 将表单内容渲染在task-list上
    主要是render_task_list()和render_task_tpl()来实现
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
/*渲染task-lis,传入数据和数据索引*/
function render_task_tpl(data,index){
if(!data||!index) return;//不存在返回
var list_item_tpl=
'<div class="task-item" data-index="'+ index+'">'+
'<span><input class="complete"'+(data.complete ? 'checked':'')+' type="checkbox"></span>'+
'<span class="task-content">'+data.content+'</span>'+
'<span class="fc">'+
'<span class="action delete">删除 </span>'+
'<span class="action detail"> 详细 </span>'+
'<span>'+
'</div>'
return $(list_item_tpl);
}
//数据依次渲染,并绑定删除和详细事件
function render_task_list(){
var $task_list=$('.task-list');
$task_list.html('');
var complete_items=[];
//将已经完成的和还没完成的分开渲染
for(var i=0;i<task_list.length;i++){
var item=task_list[i];
if(item&&item.complete)
complete_items[i]=item;
else
var $task=render_task_tpl(task_list[i],i);
$task_list.prepend($task);
}
for(var j=0;j<complete_items.length;j++){
$task=render_task_tpl(complete_items[j],j);
if(!$task) continue;
//完成的添加completed类,方便添加完成样式
$task.addClass("completed");
$task_list.append($task);
}
$delete_task=$('.action.delete');/*获取delete类*/
$delail_task=$('.action.detail');//获取detail类
$checkbox_complete=$('.complete');
list_task_delete();/*删除事件*/
listion_task_detail();//详情事件
listen_checkbox_complete();//勾选事件
}
  1. 渲染详情

当用户点击详情或双击list时显示详情内容
listion_task_detail()事件如下:点击或双击时触发show_task_detail函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function listion_task_detail(){
var index;
$('.task-item').on('dblclick',function(){
index=$(this).data('index');//获得索引
show_task_detail(index);//显示内容
})
$delail_task.on('click',function(){
var $this=$(this);
var $item=$this.parent().parent();//获得索引
index=$item.data('index');
show_task_detail(index);//显示内容
})
}

show_task_detail()和render_task_detail()函数如下:,其中日期使用了datetimepicker.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
function show_task_detail(index){
render_task_detail(index);
current_index=index;
$task_detail.show();
$task_detail_masks.show();
}
//渲染详情的html界面
function render_task_detail(index){
if(index===undefined||!task_list[index])
return;
var item=task_list[index];
var tpl='<form>'+
'<div class="content">'+
item.content+
'</div>'+
'<div><input style="display:none" type="text" name="content" value="'+item.content+'"></div>'+
'<div>'+
'<div class="desc">'+
'<textarea name="desc" >'+(item.desc||'')+'</textarea>'+
'</div>'+
'</div>'+
'<div class="remind">'+'<label>提醒时间</label>'+
'<input class="datetime" type="text" value="'+(item.remain_data||"")+'" name="remind_date">'+
'</div>'+
'<div><button type="submit">更新</button></div>'+
'</form>';
$task_detail.html(null);
$task_detail.html(tpl);
//调用datetimepicker.js
$(".datetime").datetimepicker();
$upate_form=$task_detail.find('form');//获取更新的表单
$task_detail_content=$upate_form.find('.content');
$task_detail_content_input=$upate_form.find('[name=content]');
//双击更改content内容
$task_detail_content.on('dblclick',function(){
$task_detail_content_input.show();
$task_detail_content.hide();
})
//表单提交的事件
$upate_form.on('submit',function(e){
e.preventDefault();
var data={};
//更新数据
data.content = $(this).find('[name=content]').val();
data.desc=$(this).find('[name=desc]').val();
data.remain_data=$(this).find('[name=remind_date]').val();
//更新html
upate_task(index,data);
//隐藏详细
hidden_task_detail();
})
}
//隐藏函数
function hidden_task_detail(){
$task_detail.hide();
$task_detail_masks.hide();
}

upate_task()函数代码如下:

1
2
3
4
5
6
7
function upate_task(index,data){
//不存在时返回
if(!index||!task_list[index])
return;
task_list[index]=$.extend({},task_list[index],data);
refresh_task_list();
}

  1. 删除事件

删除使用了自定义的提示框pop(),listen_msg_event()代码如下:

1
2
3
4
5
6
7
8
9
10
11
function list_task_delete(){
$delete_task.on('click',function(){
var $this=$(this);
var $item=$this.parent().parent();//获取索引
var index=$item.data('index');
//y调用提示框和删除lisdt
pop("Are you sure?").then(function(r){
r? delete_task(index):null;
})
})
}

pop()函数如下:使用了jquery的Deferred

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
function pop(arg){
//arg为显示内容
if(!arg){
console.error('error');
}
var conf={},$box,$mask,$title,$content,$confirm,$cancel,dfd,
confirmed,timer;
//判断arg为字符或对象
if(typeof arg=='string')
conf.title=arg;
else {
conf=$.extend(conf,arg);
}
//调用Deferred();
dfd=$.Deferred();
//获得浏览器的宽度和高度,并应用在$box上
function adjust_box_position(){
var window_width=$window.width(),
window_height=$window.height(),
box_width=$box.width(),
box_height=$box.height(),
move_x,
move_y
;
move_x=(window_width-box_width)/2;
move_y=((window_height-box_height)/2)-30;
$box.css({
left:move_x,
top:move_y,
})
}
//移除提示框
function dismiss_pop(){
$mask.remove();
$box.remove();
}
//$box的html和css
$box=$('<div>'+'<div class="pop-title">'+conf.title+'</div>'+
'<div class="pop-content">'+
'<div><button style="margin-right:5px;" class="primary confirm">确定</button>'+
'<button class="cancel">取消</button></div>'+
'</div>'+
'</div>').css({
width:300,
height:200,
background: '#fff',
position:'fixed',
'border-radius':3,
'box-shadow':'0 1px 2px rgba(0,0,0,.3)',
color:'#444'
})
//$mask的html和css
$mask=$('<div></div>').css({
position:'fixed',
background:'rgba(0,0,0,0.4)',
top:0,
bottom:0,
left :0,
right :0,
})
//提示内容样式
$title=$box.find('.pop-title').css({
padding:'5px 10px',
'font-weight':900,
'font-size':20,
'text-align':'center'
})
$content =$box.find('.pop-content').css({
padding:'5px 10px',
'text-align':'center'
})
$confirm=$content.find('button.confirm');
$cancel=$content.find('button.cancel');
//不断等待用户点击,用户点击后停止
timer=setInterval(function(){
if(confirmed!==undefined){
//将confirmed传入resolve方法
dfd.resolve(confirmed);
//停止setInterval
clearInterval(timer);
dismiss_pop();
}
},50)
//按钮点击事件
$confirm.on('click',function(){
confirmed=true;
})
$cancel.on('click',function(){
confirmed=false;
})
//mask点击事件
$mask.on('click',function(){
confirmed=false;
})
//当调整浏览器窗口的大小时,发生 resize 事件。
$window.on('resize',function(){
adjust_box_position();
})
//将$mask和$box添加到body
$mask.appendTo($body);
$box.appendTo($mask);
$window.resize();
//将promise返回
return dfd.promise();
}
  1. 定时功能

主要使用task_remind_check()函数实现

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
function task_remind_check(){
var current_timestamp;
var itl =setInterval(function(){
for(var i=0;i<task_list.length;i++){
var item =task_list[i],task_timestamp;
//还没完成的进行判断
if(!item || !item.remain_data || item.informed)
continue;
current_timestamp = (new Date()).getTime();
//getTime() 方法可返回距 1970 年 1 月 1 日之间的毫秒数
task_timestamp=(new Date(item.remain_data)).getTime();
if(current_timestamp-task_timestamp>=1){
//更新informed
upate_task(i,{informed:true});
//显示提示
show_msg(item.content);
}
}
},300);
}
//show_msg函数
function show_msg(msg){
if(!msg) return;
$msg_content.html(msg);
//播放music
$alerter.get(0).play();
$msg.show();
}
function hide_msg(msg){
$msg.hide();
}
//显示后点击$msg_confirm事件
function listen_msg_event(){
$msg_confirm.on('click',function(){
hide_msg();
})
}

将listen_msg_event()和task_remind_check()都注册到init()

1
2
3
4
5
6
7
function init(){
task_list=store.get('task_list')||[];
listen_msg_event();
if(task_list.length)
render_task_list();
task_remind_check();
}

  1. 勾选事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function listen_checkbox_complete(){
$checkbox_complete.on('click',function(){
var $this=$(this);
//获取索引
var index=$this.parent().parent().data('index');
var item=store.get('task_list')[index];
//更新complete
if(item.complete){
upate_task(index,{complete:false});
}
else{
upate_task(index,{complete:true});
}
})
}

附录