Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Событие при каждом третьем посещении (https://javascript.ru/forum/events/77600-sobytie-pri-kazhdom-tretem-poseshhenii.html)

Alexodiy 25.05.2019 10:55

Событие при каждом третьем посещении
 
Доброго времени суток, уважаемые форумчане.

Не понимаю как запустить событие при каждом третьем посещении страницы.

Хочу использовать для этого LocalStorage и sessionStorage. Может кто подсказать, показать пример как этого добиться.

рони 25.05.2019 12:32

localStorage и sessionStorage счётчик посещений
 
Alexodiy,
document.addEventListener("DOMContentLoaded", function() {
    var num = localStorage.getItem("num") || 0,
        today = sessionStorage.getItem("today");
    if(today === "yes") return;
    sessionStorage.setItem("today", "yes");
    num = +num + 1;
    localStorage.setItem("num", ""+num);
    if(num % 3 === 0 ) alert("3");
});

Alexodiy 25.05.2019 15:08

Цитата:

Сообщение от рони (Сообщение 508267)
Alexodiy,
document.addEventListener("DOMContentLoaded", function() {
    var num = localStorage.getItem("num") || 0,
        today = sessionStorage.getItem("today");
    if(today === "yes") return;
    sessionStorage.setItem("today", "yes");
    num = +num + 1;
    localStorage.setItem("num", ""+num);
    if(num % 3 === 0 ) alert("3");
});

Я смысл понял, но данный код почему то не работает.

Malleys 25.05.2019 15:31

Цитата:

Сообщение от Alexodiy
Я смысл понял, но данный код почему то не работает.

Он работает... он срабатывает на третий раз, если открывать вкладку... Кстати можно попроще... (нажмите запустить и закройте вкладку, откройте снова нажмите запустить... на третий раз сработает)
<script>
	document.addEventListener("DOMContentLoaded", function() {
		var num = Number(localStorage.num) || 0;
		if(sessionStorage.today === "yes") return;
		sessionStorage.today = "yes";
		localStorage.num = ++num;
		if(num % 3 === 0) alert("3");
	});
</script>


если вам надо при третьем обновлении страницы, то можно так... (нажмите три раза кнопку запустить)
<script>
	document.addEventListener("DOMContentLoaded", function() {
		var num = Number(localStorage.num) || 0;
		localStorage.num = ++num;
		if(num % 3 === 0) alert("3");
	});
</script>

Alexodiy 25.05.2019 16:15

да работает, спасибо. а можно ли остановить выполнение например по клику по кнопке? это получается просто переменную num переписать?

Или объявить новый localStorageи на него завязать, если например кликнули по кнопке, то больше ничего не делаем, а если не нажимали прогнем выше написанное условие

Malleys 25.05.2019 16:20

Вы имеете в виду, чтобы при нажатии на кнопку вообще больше не запускалось?

Вот пример с возможностью включения и отключения запуска... Если на кнопке стоит галочка, то оно запускается через три раза, если не стоит галочка, то не запускается
<script>
	document.addEventListener("DOMContentLoaded", function() {
		var checkbox = document.getElementById("toggle-launch");
		checkbox.addEventListener("change", function() {
			localStorage.launch = checkbox.checked;
			
			if(!checkbox.checked) localStorage.num = 0;
		});
		if("launch" in localStorage) {
			checkbox.checked = localStorage.launch === "true";
		} else {
			localStorage.launch = checkbox.checked;
		}
		
		if(!checkbox.checked) return;
		
		var num = Number(localStorage.num) || 0;
		localStorage.num = ++num;
		if(num % 3 === 0) alert("3");
	});
</script>

<label><input type="checkbox" id="toggle-launch" checked>Запускать</label>
<script></script>

Alexodiy 25.05.2019 16:38

Да именно, только по клику по линку, а не через инпут. Спасибо, я все пнял.

Malleys 25.05.2019 16:44

Цитата:

Сообщение от Alexodiy
только по клику по линку

Это совершенно неправильно так делать! Используйте либо <button> либо <input>. Ссылка <a> предназначена, чтобы совершать переход на другой документ, здесь такого нет, поэтому используйте подходящий элемент! (кнопку или чек-бокс, чтобы показать текущее состояние!)

Также насчёт обмана и заблуждении, в которые вас ввели: на самом деле эти элементы могут быть стилизованы при помощи CSS!

Alexodiy 25.05.2019 16:55

Malleys, так у меня и планируется переход на другой документ. Смысл такой, по событию падают уведомляшки с просьбой перейти на другую страницу, так вот если пользователь переходит, то эти уведомления я отрубаю.

Alexodiy 25.05.2019 21:12

Цитата:

Сообщение от Malleys (Сообщение 508280)
Это совершенно неправильно так делать! Используйте либо <button> либо <input>. Ссылка <a> предназначена, чтобы совершать переход на другой документ, здесь такого нет, поэтому используйте подходящий элемент! (кнопку или чек-бокс, чтобы показать текущее состояние!)

Также насчёт обмана и заблуждении, в которые вас ввели: на самом деле эти элементы могут быть стилизованы при помощи CSS!

А как лучше сделать, тоесть вместо localStorage.launch = checkbox.checked; сделать событие например

$(".link").on("click", function(){
// тут запишем ключ и по нему потом проверяем вместо checkbox.checked
}


?

Malleys 25.05.2019 21:51

Цитата:

Сообщение от Alexodiy
А как лучше сделать, тоесть вместо localStorage.launch = checkbox.checked; сделать событие например

$(".link").on("click", function(){
// тут запишем ключ и по нему потом проверяем вместо checkbox.checked
}


?

Что-то вы намудрили... И очень сильно... Вот, смотрите, в телефоне есть переключатель Wi-Fi, я нажимаю на него и Wi-Fi выключается, ещё раз нажму... Wi-Fi включится! Так я тут сделал. Вы нажимаете, оно выключается, еще раз нажимаете: включается!

А то, что вы предложили с ссылкой, я такого не понял... Для аналогии: допустил это был бы не переключатель Wi-Fi, а по вашему методу: ссылка. Вот, нажимает пользователь в телефоне ссылку Wi-Fi, и куда-то переходит, и как понять такой переключатель?

Alexodiy 26.05.2019 07:26

Цитата:

Сообщение от Malleys (Сообщение 508303)
Что-то вы намудрили... И очень сильно... Вот, смотрите, в телефоне есть переключатель Wi-Fi, я нажимаю на него и Wi-Fi выключается, ещё раз нажму... Wi-Fi включится! Так я тут сделал. Вы нажимаете, оно выключается, еще раз нажимаете: включается!

А то, что вы предложили с ссылкой, я такого не понял... Для аналогии: допустил это был бы не переключатель Wi-Fi, а по вашему методу: ссылка. Вот, нажимает пользователь в телефоне ссылку Wi-Fi, и куда-то переходит, и как понять такой переключатель?

Почему намудрил... Мне надо отследить переход по ссылке на другой источник и офнуть всю выше изложенную логику. Скажем так, есть страница, на которой присутствует различная информация - к ней я как раз и подвязываю "Отображать уведомление при каждой третьей загрузке"... Каждый третий раз, к примеру, появляется уведомление "Оставьте отзыв на этой странице" и это ссылка с переходом на другой ресурс вообще с target="_blank"-ом. Если пользователь кликает по этой ссылке, уведомление каждый третий раз перестает появляться.

Я написал вам в личку, с подробностями, так как мне не желательно светить тему публично

Malleys 26.05.2019 09:33

Простите, что не сразу ответил! Да, то что вы описали в видео, лучше всего сделать при помощи ссылки, ведь она ведёт на страницу отзывов!

В таком случае, там совсем другая логика!

Каждый третий раз ссылка, на которую ещё не нажимали, появляется. Если на неё нажать, происходит переход, а вместо ссылки появляется «Спасибо»! При следующих заходах вместо такой ссылки пишут, что вы уже оставляли отзыв!

Данные получаются/сохраняются при помощи функции getData/saveData, которые получают/сохраняют данные в локальном хранилище, но вы можете, если хотите, переписать эти функции, чтобы данные получались/сохранялись удалённо (например на сервере)

Сама ссылка всегда открывается в новой вкладке (если функционал предполагает, то почему бы не автоматизировать!) Каждая такая ссылка должна иметь в атрибуте id префикс (в данном случае rating-), после которого идёт уникальный номер (например, натуральные числа по порядку) Это позволяет однозначно обозначить ссылку на любой странице и сказать, посещали её или нет!

Вот пример...
<script>
document.addEventListener("DOMContentLoaded", function() {
	function getData() {
		var data = "ratingData" in localStorage ?
			JSON.parse(localStorage.ratingData) : { count: 1 };
		return Promise.resolve(data);
	}
	function saveData(ratingData) {
		localStorage.ratingData = JSON.stringify(ratingData);
		return Promise.resolve("ok");
	}

	var PREFIX = "rating-";
	var links = Array.from(
		document.querySelectorAll("a[id^='" + PREFIX.replace(/'/g, "\\'") + "']")
	);
	
	var hasBeenRatedElement = document.createElement("span");
	hasBeenRatedElement.innerHTML = "Вы уже оставляли отзыв!";
	
	var thanksElement = document.createElement("span");
	thanksElement.innerHTML = "Спасибо!";
	
	getData().then(function(ratingData) {		
		links.forEach(function(link) {
			var id = link.id.replace(PREFIX, "");

			if(id in ratingData) {
				link.parentNode.insertBefore(hasBeenRatedElement.cloneNode(true), link);
				link.parentNode.removeChild(link);
			} else {
				if(ratingData.count !== 0) {
					link.parentNode.removeChild(link);
					return;
				}
				
				link.target = "_blank";
				link.addEventListener("click", function() {
					ratingData[id] = 1;
					saveData(ratingData);
					
					link.parentNode.insertBefore(thanksElement.cloneNode(true), link);
					link.parentNode.removeChild(link);
				});
			}
		});
		
		ratingData.count = (ratingData.count + 1) % 3;
		saveData(ratingData);
	});
});
</script>

<p><a id="rating-1" href="https://google.com/">Оставить отзыв 1</a></p>
<p><a id="rating-2" href="https://ya.ru/">Оставить отзыв 2</a></p>


Такие ссылки могут храниться в таблице в базе данных, тогда вы можете легко ими управлять, также в других таблицах может быть ссылка на первичный ключ `id` и пр.
Код:

+------+---------------------+
| id  | link                |
+------+---------------------+
|    1 | https://google.com/ |
|    2 | https://ya.ru/      |
+------+---------------------+


О, да! Язык не называется YuhvuhScreapt, он называется JavaScript. Может вам поможет эта табличка с некоторыми словами web-разработки! http://malleys.lark.ru/english.html

рони 26.05.2019 10:11

Цитата:

Сообщение от Malleys
PREFIX.replace(/'/g, "\\'")

зачем replace?

Malleys 26.05.2019 10:25

Цитата:

Сообщение от рони
зачем replace?

PREFIX — это префикс, который можно поменять, вдруг человек захочет var PREFIX = "click'n'rate-"; и сейчас это будет работать, поскольку селектор на 15 строке не поломается! Ну чтобы было...
<p><a id="click'n'rate-1" href="https://google.com/">Оставить отзыв 1</a></p>
и т. д.

рони 26.05.2019 10:34

Цитата:

Сообщение от Malleys
Ну чтобы было...

тогда вопрос, зачем нужен такой префикс? где это применяется?

Malleys 26.05.2019 10:39

Цитата:

Сообщение от рони
тогда вопрос, зачем нужен такой префикс? где это применяется?

Вот, на 14 строке ведь написано, что находятся все ссылки, которые будут себя вести таким образом (т. е. появляться раз в три раза, говорить «Спасибо»)

Префикс нужен, чтобы отличить от других ссылок, которые так не должны себя вести!

Применяется при поиске элементов, при сохранении списка посещённых ссылок.

рони 26.05.2019 10:50

Цитата:

Сообщение от Malleys
Вот, на 14 строке ведь написано

я спрашивал про ', что даёт одинарная кавычка в id, это где-то применяется(например в каком-то фреймворке, только так пишут id) или это искуственно созданная проблема?
и так на всякий случай ... вариант без replace.
<p><a id="click'n'rate-1" href="https://google.com/">Оставить отзыв 1</a></p>
<script>
var PREFIX = "click'n'rate-";
var el = document.querySelector('[id^="'+PREFIX+'"]');
alert(el);
</script>

Malleys 26.05.2019 11:03

Цитата:

Сообщение от рони
вариант без replace

Ок, теперь всё ломается, если в имени префикса есть "!

рони 26.05.2019 11:21

Malleys,
Цитата:

Сообщение от рони
это искуственно созданная проблема


Malleys 26.05.2019 11:36

рони, вообще-то это это вы раздули проблему из-за того, что я использовал символ в селекторе в качестве «обычного символа языка», чтобы не было никаких проблем, даже если префикс можно будет вводить, например, через текстовое поле!

Я думаю, эти упрёки были бы к месту, если бы я как раз таки не использовал бы экранирование!

Уязвимость
Экранирование символов

рони 26.05.2019 11:42

Malleys,
я не могу вас понять.

Alexodiy 26.05.2019 12:26

Malleys, огромнейшее спасибо. Как вы так быстро решаете такие вопросы, я тоже хочу так научится на JS. Говорят JS легкий язык, но мне почему то очень сложно на него адаптироватся после других


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