Задать вопрос

Как сделать счетчик через ООП?

Здравствуйте, делаю счетчик событий, так сказать улучшаю, но то ли не могу сообразить то ли еще хуже, я не могу понять как его переписать на ООП, всё что я смог, получилось вот:

https://pastebin.com/ap3icrqc

Есть вполне себе рабочий код:
;
// берем все счетчики с сайта
var counter = document.querySelectorAll(".counter");
// если счетчик имеется берем переменные и работаем с ними
if(counter){
    // берем у всех счетчиков их значения
    for(var c=0;c<counter.length;c++){
        if(counter[c].dataset.event){
            var counter_event = counter[c].dataset.event;
            counter_event = counter_event.replace(/\s/g, "");
        }
        if(counter[c].dataset.background){
            var counter_theme = counter[c].dataset.background;
            counter_theme = counter_theme.replace(/\s/g, "");
            // приравниваем старые значения счетчика к новым
            switch(counter_theme){
                case "dark300":
                    counter_theme = "dark";
                    break;
                case "light300":
                    counter_theme = "light";
                    break;
                default:
                    break;
            }
        }
        else if(counter[c].dataset.theme){
            var counter_theme = counter[c].dataset.theme;
            counter_theme = counter_theme.replace(/\s/g, "");
        }
        if(counter[c].dataset.day){
            var counter_date = counter[c].dataset.day;
            counter_date = counter_date.replace(/\s/g, "");
        }
        else if(counter[c].dataset.date){
            var counter_date = counter[c].dataset.date;
            counter_date = counter_date.replace(/\s/g, "");
        }
        if(counter[c].dataset.link){
            var counter_link = counter[c].dataset.link;
            counter_link = counter_link.replace("/\s/g", "");
        }
        // вызываем метод создания счетчика для каждого элемента
        counter[c].appendChild(makeCounter(counter_theme, counter_event, counter_date, counter_link));
    }
    // метод создания шаблона счетчика
    function makeCounter(theme, event, date, link){
        // создаем основную обертку и обертку для самого счетчика
        var block = document.createElement("div");
        if(block){
            // создаем переменную для пути к стилевому файлу счетчика
            var styles = document.createElement("link");
            if(styles){
                styles.href = "j/css/counter/"+event+"/"+theme+".css";
                styles.rel = "stylesheet";
                // добавляем подключение стилей счетчика в head
                document.querySelectorAll("head")[0].appendChild(styles);
            }
            block.className = event+"-"+theme+" template";
            var timer_if = new Date(date.replace(/(\d+).(\d+).(\d+)/, '$3/$2/$1')) - new Date();
            if (timer_if <= 0){
                block.className = event+"-"+theme+" template zero";
            }
            else{
                var wrap = document.createElement("div");
                if(wrap){
                    wrap.className = "counter-wrap";
                    // создаем структуру счетчика
                    block.appendChild(wrap);
                }
                // добавляем ссылку на счетчик, если она у нас указана в нем
                if(link){
                    var linker = document.createElement("a");
                    linker.className = "counter-link";
                    linker.href = link;
                    linker.target = "_blank";
                    block.appendChild(linker);
                }
                // переменная для условия, при котором у нас счетчик приходит в 0
                var resetCount={
                    obj:null
                };
                // вызываем функцию создания обратного отсчета
                var timer = setInterval(makeCount.bind(this, wrap, date, resetCount), 1000);
                // стоп точка, чтобы дальше 0 не отсчитывать
                resetCount.obj = timer;
            }
        }
        // генерируем счетчик
        return block;
    }
    // создаем функцию генерации обратного отсчета
    function makeCount(layout, timecount, reset){
        // берем дату и преобразуем ее в нужный для работы с ней формат
        var now = new Date();
        var event_date = new Date(timecount.replace(/(\d+).(\d+).(\d+)/, '$3/$2/$1'));
        // вычисляем разницу от даты события до сегодня
        var distance = event_date - now;
        // вычисляем сколько дней, часов, минут и секунд осталось до события
        var counter_time =
            {
                days:Math.floor(distance / (1000 * 60 * 60 * 24)),
                hours:Math.floor(distance % (1000 * 60 * 60 * 24) / (1000 * 60 * 60)),
                mins:Math.floor(distance % (1000 * 60 * 60) / (1000 * 60)),
                secs:Math.floor(distance % (1000 * 60) / 1000)
            };
        // если дни, часы, минуты, секунды меньше 10, то мы спереди для них добавляем 0, вместо "9" например должно быть "09"
        for(var i in counter_time){
            if(counter_time[i] < 10){
                counter_time[i] = "0" + counter_time[i];
            }

        };
        // если мы достигаем по счетчику 0:00:00, то скрываем и сбрасываем отсчет
        if(distance <= 0){
            layout.style.display = "none";
            if(reset.obj!==null){
                clearInterval(reset.obj);
            }
        }
        // вставляем время в счетчик
        layout.innerHTML =
            '<div id="days" class="inline"> '+counter_time.days+' <span>:</span> </div><div id="hours" class="inline">'+counter_time.hours+' <span>:</span> </div><div id="mins" class="inline">'+counter_time.mins+' <span>:</span> </div><div id="secs" class="inline">'+counter_time.secs+'</div>';
    }
}


Но хоть ты тресни не могу переписать на ООП, а очень хочется.

Проблема у меня возникает очень глупая, а именно как сделать инкремент?

В рабочем примере я это реализовал через две функции - в одной вызываю и инкрементирую вторую.

Но дело в том, что есть условие:
if(distance <= 0){
    // показывать один код
}
else{
    // показывать другой код
}


И в функции, которую я инкрементирую, та же самая переменная снова объявляется.

Вопрос: можно ли как-то избежать повтора? И как без повтора реализовать ООП подход?

Буду благодарен за любую помощь!
  • Вопрос задан
  • 672 просмотра
Подписаться 4 Простой 9 комментариев
Решения вопроса 1
And__Smi
@And__Smi Автор вопроса
Благодаря одному пользователю данного сайта, который удалил свой ответ, видимо (не знаю зачем, а потом еще говорят, гугли, когда люди чистят за собой), я привел свой код к такому решению и это еще не окончательное, в планах создать еще два метода - для counter_time и для layout.innerHTML. Пока не соображу как, вот решение, которое меня устроило, но не до конца, о чем я упомянул выше:
;
var counterList = document.querySelectorAll(".counter");
function myCounter(counterEl){
    this.counter = counterEl;
    this.init = function(){
        var counter_event;
        var counter_theme;
        var counter_date;
        var counter_link;

        if(this.counter.hasAttribute("data-event")){
            counter_event = this.counter.getAttribute("data-event").replace(/\s/g, '');
        }
        if(this.counter.hasAttribute("data-theme")){
            counter_theme = this.counter.getAttribute("data-theme").replace(/\s/g, '');
        }
        else if(this.counter.hasAttribute("data-background")){
            counter_theme = this.counter.getAttribute("data-background").replace(/\s/g, '');
        }
        if(this.counter.hasAttribute("data-date")){
            counter_date = this.counter.getAttribute("data-date").replace(/\s/g, '');
        }
        else if(this.counter.hasAttribute("data-day")){
            counter_date = this.counter.getAttribute("data-day").replace(/\s/g, '');
        }
        if(this.counter.hasAttribute("data-link")){
            counter_link = this.counter.getAttribute("data-link").replace(/\s/g, '');
        }

        var counterChild = this.makeCounter(counter_event, counter_theme, counter_date, counter_link);
        this.counter.appendChild(counterChild);
    };
    this.makeCounter = function(theme, event, day, link){
        var block = document.createElement("div");
        var styles = document.createElement("link");

        if(styles){
            styles.href="j/css/counter"+ "/" + theme + "/" + event + ".css";
            styles.rel = "stylesheet";

            document.querySelectorAll("head")[0].appendChild(styles);
        }

        if(block){
            block.className = theme + "-" + event + " template";

            var timerIf = new Date(day.replace(/(\d+).(\d+).(\d+)/, '$3/$2/$1')) - new Date();
            if(timerIf <= 0){
                block.className += " zero";
            }
            else{
                var wrap = document.createElement("div");
                if(wrap){
                    wrap.className = "counter-wrap";

                    block.appendChild(wrap);
                }
            }

            if(link){
                var linker = document.createElement("a");
                if(linker){
                    linker.className = "counter-link";
                    linker.href=link;
                    linker.target="_blank";

                    block.appendChild(linker);
                }
            }

            var resetCount = {
                obj: null
            };

            var timer = setInterval(this.makeCount.bind(this, wrap, day, resetCount), 1000);

            resetCount.obj = timer;
        }

        return block;
    };
    this.makeCount = function(layout, timecount, reset){
        var now = new Date();
        var eventDate = new Date(timecount.replace(/(\d+).(\d+).(\d+)/, '$3/$2/$1'));
        var distance = eventDate - now;

        var counterTime = {
            days: Math.floor(distance / (1000 * 60 * 60 * 24)),
            hours: Math.floor(distance % (1000 * 60 * 60 * 24) / (1000 * 60 * 60)),
            mins: Math.floor(distance % (1000 * 60 * 60) / (1000 * 60)),
            secs: Math.floor(distance % (1000 * 60) / 1000)
        };

        for(var i in counterTime){
            if(counterTime[i] < 10){
                counterTime[i] = "0" + counterTime[i];
            }
        }

        if(distance <= 0){
            if(reset.obj !== null){
                clearInterval(reset.obj);
            }
        }
        else{
            layout.innerHTML = '<div id="days" class="inline">'+counterTime.days+'<span>:</span></div>';
            layout.innerHTML += '<div id="hours" class="inline">'+counterTime.hours+'<span>:</span></div>';
            layout.innerHTML += '<div id="mins" class="inline">'+counterTime.mins+'<span>:</span></div>';
            layout.innerHTML += '<div id="secs" class="inline">'+counterTime.secs+'</div>';
        }
    };
}

for(var c = 0; c<counterList.length; c++){
    var counter = new myCounter(counterList[c]);
    counter.init();
}


Если есть у кого что сказать по коду, как можно было бы оформить еще лучше, я не против послушать и пообщаться на данную тематику. Сразу оговорюсь заранее (я до этого не сказал), код пишется исключительно под ие8+ и никак иначе. Все новомодные штучки, к сожалению, приходится избегать, включая const, let, class.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
23 дек. 2024, в 09:41
5000 руб./за проект
23 дек. 2024, в 09:39
1000000 руб./за проект