├── .gitignore
├── README.md
├── js
├── demo.json
├── storage.js
└── note.js
├── index.html
└── css
└── style.css
/.gitignore:
--------------------------------------------------------------------------------
1 | .fuse*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [百度前端学院task3](https://github.com/baidu-ife/ife/tree/master/2015_spring/task/task0003)
2 | 使用vue.js编写的记事本,localstorage作为数据存储。
--------------------------------------------------------------------------------
/js/demo.json:
--------------------------------------------------------------------------------
1 | {
2 | "catalogs": {
3 | "length": 3,
4 | "catalogs": [
5 | {
6 | "id": 0,
7 | "name": "python"
8 | },
9 | {
10 | "id": 1,
11 | "name": "javascript"
12 | },
13 | {
14 | "id": 2,
15 | "name": "css"
16 | }
17 | ]
18 | },
19 | "tasks": {
20 | "0": [
21 | {
22 | "title": "call, apply和bind",
23 | "content": "call, apply和bindcall, apply和bind",
24 | "size": "1823",
25 | "createTime": "2015/11/2",
26 | "updateTime": "2015/11/14"
27 | }
28 | ],
29 | "1": [
30 | {
31 | "title": "call, apply和bind",
32 | "content": "call, apply和bindcall, apply和bind",
33 | "size": "1823",
34 | "createTime": "2015/11/2",
35 | "updateTime": "2015/11/14"
36 | },
37 | {
38 | "title": "call, apply和bind",
39 | "content": "call, apply和bindcall, apply和bind",
40 | "size": "1823",
41 | "createTime": "2015/11/2",
42 | "updateTime": "2015/11/14"
43 | }
44 | ]
45 | }
46 | }
--------------------------------------------------------------------------------
/js/storage.js:
--------------------------------------------------------------------------------
1 | function Storage() {
2 | this.storage = window.localStorage;
3 | }
4 |
5 | Storage.prototype = {
6 |
7 | fetchCatalog: function() {
8 | return JSON.parse(this.storage.getItem('catalog') || '{"length":2,"catalogs":[{"id":0,"name":"python","length":0},{"id":1,"name":"javascript","length":0}]}')
9 | },
10 |
11 | saveCatalog: function(catalogs) {
12 | this.storage.setItem('catalog', JSON.stringify(catalogs));
13 | },
14 |
15 | fetchTask: function() {
16 | return JSON.parse(this.storage.getItem('task')) || {"0":[{"title":"python列表推导式与字典推导式","content":"[i for i in range(100)]
{k:v for k,v in enumerate('abced')}","size":62,"createTime":"13/12/2015, 10:00:31","updateTime":"13/12/2015, 10:13:48"},{"title":"切片命名","content":"str = 'wangxiansdfasfasfasdfas'
name = slice(8)
str[name] // wangxian","size":93,"createTime":"13/12/2015, 10:05:35","updateTime":"13/12/2015, 10:11:50"}],"1":[{"title":"ES6 promise的用法","content":"p.then(data =>{
// dosomething
}).catch(err => {
});","size":90,"createTime":"13/12/2015, 10:16:29","updateTime":"13/12/2015, 10:16:29"}]};
17 | },
18 |
19 | saveTask: function(tasks) {
20 | this.storage.setItem('task', JSON.stringify(tasks));
21 | },
22 |
23 | getCid: function() {
24 | return JSON.parse(this.storage.getItem('taskOfCatalogId')) || 0;
25 | },
26 |
27 | saveCid: function(cid) {
28 | this.storage.setItem('taskOfCatalogId', JSON.stringify(cid));
29 | },
30 |
31 | getEditTask: function() {
32 | return JSON.parse(this.storage.getItem('editTask')) || this.fetchTask()[0][0] || {};
33 | },
34 |
35 | saveEditTask: function(task) {
36 | this.storage.setItem('editTask', JSON.stringify(task));
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 | -
17 | {{ catalog.name }}
18 | ({{ tasks[catalog.id].length}})
19 |
20 |
21 |
22 |
23 | 新增分类
24 |
25 |
26 |
27 |
33 |
34 | 新增笔记
35 |
36 |
37 |
38 |
39 |
48 |
49 |
50 | 创建于: {{ editTask.createTime }}
51 | 更新于:{{ editTask.updateTime }}
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/js/note.js:
--------------------------------------------------------------------------------
1 | var storage = new Storage();
2 | var vm = new Vue({
3 | el: 'body',
4 | data: {
5 | tasks: storage.fetchTask(),
6 | catalogs: storage.fetchCatalog(),
7 | taskOfCatalogId: storage.getCid(),
8 | editTask: storage.getEditTask(),
9 | editable: false,
10 | newCatalog: '',
11 | model: false,
12 | },
13 | methods: {
14 | toggleModel: function(event) {
15 | this.model = !this.model;
16 | },
17 |
18 | addCatalog: function() {
19 | var catalogname = this.newCatalog;
20 | if (catalogname) {
21 | if (!this.catalogs['length']) {
22 | this.catalogs['length'] = 0;
23 | this.catalogs.catalogs = [];
24 | }
25 | var len = this.catalogs.length;
26 | var catalog = {
27 | 'id': len,
28 | 'name': catalogname,
29 | 'length': 0,
30 | }
31 | this.catalogs.length++;
32 | this.catalogs.catalogs.push(catalog);
33 | Vue.set(this.tasks, len, []);
34 | this.newCatalog = '';
35 | this.model = false;
36 | this.taskOfCatalogId = len;
37 | }
38 | },
39 | removeCatalog: function(catalog) {
40 | this.catalogs.catalogs.$remove(catalog);
41 | },
42 | removeTask: function() {
43 | this.tasks[this.taskOfCatalogId].$remove(this.editTask);
44 | },
45 | toggleTaskPanel: function() {
46 | this.editable = true;
47 | this.editTask = {};
48 | document.getElementsByClassName('note-text')[0].innerHTML = '';
49 | document.getElementsByClassName('edit-content')[0].innerHTML = '';
50 | },
51 | saveTask: function() {
52 | if (!this.editable)
53 | return;
54 | var id = this.taskOfCatalogId;
55 | var title = document.getElementsByClassName('note-text')[0].textContent.trim();
56 | var content = document.getElementsByClassName('edit-content')[0].innerHTML.trim();
57 | if (!this.editTask.title && title) {
58 | var task = {
59 | title: title,
60 | content: content,
61 | size: content.length,
62 | createTime: new Date().toLocaleString('en-GB', {hour12:false}),
63 | updateTime: new Date().toLocaleString('en-GB', {hour12:false})
64 | };
65 | this.tasks[id].push(task);
66 | this.editTask = task;
67 |
68 | } else {
69 | this.editTask.title = title ? title: 'untitled';
70 | this.editTask.content = content;
71 | this.editTask.size = content.length;
72 | this.editTask.updateTime = new Date().toLocaleString('en-GB', {hour12:false});
73 | }
74 | this.editable = false;
75 | },
76 | },
77 | watch: {
78 | catalogs: {
79 | handler: function(catalogs) {
80 | storage.saveCatalog(catalogs);
81 | },
82 | deep: true,
83 | },
84 | editable: {
85 | handler: function() {
86 | storage.saveTask(this.tasks);
87 | },
88 | deep: true,
89 | },
90 | tasks: {
91 | handler: function(tasks) {
92 | storage.saveTask(this.tasks);
93 | },
94 | deep: true,
95 | },
96 | taskOfCatalogId: {
97 | handler: function(cid) {
98 | storage.saveCid(cid);
99 | this.editTask = this.tasks[cid][0] || {};
100 | }
101 | },
102 | editTask: {
103 | handler: function(task) {
104 | storage.saveEditTask(task);
105 | }
106 | }
107 | }
108 | });
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/css/style.css:
--------------------------------------------------------------------------------
1 | /*reset*/
2 |
3 | * {
4 | box-sizing: border-box;
5 | }
6 |
7 | html,
8 | body {
9 | height: 100%;
10 | padding: 0;
11 | margin: 0;
12 | font-family: "Lucida Console", Helvetica, "Microsoft Yahei", "Hiragino Sans GB", sans-serif;
13 | }
14 |
15 | ul {
16 | padding: 0;
17 | margin: 0;
18 | }
19 |
20 | li {
21 | display: block;
22 | padding-left: 25px;
23 | line-height: 35px;
24 | }
25 |
26 | a {
27 | color: #000;
28 | text-decoration: none;
29 | }
30 |
31 | .btn {
32 | padding: 5px;
33 | cursor: pointer;
34 | background-color: rgba(10, 10, 10, 0.1);
35 | border: 1px solid #ccc;
36 | border-radius: 4px;
37 | }
38 |
39 | /*头部*/
40 |
41 | .header {
42 | position: absolute;
43 | top: 0;
44 | width: 100%;
45 | height: 55px;
46 | padding-left: 20px;
47 | line-height: 55px;
48 | background-color: #c7c7c7;
49 | border-bottom: 1px solid #aaa;
50 | }
51 |
52 | .title {
53 | font-size: 1.6em;
54 | line-height: 55px;
55 | color: #888;
56 | }
57 |
58 | /*内容区大致布局*/
59 |
60 | .content {
61 | height: 100%;
62 | padding-top: 55px;
63 | }
64 |
65 | .catalog,
66 | .task {
67 | position: relative;
68 | z-index: 1;
69 | padding-bottom: 41px;
70 | border-right: 1px solid #ccc;
71 | }
72 |
73 | .catalog {
74 | float: left;
75 | width: 200px;
76 | height: 100%;
77 | }
78 |
79 | .task {
80 | float: left;
81 | width: 300px;
82 | height: 100%;
83 | }
84 |
85 | .detail {
86 | position: relative;
87 | height: 100%;
88 | padding-left: 500px;
89 | }
90 |
91 | /*左侧目录*/
92 |
93 | .catalog .list {
94 | height: 100%;
95 | overflow-x: hidden;
96 | overflow-y: auto;
97 | }
98 |
99 | .catalog .item {
100 | cursor: pointer;
101 | /*background-color: #eff;*/
102 | border-bottom: 1px solid #eee;
103 | }
104 |
105 | .catalog .item.active,
106 | .catalog .item:hover {
107 | background-color: #eee;
108 | }
109 |
110 | .add {
111 | position: absolute;
112 | bottom: 0;
113 | left: 0;
114 | z-index: 3;
115 | width: 100%;
116 | height: 40px;
117 | line-height: 39px;
118 | text-align: center;
119 | border-top: 1px solid #aaa;
120 | cursor: pointer;
121 | }
122 |
123 | .delete {
124 | color: #aaa;
125 | cursor: pointer;
126 | position: absolute;
127 | right: 10px;
128 | }
129 |
130 | /*中间任务列表*/
131 |
132 | .task .btn {
133 | position: relative;
134 | left: 60px;
135 | }
136 |
137 | .task .list {
138 | position: relative;
139 | height: 100%;
140 | overflow-y: auto;
141 | }
142 |
143 | .task .item {
144 | padding: 10px 25px;
145 | word-break: break-all;
146 | cursor: pointer;
147 | background-color: #fff;
148 | border-bottom: 1px solid #cfe;
149 | }
150 |
151 | .task .item .date {
152 | font-size: 0.8em;
153 | color: rgba(0, 0, 0, 0.3);
154 | }
155 |
156 | .task .item.active,
157 | .task .item:hover {
158 | background-color: #eee;
159 | }
160 |
161 | /*右侧笔记区域*/
162 | .detail-box {
163 | height: 100%;
164 | }
165 |
166 | .detail-date.editing,
167 | .detail-title.editing,
168 | .edit-content.editing {
169 | border-left: 3px solid #aaa;
170 | }
171 |
172 | .detail-title {
173 | position: absolute;
174 | right: 0;
175 | left: 500px;
176 | height: 50px;
177 | padding: 8px 20px;
178 | line-height: 33px;
179 | background-color: #fbfbfb;
180 | border-bottom: 1px solid #ccc;
181 | }
182 |
183 | .detail-title .note-text {
184 | width: 100%;
185 | height: 100%;
186 | }
187 |
188 | .detail-title .btns {
189 | float: right;
190 | }
191 |
192 | .detail-date {
193 | position: absolute;
194 | top: 50px;
195 | right: 0;
196 | left: 500px;
197 | height: 40px;
198 | padding-left: 20px;
199 | font-size: 0.9em;
200 | line-height: 40px;
201 | color: #bbb;
202 | background-color: #fbfbfb;
203 | border-bottom: 1px solid #ccc;
204 | }
205 |
206 | .edit-content {
207 | height: 100%;
208 | padding: 110px 20px 20px;
209 | font-size: 1.1em;
210 | word-wrap: break-word;
211 | font-family: "Source Code Pro",Consolas,Menlo,Monaco,"Courier New",monospace
212 | }
213 |
214 | /* 模态框*/
215 |
216 | .model {
217 | position: absolute;
218 | top: 50%;
219 | left: 50%;
220 | z-index: 10;
221 | width: 300px;
222 | height: 100px;
223 | background-color: #fff;
224 | border: 1px solid #eef;
225 | transform: translate(-50%, -50%);
226 | box-shadow: 2px 2px 4px -1px rgba(0, 0, 0, 0.25);
227 | }
228 |
229 | .model-body {
230 | height: 100%;
231 | line-height: 100px;
232 | text-align: center;
233 | }
234 |
235 | .model input {
236 | width: 220px;
237 | height: 30px;
238 | padding-left: 8px;
239 | border: 1px solid #ccc;
240 | border-radius: 8px;
241 | }
242 |
243 | .model input:focus {
244 | border: 1px solid #aaa;
245 | }
246 |
--------------------------------------------------------------------------------