/*
* @title TOEFL Vocabulary List で覚えたワードを消したりテストしたりできるようにするもの
* @description http://www.examword.com/toefl で紹介されている TOEFL Vocabulary List の機能拡張
* @include http://www.examword.com/toefl/practice.aspx
* @license MIT License
* @require
*/
(function(){
var findWords = function(){
var getWordFromElement = function(wordElem){
var content = wordElem.textContent;
return content.replace(/:$/, '');
};
var getExplain = function(wordElem){
for(var n = wordElem.nextSibling;n;n = n.nextSibling){
if(String(n.className) == 'listWordExplanation') return n;
}
return null;
};
var getBRs = function(exp){
var R = [];
for(var n = exp.nextSibling;n;n=n.nextSibling){
if(String(n.tagName).toLowerCase() == 'br')R.push(n);
if(String(n.tagName).toLowerCase() == 'span')break;
}
return R;
};
var R = {};
var words = document.querySelectorAll(".listWordWord");
for(var i=0,l=words.length;i<l;i++){
var target = words[i];
var word = getWordFromElement(target);
var explain = getExplain(target);
var brs = getBRs(explain);
R[word] = {
text: word,
word: target,
explain: explain,
brs: brs
};
}
return R;
};
var detectId = function(){
var getQuery = function(){
var src = location.search;
if(!src || src.length < 3) return {};
var pairs = src.substring(1).split("&");
var R = {};
for(var i=0,l=pairs.length;i<l;i++){
var kv = pairs[i].split("=");
var key = decodeURIComponent(kv[0]);
var val = decodeURIComponent(kv[1]);
R[key]=val;
}
return R;
};
var query = getQuery();
return query.id;
};
var createNote = function(){
var note = {
id: detectId(),
wordsList:findWords(),
session: {memorised:{}},
container: document.querySelector('#core div.ewnormaltextPanel'),
wordContainer: null,
initWordButton: function(s){
var note = this;
var container = document.createElement('div');
var word = s.word;
var exp = s.explain;
var brs = s.brs;
word.parentNode.insertBefore(container, word);
var elems = [word, exp].concat(brs);
for(var i=0,l=elems.length;i<l;i++){
var e = elems[i];
e.parentNode.removeChild(e);
if(String(e.tagName).toLowerCase() == 'br')continue;
container.appendChild(e);
}
s.container = container;
var button = document.createElement('span');
button.appendChild(document.createTextNode('X'));
button.style.cssText = [
'display: inline-blodk;',
'width: 10px;',
'height: 10px;',
'line-height: 8px;',
'font-size: 8px;',
'color: white;',
'background-color: red;',
'border-radius: 5px;',
'font-weight:900;',
'cursor: pointer;'
].join('\n');
button.addEventListener(
'click',
function(){
note.hide(s);
note.learned(s.text);
},
false
);
s.deleteButton = button;
word.insertBefore(document.createTextNode(' '), word.firstChild);
word.insertBefore(button, word.firstChild);
if(this.session.memorised[s.text]){
this.hide(s);
}
},
learned: function(word){
this.session.memorised[word] = true;
this.saveStorage();
},
hide: function(s){
s.container.style.display = 'none';
},
show: function(s){
s.container.style.display = null;
},
loadStorage: function(){
var stored = sessionStorage.getItem(note.id);
if(!stored){
this.session = {
memorised: {}
};
return;
}
var decoded = decodeURIComponent(stored);
this.session = JSON.parse(decoded);
},
saveStorage: function(){
var decoded = JSON.stringify(this.session);
var encoded = encodeURIComponent(decoded);
sessionStorage.setItem(note.id, encoded);
},
initContainer: function(){
this.container.style.width =
this.container.clientWidth + 'px';
},
init: function(){
this.loadStorage();
this.initContainer();
var words = this.wordsList;
for(var w in words){
var s = words[w];
this.initWordButton(s);
}
},
isMemorised: function(s){
return !!this.session.memorised[s.text];
},
update: function(){
var words = this.wordsList;
for(var w in words){
var s = words[w];
if(this.isMemorised(s)){
this.hide(s);
}else{
this.show(s);
}
}
},
reset: function(){
this.session.memorised = {};
this.saveStorage();
if(this.savedFragment){
this.endQuestion();
}else{
this.update();
}
},
getMemorised: function(){
var tmp = this.session.memorised;
var R = [];
for(var f in tmp) R.push(f);
return R;
},
examine: function(){
var memorised = this.getMemorised();
if(memorised.length < 1){
alert('You memorised no words.');
return;
}
var shuffle = function(a) {
var i = a.length, j, temp;
if ( i == 0 ) return;
while ( --i ) {
j = Math.floor( Math.random() * ( i + 1 ) );
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
};
shuffle(memorised);
this.questions = memorised;
var frgn = document.createDocumentFragment();
var cont = this.container;
while(cont.firstChild){
var e = cont.firstChild;
cont.removeChild(e);
frgn.appendChild(e);
}
this.savedFragment = frgn;
this.nextQuestion();
},
nextQuestion: function(){
var word = this.questions.shift();
if(!word){
this.endQuestion();
return;
}
this.container.innerHTML = '';
var s = this.wordsList[word];
var input = document.createElement('input');
var self = this;
input.addEventListener(
'keyup',
function(ev){
if(ev.keyCode != 13) return;
self.checkAnswer(s, input.value);
}
);
var exp = s.explain.cloneNode(true);
exp.style.display = 'block';
this.container.appendChild(input);
this.container.appendChild(exp);
input.focus();
},
checkAnswer: function(s, answer){
if(s.text != answer){
delete this.session.memorised[s.text];
this.saveStorage();
this.container.style.background = '#FCC';
this.container.innerHTML = '';
this.container.appendChild(document.createTextNode(s.text));
var exp = s.explain.cloneNode(true);
exp.style.display = 'block';
this.container.appendChild(exp);
var self = this;
var lstnr = function(){
self.container.style.background = null;
self.nextQuestion();
self.container.removeEventListener('click',lstnr, false );
};
this.container.addEventListener( 'click',lstnr, false );
}else{
this.nextQuestion();
}
},
endQuestion: function(){
this.container.innerHTML = '';
this.container.appendChild(this.savedFragment);
delete this.questions;
delete this.savedFragment;
this.update();
}
};
return note;
};
var createControler = function(note){
var genButton = function(title, action){
var span = document.createElement('span');
span.appendChild(document.createTextNode(title));
span.addEventListener('click', action, false);
var csstext = Array.prototype.slice.apply(
arguments, [2]
).join("\n");
span.style.cssText = csstext;
span.style.display = 'inline-table';
span.style.margin = '2px';
span.style.padding = '1px 3px';
span.style.borderRadius = '3px';
span.style.cursor = 'pointer';
return span;
};
var initGUI = function(ctrl){
var container = document.querySelector('div#core td.rdtop_title');
var reset = genButton(
'reset', function(){
if(confirm('really?')) ctrl.reset();
},
'background-color: red;',
'color: white;'
);
var exam = genButton(
'examine', function(){
ctrl.examine();
},
'background-color: green;',
'color:white;'
);
container.appendChild(exam);
container.appendChild(reset);
};
var ctrl = {
note: note,
reset: function(){
this.note.reset();
},
examine: function(){
this.note.examine();
},
init: function(){
initGUI(this);
}
};
return ctrl;
};
var main = function(){
var note = createNote();
var ctrl = createControler(note);
note.init();
ctrl.init();
};
main();
})();