Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   100-200 уникальных таймеров на одной странице. (https://javascript.ru/forum/dom-window/39427-100-200-unikalnykh-tajjmerov-na-odnojj-stranice.html)

Aeliot 29.06.2013 18:24

100-200 уникальных таймеров на одной странице.
 
Везде пишут как вывести на странице один таймер. А как вывести на одной странице много (неопределённо неопределённое количество) уникальных таймеров? Есть список задач и напротив каждой из них нужно вывести таймер с дедлайном.

рони 29.06.2013 18:34

Aeliot,
а что мешает вывести 500 таймеров?

Aeliot 29.06.2013 18:48

Цитата:

Сообщение от рони (Сообщение 259187)
Aeliot,
а что мешает вывести 500 таймеров?

отсутствие знаний как это сделать :)

Aeliot 29.06.2013 20:15

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 259190)
Всё можно сделать одним таймером.

спасибо, интересная функция. Буду изучать.

Права, пока не понятно как стартовать все таймеры автоматически при загрузке страницы и как им всем объяснить кто откуда должен брать своё время для дедлайна.

Aeliot 29.06.2013 20:44

да. я пока больше в php и vba разбираюсь.
кое-что писал на javascript, но не много.

на сколько успел разобраться, в вашей функции основная отработка таймера идет в функции "update" и все таймеры хранятся в массиве "timers".

Aeliot 29.06.2013 21:27

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 259197)
не стоит уповать на этот мой старый говнокод, он написан из рук вон плохо. Я просто хотел показать, что всё не так сложно, как кажется на первый взгляд. ;)

На вашем уровне может это и "говнокод", а на моём это пока лучшее, что нашел. :)

Aeliot 29.06.2013 21:36

идея с хешем мне понравилась. Думается это лучше, чем перебирать через foreach все элементы (например, спаны) и обновлять подходящие.
Правда, ещё вопрос сколько такой вариант памяти съест, скажем на 500-а таймерах и не подвесит ли это страницу?

Deff 29.06.2013 21:50

Цитата:

Сообщение от Aeliot
Правда, ещё вопрос сколько такой вариант памяти съест, скажем на 500-а таймерах и не подвесит ли это страницу?

Там единственный таймер: interval = setInterval(update, 100);
Который тестит стек каждые 100мс

Aeliot 29.06.2013 22:34

Цитата:

Сообщение от Deff (Сообщение 259204)
Там единственный таймер: interval = setInterval(update, 100);
Который тестит стек каждые 100мс

Это понятно.
Я про другое.
В хэш "timers" много чего хранится. В функции "add" есть такие строки:
timers[nextId++] = {
      state: "active",
      deadline: now() + duration,
      row: row
    };

где "row" - это фактически строка таблицы примерно такого вида:
<tr class="timer-fired"><td>Вася</td><td>00:00:00</td><td><span class="timer-control">пауза</span><span class="timer-control">удалить</span></td></tr>

Если мы в хеш сохраним 500 таких строк, то это должно как-то сказаться на его производительности. :)

Aeliot 29.06.2013 22:48

Ладно, 500 таймеров на одной странице это возможное, но крайне редкое событие, ток что с памятью будем разбираться потом.

Помогите, пожалуйста, переделать эту функцию под мои нужды.
Мне нужен простой список задач с таймерами напротив каждой и чтобы они самостоятельно стартовали после загрузки страницы. и ни каких кнопок и дополнительных полей.

Deff 29.06.2013 22:48

Aeliot,
Ну вродь по окончании их ремовим...
И по опыту любой Aякс нескольких страниц - глотает памяти много более..., а таких сайтов масса и есть с оч шустрой организацией.. и без зависа браузера несколькими сайтами

Deff 29.06.2013 22:51

Цитата:

Сообщение от Aeliot
Мне нужен простой список задач

Приведите примеры пары тройки функций, с нужными запросами к таймеру,
наверно типично такие
1. Запустить через столько то, функцию такую то, с такими то параметрами

Aeliot 29.06.2013 22:59

Цитата:

Сообщение от Deff (Сообщение 259224)
Приведите примеры пары тройки функций, с нужными запросами к таймеру,
наверно типично такие
1. Запустить через столько то, функцию такую то, с такими то параметрами

Я может не так выразился...
Имеется в виду некий список задач для человека (исполнителя):
1) Пожарить блины (осталось 15 мин, 20 сек...)
2) заварить чаю (осталось 5 мин, 48 сек...)
3) построить дом (осталось 37 дней, 8 часов, 16 мин, 12 сек...)
... и т.д.

Другими словами, загружается с сервера некий список работ и каждая имеет свой дедлайн. Вот время до этого дедлайна и должны показывать таймеры.

Deff 29.06.2013 23:04

Aeliot,
Вопрос такой - подсчет остатков времени нужно выводить на страницу - или чисто запуск функций в очереди ?

Aeliot 29.06.2013 23:06

Нужно просто отобразить оставшееся время пользователю, чтобы он не проспал крайний срок.

Deff 29.06.2013 23:11

Aeliot,
Через час - два -сваяю... если фильмом не увлекусь

vadim5june 29.06.2013 23:21

<!DOCTYPE HTML>
<html>
<table border=1 width=100%>
<tr><td width=80%>пожарить блины</td><td class='time'>15</td></tr>
<tr><td>заварить чай</td><td class='time'>8</td></tr></table>
<script>
setInterval(function(){var els=document.querySelectorAll('.time');
for(var i=0;i<els.length;i++)
{var t=els[i].innerHTML;if(t==0)continue;t--;els[i].innerHTML=t;if(t==0){alert(els[i].parentNode.querySelector('td').innerHTML); els[i].parentNode.style.background='red';}}
},1000)
</script>

Aeliot 29.06.2013 23:23

Цитата:

Сообщение от Deff (Сообщение 259233)
Через час - два -сваяю...

это было бы супер

Aeliot 29.06.2013 23:34

vadim5june
Спасибо. Прикольно работает. Буду развлекаться. :)

vadim5june 29.06.2013 23:47

Цитата:

Сообщение от Aeliot
Буду развлекаться

Развлекайся-я там слегка изменил код

Aeliot 29.06.2013 23:59

vadim5june, спасибо

Deff 30.06.2013 00:03

vadim5june,
Симпатично, но для полного счастья(полноценного API) - интересно возможность динамического добавления/cнятие/изъятия пунктов,
И думаю - формат отображалки - отдельной подключаемой функцией

Aeliot 30.06.2013 00:28

vadim5june,
А можно, чтобы не просто счётчик 1, 2, 3...
а чтобы время указывалось.

vadim5june 30.06.2013 00:55

Цитата:

Сообщение от Deff
Симпатично, но для полного счастья(полноценного API) - интересно возможность динамического добавления/cнятие/изъятия пунктов,
И думаю - формат отображалки - отдельной подключаемой функцией

Ну да-согласен-если есть время напиши
Цитата:

Сообщение от Aeliot
А можно, чтобы не просто счётчик 1, 2, 3...
а чтобы время указывалось.

это время в секундах-нужно написать-а легче найти 2 функции-из секунд-в дни часы минуты-и 2 я функция обратная
и вставить
тогда будет примерно так осталось 2дня 12 часов 34мин 34сек

bes 30.06.2013 01:04

Цитата:

Сообщение от Deff
для полного счастья(полноценного API) - интересно возможность динамического добавления/cнятие/изъятия пунктов,

хотя бы чтобы он останавливался, когда все задачи выполнены :)

Aeliot 30.06.2013 01:14

Если я правильно понимаю, то распарсить вариант "2дня 12 часов 34мин 34сек", чтобы получить время в секундах будет проблематично. Значит используемое время для дедлайна и отображаемое пользователю должны быть внутри разных тегов.

Только у меня ни как не получается взять время из одного тега и положить в другой.

Ни то, чтобы я не знал как это делается (сделать выборку тегов и перебрать их я умею), но что-то не выходит.

Aeliot 30.06.2013 01:23

страница имеет такой код:
<span class="timer-wrp"><span class="time_in">15</span>[<span class="time_out"></span>]</span>


Для начала, так переписал предложенный скрипт:
setInterval(function() {
	myTimer()
}, 1000)

function myTimer() {
	var els = document.querySelectorAll('.timer-wrp');
	for ( var i = 0; i < els.length; i++) {
		
		var el_in = els[i].querySelectorAll('.time_in');
		var el_out = els[i].querySelectorAll('.time_out');
		
		var t = el_in.innerHTML;

		if (t == 0)
			continue;
		t--;

		el_in.innerHTML = t;
		el_out.innerHTML = t;
	}
}


Но почему-то не находит нужных элементов.

Aeliot 30.06.2013 01:43

Как взять и положить значение разобрался
setInterval(function() {
	myTimer()
}, 1000)

function myTimer() {
	var els = document.querySelectorAll('.timer-wrp');
	for ( var i = 0; i < els.length; i++) {
		var el_in = els[i].querySelectorAll('.time_in');
		var el_out = els[i].querySelectorAll('.time_out');
		
		var t = el_in[0].innerHTML;

		if (t == 0)
			continue;
		t--;

		el_in[0].innerHTML = t;
		el_out[0].innerHTML = t;
	}
}


копаюсь дальше

vadim5june 30.06.2013 02:28

вот здесь нашел функцию преобразования
http://snippets.artvolk.sumy.ua/view...-na-javascript
с ней так получается
<!DOCTYPE HTML>
<html>
<table border=1 width=100%>
<tr><td>пожарить блины</td><td 

class='time'>125</td></tr>
<tr><td>заварить чай</td><td 

class='time'>81</td></tr></table>
<script>
setInterval(function(){var els=document.querySelectorAll('.time');
for(var i=0;i<els.length;i++)
{if(!els[i].t)els[i].t=els[i].innerHTML;var t=els[i].t;if(t==0)continue;t--;els[i].innerHTML=toFormattedTime(t,1,1);els[i].t=t;if(t==0){alert(els[i].parentNode.querySelector('td').innerHTML);els[i].parentNode.style.background='red';}}
},1000);
//-------
function toFormattedTime(input, withHours, roundSeconds)
{if (input<=0)return '00:00:00';
    if (roundSeconds)
    {
        input = Math.ceil(input);
    }

    var hoursString = '00';
    var minutesString = '00';
    var secondsString = '00';
    var hours = 0;
    var minutes = 0;
    var seconds = 0;

    hours = Math.floor(input / (60 * 60));
    input = input % (60 * 60);

    minutes = Math.floor(input / 60);
    input = input % 60;

    seconds = input;

    hoursString = (hours >= 10) ? hours.toString() 

: '0' + hours.toString();
    minutesString = (minutes >= 10) ? 

minutes.toString() : '0' + minutes.toString();
    secondsString = (seconds >= 10) ? 

seconds.toString() : '0' + seconds.toString();

    return ((withHours) ? hoursString + ':' : '') 

+ minutesString + ':' + secondsString;
}

</script>

рони 30.06.2013 02:44

Aeliot,
<!DOCTYPE HTML>
<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
</head>
<body>
<span class="timer-wrp"><span class="time_in">15</span>[<span class="time_out"></span>]</span>
 <script>
  setInterval(function() {
	myTimer()
}, 1000)
function myTimer() {
	var els = document.querySelectorAll('.timer-wrp');
	for ( var i = 0; i < els.length; i++) {
		var el_in = els[i].querySelector('.time_in');
		var el_out = els[i].querySelector('.time_out');
		var t = el_out.innerHTML||+el_in.innerHTML+1;
        if (t == 0)continue;
        t--;
        el_out.innerHTML = t;
	}
}
</script>
</body>
</html>

Aeliot 30.06.2013 02:54

Всем большое спасибо за помощь. Работает. :dance:
Выкладываю то, что получилось.

Скрипт:
setInterval(function() {
	myTimer()
}, 1000)

function myTimer() {
	var now = new Date();
	var els = document.querySelectorAll('.timer-wrp');

	for ( var i = 0; i < els.length; i++) {
		var el_in = els[i].querySelectorAll('.time_in');

		var t = parseInputInt(el_in[0]);

		if (t == 0)
			continue;

		t--;

		el_in[0].innerHTML = t;

		var d = Math.floor(t / 86400);
		var h = Math.floor((t - d * 86400) / 3600);
		var m = Math.floor((t - d * 86400 - h * 3600) / 60);
		var s = (t - d * 86400 - h * 3600 - m * 60);

		var t_out = ((d > 0) ? d + ' days ' : '')
				+ (((d > 0) || (h > 0)) ? h + ':' : '')
				+ (((d > 0) || (h > 0) || (m > 0)) ? lid0(m) + ':' : '')
				+ (((d > 0) || (h > 0) || (m > 0) || (s > 0)) ? lid0(s) : '');

		var el_out = els[i].querySelectorAll('.time_show');
		el_out[0].innerHTML = t_out;
	}
}

function parseInputInt(el) {
	var value = el.innerHTML;
	return (value != "") ? parseInt(value, 10) : 0;
}

function lid0(num) {
	return (num < 10) ? '0' + num : num;
}


Код страницы:
<span class="timer-wrp"><span class="time_in">53931</span>[<span class="time_show" title="Time ot deadline"></span>]</span>


CSS:
/** Timer */
span.time_in{
	visibility: hidden;
	display: none;
}

span.time_show{
	color: red;
	font-weight: bold;
}


Если будут предложения по улучшению кода, с радостью прислушаюсь и буду использовать себе во благо. :)

Deff 30.06.2013 03:58

Вродь такая отображалка - попроще ?
<div class="time_show"></div>
<div class="time_show"></div>
<div class="time_show"></div>
<script type="text/javascript">

//Распарс кол-ва секунд в дни и часы/Максимум - 30 дней/
function outViewTime(el,t){
var t1=new Date(0).setUTCMilliseconds(t*1000);
t1=(new Date(t1).toUTCString()).replace(/^.*?(\d+ ).*?(\d{2}:\d{2}:\d{2}).*$/i,"$1$2").split(' ');
el.innerHTML=(t1[0]-1)+' '+t1[1];
}


//Тут, должна быть функция перебора стека текущих остаточных времен;
var el_out = document.querySelectorAll('.time_show');
var t = 2*24*60*60 + 2*60*60 + 51*60 + 21//сек;
var i = 0;
outViewTime(el_out[i],t);

var t = 0*24*60*60 + 6*60*60 + 1*60 + 2//сек;
outViewTime(el_out[1],t);
</script>

vadim5june 30.06.2013 06:47

Цитата:

Сообщение от Aeliot
var el_out = els[i].querySelectorAll('.time_show');
32
        el_out[0].innerHTML = t_out;

можно так
var el_out = els[i].querySelector('.time_show');
el_out.innerHTML = t_out;

bes 30.06.2013 09:26

так кто-нибудь остановит этот таймер :stop:

Deff 30.06.2013 09:48

Цитата:

Сообщение от bes
так кто-нибудь остановит этот таймер

Ну пока он не красив, нужен стек и добавка изъятие из очереди.

По таймеру опрашиваем стек, уменьшаем времена в стеке и выводим, по значению 0 в стеке, очищаем очередь от этого элемента и проверяем стек на нулевую длину, при 0 - сбрасываем таймер.
Собственно задача добавки/изъятия из стека по требованию(тут желательно упорядочить стек по увеличению остаточного времени), нун её добить, поскольку тут возникает и требование повторного перезапуска

Aeliot 30.06.2013 16:47

Цитата:

Сообщение от vadim5june (Сообщение 259290)
можно так
var el_out = els[i].querySelector('.time_show');
el_out.innerHTML = t_out;

Спасибо. Я читал об этом ночью, но что-то не отложилось. :)

Цитата:

Сообщение от bes (Сообщение 259297)
так кто-нибудь остановит этот таймер :stop:

В данном случае (моём), думается, это не принципиально. Таймеры обычно выставляются на 1-3 суток. Все просроченные просто не выводятся при формировании страницы в php. А как долго пользователь находится на странице не обновляя её? 20 секунд? 1-2 минуты? Пусть даже час она провесит у него не обновляясь... Ну закончатся пара таймеров. Это совсем мелкая нагрузка по сравнению в ещё парой сотен таймеров. Это конечно же подход не супер-пупер, но на первое время сойдёт. Кстати, сегодня запустил около 300-а таймеров на одной странице. Всё работает просто огонь. :)

Цитата:

Сообщение от Deff (Сообщение 259301)
Ну пока он не красив, нужен стек и добавка изъятие из очереди.

По таймеру опрашиваем стек, уменьшаем времена в стеке и выводим, по значению 0 в стеке, очищаем очередь от этого элемента и проверяем стек на нулевую длину, при 0 - сбрасываем таймер.
Собственно задача добавки/изъятия из стека по требованию(тут желательно упорядочить стек по увеличению остаточного времени), нун её добить, поскольку тут возникает и требование повторного перезапуска

Это всё конечно же супер, но из-за отсутствия должных знаний сам такого не напишу. Если допилите для общего пользования, думаю, многие скажут вам спасибо.

bes 30.06.2013 18:59

ладно, сам остановлю
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<style>
span {
	padding: 0.3em;
	margin: 0.1em;
}
</style>
<script>
jQuery(function ($) { 
	for (var i = 0; i < 1000; i++) {
		if (i % 50 == 0) {
			$("body").append("<br>");
		}
		$("body").append("<span>" + parseInt(Math.abs(10 * Math.random() - 5 * Math.random())) + "</span>");
	}
	function color() {
		function r() {
			return Math.floor(Math.abs(255 * Math.random()));
		}
		return "rgb(" + r() + "," + r() + "," + r() + ")";
	}
	var spans, len;
	var int = setInterval(function () {
		spans = $("span");
		len = spans.filter(function () {return $(this).html() != 0}).length;
		if (window.console) console.log(len);
		if (len == 0) {
			spans.css("background", "lightgreen");
			clearInterval(int);
			return;
		}
		spans.each(function () {
			if ($(this).html() != 0) {
				$(this).html($(this).html() - 1);
			} else {
				this.style.background =  color();
			}
		});
	}, 1000);
});
</script>


Часовой пояс GMT +3, время: 02:37.