Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 39 additions & 32 deletions homework/content.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,44 @@
'use strict';

(function() {
var _wrapper = document.querySelector('#note-content-wrapper');
(function(exports) {
var NoteContentManager = function() {
this._wrapper = document.querySelector('#note-content-wrapper');
};

function start() {
window.addEventListener('note-open', function(event) {
var note = event.detail;
resetWrapper();
drawNote(note);
});
}
NoteContentManager.prototype = {
start() {
window.addEventListener('note-open', function(event) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to use addEventListener('note-open', this) instead of binding on a function, since in this way all events could be redirected to this.handleEvent, and the this keyword in that method will refer to the instance you want to bind.

See this:
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Example

var note = event.detail;
this.resetWrapper()
.then((function(){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, you can use Arrow function instead of binding every thing.
See:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

this.drawNote(note);
}).bind(this));
}.bind(this));
},

resetWrapper() {
this._wrapper.innerHTML = '';
return Promise.resolve();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well there is no need to use Promise here.

},

function resetWrapper() {
_wrapper.innerHTML = '';
}
drawNote(note) {
var title = note.title;
var h = document.createElement('h2');
h.textContent = title;
var passages = note.passages;
var buff = document.createDocumentFragment();
passages.forEach(function(passage) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to see the forEach.

var p = document.createElement('p');
p.classList.add('note-passage');
p.textContent = passage;
buff.appendChild(p);
});
this._wrapper.appendChild(h);
this._wrapper.appendChild(buff);
}

};

exports.NoteContentManager = NoteContentManager;

function drawNote(note) {
var title = note.title;
var h = document.createElement('h2');
h.textContent = title;
var passages = note.passages;
var buff = document.createDocumentFragment();
passages.forEach(function(passage) {
var p = document.createElement('p');
p.classList.add('note-passage');
p.textContent = passage;
buff.appendChild(p);
});
_wrapper.appendChild(h);
_wrapper.appendChild(buff);
}

document.addEventListener('DOMContentLoaded', function(event) {
start();
});
})();
})(window);
3 changes: 2 additions & 1 deletion homework/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
<head>
<meta charset="UTF-8">
<title> Homework - Note List </title>
<script defer src="list.js"></script>
<script defer src="main.js"></script>
<script src="list.js"></script>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's recommended to use defer to avoid blocking page loading.

<script defer src="content.js"></script>
<link rel="stylesheet" type="text/css" href="main.css" />
</head>
Expand Down
159 changes: 86 additions & 73 deletions homework/list.js
Original file line number Diff line number Diff line change
@@ -1,79 +1,92 @@
'use strict';

(function() {
(function(exports) {
var TodoListManager = function() {
this._listNoteContent = [];
this._wrapper = document.querySelector('#note-list-wrapper');
};

var _listNoteContent = [];
var _wrapper = document.querySelector('#note-list-wrapper');
TodoListManager.prototype = {
start() {
this.fetchList(function(data) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arrow function is better.

this.updateList(data)
.then((function(){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use .then(this.drawList.bind(this)) to improve the expressiveness.

this.drawList();
}).bind(this)).then((function(){
this.preloadFirstNote();
}).bind(this)).catch((function(error){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't catch error and then silent it if you don't know what you're doing. Think about that: if an error really occur, you chain will eat it without any message. And the following chain will execute as usual. It could devastate your debugging strategy and cause lots of pain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And please be careful: this is a serious issue which definitely deserve a review- if you're working and set the review for this patch.

}).bind(this));
}.bind(this));


window.addEventListener('click', function(event) {
this.onNoteOpen(event);
}.bind(this));
},

onNoteOpen(event) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's a convention to prefix with on to handle the corresponding event, rather than to fire it. So, you should rename this function as onClick and to dispatch the note-open.

if (event.target.classList.contains('note-title')) {
var id = event.target.dataset.noteId;
var content = this._listNoteContent[id];
window.dispatchEvent(new CustomEvent('note-open',{ detail: content }));
};
},

preloadFirstNote() {
if (this._listNoteContent.length !== 0) {
var content = this._listNoteContent[0];
window.dispatchEvent(new CustomEvent('note-open',{ detail: content }));
}
return Promise.resolve();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well even for the demo purpose you don't need to "Promisified" every method, although I know I once mentioned that we now have a final strategy to make every method as a Promise. However, the premise was you firstly know why you need that, so that you can explain the strategy for your reviewer if it's necessary.

},

updateList(list) {
this._listNoteContent = list;
return Promise.resolve();
},

drawList() {
var list = this._listNoteContent;
var ul = document.createElement('ul');
ul.id = 'note-title-list';
var buff = document.createDocumentFragment();
list.forEach(function(note, i) {
var li = document.createElement('li');
li.dataset.noteId = i;
li.classList.add('note-title');
li.textContent = note.title;
// Note: buff is captured, so we now have a
// little closure naturally.
buff.appendChild(li);
});
ul.appendChild(buff);
this._wrapper.appendChild(ul);
return Promise.resolve();
},

fetchList(afterFetch) {
return new Promise((function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1/hw1/demo-list-notes.json', true);
xhr.responseType = 'json';
xhr.onreadystatechange = function(e) {
// Watch out: we have a mysterious unknown 'this'.
if (this.readyState === 4 && this.status === 200) {
var listData = this.response;
// The flow ends here.
afterFetch(listData);
} else if (this.status !== 200 ){
// Ignore error in this case.
}
}.bind(xhr);
xhr.send();
}).bind(this));
}

};

function start() {
fetchList(function(data) {
updateList(data);
drawList();
preloadFirstNote();
});
window.addEventListener('click', function(event) {
onNoteOpen(event);
});
}
exports.TodoListManager = TodoListManager;

function onNoteOpen(event) {
if (event.target.classList.contains('note-title')) {
var id = event.target.dataset.noteId;
var content = _listNoteContent[id];
window.dispatchEvent(new CustomEvent('note-open',
{ detail: content }));
};
}


function preloadFirstNote() {
if (_listNoteContent.length !== 0) {
var content = _listNoteContent[0];
window.dispatchEvent(new CustomEvent('note-open',
{ detail: content }));
}
}

function updateList(list) {
_listNoteContent = list;
}

function drawList() {
var list = _listNoteContent;
var ul = document.createElement('ul');
ul.id = 'note-title-list';
var buff = document.createDocumentFragment();
list.forEach(function(note, i) {
var li = document.createElement('li');
li.dataset.noteId = i;
li.classList.add('note-title');
li.textContent = note.title;
// Note: buff is captured, so we now have a
// little closure naturally.
buff.appendChild(li);
});
ul.appendChild(buff);
_wrapper.appendChild(ul);
}

function fetchList(afterFetch) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/demo-list-notes.json', true);
xhr.responseType = 'json';
xhr.onreadystatechange = function(e) {
// Watch out: we have a mysterious unknown 'this'.
if (this.readyState === 4 && this.status === 200) {
var listData = this.response;
// The flow ends here.
afterFetch(listData);
} else if (this.status !== 200 ){
// Ignore error in this case.
}
};
xhr.send();
}

document.addEventListener('DOMContentLoaded', function(event) {
start();
});

})();
})(window);
6 changes: 6 additions & 0 deletions homework/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
document.addEventListener('DOMContentLoaded', function(event) {
var todoListManager = new TodoListManager();
var noteContentManager = new NoteContentManager();
todoListManager.start();
noteContentManager.start();
});
18 changes: 17 additions & 1 deletion homework/test/test-list.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
var MathFunc=function(){};

MathFunc.prototype = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to register this method in the manager, rather than just write it in the test file.


addNumber: function(a,b){
return (a+b);
}
};


var assert= require("assert");
describe('Test > ', function() {
beforeEach(function() {
mathFunc = new MathFunc();
});

it('will test some pure functions', function() {
it('will add two numbers', function() {
assert.equal(16,mathFunc.addNumber(15, 1));

// Write any pure function assertion here.
});
});