TOEFL Vocabulary List で覚えたワードを消したりテストしたりできるようにするもの

  • /*
     * @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();
    })();
    
    
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2014/04/23 06:13:42 - 2014-04-23
  2. 2014/04/22 22:45:37 - 2014-04-22