2016-07-26 4 views
0

Я пытаюсь использовать шаблон раскрывающегося модуля вместе с шаблоном конструктора, чтобы создать несколько красивых JS! Я хочу иметь возможность создавать несколько экземпляров, если «Обратный отсчет» выглядит следующим образом:это не определено в шаблоне модуля

var c1 = new Countdown(); 
c1.init(); 
var c2 = new Countdown(); 
c2.init(); 

Они должны быть независимыми. Поэтому вместо объявления переменных с «var» я использую «this» в прототипе. Я ссылаюсь на «это» внутри функции, но она не определена. Как я могу получить доступ к «этому»?

var Countdown = function() {}; 

Countdown.prototype = (function(doc) { 

    return { 
     init: init 
    }; 

    function init() { 
     // day 
     this.d1 = doc.createElement('div'); 
     this.d1.setAttribute('class', 'day-1 elem'); 

     // ... more elements left out here 
    } 

    function updateView(time) { 
     this.d1.textContent = getDays(secs)[0]; 
    } 

    function getDays(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = secs/(60 * 60 * 24); 
     } 

     return Math.floor(result); 
    } 

})(document); 

--- EDIT ---

Вот мой полный код:

"use strict"; 

var Countdown = function() { 
    //this.self = this; 
}; 

Countdown.prototype = (function(doc) { 

    return { 
     initialize: initialize 
    }; 

    function createElements() { 
     var countdown = doc.createElement('div'); 
     countdown.setAttribute('class', 'countdown'); 

     var heading = doc.createElement('h2'); 
     heading.textContent = 'Countdown'; 
     countdown.appendChild(heading); 
     document.body.appendChild(countdown); 



     // day 
     var wrapDay = doc.createElement('div'); 
     wrapDay.setAttribute('class', 'wrap-day'); 
     countdown.appendChild(wrapDay); 

     this.d1 = doc.createElement('div'); 
     this.d1.setAttribute('class', 'day-1 elem'); 
     wrapDay.appendChild(this.d1); 

     this.d2 = doc.createElement('div'); 
     this.d2.setAttribute('class', 'day-2 elem'); 
     wrapDay.appendChild(this.d2); 

     var lblDay = doc.createTextNode('dage'); 
     wrapDay.appendChild(lblDay); 

     var sepDay = doc.createElement('div'); 
     sepDay.setAttribute('class', 'separator'); 
     sepDay.textContent = ':'; 
     countdown.appendChild(sepDay); 



     // hour 
     var wrapHour = doc.createElement('div'); 
     wrapHour.setAttribute('class', 'wrap-hour'); 
     countdown.appendChild(wrapHour); 

     this.h1 = doc.createElement('div'); 
     this.h1.setAttribute('class', 'hour-1 elem'); 
     wrapHour.appendChild(this.h1); 

     this.h2 = doc.createElement('div'); 
     this.h2.setAttribute('class', 'hour-2 elem'); 
     wrapHour.appendChild(this.h2); 

     var lblHour = doc.createTextNode('timer'); 
     wrapHour.appendChild(lblHour); 

     var sepHour = doc.createElement('div'); 
     sepHour.setAttribute('class', 'separator'); 
     sepHour.textContent = ':'; 
     countdown.appendChild(sepHour); 



     // min 
     var wrapMin = doc.createElement('div'); 
     wrapMin.setAttribute('class', 'wrap-min'); 
     countdown.appendChild(wrapMin); 

     this.m1 = doc.createElement('div'); 
     this.m1.setAttribute('class', 'min-1 elem'); 
     wrapMin.appendChild(this.m1); 

     this.m2 = doc.createElement('div'); 
     this.m2.setAttribute('class', 'min-2 elem'); 
     wrapMin.appendChild(this.m2); 

     var lblMin = doc.createTextNode('minutter'); 
     wrapMin.appendChild(lblMin); 

     var sepMin = doc.createElement('div'); 
     sepMin.setAttribute('class', 'separator'); 
     sepMin.textContent = ':'; 
     countdown.appendChild(sepMin); 



     // sec 
     var wrapSec = doc.createElement('div'); 
     wrapSec.setAttribute('class', 'wrap-sec'); 
     countdown.appendChild(wrapSec); 

     this.s1 = doc.createElement('div'); 
     this.s1.setAttribute('class', 'sec-1 elem'); 
     wrapSec.appendChild(this.s1); 

     this.s2 = doc.createElement('div'); 
     this.s2.setAttribute('class', 'sec-2 elem'); 
     wrapSec.appendChild(this.s2); 

     var lblSec = doc.createTextNode('sekunder'); 
     wrapSec.appendChild(lblSec); 
    } 

    function initialize() { 
     domReady(function() { 

      // create DOM 
      createElements(); 

      // get time 
      var now = new Date(); 
      var year = now.getFullYear(); 
      var month = now.getMonth(); 
      var dateFinal = new Date(year, month + 1, 1, 0, 0, 0); // first day next month 
      var seconds = getSecsLeft(dateFinal); 
      var time = getTimeLeftObject(seconds); 

      // update view every second 
      setInterval(function() { 
       seconds = getSecsLeft(dateFinal); 
       time = getTimeLeftObject(seconds); 
       updateView(time); 
      }, 1000); 

      // first time 
      updateView(time); 
     }); 
    } 

    function updateView(time) { 
     var days = zeroPadding(time.days); 
     var hours = zeroPadding(time.hours); 
     var mins = zeroPadding(time.mins); 
     var secs = zeroPadding(time.secs); 

     this.d1.textContent = days[0]; 
     this.d2.textContent = days[1]; 

     this.h1.textContent = hours[0]; 
     this.h2.textContent = hours[1]; 

     this.m1.textContent = mins[0]; 
     this.m2.textContent = mins[1]; 

     this.s1.textContent = secs[0]; 
     this.s2.textContent = secs[1]; 
    } 

    function getDays(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = secs/(60 * 60 * 24); 
     } 

     return Math.floor(result); 
    } 
    function getHours(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = (secs/(60*60)) % 24; 
      result = result === 24 ? 0 : result; 
     } 

     return Math.floor(result); 
    } 
    function getMins(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = (secs/60) % 60; 
      result = result === 60 ? 0 : result; 
     } 

     return Math.floor(result); 
    } 
    function getSecs(secs) { 
     var result = 0; 
     if (secs > 0) { 
      result = secs % 60; 
      result = result === 60 ? 0 : result; 
     } 

     return Math.floor(result); 
    } 

    function zeroPadding(num) { 
     var result; 
     result = num < 10 ? "0" + num : num; 

     return new String(result); 
    } 

    function getTimeLeftObject(seconds) { 
     var secs = getSecs(seconds); 
     var mins = getMins(seconds); 
     var hours = getHours(seconds); 
     var days = getDays(seconds); 

     return { 
      days: days, 
      hours: hours, 
      mins: mins, 
      secs: secs 
     }; 
    } 

    function getSecsLeft(dateFinal) { 
     var result = (dateFinal - new Date())/1000; 
     return result < 0 ? 0 : result; 
    } 

    function domReady(callback) { 
     document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback); 
    } 

})(document); 
+0

ли вы имеете в виду вы хотите позвонить 'updateView' внутри' init' функции? Если да, используйте 'updateView.call (this, 100)' –

+0

Я обновляю текст каждую секунду с помощью таймера интервала (код опущен) – olefrank

+0

Я думаю, вам просто нужно вызвать this.init() в конструкторе Countdown? Я не уверен, чего вы пытаетесь достичь ... Потому что для меня это должно быть определено, я его протестировал, и он работает ... –

ответ

4

Кажется, что вы звоните updateView в setInterval

function init() { 
    // day 
    this.d1 = doc.createElement('div'); 
    this.d1.setAttribute('class', 'day-1 elem'); 

    var update = updateView.bind(this); // you need to bind updateView context 
    setInterval(function() { 
     var time = ??? 
     update(time); // `this` will be current instance 
    }, 1000) 
} 

UPD Поскольку вы устанавливают интервал от domReady вы должны либо привязать сам обратный вызов, либо связать updateView перед началом работы.

function initialize() { 
    domReady(function() { 

     // create DOM 
     createElements.call(this); // call with current context 

     // get time 
     var now = new Date(); 
     var year = now.getFullYear(); 
     var month = now.getMonth(); 
     var dateFinal = new Date(year, month + 1, 1, 0, 0, 0); // first day next month 
     var seconds = getSecsLeft(dateFinal); 
     var time = getTimeLeftObject(seconds); 

     var update = updateView.bind(this); 

     // update view every second 
     setInterval(function() { 
      seconds = getSecsLeft(dateFinal); 
      time = getTimeLeftObject(seconds); 
      update(time); 
     }, 1000); 

     // first time 
     update(time); 
    }.bind(this)); //bind callback 
} 

Или

function initialize() { 
    var update = updateView.bind(this), 
     create = createElements.bind(this); // prebind functions that use this 
    domReady(function() { 

     // create DOM 
     create(); //call prebinded function 

     // get time 
     var now = new Date(); 
     var year = now.getFullYear(); 
     var month = now.getMonth(); 
     var dateFinal = new Date(year, month + 1, 1, 0, 0, 0); // first day next month 
     var seconds = getSecsLeft(dateFinal); 
     var time = getTimeLeftObject(seconds); 

     // update view every second 
     setInterval(function() { 
      seconds = getSecsLeft(dateFinal); 
      time = getTimeLeftObject(seconds); 
      update(time); 
     }, 1000); 

     // first time 
     update(time); 
    }); 
} 
+0

well spotted (хорошо, понял - на вопрос не было, просто комментарии!) – Jamiec

+0

ohhh ok now Я понимаю вопрос! Nice;) –

+0

Как раз для моих собственных интересов, почему вам нужно связать 'this' с функцией' updateView'? – LeDoc