PageSourceSearch

https://www.tio.ch/js/app.tio.js?fmt=e869c4bc

js tio.ch collected 2026-10-02 03:18:38 UTC 59,447 bytes, 1,702 lines download raw bytes

1App.prototype.loadUserToken = function() {
2	if (!this.checkMyTioInit()) {
3		return Promise.resolve(null);
4	}
5
6	if (!this.myTio || !this.myTio.user) {
7		return Promise.resolve('');
8	}
9
10	const tokenPromise = (this.myTio && this.myTio.fbAuth && this.myTio.fbAuth.currentUser)
11		? Promise.resolve(this.myTio.fbAuth.currentUser.getIdToken())
12		: Promise.resolve('');
13
14	return tokenPromise;
15};
16
17App.prototype.loadCommentForm = function() {
18	var commentTool = '';
19	var modalcontent = '';
20
21	if (!this.checkMyTioInit()) {
22		this.commentForm = true;
23		return;
24	}
25
26	if (!this.myTio || !this.myTio.user) {
27
28		commentTool += '<div style="margin-bottom:16px;text-align:center;">';
29		commentTool += '<button style="margin-top:20px;" class="btn" onclick="window.location.href=\'' + app.m.config.mytio + '/?action=login&redirect=' + window.location.href + '\'">';
30		commentTool += '<i class="fa fa-key"></i> Accedi per leggere i commenti';
31		commentTool += '</button>';
32		commentTool += '</div>';
33
34	} else {
35
36		modalcontent += '<div class="modal fade" id="commentModal" tabindex="-1" aria-labelledby="commentModalLabel" aria-hidden="true">';
37		modalcontent += '<div class="modal-dialog-centered modal-dialog-scrollable">';
38		modalcontent += '<div class="modal-dialog modal-lg modal-dialog-scrollable" style="max-height:500px; margin-top:25vh;">';
39		modalcontent += '<div class="modal-content fs-6">';
40
41		modalcontent += '<div class="modal-header">';
42		modalcontent += '<b>Condizioni Generali per commentare gli articoli su tio.ch</b>';
43		modalcontent += '<button type="button" class="btn-close" data-mdb-dismiss="modal" aria-label="Chiudi"></button>';
44		modalcontent += '</div>';
45
46		modalcontent += '<div class="modal-body">';
47
48		modalcontent += '<div>';
49		modalcontent += '<ol>';
50		modalcontent += '<li><b>Rispetto reciproco:</b> Tutti i commentatori devono mantenere un tono rispettoso e cortese nei confronti degli altri utenti e degli autori degli articoli.</li>';
51		modalcontent += '<li><b>Contenuti appropriati:</b> È vietato pubblicare commenti diffamatori, osceni, discriminatori, illegali o in violazione dei diritti di terzi.</li>';
52		modalcontent += '<li><b>Veridicità delle informazioni:</b> I commenti devono essere accurati e basati su fatti verificabili. La diffusione di notizie false o fuorvianti non è permessa.</li>';
53		modalcontent += '<li><b>Proprietà intellettuale:</b> È proibito pubblicare materiale protetto da copyright senza l\'autorizzazione dell\'autore.</li>';
54		modalcontent += '<li><b>Riservatezza e sicurezza:</b> Non condividere informazioni personali o sensibili nei commenti. Presta attenzione alla tua sicurezza e a quella degli altri utenti.</li>';
55		modalcontent += '<li><b>Gestione dei commenti:</b> La redazione si riserva il diritto di rimuovere o modificare i commenti che violano queste condizioni senza preavviso. I commenti possono essere moderati prima della pubblicazione.</li>';
56		modalcontent += '<li><b>Responsabilità dell\'utente:</b> Gli utenti sono responsabili dei propri commenti e delle conseguenze derivanti dalle loro azioni.</li>';
57		modalcontent += '<li><b>Politica anti-spam:</b> È vietato fare spam o promuovere in modo non autorizzato prodotti, servizi o siti web.</li>';
58		modalcontent += '</ol>';
59		modalcontent += '</div>';
60
61		modalcontent += '<div style="margin-top:20px;">';
62		modalcontent += '<b>Etichetta per commentare gli articoli su tio.ch:</b>';
63		modalcontent += '<ol style="margin-top:10px;">';
64		modalcontent += '<li><b>Costruttività:</b> Offri contributi costruttivi che arricchiscano la discussione e contribuiscano alla comprensione dell\'argomento trattato nell\'articolo.</li>';
65		modalcontent += '<li><b>Rispetto delle opinioni:</b> Rispetta le opinioni altrui anche se non sei d\'accordo con esse. Evita linguaggio offensivo o polemico.</li>';
66		modalcontent += '<li><b>Pertinenza:</b> Assicurati che i tuoi commenti siano pertinenti all\'articolo e alla discussione in corso.</li>';
67		modalcontent += '<li><b>Chiarezza:</b> Esprimiti in modo chiaro e conciso, evitando discorsi confusi o ambigui.</li>';
68		modalcontent += '<li><b>Evita lo spam:</b> Non pubblicare ripetutamente lo stesso commento o link. Rispetta la politica anti-spam del sito.</li>';
69		modalcontent += '<li><b>Apertura al confronto:</b> Accetta il confronto e rispondi in modo costruttivo alle critiche o alle domande degli altri utenti.</li>';
70		modalcontent += '<li><b>Gratitudine:</b> Mostra apprezzamento per i commenti informativi o interessanti degli altri utenti.</li>';
71		modalcontent += '<li><b>Rispetto delle regole:</b> Rispetta le regole del sito e collabora con la moderazione per mantenere un ambiente positivo e costruttivo per tutti gli utenti.</li>';
72		modalcontent += '</ol>';
73		modalcontent += '</div>';
74
75		modalcontent += '<div style="margin-top:20px;">';
76		modalcontent += 'Tenere presente che queste regole possono essere soggette a modifiche e adattamenti da parte della redazione del sito in qualsiasi momento.';
77		modalcontent += '</div>';
78
79		modalcontent += '</div>';
80		modalcontent += '</div>';
81		modalcontent += '</div>';
82		modalcontent += '</div>';
83		modalcontent += '</div>';
84
85		commentTool += '';
86
87		var profileImg = '';
88		if (this.myTio.user.profile.photo) {
89			profileImg = '<img width="50" height="50" src="' + this.myTio.user.profile.photo + '" alt="" />';
90		} else {
91			profileImg = this.myTio.user.tiolounge.nickname;
92		}
93
94		commentTool += '<div class="comment-reply-tool">';
95		commentTool += '<div class="comment-picture rounded-circle profileImg">' + profileImg + '</div>';
96		commentTool += '<div class="comment-text" style="margin-top:5px;">';
97		commentTool += '<span id="replyinfo"><!-- // --></span>';
98		commentTool += '<textarea maxlength="4000" onfocus="app.writeComment(this)" data-blockid="0" data-replytoname="" data-replyto="" data-contentid="' + this.m.server.content_id + '" id="usercomment" placeholder="Scrivi un commento"></textarea>';
99		commentTool += '<div class="comment-terms d-flex align-items-center">';
100		commentTool += '<input type="checkbox" id="comment-terms" name="comment-terms" value="1">';
101		commentTool += '<label for="comment-terms" class="ps-2">Dichiaro di aver letto e accettato le</label>';
102		commentTool += '&nbsp;<a class="text-black" data-mdb-toggle="modal" data-mdb-target="#commentModal"><b><u>Condizioni del blog</u></b></a>.';
103		commentTool += '</div>';
104		commentTool += '<div class="d-flex align-items-center justify-content-end"><button class="btn btn-success"onclick="app.newComment(this)">Invia</button></div>';
105		commentTool += '</div>';
106		commentTool += '<a href="#" target="_blank" id="fwdlink" class="fwdlink" style="display:none;">Rispondi a questo post su facebook</a>';
107		commentTool += '</div>';
108		commentTool += modalcontent;
109
110		if (this.m.config.nativeFrame) {
111			if (window.webkit && window.webkit.messageHandlers) {
112				window.webkit.messageHandlers.login.postMessage({ status: true });
113			} else {
114				try { tionativehandler.nativeLogin(JSON.stringify({ 'status': true })); } catch (error) { }
115			}
116		}
117	}
118
119	jQuery("#usercommentbox").html(commentTool);
120};
121
122App.prototype.loadComments = function() {
123
124	if (!document.getElementById("commentslist")) {
125		return;
126	}
127
128	if (!this.checkMyTioInit()) {
129		this.commentsList = true;
130		return;
131	}
132
133	const _this = this;
134
135	const commentsListElement = document.getElementById("commentslist");
136
137	this.loadUserToken().then(function(token) {
138		var p = {};
139		p.action = 'comments';
140		p.token = token;
141		p.id_content = commentsListElement.getAttribute('data-contentid');
142		p.limit = commentsListElement.getAttribute('data-limit');
143		p.collapsed = commentsListElement.getAttribute('data-collapsed');
144		p.redirect_url = window.location.href;
145		fetch('/ext/mytio/', {
146			method: 'POST',
147			headers: {
148				'Content-Type': 'application/x-www-form-urlencoded',
149			},
150			body: new URLSearchParams(p)
151		})
152		.then(response => response.json())
153		.then(data => {
154			if (data.message == 'OK') {
155				commentsListElement.innerHTML = data.html;
156				_this.hideAds();
157            	_this.parseLinks();
158			} else {
159				commentsListElement.innerHTML = '';
160				commentsListElement.style.display = 'none';
161			}
162		})
163		.catch(error => {
164			commentsListElement.innerHTML = '';
165			commentsListElement.style.display = 'none';
166		});
167	});
168};
169
170var user_processing = false;
171
172App.prototype.showBlogProfile = function(nickname) {
173	const _this = this;
174
175	if (!this.myTio || !this.myTio.user) {
176		return;
177	}
178
179	user_processing = true;
180
181	this.showLoading();
182
183	this.loadUserToken().then(function(token) {
184
185		if(token.length <= 0) {
186			user_processing = false;
187			_this.hideLoading();
188			return;
189		}
190
191		var p = {};
192		p.action = 'blog_profile';
193		p.token = token;
194		p.nickname = nickname;
195		fetch('/ext/mytio/', {
196			method: 'POST',
197			headers: {
198				'Content-Type': 'application/x-www-form-urlencoded',
199			},
200			body: new URLSearchParams(p)
201		})
202		.then(response => response.json())
203		.then(data => {
204
205			user_processing = false;
206
207			_this.hideLoading();
208
209			if (data.message == 'OK') {
210				Swal.fire({
211					title: 'Profilo di ' + nickname,
212					html: data.html,
213					width: '600px',
214					showCloseButton: true,
215					showConfirmButton: false,
216					backdrop: true
217				});
218			} else {
219				Swal.fire({
220					title: 'Errore',
221					html: 'Non è stato possibile caricare il profilo utente.',
222					icon: 'error',
223					timer: 4000
224				});
225			}
226		})
227		.catch(error => {
228			user_processing = false;
229			_this.hideLoading();
230			Swal.fire({
231				title: 'Errore',
232				html: 'Non è stato possibile caricare il profilo utente.',
233				icon: 'error',
234				timer: 4000
235			});
236		});
237	});
238};
239
240App.prototype.highlightBlogComment = function(id) {
241
242	jQuery('.comment.highlight').removeClass('highlight');
243
244	jQuery('[data-commentid="' + id + '"]').addClass('highlight');
245
246	jQuery('html, body').animate({
247		scrollTop: jQuery('[data-commentid="' + id + '"]').offset().top - 200
248	}, 500);
249};
250
251App.prototype.newComment = function(el) {
252	const _this = this;
253
254	if (this.netLock()) {
255		return false;
256	}
257
258	if (jQuery('#usercomment').val().trim().length <= 1) {
259		swal.fire({
260			title: 'Errore',
261			html: 'Scrivi un commento',
262			icon: 'error',
263			timer: 5000
264		});
265		jQuery('#usercomment').focus();
266		return false;
267	}
268
269	if (jQuery('#comment-terms').prop('checked') == false) {
270		swal.fire({
271			title: 'Errore',
272			html: 'Per inserire commenti è necessario accettare le condizioni del blog.',
273			icon: 'error',
274			timer: 5000
275		});
276		return false;
277	}
278
279	var p = {
280		'idarticolo': jQuery('#usercomment').attr('data-contentid'),
281		'commento': jQuery('#usercomment').val(),
282		'id_commento': jQuery('#usercomment').attr('data-replyto'),
283		'id_risposta': jQuery('#usercomment').attr('data-replyto'),
284		'risposta_a': jQuery('#usercomment').attr('data-replytoname'),
285		'id_blocco': jQuery('#usercomment').attr('data-blockid'),
286		'titolo': '',
287	};
288
289	jQuery(el).prop('disabled', true).addClass('btn-disabled');
290
291	jQuery("#c").html('<span class="fa loading loading-lock"> </span>').css({ 'display': 'block' }).stop().animate({ 'opacity': '.5' }, 200);
292
293	this.showLoading();
294
295	this.loadUserToken().then(function(token) {
296
297		if(token.length <= 0) {
298			_this.hideLoading();
299			return;
300		}
301
302		p.token = token;
303		p.action = 'blog';
304		jQuery.ajax({
305			url: '/ext/mytio/',
306			type: 'POST',
307			dataType: "json",
308			data: p,
309			success: function(data, textStatus, jqXHR) {
310
311				_this.hideLoading();
312
313				var displayError = '';
314				var errorClass = 'error';
315				var errorTitle = 'Errore';
316				var errorTimer = 6000;
317
318				const dataMessage = data && data.message ? data.message : '';
319				const dataMessageText = data && data.messageText ? data.messageText : '';
320
321				if (dataMessage == 'SUCCESS') {
322					swal.fire({
323						title: "",
324						html: "Commento inserito con successo",
325						icon: "success",
326						timer: 5000
327					}).then(function() {
328						app.reloadPage();
329					});
330				} else if (dataMessage == "DATA_MISSING") {
331					displayError = "<p>Manca il commento.</p>";
332				} else if (dataMessage == "ARTICLE_MISSING") {
333					displayError = "<p>L'articolo non esiste o non è commentabile.</p>";
334				} else if (dataMessage == "PROFILE_NOT_COMPLETED") {
335					var messageText = 'Il profilo usato non è abilitato a scrivere su TioBlog.';
336					if (dataMessageText) {
337						messageText = dataMessageText;
338					}
339					displayError = '<p>' + messageText + '<br><br><a href="https://mytio.ch/blog" target="_blank" style="background-color:#42b179;padding:8px 12px;border-radius:4px;color:#FFF;">Clicca qui per completare il profilo.</a></p>';
340					errorClass = 'warning';
341					errorTitle = 'Attenzione';
342					errorTimer = 20000;
343				} else if (dataMessage == "DUPLICATED") {
344					displayError = "<p>Commento Duplicato.</p><p>Non è permesso scrivere lo stesso commento due volte nel blog.</p>";
345				} else if (dataMessage == "HTML") {
346					displayError = "<p>Del codice HTML è stato indentificato all'interno del commento.</p>";
347				} else if (dataMessage == "DELAYED") {
348					errorTitle = 'Attenzione';
349					displayError = "<p>I commenti vengono pubblicati in automatico durante i giorni feriali dalle 07:00 alle 22:00.</p><p>Al di fuori da questo orario devono essere accettati manualmente dalla redazione e può volerci del tempo prima che appaiano sul sito.</p>";
350					errorClass = 'success';
351				} else if (dataMessage == "TIME_ENDED") {
352					displayError = "<p>Gli articoli sono commentabili solo fino a 10 giorni dopo la loro pubblicazione.</p>";
353				} else if (dataMessage == "NIGHT_PAUSE") {
354					displayError = "<p>Per questioni di moderazione è possibile commentare solo dalle 07:00 alle 22:00.</p>";
355				} else if (dataMessage == 'NOT_LOGGED') {
356					displayError = "<p>Sessione scaduta: Per favore cliccare su logout ed eseguire di nuovo il login.</p>";
357				} else if (dataMessage == 'COMMENT_WORDS') {
358					errorTitle = 'Attenzione';
359					errorClass = 'warning';
360					errorTimer = 10000;
361					if (dataMessageText) {
362						displayError = '<p>' + dataMessageText + '</p>';
363					} else {
364						displayError = "<p>Il commento contiene parole non permesse.</p>";
365					}
366				} else if (dataMessageText) {
367					displayError = dataMessageText;
368				} else {
369					displayError = "<p>Non è stato possibile inserire il commento.</p>";
370					debug.log('Unknown reply: ' + data);
371				}
372
373				if (displayError.length > 0) {
374					swal.fire({
375						title: errorTitle,
376						html: displayError,
377						icon: errorClass,
378						timer: errorTimer,
379						backdrop: true
380					});
381				}
382				jQuery(el).prop('disabled', false).removeClass('btn-disabled');
383				jQuery("#c").html('').fadeOut();
384			},
385			error: function(jqXHR, textStatus, errorThrown) {
386
387				_this.hideLoading();
388
389				swal.fire({
390					title: 'Errore',
391					html: 'Non è stato possibile inserire il commento.',
392					icon: 'error',
393					timer: 4000
394				});
395				debug.log('POST XHR ERROR: ' + textStatus);
396				jQuery(el).prop('disabled', false).removeClass('btn-disabled');
397				jQuery("#c").html('').fadeOut();
398			}
399		});
400	});
401};
402
403App.prototype.replyToComment = function(el) {
404	this.setComment(jQuery(el).closest('.comment'));
405};
406
407App.prototype.expandCommentReplies = function(el) {
408
409	const info = JSON.parse(jQuery(el).attr('data-info'));
410
411	const blockId = String(info.blockid);
412
413	const title_expand = info.title_expand;
414	const title_collapse = info.title_collapse;
415
416	jQuery('[data-blockid="' + blockId + '"]').each(function() {
417
418		if (jQuery(this).attr('data-commentid') !== blockId) {
419			const reply = jQuery(this);
420
421			if (reply.hasClass('d-none')) {
422				reply.removeClass('d-none').css({
423					opacity: 0,
424					transform: 'translateY(-10px)'
425				}).animate({
426					opacity: 1
427				}, 250).css({
428					transform: 'translateY(0)'
429				});
430				jQuery(el).html(title_collapse);
431			} else {
432				reply.animate({
433					opacity: 0
434				}, 200, function() {
435					jQuery(this).addClass('d-none').css({
436						opacity: '',
437						transform: ''
438					});
439				});
440				jQuery(el).html(title_expand);
441			}
442		}
443	});
444};
445
446var comments_processing = [];
447
448App.prototype.voteComment = function(el, vote) {
449
450	_this = this;
451
452	const comment = jQuery(el).closest('.comment');
453	const commentId = jQuery(comment).attr('data-commentid');
454
455	if(comments_processing.includes(commentId)) {
456		return;
457	}
458
459	comments_processing.push(commentId);
460
461	var current_vote = '';
462	if(jQuery(comment).find('.comment-button-like').hasClass('active')) {
463		current_vote = 'like';
464	} else if(jQuery(comment).find('.comment-button-dislike').hasClass('active')) {
465		current_vote = 'dislike';
466	}
467
468	if(current_vote == vote) {
469		vote = 'none';
470	}
471
472	jQuery(comment).find('.comment-button-like').removeClass('active');
473	jQuery(comment).find('.comment-button-dislike').removeClass('active');
474
475	const like_count = parseInt(jQuery(comment).find('.comment-count-like').text(), 10) || 0;
476	const dislike_count = parseInt(jQuery(comment).find('.comment-count-dislike').text(), 10) || 0;
477
478	var new_like_count = like_count;
479	var new_dislike_count = dislike_count;
480
481	if (vote == 'like') {
482		jQuery(comment).find('.comment-button-like').addClass('active');
483		new_like_count += 1;
484	} else if (vote == 'dislike') {
485		jQuery(comment).find('.comment-button-dislike').addClass('active');
486		new_dislike_count += 1;
487	}
488
489	if(current_vote == 'like') {
490		new_like_count -= 1;
491	} else if(current_vote == 'dislike') {
492		new_dislike_count -= 1;
493	}
494
495	jQuery(comment).find('.comment-count-like').text(new_like_count > 0 ? new_like_count : '');
496	jQuery(comment).find('.comment-count-dislike').text(new_dislike_count > 0 ? new_dislike_count : '');
497
498	this.loadUserToken().then(function(token) {
499
500		var p = {};
501		p.action = 'comment_vote';
502		p.token = token;
503		p.id_comment = commentId;
504		p.vote = vote;
505		p.id_analytics = _this.m.device.analyticsUserID ? _this.m.device.analyticsUserID : '';
506		jQuery.ajax({
507			url: '/ext/mytio/',
508			type: 'POST',
509			dataType: "json",
510			data: p,
511			success: function(data, textStatus, jqXHR) {
512				comments_processing = comments_processing.filter(id => id !== commentId);
513			},
514			error: function(jqXHR, textStatus, errorThrown) {
515				comments_processing = comments_processing.filter(id => id !== commentId);
516				debug.log('POST XHR ERROR: ' + textStatus);
517			}
518		});
519	});
520};
521
522App.prototype.reportComment = function(el) {
523	_this = this;
524
525	var nickname = '';
526
527	const comment = jQuery(el).closest('.comment');
528	if (typeof jQuery(comment).attr('data-nickname') !== undefined) {
529		nickname = jQuery(comment).attr('data-nickname');
530	}
531
532	var p = {
533		'id_commento': jQuery(comment).attr('data-commentid')
534	};
535
536	Swal.fire({
537		title: 'Segnala commento',
538		input: 'checkbox',
539		inputPlaceholder: '<div style="text-align:left;padding-left:10px;">Confermo di voler segnalare il commento come inappropriato</div>',
540		showCancelButton: true,
541		confirmButtonText: 'Segnala',
542		cancelButtonText: 'Annulla',
543		reverseButtons: true,
544		allowOutsideClick: true,
545		allowEscapeKey: true,
546		inputValidator: (result) => {
547			return !result && "È necessario confermare la segnalazione per procedere.";
548		}
549	}).then((result) => {
550
551		if (result.value) {
552
553			_this.showLoading();
554
555			_this.loadUserToken().then(function(token) {
556
557				if(token.length <= 0) {
558					_this.hideLoading();
559					return;
560				}
561
562				p.token = token;
563				p.action = 'report';
564				jQuery.ajax({
565					url: '/ext/mytio/',
566					type: 'POST',
567					dataType: "json",
568					data: p,
569					success: function(data, textStatus, jqXHR) {
570
571						_this.hideLoading();
572
573						var errorTitle = "Errore";
574						var errorMessage = "Errore durante l'invio della segnalazione.";
575						var errorTimer = 5000;
576
577						if (data && data.message) {
578
579							if (data.message == 'SUCCESS') {
580								Swal.fire({
581									title: "Segnalazione",
582									html: "La segnalazione è stata inviata alla redazione.",
583									icon: "success",
584									timer: 5000,
585									backdrop: true
586								});
587								return;
588							}
589
590							if (data.messageText) {
591								errorMessage = data.messageText;
592							}
593
594							if (data.message == "PROFILE_NOT_COMPLETED") {
595								errorMessage = errorMessage + '<br><br><a href="https://mytio.ch/blog" target="_blank" style="background-color:#42b179;padding:8px 12px;border-radius:4px;color:#FFF;">Clicca qui per completare il profilo.</a>';
596								errorTitle = "Attenzione";
597								errorTimer = 20000;
598							}
599						}
600
601						Swal.fire({
602							title: errorTitle,
603							html: errorMessage,
604							icon: "error",
605							timer: errorTimer,
606							backdrop: true
607						});
608					},
609					error: function(jqXHR, textStatus, errorThrown) {
610
611						_this.hideLoading();
612
613						Swal.fire({
614							title: "Errore",
615							html: "Errore durante l'invio della segnalazione.",
616							icon: "error",
617							timer: 5000,
618							backdrop: true
619						});
620					}
621				});
622			});
623		}
624	});
625};
626
627App.prototype.adBlockDetail = function(el, evt) {
628
629	var id;
630	if (typeof jQuery(el).attr('data-id') !== undefined) {
631		id = jQuery(el).attr('data-id');
632	}
633	jQuery('.adblockList li').removeClass('active');
634	jQuery(el).addClass('active');
635	jQuery('.adblock_detail').hide();
636	jQuery('#' + id + '_detail').show();
637};
638
639App.prototype.initBiglietteria = function() {
640	if (jQuery('.slick.biglietteria').length) {
641		if (!jQuery('.slick.biglietteria').hasClass("slick-initialized")) {
642			var initSlide = Math.floor((Math.random() * jQuery('.slick.biglietteria').find('.slide').length));
643			jQuery('.slick.biglietteria').slick({ initialSlide: initSlide, dots: true, infinite: true, arrows: fal
643se, autoplay: true });
644		}
645	}
646};
647
648App.prototype.disabledDiv = '<div class="title">Questo contenuto è stato bloccato dalle vostre impostazioni sulla privacy.<br />Modificare le impostazioni per accedere a questo tipo di contenuti.</div><button id="ot-sdk-btn" class="ot-sdk-show-settings" style="color: #FFFFFF;">Modifica Impostazioni Cookies</button>';
649
650App.prototype.disableSocials = function() {
651	if (!this.checkGDPR('socials')) {
652		jQuery('.native_socials').remove();
653		jQuery('.script_obj').addClass('disabled');
654		jQuery('.script_obj').html(this.disabledDiv);
655	}
656};
657
658
659App.prototype.disableFunctions = function() {
660	if (!this.checkGDPR('functions')) {
661		$("#content_frame").replaceWith('<div class="disabledDiv">' + this.disabledDiv + '</div>');
662		$('[data-video-type="video/youtube"]').replaceWith('<div class="disabledDiv">' + this.disabledDiv + '</div>');
663	}
664};
665
666/**
667 * Rimuove cookie legacy ".www.tio.ch", lasciando solo ".tio.ch"
668 */
669function OptanonRemoveLegacyCookies() {
670
671	if (location.hostname !== 'www.tio.ch') {
672		return;
673	}
674
675	const script = document.querySelector('script[data-domain-script]');
676	if (!script || script.getAttribute('data-domain-script').indexOf('01a066b1-2b5a-702e-bf05-3d3ffc4d1df4') !== 0) {
677		return;
678	}
679
680	// Solo i cookie presenti due volte
681	['OptanonConsent', 'OptanonAlertBoxClosed', 'eupubconsent-v2', 'OTAdditionalConsentString'].forEach(name => {
682		if ((document.cookie.match(new RegExp('(?:^|;\\s*)' + name + '=', 'g')) || []).length > 1) {
683			document.cookie = name + '=; path=/; domain=.www.tio.ch; expires=Thu, 01 Jan 1970 00:00:00 GMT';
684		}
685	});
686}
687
688function OptanonWrapper() {
689
690	OptanonRemoveLegacyCookies();
691
692	if (typeof OneTrust === 'undefined') {
693		return;
694	}
695
696	if (!OneTrust.IsAlertBoxClosed()) {
697		document.querySelector('html').classList.toggle('noscroll', true);
698		return;
699	}
700	document.querySelector('html').classList.toggle('noscroll', false);
701	if (!app.checkMyTioInit()) {
702		return;
703	}
704	if (app.checkOneTrust('analytics')) {
705		app.checkUserID();
706		app.googleAnalyticsInit();
707		app.mediaPulseCall(app.m.server.section_name, app.m.server.sub_section_name);
708	}
709	if (!app.checkOneTrust('functions')) {
710		app.disableFunctions();
711	}
712	if (!app.checkOneTrust('socials')) {
713		app.disableSocials();
714	}
715
716	app.tioAnalyticsCall();
717
718	if (app.checkBotUa()) {
719		return;
720	}
721
722	if (app.myTio && app.myTio.checkPermissions && app.myTio.checkPermissions('mytioabo')) {
723		return;
724	}
725	if (!app.checkOneTrust('all')) {
726		app.showOneTrustMytio('');
727		return;
728	}
729	if (window.__tcfapi) {
730		__tcfapi('addEventListener', 2, function(tcData, success) {
731			if (success && (tcData.eventStatus === 'tcloaded' || tcData.eventStatus === 'cmpuishown' || tcData.eventStatus === 'useractioncomplete')) {
732				OptanonCheckTcData(tcData)
733			}
734		});
735	}
736	return;
737
738
739}
740
741function OptanonCheckTcData(tcData) {
742	app.adsLog(tcData);
743
744	let check_publisher_consents = true;
745	if (Object.keys(tcData.publisher.consents).length == 0) {
746		check_publisher_consents = false;
747	} else {
748		Object.keys(tcData.publisher.consents).forEach(key => {
749			if (key == 1) {
750				return;
751			}
752			if (!tcData.publisher.consents[key]) {
753				check_publisher_consents = false;
754			}
755		});
756	}
757
758	app.adsLog('check_publisher_consents', check_publisher_consents);
759	if (!check_publisher_consents) {
760		app.showOneTrustMytio('check_publisher_consents');
761		return;
762	}
763
764	let check_purpose_consent = true;
765	if (Object.keys(tcData.purpose.consents).length == 0) {
766		check_purpose_consent = false;
767	} else {
768		Object.keys(tcData.purpose.consents).forEach(key => {
769			if (key == 1) {
770				return;
771			}
772			if (!tcData.purpose.consents[key]) {
773				check_purpose_consent = false;
774			}
775		});
776	}
777	app.adsLog('check_purpose_consent', check_purpose_consent);
778	if (!check_purpose_consent) {
779		app.showOneTrustMytio('check_purpose_consent');
780		return;
781	}
782
783	let specialFeatureOptins = true;
784	if (Object.keys(tcData.specialFeatureOptins).length < 2) {
785		specialFeatureOptins = false;
786	} else {
787		Object.keys(tcData.specialFeatureOptins).forEach(key => {
788			if (!tcData.specialFeatureOptins[key]) {
789				specialFeatureOptins = false;
790			}
791		});
792	}
793	app.adsLog('specialFeatureOptins', specialFeatureOptins);
794	if (!specialFeatureOptins) {
795		app.showOneTrustMytio('specialFeatureOptins');
796		return;
797	}
798
799
800
801	let count_vendor_consent = 0;
802	Object.values(tcData.vendor.consents).forEach(val => {
803		if (val) {
804			count_vendor_consent++;
805		}
806	});
807
808	/**
809	 *  ONETRUST VENDOR CONSENT COUNT
810	 */
811	let min_vendor_consent = 200;
812	app.adsLog('count_vendor_consent', count_vendor_consent);
813	if (count_vendor_consent < min_vendor_consent) {
814		app.showOneTrustMytio('count_vendor_consent');
815		return;
816	}
817
818	if (app.oneTrustAlertLoaded) {
819		app.oneTrustAlertLoaded = false;
820		swal.close();
821	}
822
823	if (app.m.device.adblock) {
824		app.adblockMsg();
825		return;
826	}
827
828	app.startAdsTypes();
829}
830
831App.prototype.hideReactions = function(el, evt) {
832	jQuery('.reactionListTouchExit').hide();
833	jQuery('.reactionsList').hide();
834}
835
836
837App.prototype.reactionStatus = 'init';
838App.prototype.loadReactions = function(el, evt) {
839
840	if (jQuery('[data-field=current]').length > 0) {
841		var current = jQuery('[data-field=current]').html()
842		if (current == 'disabled') {
843			jQuery('.reactions').hide();
844		}
845	}
846
847	var reactions_json = [];
848	if (jQuery('.reactions_json').length > 0) {
849		try {
850			reactions_json = JSON.parse(jQuery('.reactions_json').html());
851		} catch (e) { }
852	}
853	var reactions_user_json = [];
854	if (jQuery('.reactions_user_json').length > 0) {
855		try {
856			reactions_user_json = JSON.parse(jQuery('.reactions_user_json').html());
857		} catch (e) { }
858	}
859
860
861
862	var currentReaction = '';
863	if (reactions_user_json.length > 0) {
864		jQuery('.mainReaction .reactionIconMedium').removeClass().addClass('reactionIconMedium').addClass(reactions_user_json[0]['name']).attr('data-type', reactions_user_json[0]['name']);
865		currentReaction = reactions_user_json[0]['name'];
866		jQuery('.reactionIconSmall.' + currentReaction).addClass('active');
867		jQuery('.reactionIconMedium.' + currentReaction).addClass('active');
868		jQuery('.reactionIconBig.' + currentReaction).addClass('active');
869		jQuery('.nReactions.' + currentReaction).addClass('active');
870		jQuery('.totReactions').addClass('active');
871	}
872
873	if (this.reactionStatus == 'init') {
874		this.reactionStatus = 'start';
875		if (this.m.config.type == 'web') {
876			jQuery('.mainReaction .reactionIconMedium').on('click', function(evt) {
877				app.setReaction(this, evt);
878			});
879		} else {
880			jQuery('.mainReaction .reactionIconMedium').on('click', function(evt) {
881				if (!jQuery('.reactionsList').is(':visible')) {
882					app.setReaction(jQuery('.mainReaction .reactionIconMedium'));
883				}
884			});
885			this.longPress(el, function() {
886			}, function() {
887				if (!jQuery('.reactionsList').is(':visible')) {
888					jQuery('.reactionListTouchExit').show();
889					jQuery('.reactionsList').show();
890				}
891			})
892		}
893	}
894
895
896	var countSmallReactions = 0;
897	jQuery('.smallReactions').html('');
898
899	for (var i = 0; i < reactions_json.length; i++) {
900		if (currentReaction == '' && i == 0) {
901			if (reactions_json[i]['tot'] >= 10) {
902				jQuery('.mainReaction .reactionIconMedium').removeClass().addClass('reactionIconMedium').addClass(reactions_json[i]['name']).attr('data-type', reactions_json[i]['name'])
903				currentReaction = reactions_json[i]['name'];
904			} else {
905				currentReaction = 'up';
906			}
907		}
908
909		if (currentReaction != reactions_json[i]['name'] && countSmallReactions < 3) {
910			jQuery('.smallReactions').prepend('<div class="reactionIconSmall ' + reactions_json[i]['name'] + '"></div>');
911			countSmallReactions++;
912		}
913
914		jQuery('.nReactions.' + reactions_json[i]['name']).html(dataFormat(reactions_json[i]['tot'], 'quotes'));
915	}
916
917	this.reactionStatus = 'ready';
918}
919
920
921App.prototype.setReaction = function(el, evt) {
922	if (this.reactionStatus == 'procesing') {
923		return;
924	}
925	if (this.scrolling) {
926		return;
927	}
928
929	if (!this.enabledAnalytics()) {
930		_this.notify({
931			content: 'Reazione articolo: stastitiche disattivate',
932			class: 'error',
933			timeout: 6
934		});
935		return;
936	}
937	if (evt) {
938		evt.preventDefault();
939		evt.stopPropagation();
940	}
941
942	if (typeof jQuery(el).attr('data-type') === 'undefined') {
943		return;
944	}
945
946	this.reactionStatus = 'procesing';
947
948	if (jQuery('.reactions_user_json').length > 0) {
949		try {
950			reactions_user_json = JSON.parse(jQuery('.reactions_user_json').html());
951		} catch (e) { }
952	}
953
954	var type = jQuery(el).attr('data-type');
955
956	if (jQuery(el).hasClass('active')) {
957		type = 'none';
958	}
959	u = _this.m.config.analyticsUrl + "/ext/api.php?output=thumbs&type=" + type + "&uid=" + this.m.device.analyticsUserID + "&id=" + this.m.server.content_id;
960
961
962	jQuery.get(u, function(type) {
963		return function(data) {
964			if (data && data.result && data.result == 'OK') {
965				jQuery('.reactions .active').removeClass('active');
966				jQuery('.nReactions').html('');
967				var reactions_json = [];
968				try {
969					reactions_json = JSON.parse(jQuery('.reactions_json').html());
970				} catch (e) { }
971
972				var old_reactions_user_json = [];
973				try {
974					old_reactions_user_json = JSON.parse(jQuery('.reactions_user_json').html());
975				} catch (e) { }
976
977				var totReactions = parseInt(jQuery('.totReactions').html(), 10)
978				var reactions_user_json = [];
979				var checkReactionAdd = false;
980				if (type == 'none') {
981					totReactions = totReactions - 1;
982
983				} else {
984					if (old_reactions_user_json.length == 0) {
985						totReactions = totReactions + 1;
986					}
987					var reactions_user_json = [{
988						name: type,
989						tot: 1
990					}];
991					checkReactionAdd = true;
992				}
993
994				var checkReactionRemove = false;
995				for (var i = 0; i < reactions_json.length; i++) {
996					if (reactions_json[i].name == type) {
997						reactions_json[i].tot = parseInt(reactions_json[i].tot, 10) + 1;
998						reactions_user_json[0].tot = parseInt(reactions_json[i].tot, 10) + 1;
999						checkReactionAdd = false;
1000					}
1001					if (old_reactions_user_json.length > 0) {
1002						if (reactions_json[i].name == old_reactions_user_json[0].name) {
1003							reactions_json[i].tot = parseInt(reactions_json[i].tot, 10) - 1;
1004							if (reactions_json[i].tot == 0) {
1005								checkReactionRemove = i;
1006							}
1007						}
1008					}
1009				}
1010				if (checkReactionRemove) {
1011					reactions_json.splice(checkReactionRemove, 1);
1012				}
1013				if (checkReactionAdd) {
1014					reactions_json.push(reactions_user_json[0]);
1015				}
1016
1017				jQuery('.reactions_user_json').html(JSON.stringify(reactions_user_json));
1018				jQuery('.reactions_json').html(JSON.stringify(reactions_json));
1019				jQuery('.totReactions').html(totReactions);
1020				app.loadReactions();
1021				_this.notify({
1022					content: 'Reazione registrata',
1023					class: 'success',
1024					timeout: 5
1025				});
1026				return;
1027			}
1028
1029			app.reactionStatus = 'error';
1030			_this.notify({
1031				content: 'Errore, riprova tra un attimo',
1032				class: 'error',
1033				timeout: 5
1034			});
1035		}
1036	}(type));
1037}
1038
1039App.prototype.forgetMyTioAboReminder = function() {
1040	swal.close();
1041	this.setStorage('mytio_abo_reminder', '-1');
1042}
1043
1044App.prototype.openMyTioAboReminder = function() {
1045
1046	const checkDays = 14, // giorni da controllare
1047		mindays = 5, // giorni minimi da mostrare
1048		minValue = 2, // valore minimo per mostrare
1049		maxDisabledDays = 90; // giorni massimi per non mostrare
1050
1051	let loyal_accesslog = new Map();
1052	try {
1053		loyal_accesslog = this.getStorage('lacsl')
1054		loyal_accesslog = loyal_accesslog ? new Map(JSON.parse(loyal_accesslog.base64Decode())) : new Map();
1055	} catch {
1056		loyal_accesslog = new Map();
1057	}
1058	const currentDay = new Date().toISOString().split('T')[0].replaceAll('-', '');
1059	loyal_accesslog.set(currentDay, loyal_accesslog.get(currentDay) ? loyal_accesslog.get(currentDay) + 1 : 1);
1060	this.setStorage('lacsl', JSON.stringify(Array.from((loyal_accesslog))).base64Encode());
1061
1062	const maxDay = new Date(new Date().setDate(new Date().getDate() - checkDays)).toISOString().split('T')[0].replaceAll('-', '');
1063
1064	for (let [day, value] of loyal_accesslog) {
1065		if (day == currentDay) {
1066			continue;
1067		}
1068		if (day < maxDay || value <= minValue) {
1069			//se il giorno è più vecchio di 14 giorni o se il valore è minore di 2 cancella
1070			loyal_accesslog.delete(day);
1071		}
1072	}
1073
1074	if (loyal_accesslog.size < mindays) {
1075		//se rimangono meno di 5 giorni non mostrare
1076		return;
1077	}
1078
1079	const mytio_abo_reminder = this.getStorage('mytio_abo_reminder');
1080	const dayInMs = 1000 * 60 * 60 * 24;
1081	if (mytio_abo_reminder &&
1082		(
1083			mytio_abo_reminder == '-1' ||
1084			Date.now() - mytio_abo_reminder < (maxDisabledDays * dayInMs)
1085		)
1086	) {
1087		// Già mostrato o mostrato meno di 90 giorni fa
1088		return;
1089	}
1090
1091	/*
1092	Swal.fire({
1093		'title': 'Sei stanco di vedere i Banner ?',
1094		'html': 'Abbonati a Tio.ch e non li vedrai più<br /><button class="btn-sm border-0 fw-light fst-italic mt-3" onclick="app.forgetMyTioAboReminder(); return false;">Non ricordarmelo più</button>',
1095		'imageUrl': 'https://www.mytio.ch/img/logo-mytio.png',
1096		'imageHeight': 100,
1097		'showCancelButton': true,
1098		'confirmButtonText': 'Abbonati',
1099		'cancelButtonText': 'Non adesso',
1100		'reverseButtons': true,
1101		'allowOutsideClick': false,
1102		'allowEscapeKey': false,
1103	}).then((result) => {
1104		this.setStorage('mytio_abo_reminder', Date.now());
1105
1106		if (result.value) {
1107			window.location.href = 'https://mytio.ch/mytioabo';
1108			return;
1109		}
1110	});
1111	*/
1112}
1113App.prototype.initConcorso = function() {
1114
1115	var _this = this;
1116
1117	var boxes      = Array.from({length: 6}, function(_, i) { return document.getElementById('d' + i); });
1118	var termsCheck = document.getElementById('tio-terms-check');
1119	var submitBtn  = document.getElementById('tio-submit-btn');
1120	var spinner    = document.getElementById('tio-spinner');
1121	var btnLabel   = document.getElementById('tio-btn-label');
1122	var statusMsg  = document.getElementById('tio-status-msg');
1123
1124	if (!submitBtn) { return; }
1125
1126	var openDate = new Date('2026-04-01T00:00:00');
1127	if (new URLSearchParams(window.location.search).get('y') === 'tiotest') {
1128		openDate = new Date(Date.now() - 1000);
1129	}
1130
1131	fetch('/favicon.ico', { method: 'HEAD', cache: 'no-store' })
1132		.then(function(res) {
1133			var serverDate = new Date(res.headers.get('Date'));
1134			_this._checkConcorsoOpen((serverDate && !isNaN(serverDate)) ? serverDate : new Date());
1135		})
1136		.catch(function() {
1137			_this._checkConcorsoOpen(new Date());
1138		});
1139
1140	this._openDate = openDate;
1141	this._concorsoElements = { boxes: boxes, termsCheck: termsCheck, submitBtn: submitBtn, spinner: spinner, btnLabel: btnLabel, statusMsg: statusMsg };
1142};
1143
1144App.prototype._checkConcorsoOpen = function(now) {
1145
1146	var _this    = this;
1147	var openDate = this._openDate;
1148	var el       = this._concorsoElements;
1149
1150	if (now < openDate) {
1151
1152		var style = document.createElement('style');
1153		style.textContent =
1154			'#tio-countdown { padding: 1.5rem 0; }' +
1155			'.tio-countdown-label { font-size: 12px; font-weight: 600; color: #aaa; text-transform: uppercase; letter-spacing: 0.08em; margin: 0 0 1rem; }' +
1156			'.tio-countdown-boxes { display: flex; align-items: flex-start; gap: 8px; flex-wrap: wrap; }' +
1157			'.tio-cd-block { display: flex; flex-direction: column; align-items: center; gap: 5px; flex: 1; min-width: 0; }' +
1158			'.tio-cd-num { font-family: "DM Serif Display", serif; font-size: clamp(26px, 4vw, 40px); color: #E8001A; line-height: 1; width: 100%; text-align: center; background: #fff8f8; border: 2px solid #E8001A; border-radius: 10px; padding: 12px 4px; display: block; }' +
1159			'.tio-cd-unit { font-size: 11px; font-weight: 600; color: #bbb; text-transform: uppercase; letter-spacing: 0.06em; }' +
1160			'.tio-cd-sep { font-family: "DM Serif Display", serif; font-size: clamp(22px, 3vw, 32px); color: #ddd; line-height: 1; padding-top: 14px; flex-shrink: 0; }' +
1161			'.tio-countdown-note { font-size: 13px; color: #999; margin: 1.25rem 0 0; line-height: 1.6; }' +
1162			'.tio-countdown-note strong { color: #555; }';
1163		document.head.appendChild(style);
1164
1165		var colRight = el.submitBtn.closest('.tio-col-right');
1166		if (colRight) {
1167			colRight.innerHTML =
1168				'<div class="tio-divider"></div>' +
1169				'<div id="tio-countdown">' +
1170				'<p class="tio-countdown-label">Il concorso inizia tra</p>' +
1171				'<div class="tio-countdown-boxes">' +
1172				'<div class="tio-cd-block"><span class="tio-cd-num" id="tio-cd-days">--</span><span class="tio-cd-unit">giorni</span></div>' +
1173				'<div class="tio-cd-sep">:</div>' +
1174				'<div class="tio-cd-block"><span class="tio-cd-num" id="tio-cd-hours">--</span><span class="tio-cd-unit">ore</span></div>' +
1175				'<div class="tio-cd-sep">:</div>' +
1176				'<div class="tio-cd-block"><span class="tio-cd-num" id="tio-cd-mins">--</span><span class="tio-cd-unit">minuti</span></div>' +
1177				'<div class="tio-cd-sep">:</div>' +
1178				'<div class="tio-cd-block"><span class="tio-cd-num" id="tio-cd-secs">--</span><span class="tio-cd-unit">secondi</span></div>' +
1179				'</div>' +
1180				'<p class="tio-countdown-note">Il concorso sarà attivo dal <strong>1° aprile</strong> al <strong>30 giugno 2026</strong>.<br>Torna qui il 1° aprile per inserire il tuo numero fortunato!</p>' +
1181				'</div>';
1182		}
1183
1184		function pad(n) { return n < 10 ? '0' + n : String(n); }
1185
1186		function tick() {
1187			var diff = openDate - new Date();
1188			if (diff <= 0) { window.location.reload(); return; }
1189			var d = Math.floor(diff / 86400000);
1190			var h = Math.floor((diff % 86400000) / 3600000);
1191			var m = Math.floor((diff % 3600000) / 60000);
1192			var s = Math.floor((diff % 60000) / 1000);
1193			document.getElementById('tio-cd-days').textContent  = pad(d);
1194			document.getElementById('tio-cd-hours').textContent = pad(h);
1195			document.getElementById('tio-cd-mins').textContent  = pad(m);
1196			document.getElementById('tio-cd-secs').textContent  = pad(s);
1197		}
1198
1199		tick();
1200		setInterval(tick, 1000);
1201		return;
1202	}
1203
1204	this._initConcorsoForm();
1205};
1206
1207App.prototype._initConcorsoForm = function() {
1208	var _this = this;
1209	var el    = this._concorsoElements;
1210
1211	if (!_this.checkMyTioInit()) {
1212		_this.concorsoForm = true;
1213		return;
1214	}
1215
1216	_this.loadUserToken().then(function(token) {
1217
1218		if (!token) {
1219			var colRight = el.submitBtn.closest('.tio-col-right');
1220			if (!colRight) { return; }
1221
1222			var loginUrl    = _this.m.config.mytio + '/?action=login&redirect='    + encodeURIComponent(window.location.href);
1223			var registerUrl = _this.m.config.mytio + '/register/?redirect=' + encodeURIComponent(window.location.href);
1224
1225			colRight.innerHTML =
1226				'<div class="tio-divider"></div>' +
1227				'<p class="tio-instruction">Come partecipare</p>' +
1228				'<p style="font-family:\'DM Serif Display\',serif;font-size:clamp(22px,3vw,28px);color:#1a1a1a;margin:0 0 1rem;line-height:1.2;">Accedi e inserisci il tuo numero fortunato</p>' +
1229				'<p style="font-size:15px;color:#555;margin:0 0 0.75rem;line-height:1.7;">Per partecipare al concorso basta loggarsi a <strong>mytio.ch</strong>, compilare i campi necessari, inserire il numero e aspettare che la fortuna faccia la sua parte.</p>' +
1230				'<p style="font-size:15px;color:#555;margin:0 0 2rem;line-height:1.7;">Non hai un utente mytio.ch? Ti basta creare l\'account e partecipare al concorso.</p>' +
1231				'<div style="display:flex;gap:12px;flex-wrap:wrap;">' +
1232				'<a href="' + loginUrl + '" style="display:inline-flex;align-items:center;justify-content:center;padding:14px 28px;background:#E8001A;color:#fff !important;font-family:\'Open Sans\',sans-serif;font-size:15px;font-weight:700;border-radius:10px;text-decoration:none !important;">Accedi</a>' +
1233				'<a href="' + registerUrl + '" style="display:inline-flex;align-items:center;justify-content:center;padding:14px 28px;background:#fff;color:#E8001A !important;font-family:\'Open Sans\',sans-serif;font-size:15px;font-weight:700;border-radius:10px;text-decoration:none !important;border:2px solid #E8001A;">Crea account</a>' +
1234				'</div>';
1235			return;
1236		}
1237
1238		// Loggato: inizializza il form
1239		_this._initConcorsoFormLogged();
1240	});
1241};
1242
1243App.prototype._initConcorsoFormLogged = function() {
1244
1245	var _this     = this;
1246	var el        = this._concorsoElements;
1247	var boxes     = el.boxes;
1248
1249	// Pre-compila i box se c'è ?number= nell'URL
1250	var urlNumber = new URLSearchParams(window.location.search).get('number');
1251	if (urlNumber && /^\d{6}$/.test(urlNumber)) {
1252		urlNumber.split('').forEach(function(d, i) {
1253			if (boxes[i]) { boxes[i].value = d; boxes[i].classList.add('tio-filled'); }
1254		});
1255	}
1256	if (urlNumber) {
1257		var url = new URL(window.location.href);
1258		url.searchParams.delete('number');
1259		window.history.replaceState({}, '', url.toString());
1260	}
1261
1262	var termsCheck = el.termsCheck;
1263	var submitBtn  = el.submitBtn;
1264	var spinner    = el.spinner;
1265	var btnLabel   = el.btnLabel;
1266	var statusMsg  = el.statusMsg;
1267
1268	var countryTranslations = {
1269		'Switzerland': 'Svizzera',
1270		'Italy': 'Italia',
1271		'Germany': 'Germania',
1272		'France': 'Francia',
1273		'Austria': 'Austria',
1274		'Liechtenstein': 'Liechtenstein',
1275		'Belgium': 'Belgio',
1276		'Netherlands': 'Paesi Bassi',
1277		'Spain': 'Spagna',
1278		'Portugal': 'Portogallo',
1279		'United Kingdom': 'Regno Unito',
1280		'United States': 'Stati Uniti',
1281		'United States of America': 'Stati Uniti',
1282		'Canada': 'Canada',
1283		'Australia': 'Australia',
1284		'San Marino': 'San Marino',
1285		'Vatican City': 'Città del Vaticano',
1286		'Monaco': 'Monaco',
1287		'Luxembourg': 'Lussemburgo',
1288		'Slovenia': 'Slovenia',
1289		'Croatia': 'Croazia',
1290		'Czech Republic': 'Repubblica Ceca',
1291		'Czechia': 'Repubblica Ceca',
1292		'Poland': 'Polonia',
1293		'Hungary': 'Ungheria',
1294		'Romania': 'Romania',
1295		'Greece': 'Grecia',
1296		'Sweden': 'Svezia',
1297		'Norway': 'Norvegia',
1298		'Denmark': 'Danimarca',
1299		'Finland': 'Finlandia',
1300	};
1301
1302	function translateCountry(country) {
1303		return countryTranslations[country] || country;
1304	}
1305
1306	function getNumber()  { return boxes.map(function(b) { return b.value; }).join(''); }
1307	function isComplete() { return boxes.every(function(b) { return b.value !== ''; }); }
1308
1309	function updateDots() {
1310		boxes.forEach(function(b, i) {
1311			document.getElementById('dot-' + i).classList.toggle('tio-active', b.value !== '');
1312		});
1313	}
1314
1315	function updateBtn() {
1316		submitBtn.disabled = !(isComplete() && termsCheck.checked);
1317	}
1318
1319	function showStatus(type, msg) {
1320		statusMsg.className = 'tio-status-msg tio-' + type;
1321		statusMsg.textContent = msg;
1322		statusMsg.style.display = 'block';
1323		setTimeout(function() {
1324			statusMsg.scrollIntoView({ behavior: 'smooth', block: 'center' });
1325		}, 100);
1326	}
1327
1328	function setLoading(on) {
1329		spinner.style.display = on ? 'block' : 'none';
1330		btnLabel.textContent  = on ? 'Invio in corso...' : 'Partecipa';
1331		submitBtn.disabled    = on;
1332	}
1333
1334	function initAddressAutocomplete() {
1335		var addrInput   = document.getElementById('swal-address');
1336		var suggestions = document.getElementById('swal-address-suggestions');
1337		if (!addrInput || !suggestions) { return; }
1338
1339		var debounceTimer = null;
1340		var lastQuery = '';
1341
1342		addrInput.addEventListener('input', function() {
1343			clearTimeout(debounceTimer);
1344			var q = addrInput.value.trim();
1345			lastQuery = q;
1346			if (q.length < 4) { suggestions.style.display = 'none'; return; }
1347
1348			debounceTimer = setTimeout(function() {
1349				fetch('https://photon.komoot.io/api/?q=' + encodeURIComponent(q) + '&limit=5&lang=en&lat=46.0037&lon=8.9511')
1350					.then(function(r) {
1351						if (!r.ok) { suggestions.style.display = 'none'; return null; }
1352						return r.json();
1353					})
1354					.then(function(data) {
1355						if (!data) { return; }
1356						suggestions.innerHTML = '';
1357
1358						var keepItem = document.createElement('div');
1359						keepItem.style.cssText = 'padding:8px 12px;cursor:pointer;border-bottom:2px solid #e0e0e0;font-size:13px;color:#E8001A;font-weight:600;';
1360						keepItem.textContent = '✎ Usa "' + lastQuery + '"';
1361						keepItem.addEventListener('mouseenter', function() { keepItem.style.background = '#fff5f5'; });
1362						keepItem.addEventListener('mouseleave', function() { keepItem.style.background = '#fff'; });
1363						keepItem.addEventListener('mousedown', function(e) {
1364							e.preventDefault();
1365							addrInput.value = lastQuery;
1366							suggestions.style.display = 'none';
1367						});
1368						suggestions.appendChild(keepItem);
1369
1370						if (!data.features || !data.features.length) {
1371							suggestions.style.display = 'block';
1372							return;
1373						}
1374
1375						var seenLabels = {};
1376						data.features.forEach(function(f) {
1377							var p        = f.properties;
1378							var street   = p.street || '';
1379							if (!street) { return; }
1380							var number   = p.housenumber || '';
1381							var city     = p.city || p.town || p.village || '';
1382							var postcode = p.postcode || '';
1383							var state    = p.state || p.county || '';
1384							var country  = translateCountry(p.country || '');
1385							var label    = [street + (number ? ' ' + number : ''), city, country].filter(Boolean).join(', ');
1386							if (!label || seenLabels[label]) { return; }
1387							seenLabels[label] = true;
1388
1389							var item = document.createElement('div');
1390							item.style.cssText = 'padding:8px 12px;cursor:pointer;border-bottom:1px solid #f0f0f0;font-size:13px;';
1391							item.textContent = label;
1392
1393							item.addEventListener('mouseenter', function() { item.style.background = '#f5f5f5'; });
1394							item.addEventListener('mouseleave', function() { item.style.background = '#fff'; });
1395
1396							item.addEventListener('mousedown', function(e) {
1397								e.preventDefault();
1398								addrInput.value = street + (number ? ' ' + number : '');
1399								var cityEl    = document.getElementById('swal-city');
1400								var zipEl     = document.getElementById('swal-zip');
1401								var stateEl   = document.getElementById('swal-state');
1402								var countryEl = document.getElementById('swal-country');
1403								if (cityEl    && city)     { cityEl.value    = city; }
1404								if (zipEl     && postcode) { zipEl.value     = postcode; }
1405								if (stateEl   && state)    { stateEl.value   = state; }
1406								if (countryEl && country)  { countryEl.value = country; }
1407								suggestions.style.display = 'none';
1408							});
1409
1410							suggestions.appendChild(item);
1411						});
1412
1413						suggestions.style.display = 'block';
1414					})
1415					.catch(function() { suggestions.style.display = 'none'; });
1416			}, 300);
1417		});
1418
1419		addrInput.addEventListener('blur', function() {
1420			setTimeout(function() { suggestions.style.display = 'none'; }, 150);
1421		});
1422	}
1423
1424	updateDots();
1425	updateBtn();
1426
1427	boxes.forEach(function(box, i) {
1428
1429		box.addEventListener('keydown', function(e) {
1430			if (e.key === 'Backspace') {
1431				if (box.value === '' && i > 0) {
1432					boxes[i - 1].value = '';
1433					boxes[i - 1].classList.remove('tio-filled');
1434					boxes[i - 1].focus();
1435				} else {
1436					box.value = '';
1437					box.classList.remove('tio-filled');
1438				}
1439				updateDots();
1440				updateBtn();
1441				e.preventDefault();
1442			}
1443			if (e.key === 'ArrowLeft'  && i > 0) boxes[i - 1].focus();
1444			if (e.key === 'ArrowRight' && i < 5) boxes[i + 1].focus();
1445		});
1446
1447		box.addEventListener('input', function() {
1448			var val = box.value.replace(/[^0-9]/g, '');
1449			if (val.length > 1) {
1450				val.split('').forEach(function(d, j) {
1451					if (i + j < 6) { boxes[i + j].value = d; boxes[i + j].classList.add('tio-filled'); }
1452				});
1453				boxes[Math.min(i + val.length, 5)].focus();
1454			} else {
1455				box.value = val;
1456				if (val !== '') { box.classList.add('tio-filled'); if (i < 5) boxes[i + 1].focus(); }
1457				else              box.classList.remove('tio-filled');
1458			}
1459			updateDots();
1460			updateBtn();
1461		});
1462
1463		box.addEventListener('focus', function() { box.select(); });
1464	});
1465
1466	termsCheck.addEventListener('change', updateBtn);
1467
1468	submitBtn.addEventListener('click', function() {
1469
1470		var number = getNumber();
1471		if (number.length !== 6) { return; }
1472		if (termsCheck.checked === false) { return; }
1473		statusMsg.style.display = 'none';
1474		setLoading(true);
1475
1476		_this.loadUserToken().then(function(token) {
1477
1478			if (!token) {
1479				setLoading(false);
1480				updateBtn();
1481				window.location.href = _this.m.config.mytio + '/?action=login&redirect=' + encodeURIComponent(window.location.href + '?number=' + number);
1482				return;
1483			}
1484
1485			var p = {};
1486			p.action = 'contest_number';
1487			p.token  = token;
1488			p.number = number;
1489
1490			fetch('/ext/mytio/', {
1491				method: 'POST',
1492				headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
1493				body: new URLSearchParams(p)
1494			})
1495				.then(function(res) { return res.json(); })
1496				.then(function(data) {
1497
1498					if (data && data.message === 'OK') {
1499
1500						showStatus('success', 'Numero ' + number + ' registrato! Riceverai una conferma via email. Buona fortuna!');
1501						boxes.forEach(function(b) { b.value = ''; b.classList.remove('tio-filled'); });
1502						termsCheck.checked = false;
1503						updateDots();
1504						updateBtn();
1505
1506					} else if (data && data.message === 'PROFILE_NOT_COMPLETED') {
1507
1508						setLoading(false);
1509						var user = data.user || {};
1510
1511						function buildStudyTitle(current) {
1512							var opts = [
1513								['', '-'], ['1', 'Scuole medie'], ['2', 'Scuole superiori'],
1514								['3', 'Formazione professionale'], ['4', 'Università']
1515							];
1516							return opts.map(function(o) {
1517								return '<option value="' + o[0] + '"' + (String(current) === o[0] ? ' selected' : '') + '>' + o[1] + '</option>';
1518							}).join('');
1519						}
1520
1521						function buildJobTitle(current) {
1522							var opts = [
1523								['', '-'], ['1', 'Indipendente'], ['2', 'Professionista'],
1524								['3', 'Artigiano'], ['4', 'Impiegato'], ['5', 'Dirigente'],
1525								['6', 'Casalinga'], ['7', 'Studente']
1526							];
1527							return opts.map(function(o) {
1528								return '<option value="' + o[0] + '"' + (String(current) === o[0] ? ' selected' : '') + '>' + o[1] + '</option>';
1529							}).join('');
1530						}
1531
1532						var row  = 'display:grid; grid-template-columns:1fr 1fr; gap:12px;';
1533						var lbl  = 'font-size:12px;font-weight:600;color:#555;display:block;margin-bottom:4px;';
1534						var star = '<span style="color:#E8001A">*</span>';
1535						var birthVal      = user.birthDay || '';
1536						var birthEditable = !birthVal || birthVal.slice(5) === '01-01';
1537						var birthAttrs    = birthEditable ? '' : ' readonly style="background:#f5f5f5;color:#aaa;cursor:not-allowed;"';
1538
1539						var formHtml =
1540							'<p class="text-muted" style="font-size:13px;">Controlla e completa i dati del tuo profilo per partecipare al concorso.<br>I dati non validi annulleranno la partecipazione.</p>' +
1541							'<div style="background:#f8f8f8;border:1px solid #e0e0e0;border-radius:8px;padding:10px 14px;font-size:13px;color:#555;margin-bottom:4px;">La conferma di partecipazione sarà inviata a: <strong style="color:#1
1541a1a1a;">' + (user.email || '') + '</strong></div>' +
1542
1543							'<div style="' + row + '">' +
1544							'<div><label style="' + lbl + '">Nome ' + star + '</label><input id="swal-firstName" class="form-control" type="text" placeholder="Nome" value="' + (user.firstName || '') + '"></div>' +
1545							'<div><label style="' + lbl + '">Cognome ' + star + '</label><input id="swal-lastName" class="form-control" type="text" placeholder="Cognome" value="' + (user.lastName || '') + '"></div>' +
1546							'</div>' +
1547
1548							'<div><label style="' + lbl + '">Data di nascita ' + star + '</label><input id="swal-birthDay" class="form-control" type="date" value="' + birthVal + '"' + birthAttrs + '></div>' +
1549
1550							'<div style="position:relative;">' +
1551							'<label style="' + lbl + '">Indirizzo ' + star + '</label>' +
1552							'<input id="swal-address" class="form-control" type="text" placeholder="Via/Piazza e numero civico" value="' + (user.address || '') + '" autocomplete="off">' +
1553							'<div id="swal-address-suggestions" style="position:absolute;z-index:99999;background:#fff;border:1px solid #ddd;border-radius:6px;width:100%;max-height:220px;overflow-y:auto;display:none;box-shadow:0 4px 12px rgba(0,0,0,0.1);"></div>' +
1554							'</div>' +
1555
1556							'<div style="' + row + '">' +
1557							'<div><label style="' + lbl + '">Città ' + star + '</label><input id="swal-city" class="form-control" type="text" placeholder="Città" value="' + (user.city || '') + '"></div>' +
1558							'<div><label style="' + lbl + '">CAP ' + star + '</label><input id="swal-zip" class="form-control" type="text" placeholder="6900" value="' + (user.zip || '') + '"></div>' +
1559							'</div>' +
1560
1561							'<div style="' + row + '">' +
1562							'<div><label style="' + lbl + '">Cantone / Regione ' + star + '</label><input id="swal-state" class="form-control" type="text" placeholder="Ticino" value="' + (user.state || '') + '"></div>' +
1563							'<div><label style="' + lbl + '">Paese ' + star + '</label><input id="swal-country" class="form-control" type="text" placeholder="Svizzera" value="' + (user.country || '') + '"></div>' +
1564							'</div>' +
1565
1566							'<div style="' + row + '">' +
1567							'<div><label style="' + lbl + '">Titolo di studio ' + star + '</label><select id="swal-studyTitle" class="form-control">' + buildStudyTitle(user.studyTitle) + '</select></div>' +
1568							'<div><label style="' + lbl + '">Professione ' + star + '</label><select id="swal-jobTitle" class="form-control">' + buildJobTitle(user.jobTitle) + '</select></div>' +
1569							'</div>' +
1570
1571							'</div>';
1572
1573						swal.fire({
1574							title: 'Completa il tuo profilo',
1575							html: formHtml,
1576							confirmButtonText: 'Salva e partecipa',
1577							confirmButtonColor: '#E8001A',
1578							cancelButtonText: 'Annulla',
1579							showCancelButton: true,
1580							reverseButtons: true,
1581							allowOutsideClick: false,
1582							allowEscapeKey: false,
1583							onOpen: function() {
1584								initAddressAutocomplete();
1585							},
1586							preConfirm: function() {
1587
1588								var fields = {};
1589								var missing = [];
1590
1591								var elFirst   = document.getElementById('swal-firstName');
1592								var elLast    = document.getElementById('swal-lastName');
1593								var elBirth   = document.getElementById('swal-birthDay');
1594								var elAddress = document.getElementById('swal-address');
1595								var elCity    = document.getElementById('swal-city');
1596								var elZip     = document.getElementById('swal-zip');
1597								var elState   = document.getElementById('swal-state');
1598								var elCountry = document.getElementById('swal-country');
1599								var elStudy   = document.getElementById('swal-studyTitle');
1600								var elJob     = document.getElementById('swal-jobTitle');
1601
1602								if (elFirst)   { if (!elFirst.value.trim())   missing.push('Nome');             else fields.firstName  = elFirst.value.trim(); }
1603								if (elLast)    { if (!elLast.value.trim())    missing.push('Cognome');          else fields.lastName   = elLast.value.trim(); }
1604								if (elBirth)   { if (!elBirth.value)          missing.push('Data di nascita');  else fields.birthDay   = elBirth.value; }
1605								if (elAddress) { if (!elAddress.value.trim()) missing.push('Indirizzo');        else fields.address    = elAddress.value.trim(); }
1606								if (elCity)    { if (!elCity.value.trim())    missing.push('Città');            else fields.city       = elCity.value.trim(); }
1607								if (elZip)     { if (!elZip.value)            missing.push('CAP');              else fields.zip        = elZip.value; }
1608								if (elState)   { if (!elState.value.trim())   missing.push('Cantone');          else fields.state      = elState.value.trim(); }
1609								if (elCountry) { if (!elCountry.value.trim()) missing.push('Paese');
1609            else fields.country    = elCountry.value.trim(); }
1610								if (elStudy)   { if (!elStudy.value)          missing.push('Titolo di studio'); else fields.studyTitle = elStudy.value; }
1611								if (elJob)     { if (!elJob.value)            missing.push('Professione');      else fields.jobTitle   = elJob.value; }
1612
1613								if (missing.length > 0) {
1614									swal.showValidationMessage('Campi obbligatori mancanti: ' + missing.join(', '));
1615									return false;
1616								}
1617
1618								return fields;
1619							}
1620						}).then(function(result) {
1621
1622							if (!result.value) { return; }
1623
1624							_this.loadUserToken().then(function(token) {
1625
1626								var profileData = result.value;
1627								profileData.action = 'update_user_for_contest';
1628								profileData.token  = token;
1629
1630								setLoading(true);
1631
1632								fetch('/ext/mytio/', {
1633									method: 'POST',
1634									headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
1635									body: new URLSearchParams(profileData)
1636								})
1637									.then(function(res) { return res.json(); })
1638									.then(function(updateData) {
1639
1640										if (updateData && updateData.message === 'OK') {
1641
1642											var retry = {};
1643											retry.action = 'contest_number';
1644											retry.token  = token;
1645											retry.number = number;
1646											retry.fromEditProfile = true;
1647
1648											return fetch('/ext/mytio/', {
1649												method: 'POST',
1650												headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
1651												body: new URLSearchParams(retry)
1652											})
1653												.then(function(res) { return res.json(); })
1654												.then(function(retryData) {
1655													if (retryData && retryData.message === 'OK') {
1656														showStatus('success', 'Numero ' + number + ' registrato! Riceverai una conferma via email. Buona fortuna!');
1657														boxes.forEach(function(b) { b.value = ''; b.classList.remove('tio-filled'); });
1658														termsCheck.checked = false;
1659														updateDots();
1660														updateBtn();
1661													} else {
1662														var msg = (retryData && retryData.messageText) ? retryData.messageText : 'Si è verificato un errore. Riprova.';
1663														showStatus('error', msg);
1664													}
1665												});
1666
1667										} else {
1668											var msg = (updateData && updateData.messageText) ? updateData.messageText : 'Errore durante l\'aggiornamento del profilo.';
1669											showStatus('error', msg);
1670										}
1671									})
1672									.catch(function() {
1673										showStatus('error', 'Errore di connessione. Controlla la tua rete e riprova.');
1674									})
1675									.finally(function() {
1676										setLoading(false);
1677										updateBtn();
1678									});
1679							});
1680						});
1681
1682					} else {
1683
1684						var errorMsg = (data && data.messageText) ? data.messageText : 'Si è verificato un errore. Riprova.';
1685						showStatus('error', errorMsg);
1686						boxes.forEach(function(b) { b.classList.add('tio-error-shake'); });
1687						setTimeout(function() {
1688							boxes.forEach(function(b) { b.classList.remove('tio-error-shake'); });
1689						}, 400);
1690
1691					}
1692				})
1693				.catch(function() {
1694					showStatus('error', 'Errore di connessione. Controlla la tua rete e riprova.');
1695				})
1696				.finally(function() {
1697					setLoading(false);
1698					updateBtn();
1699				});
1700		});
1701	});
1702};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.