PageSourceSearch

https://uvejuegos.com/js/controles.js?now=2026100213

js uvejuegos.com collected 2026-10-02 11:43:00 UTC 29,149 bytes, 869 lines download raw bytes

1(function ($)
2{
3	/* Funciones que permiten abrir una página dentro de una ventana modal */
4	/*
5	Uso: <a href="url" data-toggle="modal-ajax" data-target="#modal">
6	Donde:
7		url: La URL que se abrirá dentro del modal. Esta página debe contener una capa con el id "contenido-modal", que será la porción de html que se muestre dentro del modal.
8		#modal: Es el modal donde se mostrará la página. Normalmente no es necesario cambiar este atributo.
9	*/
10	/* Atributos opcionales:
11		data-titulo="titulo". El título que tendrá la ventana modal. Si se omite, por defecto será "uVeJuegos.com".
12		data-url="url". URL alternativa que se cargará en el modal, si por alguna razón debe ser diferente de la del enlace. Por ejemplo, una versión reducida de la url especificada en el href.
13	*/
14	var ventana = null;
15	var ventanaContenido = null;
16
17	function modalAbriendo (event)
18	{
19		$(this).addClass ("cargando");
20	}
21
22	function modalAbierto (event)
23	{
24		var $this = $(this);
25		var href = $this.data ("url");
26		if (href == null) href = event.relatedTarget.href;
27		var contenido = $this.find (".contenido");
28
29		contenido.load (href + " #contenido-modal", {ajax: 1},
30			function (response, status, xhr)
31			{
32				$this.removeClass ("cargando");
33				if (status == "error")
34				{
35					contenido.html ("No se ha podido completar la acción debido a un error de comunicación con el servidor. Por favor, comprueba tu conexión.");
36				}
37				else
38				{
39					contenido.find ("[autofocus]").focus ();
40				}
41			}
42		);
43	}
44
45	function modalCerrado (event)
46	{
47        $(this).find (".modal-title").html ("");
48		$(this).find (".contenido").html ("");
49	}
50
51	$(document).ready (function ()
52	{
53		$(document.body).on ("click", "[data-toggle='modal-ajax'][data-target]", function (event)
54		{
55			var $this = $(this);
56            var titulo = $this.data ("titulo");
57			var modal = $($this.data ("target"));
58
59			if (modal.data ("iniciado") == null)
60			{
61				modal.on ("show.bs.modal", modalAbriendo);
62				modal.on ("shown.bs.modal", modalAbierto);
63				modal.on ("hidden.bs.modal", modalCerrado);
64				modal.find (".modal-body").append ("<div class=\"contenido container-fluid\"></div>");
65				modal.data ("iniciado", 1);
66			}
67
68            modal.find (".modal-title").html (titulo == null? "uVeJuegos.com": titulo);
69
70			event.preventDefault ();
71			modal.modal ("show", this);
72		});
73
74		$(document.body).on ("submit", ".modal form[data-ajax]", function (event)
75		{
76			var $this = $(this);
77
78			$this.ajaxSubmit ({dataType: "text", dataFilter: filtrarJson, data: {json: "1"},
79				beforeSubmit: function (data, form, options)
80				{
81					$this.find ("button[type=submit]").prop ("disabled", true);
82				},
83				success: function (data, status, xhr, form)
84				{
85					if (data.ok)
86                    {
87                        var funcionOk = $this.data ("funcion-ok");
88                        $this.parents (".modal").modal ("hide");
89                        if (funcionOk) window[funcionOk] (data);
90                    }
91                    if (data.mensaje != null && data.mensaje.length > 0) alert (data.mensaje);
92				},
93				error: function (xhr, status, error, form)
94				{
95					alert ("No se ha podido completar la acción debido a un error de comunicación con el servidor. Por favor, comprueba tu conexión.");
96					$this.find ("button[type=submit]").removeProp ("disabled");
97				}
98			});
99			event.preventDefault ();
100		});
101	});
102
103} (jQuery));
104
105(function ($, window)
106{
107	/* Funciones que gestionan las notificaciones */
108
109	var boton = null;
110	var capa = null;
111	var lista = null;
112	var timeout = null;
113	var intervaloMin = 10000; // Diez segundos
114    var intervaloMax= 600000; // Diez minutos
115	var intervalo = intervaloMin;
116	var inicializado = false;
117	var dibujado = false;
118
119	var notificaciones = null;
120	var numNotificaciones = null;
121	var noLeidas = 0;
122	var maxId = 0;
123	var tituloPagina = "";
124
125	function inicializar ()
126	{
127		if (!inicializado) actualizar ();
128		else if (!dibujado) dibujarNotificaciones ();
129	}
130
131	function actualizar ()
132	{
133		inicializado = true;
134		detenerTemporizador ();
135		capa.addClass ("actualizando").removeClass ("error actualizado");
136
137		$.ajax ({url: "/notificacionesUsuarioJSON.jsp", type: "post", dataType: "json", success: actualizarOk, error: actualizarError, complete: actualizarCompletado});
138	}
139
140	function actualizarNumNotificaciones ()
141	{
142		$("[data-notificaciones=\"num-notificaciones\"]").html (noLeidas);
143		if (noLeidas == 0)
144		{
145			document.title = tituloPagina;
146			boton.removeClass ("tiene-notificaciones");
147		}
148		else
149		{
150			document.title = "(" + noLeidas + ") " + tituloPagina;
151			boton.addClass ("tiene-notificaciones");
152		}
153	}
154
155	function dibujarNotificaciones ()
156	{
157		// Por razones de eficiencia, especialmente en móviles, no se dibujan las notificaciones si la ventana está cerrada.
158		if (!boton.hasClass ("active")) return;
159
160		var html = "";
161
162		$.each (notificaciones, function (pos, notificacion)
163		{
164			html += "<div data-notificaciones-id=\"" + notificacion.idNotificacion + "\" class=\"notificacion";
165			html += notificacion.leido? " leido": " no-leido";
166			html += notificacion.sePuedeExcluir? " puede-excluir": " no-puede-excluir";
167			html += "\">";
168			html += "<time datetime=\"" + notificacion.fecha + "\">" + notificacion.fechaHumana + "</time>";
169			html += "<div>" + notificacion.texto;
170			if (notificacion.informacionExtra.length > 0) html += "<br><span class=\"info-extra\">" + notificacion.informacionExtra + "</span>";
171			html += "</div>";
172			html += "<button type=\"button\" data-notificaciones=\"btn-opciones\"><span class=\"mdi mdi-dots-vertical\"></span></button>";
173            html += "<div class=\"notificacion-opciones\">";
174			html += "<a href=\"/notificacionLeida.jsp?idNotificacion=" + notificacion.idNotificacion + "\" data-funcion-ok=\"marcarLeido\"><span><span class=\"mdi mdi-check\"></span><br>Leída</span></a>";
175			html += "<a href=\"/notificacionNoLeida.jsp?idNotificacion=" + notificacion.idNotificacion + "\" data-funcion-ok=\"marcarNoLeido\"><span><span class=\"mdi mdi-bookmark-outline\"></span><br>No leída</span></a>";
176			html += "<a href=\"/notificacionExcluida.jsp?id=" + notificacion.id + "&tipo=" + notificacion.tipo + "&excluir=true\" data-funcion-ok=\"marcarExcluir\"><span><span class=\"mdi mdi-bell-off\"></span><br>Excluir</span></a>";
177			html += "<a href=\"/borrarNotificacion.jsp?idNotificacion=" + notificacion.idNotificacion + "\" data-funcion-ok=\"borrar\"><span><span class=\"mdi mdi-delete\"></span><br>Borrar</span></a>";
178			html += "</div>";
179			html += "</div>";
180		});
181
182		lista.html (html);
183		
184		dibujado = true;
185	}
186
187	function actualizarOk (data)
188	{
189		var nuevas = false;
190		var ultimoNoLeidas = noLeidas;
191		var ultimoMaxId = maxId;
192		noLeidas = 0;
193		notificaciones = data.notificaciones;
194
195		// Comprobación del número de notificaciones no leídas y el id de la notificación más reciente.
196		$.each (notificaciones, function (pos, notificacion)
197		{
198			if (!notificacion.leido) noLeidas ++;
199			if (notificacion.idNotificacion > maxId) maxId = notificacion.idNotificacion;
200		});
201
202		// Si no ha habido cambios desde la última actualización, se duplica el intervalo de actualización hasta el máximo establecido en intervaloMax.
203		// De lo contrario el intervalo se reinicia a su valor inicial, establecido en intervaloMin.
204		if (maxId == ultimoMaxId && noLeidas == ultimoNoLeidas)
205		{
206			intervalo *= 2;
207			if (intervalo > intervaloMax) intervalo = intervaloMax;
208		}
209		else intervalo = intervaloMin;
210
211		capa.addClass ("actualizado");	
212		dibujado = false;
213		actualizarNumNotificaciones ();
214		dibujarNotificaciones ();
215		iniciarTemporizador ();
216	}
217
218	function actualizarError ()
219	{
220		capa.addClass ("error");
221	}
222
223	function actualizarCompletado ()
224	{
225		capa.removeClass ("actualizando");
226	}
227
228	function iniciarTemporizador ()
229	{
230		detenerTemporizador ();
231		timeout = setTimeout (actualizar, intervalo);
232	}
233
234	function detenerTemporizador ()
235	{
236		if (timeout != null)
237		{
238			clearTimeout (timeout);
239			timeout = null;
240		}
241	}
242
243	function mostrarOpciones ()
244	{
245		var $this = $(this);
246		var elemento = $this.parents (".notificacion");
247		elemento.toggleClass ("mostrar-opciones");
248	}
249
250	function ejecutarAccion (event)
251	{
252		var $this = $(this);
253		var elemento = $this.parents (".notificacion");
254		$this.addClass ("cargando");
255
256		$.ajax ({url: $this.attr ("href"), dataType: "json",
257			success: function (data)
258			{
259				var funcionOk = $this.data ("funcion-ok");
260				if (funcionOk != null) eval (funcionOk) (data, elemento);
261			},
262			error: function ()
263			{
264				alert ("No se ha podido completar la acción debido a un error de comunicación con el servidor.");
265			},
266			complete: function ()
267			{
268				$this.removeClass ("cargando");
269			}
270		});
271
272		event.preventDefault ();
273	}
274
275	function marcarLeido (data, elemento)
276	{
277		noLeidas --;
278		actualizarNumNotificaciones ();
279		elemento.addClass ("leido").removeClass ("no-leido mostrar-opciones");
280	}
281
282	function marcarNoLeido (data, elemento)
283	{
284		noLeidas ++;
285		actualizarNumNotificaciones ();
286		elemento.addClass ("no-leido").removeClass ("leido mostrar-opciones");
287	}
288
289	function marcarExcluir (data, elemento)
290	{
291		actualizar ();
292		alert(data.mensaje);
293	}
294
295	function borrar (data, elemento)
296	{
297		if (elemento.hasClass ("no-leida"))
298		{
299			noLeidas --;
300			actualizarNumNotificaciones ();
301		}
302		elemento.remove ();
303	}
304
305	$(document).ready (function ($)
306	{
307		// Solo se inicializan las notificaciones si el usuario ha iniciado sesión.
308		if (!$(document.body).hasClass ("usuario-conectado")) return false;
309
310		boton = $("#boton-notificaciones");
311		capa = $("#menu-notificaciones");
312		seccionNotificaciones = $("#seccion-notificaciones");
313		lista = capa.find (".lista");
314
315		var titulo = document.title.match (/^\(([0-9]+)\) (.+)$/);
316		tituloPagina = titulo == null? document.title: titulo[2];
317
318		boton.on ("click", inicializar);
319		capa.on ("click", "[data-notificaciones=\"btn-actualizar\"]", actualizar);
320		capa.on ("click", "[data-notificaciones=\"btn-opciones\"]", mostrarOpciones);
321		capa.on ("click", ".notificacion-opciones a", ejecutarAccion);
322		seccionNotificaciones.on ("click", "[data-notificaciones=\"btn-opciones\"]", mostrarOpciones);
323		seccionNotificaciones.on ("click", ".notificacion-opciones a", ejecutarAccion);
324		
325		// Para preservar datos y batería, las notificaciones no se inicializan automáticamente en móviles.
326		// En cualquier caso se actualizan durante la navegación o si el usuario abre manualmente la ventana.
327		if ($(window).width () > 768)
328		{
329			iniciarTemporizador ();
330		}
331
332		// Esto convierte la función inicializar en pública.
333		window.inicializarNotificaciones = inicializar;
334	});
335 
336}) (jQuery, window);
337
338(function ($, window)
339{
340	// Gestión del botón "Colabora"
341	// Uso: <button data-toggle="colabora">...</button>
342	// o: <a href="#" data-toggle="colabora">...</a>
343	/* Atributos opcionales:
344		data-colabora-juego-id="id". Donde "id" es el juego al que se asociarán los nuevos contenidos. Si este atributo está presente, el usuario no tendrá que seleccionar juego.
345	*/
346
347	var $body = null;
348	var ventanaColaboraContenido = null;
349	var urlNuevoContenido = "";
350
351	function botonColaboraClick (event)
352	{
353		event.preventDefault ();
354
355		if (ventanaColaboraContenido == null)
356		{
357			ventanaColaboraContenido = $("#ventana-colabora-contenido");
358			ventanaColaboraContenido.on ("click", "[data-colabora-url]", mostrarBuscador);
359		}
360
361		if ($body.hasClass ("menu-colabora-abierto"))
362		{
363			$body.removeClass ("menu-colabora-abierto");
364			ventanaColaboraContenido.html ("");
365			ventanaColaboraContenido.removeClass ("mostrar-buscador");
366			return false;
367		}
368
369		var url ="/colabora.jsp";
370		var idJuego = $(this).data ("colabora-juego-id");
371		if (idJuego != null) url += "?idJuego=" + idJuego;
372
373		$body.addClass ("menu-colabora-abierto");
374		ventanaColaboraContenido.addClass ("cargando").load (url + " #contenido-modal", {ajax: 1},
375			function (response, status, xhr)
376			{
377				ventanaColaboraContenido.removeClass ("cargando");
378				if (status == "error")
379				{
380					ventanaColaboraContenido.html ("No se ha podido completar la acción debido a un error de comunicación con el servidor. Por favor, comprueba tu conexión.");
381				}
382			}
383		);
384	}
385
386	function mostrarBuscador (event)
387	{
388		if (ventanaColaboraContenido.hasClass ("mostrar-buscador"))
389		{
390			urlNuevoContenido = "";
391			ventanaColaboraContenido.removeClass ("mostrar-buscador");
392		}
393		else
394		{
395			urlNuevoContenido = $(this).data ("colabora-url");
396			ventanaColaboraContenido.addClass ("mostrar-buscador");
397		}
398
399		event.preventDefault ();
400	}
401
402	function dibujarJuegos (input, data)
403	{
404		var lista = $("#colabora-lista-juegos");
405		lista.html ("");
406
407		if (data.juegos.length > 0)
408		{
409			$.each (data.juegos, function (pos, juego)
410			{
411				var url = urlNuevoContenido.replace ("{idJuego}", juego.idJuego);
412				lista.append ("<div class=\"media\"><div class=\"media-body\"><span class=\"plataforma\" style=\"color: " + juego.colorPlataforma + "\">" + juego.plataformaAbreviada + "</span>" + juego.titulo + "</div><div class=\"media-right media-middle\"><a href=\""+ url + "\" class=\"btn btn-primary btn-sm\">Seleccionar</a></div></div></div>");
413			})
414		}
415	}
416
417	$(document).ready (function ($)
418	{
419		$body = $(document.body);
420		$body.on ("click", "[data-toggle=\"colabora\"]", botonColaboraClick);
421
422		window.dibujarJuegosColabora = dibujarJuegos;
423	});
424
425}) (jQuery, window);
426
427(function ($)
428{
429	/* Buscador de juegos con autobúsqueda */
430	/*
431		Uso: <input data-toggle="buscador-juegos" data-funcion-ok="funcion">
432		Donde:
433				funcion: Es la función que se ocupará de dibujar los resultados. Esta función recibe como párametros el input que lanzó la búsqueda y el json devuelto.
434	*/
435	/* Atributos opcionales:
436		data-url="url". Donde "url" es la ruta hacia donde se lanzará la petición. Si se omite, por defecto es "/listaJuegosJSON.jsp?titulo={texto}". "{texto}" se sustituye por el criterio de búsqueda.
437		data-caracteres="numero". Donde "numero" es el mínimo de caracteres que activa la búsqueda. Si se omite, por defecto es 3.
438		data-retardo="numero". Donde "numero" es el tiempo en milisegundos en el que comenzará lá búsqueda después de la última pulsación de tecla.
439							   Es necesario para que no se estén lanzando búsquedas cuando el usuario aún no ha terminado de escribir. Si se omite, por defecto es 500.
440	*/
441
442	var timeout = null;
443	var input = null;
444
445	function buscarJuegosKeyUp (event)
446	{
447		input = $(this);
448		var retardo = input.data ("retardo")? input.data ("retardo"): 500;
449
450		if (timeout != null) clearTimeout (timeout);
451		timeout = setTimeout (buscar, retardo);
452	}
453
454	function buscar (event)
455	{
456		var busqueda = input.val ();
457		var funcionOk = input.data ("funcion-ok");
458		var url = input.data ("url")? input.data ("url"): "/listaJuegosJSON.jsp?titulo={texto}";
459		var minCaracteres = input.data ("caracteres")? input.data ("caracteres"): 3;
460
461		timeout = null;
462		url = url.replace ("{texto}", busqueda);
463
464		if (busqueda.length >= minCaracteres)
465		{
466			$.ajax ({url: url, dataType: "text", dataFilter: filtrarJson,
467				success: function (data)
468				{
469					window[funcionOk] (input, data);
470				}
471			});
472		}
473		else window[funcionOk] (input, {juegos: []});
474	}
475
476	$(document).ready (function ($)
477	{
478		$(document.body).on ("keyup", "[data-toggle=\"buscador-juegos\"][data-funcion-ok]", buscarJuegosKeyUp);
479	});
480
481}) (jQuery, window);
482
483function refrescar () {
484	if (
485	  window.location.href.indexOf('configurarContrasenya')>=0 ||
486	  window.location.href.indexOf('confirmarRegistro')>=0
487	) {
488		document.location.href='/';
489	} else {
490		window.location.reload ();
491	}
492}
493
494function enfocarBuscador ()
495{
496    $("#txt-buscador-juegos").focus ();
497}
498
499function enfocarLogin ()
500{
501    $("#login-usuario").focus ();
502}
503
504function filtrarJson (data)
505{
506    var json = data.replace (/^[^\[{]+|[^\]}]+$/gm, "");
507    json = JSON.parse (data);
508    return json;
509}
510
511/* Función para validar una fecha que está en forma de cadena de texto.
512Comprueba que la fecha tenga el formato DD/MM/YYYY y que exista realmente. Por ejemplo, no acepta una fecha como 30/02/2017. */
513function validarFecha (fecha)
514{
515	var fechaOk = false;
516	if (/^\d{1,2}\/\d{1,2}\/\d{4}$/.test (fecha)) // Directamente rechazamos la fecha si no tiene el formato adecuado.
517	{
518		var partes = fecha.split ("/");
519		var dia = parseInt (partes[0]);
520		var mes = parseInt (partes[1]) - 1; // En javascript los meses van de 0 a 11.
521		var ano = parseInt (partes[2]);
522
523		// El objeto Date de javascript corrige automáticamente las fechas no válidas, así que es muy cómodo para la validación.
524		// Si los valores no han sido alterados, es que la fecha existe.
525		var objFecha = new Date (ano, mes, dia);
526		if (objFecha.getDate () == dia && objFecha.getMonth () == mes && objFecha.getFullYear () == ano) fechaOk = true;
527	}
528
529	return fechaOk;
530}
531
532function MostrarSpoiler (spoiler)
533{
534	$("#enlace"+spoiler).css ({display: "none"});
535	$("#spoiler"+spoiler).addClass ("activo");
536}
537
538function insertarVideo (capa, url, ancho, alto)
539{
540	var infoVideo = obtenerVideoEmbed (url);
541	if (infoVideo.url == "") return false; // La URL no está soportada
542
543	var $capa = $("#" + capa);
544	if (ancho == undefined) ancho = 0;
545	if (alto == undefined) alto = 0;
546	if (infoVideo.ancho > 0) ancho = infoVideo.ancho;
547	if (infoVideo.alto > 0) alto = infoVideo.alto;
548
549	var html = "<div class=\"contenedor-video\"";
550	if (ancho > 0) html += " style=\"max-width: " + ancho + "px;\"";
551	html += ">";
552	if (alto == 0) html += "<div class=\"embed-responsive embed-responsive-16by9\">";
553	html += "<iframe ";
554	if (alto == 0) html += "class=\"embed-responsive-item\"";
555	else html += "style=\"height: " + alto + "px\"";
556	html += " src=\"" + infoVideo.url + "\" allowfullscreen=\"1\"></iframe></div></div>";
557	if (alto == 0) html += "</div>";
558	html += "</div>";
559
560	$capa.append (html);
561}
562
563function generarProgresoCircular (capa, puntuacion, opciones) {
564	var $capa = $(capa);
565	var opcionesDefecto = {startAngle: -Math.PI / 2, thickness: 20, lineCap: "round", value: puntuacion / 100, size: 180};
566	var opciones = $.extend (opcionesDefecto, opciones);
567
568	if (opciones.fill == undefined)
569	{
570		if (puntuacion < 25) opciones.fill = "#CF000F";
571		else if (puntuacion < 50) opciones.fill = "#E74C3C";
572		else if (puntuacion < 75) opciones.fill = "#F5D76E";
573		else if (puntuacion < 85) opciones.fill = "#87D37C";
574		else opciones.fill = "#8CC63F";
575	}
576
577	$capa.append("<div class=\"progreso-circular-info\"><span class=\"textovj\">Puntuación<br>uVeJuegos</span><div class=\"nota open-sans-bold\">" + puntuacion + "</div><a href=\"/referenciaNotas.jsp\" class=\"color-primario\" data-toggle=\"modal-ajax\" data-target=\"#modal\" data-titulo=\"Así puntuamos en uVeJuegos.com\"><span class=\"mdi mdi-information-outline\"></span></a></div>");
578	$capa.circleProgress(opciones);
579	$capa.circleProgress();
580}
581
582(function ($)
583{
584	var $body;
585	var $header;
586
587	$(function ()
588	{
589		$body = $(document.body);
590
591		/* Función que controla los menús activados desde los botones de la cabecera u otros sitios */
592		/*
593		Uso: <a data-toggle="menu" data-activo="clases">
594		Donde:
595				clases: Son las clases de CSS que se añadirán a la etiqueta body cuando el menú esté abierto.
596		*/
597		/* Atributos opcionales:
598			data-funcion-abierto="funcion". Donde "funcion" es el nombre de la función que se ejecutará cada vez que el menú se abra.
599		*/
600        $body.on ("click", "[data-toggle=\"menu\"][data-activo]",
601			function (event)
602			{
603                event.preventDefault ();
604				var $this = $(this);
605                if ($this.hasClass ("active"))
606                {
607                    $this.removeClass ("active");
608                    $body.removeClass ($this.data ("activo"));
609                }
610                else
611                {
612					var selectorBotonesMenu = "[data-toggle=\"menu\"][data-activo].active";
613					if (prohibirDespliegueMenuPrincipal) {
614						$(selectorBotonesMenu).trigger("click");
615					} else {
616						$(selectorBotonesMenu + ":not(#botonMenuPrincipal)").trigger("click");
617					}
618                    $this.addClass ("active");
619                    $body.addClass ($this.data ("activo"));
620                    var funcionAbierto = $this.data ("funcion-abierto");
621                    if (funcionAbierto != null) window[funcionAbierto] ($this);
622                }
623			});
624
625        $body.on ("click", "a[href^=\"#\"][data-scroll]", function (event)
626        {
627            event.preventDefault ();
628
629            var capa = $(this.getAttributeNode ("href").value);
630            if (capa.length > 0)
631            {
632                var paddingTop = parseInt ($body.css ("padding-top"));
633                var posY = capa.offset ().top - paddingTop;
634                $("html, body").animate ({scrollTop: posY}, 500);
635            }
636        });
637
638        /* Script para los botones de compartir en redes sociales */
639		/* Uso: <a href="url" class="btn-social"></a> */
640		$body.on ("click", ".btn-social[href]", function (event)
641		{
642			event.preventDefault ();
643			window.open (this.href, "compartir", "toolbar=0, status=0, width=648, height=395");
644		});
645
646        // Actualizar la clase del body para indicar que javascript está activado.
647		$body.removeClass ("javascript-off").addClass ("javascript-on");
648
649	    // $("[data-toggle=\"tooltip\"]").tooltip ();
650	});
651
652} (jQuery));
653
654$(document).ready (function ()
655{
656    /* Función genérica para poder enviar cualquier formulario mediante ajax */
657	/* Uso: <form data-json> */
658	/* Atributos opcionales:
659		data-funcion-validar="funcion". Donde "funcion" es el nombre de la función que validará el formulario, y recibe como parámetro el propio formulario.
660										Si esta función devuelve false, el formulario no se envía.
661		data-funcion-ok="funcion". Donde "funcion" es el nombre de la función que se ejecutará al finalizar el envío correctamente. Recibe como parámetros
662								   la respuesta del servidor y la referencia al propio formulario.
663		data-funcion-reset. Reiniciará el formulario tras enviarse correctamente.
664	*/
665
666	$("form[data-json]").ajaxForm ({dataType: "text", dataFilter: filtrarJson, data: {json: "1"},
667		beforeSubmit: function (data, form, options)
668		{
669            if (form.hasClass ("enviando")) return false;
670
671			var textoConfirmacion = form.data ("texto-confirmacion");
672			if (textoConfirmacion == undefined || confirm (textoConfirmacion))
673			{
674				var funcionValidar = form.data ("funcion-validar");
675				if (funcionValidar)
676				{
677					var ok = window[funcionValidar] (form);
678					if (!ok) return false;
679				}
680				form.addClass ("enviando");
681			}
682			else return false;
683		},
684		success: function (data, status, xhr, form)
685		{
686            form.removeClass ("enviando");
687			if (data.ok)
688			{
689				if (form.data ("reset")) form.resetForm ();
690				var funcionOk = form.data ("funcion-ok");
691				if (funcionOk) window[funcionOk] (data, form);
692			}
693			if (data.mensaje != null && data.mensaje.length > 0) alert (data.mensaje);
694		},
695		error: function (xhr, status, error, form)
696		{
697            form.removeClass ("enviando");
698			var textoError = form.data ("texto-error");
699			alert (textoError == undefined? "No se ha podido completar la acción debi
699do a un error de comunicación con el servidor.": textoError);
700		}
701	});
702
703
704	/* Inicialización de lightbox */
705	/* Uso para una sola imagen: <a href="url-imagen-ampliada" class="lightbox">...</a> */
706	/* Uso para galería: <div class="lightbox-galeria">
707			<a href="imagen-ampliada-1">...</a>
708			<a href="imagen-ampliada-2">...</a>
709			<a href="imagen-ampliada-3">...</a>
710			...
711			<a href="imagen-ampliada-n">...</a>
712		</div>
713
714		Todos los enlaces contenidos en el div activan el lightbox (sin tener que poner la clase individualmente) y se activa la navegación con flechas.
715	*/
716
717	if (jQuery ().magnificPopup)
718	{
719		$(".lightbox").magnificPopup ({type: "image"});
720		$(".lightbox-galeria").each (function () {$(this).magnificPopup ({delegate: "a", type: "image", gallery: {enabled: true}});});
721	}
722	
723	/* Inicialización del menú para resoluciones grandes */
724	/*var anchuraGrande = matchMedia("(min-width: 1400px)");
725	desplegarMenuPrincipal(anchuraGrande.matches);
726	centrarContenido(anchuraGrande.matches);
727	
728	// Este listener se lanza cuando la media query cambia su valor
729	anchuraGrande.addListener(function(mql){
730		desplegarMenuPrincipal(mql.matches);
731	});
732	
733	// En resoluciones grandes, se modifica el ancho del contenido
734	// de la página para que se centre.
735	$( window ).resize(function() {
736		var anchuraGrande = matchMedia("(min-width: 1400px)");
737		centrarContenido(anchuraGrande.matches);
738	});*/
739});
740
741var prohibirDespliegueMenuPrincipal = false;
742
743function desplegarMenuPrincipal(desplegar) {
744	var botonMenu = $('#botonMenuPrincipal');
745	if (!prohibirDespliegueMenuPrincipal && desplegar) {	
746		if (!botonMenu.hasClass("active")) {
747            botonMenu.click();
748			$('#contenido-pagina').css("position", "absolute");
749			$('#contenido-pagina').css("left", "200px");
750			$('body.menu-abierto').css("overflow", "auto");
751			$('#menu-principal').css("width", "200px");
752			botonMenu.hide();
753		}
754	} else {
755		botonMenu.show();
756	    botonMenu.removeClass ("active");
757        $(document.body).removeClass (botonMenu.data ("activo"));
758		$('#contenido-pagina').css("width", "");
759		$('#contenido-pagina').css("position", "");
760		$('#contenido-pagina').css("left", "");
761		$('body.menu-abierto').css("overflow", "");
762		$('#menu-principal').css("width", "");
763	}
764}
765
766function centrarContenido(centrar) {
767	if(centrar) {
768		$('#contenido-pagina').width($( window ).width()-200);
769	}
770}
771
772function soloCuandoHaySkin() {
773	prohibirDespliegueMenuPrincipal = true;
774	desplegarMenuPrincipal(false)
775}
776
777/* Función que analiza una URL y devuelve un objeto con un desglose de sus distintas partes:
778	
779	url: la propia url analizada.
780	dominio: el dominio, sin las www. Por ejemplo, "uvejuegos.com"
781	rutas: array con las partes que conforman la ruta. Por ejemplo ["foro", "Nintendo", "9"]
782	qs: objeto con los parámetros pasados a través de la querystring. Por ejemplo {busquedaAvanzada: "false", titulo: "Perfect Dark", plataforma: "Xbox 360"}
783	hash: La cadena de texto que venga después del carácter #, si la hubiese. Si no, es un texto vacío.
784*/
785
786function infoURL (url)
787{
788	var patron = url.match (/^(https?\:)\/\/(?:www\.)?(([^:\/?#]*)(?:\:([0-9]+))?)\/?([^?#]*)\??([^#]*|)#?(.*|)$/);
789	var salida = {url: url, dominio: "", rutas: [], qs: {}, hash: ""};
790	if (patron == null) return salida;
791	
792	salida.dominio = patron[2]? patron[2]: "";
793	if (patron[5] != null) salida.rutas = patron[5].split ("/");
794	if (patron[6] != null)
795	{
796		var parametros = patron[6].split ("&");
797		$.each (parametros, function (pos, parametro)
798		{
799			var valores = parametro.split ("=");
800			salida.qs[valores[0]] = valores[1]? valores[1]: null;
801		});
802	}
803	salida.hash = patron[7]? patron[7]: "";
804
805	return salida;
806}
807
808function obtenerVideoEmbed (url)
809{
810	var salida = {url: "", ancho: 0, alto: 0};
811	var info = infoURL (url);
812
813	switch (info.dominio)
814	{
815		case "youtube.com":
816		case "youtu.be":
817			var videoId = info.dominio == "youtube.com"? info.qs.v: info.rutas[0];
818			salida.url = "https://www.youtube.com/embed/" + videoId;
819			if (info.qs.t)
820			{
821				if (info.qs.t.match (/^[0-9]+$/)) salida.url += "?start=" + info.qs.t;
822				else
823				{
824					var tiempo = info.qs.t.match (/([0-9]+[h|m|s])/g);
825					if (tiempo)
826					{
827						var t = 0;
828						$.each (tiempo, function (pos, valor)
829						{
830							var unidad = valor.substr (-1, 2);
831							valor = parseInt (valor);
832							if (unidad == "m") valor = valor * 60;
833							else if (unidad == "h") valor = valor * 3600;
834							t += valor;
835						});
836
837						salida.url += "?start=" + t;
838					}
839				}
840			}
841			break;
842
843		case "twitch.tv":
844			if (info.rutas[1]) salida.url = "https://player.twitch.tv/?video=v" + info.rutas[1] + "&autoplay=false";
845			break;
846
847		case "vimeo.com":
848			if (info.rutas[0]) salida.url = "https://player.vimeo.com/video/" + info.rutas[0];
849			break;
850
851		case "dailymotion.com":
852		case "dai.ly":
853			var videoId = info.dominio == "dailymotion.com"? info.rutas[1].substr (0, info.rutas[1].indexOf ("_")): info.rutas[0];
854			salida.url = "//www.dailymotion.com/embed/video/" + videoId;
855			break;
856
857		case "open.spotify.com":
858		case "play.spotify.com":
859			if (info.rutas[1])
860			{
861				salida.url = "https://open.spotify.com/embed?uri=spotify%3Atrack%3A" + info.rutas[1];
862				salida.ancho = 300;
863				salida.alto = 380;
864			}
865			break;
866	}
867
868	return salida;
869}

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.