Foros del Web » Programando para Internet » Javascript »

Evitar captura de eventos simultaneos. Lo estoy haciendo bien?

Estas en el tema de Evitar captura de eventos simultaneos. Lo estoy haciendo bien? en el foro de Javascript en Foros del Web. Perdón por el titulo que no es muy descriptivo pero no encontré otra forma de ponerlo. Estoy creando una nueva forma de editar las paginas ...
  #1 (permalink)  
Antiguo 27/07/2008, 16:07
Avatar de buzu  
Fecha de Ingreso: octubre-2006
Ubicación: San Francisco, CA
Mensajes: 2.168
Antigüedad: 17 años, 6 meses
Puntos: 122
Busqueda Evitar captura de eventos simultaneos. Lo estoy haciendo bien?

Perdón por el titulo que no es muy descriptivo pero no encontré otra forma de ponerlo.

Estoy creando una nueva forma de editar las paginas web que contiene algún tipo de CMS. Como ustedes saben, ese tipo de aplicaciones te permiten editar los textos una vez han sido creados y publicados, pero yo algunas veces me encuentro en que cuando reviso el post, me doy cuenta que me falta un acento o se me fue una letra de mas o cosas así. Entonces tengo que darle al botón editar, esperar que se cargue la pagina en la que se puede editar el contenido, editar el contenido, darle a salvar y volver a ver el post publicado. Esto es muy tedioso sobre todo cuando lo único que quiero es cambiar una letra.

Para solucionar este "problema" pensé en un sistema que permitiera seleccionar la parte del texto que se quiere edita, este automáticamente se convierte en un input tipo text listo para ser editado sin tener que dar todo el viaje redondo que expliqué anteriormente. Hasta ahi todo genial. El problema esta en que para que el texto sea enviado al servidor y el cambio reflejado en la pagina, esto es, mostrar el texto tal cual sin la caja de texto, estoy usando dos eventos. Uno es el onblur de la caja de texto, así cuando la caja pierde el foco el texto editado es impreso en la pantalla. Dos, el evento onmouseup de mi elemento en el que tengo el texto. Este segundo hace dos cosas, primero cuando seleccionas un texto por primera vez convierte dicho texto en caja de texto para ser editado. Cuando presionas por segunda vez imprime el texto.

La cosa funciona bien cuando el onblur es causado por el usuario presionando TAB o por un click fuera del elemento en el que tengo el texto. Sin embargo, cuando el onblur es causado por un click dentro del elemento en el que tengo el texto, se activan los dos evento a la vez. Primero se activa el evento onblur de la caja de texto, lo cual imprime el texto como normalmente lo haría. Segundo, se activa el evento onmouseup de mi elemento en el que tengo el texto, lo cual me crea una nueva caja de texto tal como si se hubiera seleccionado otra parte de texto y eso no me gusta. Si quieren ver lo que les digo pueden probar este codigo:

Código HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>seleccion</title>
	<script type="text/javascript">
	var editar = true;
	function sel(){
		if(editar == true){
			var texto = document.getElementById('seleccion');
			var inicio = window.getSelection().anchorOffset;
			var Final = window.getSelection().focusOffset;
			var textoIni = texto.innerHTML;
			textoAnterior = textoIni.substr(0, inicio);
			textoPosterior =  textoIni.substr(Final);
			var cajaValue = window.getSelection().toString();
			var textoFn = textoAnterior + "<input type='text' id='editando' value='" + cajaValue + "' size='" + cajaValue.length + "' />" + textoPosterior;
			texto.innerHTML = textoFn;
			document.getElementById('editando').focus();
			document.getElementById('editando').select();
			document.getElementById('editando').onblur = imprimeTexto;
			editar = false;
		}else if(editar == false){
			imprimeTexto();
		}
	}
	function imprimeTexto(){
		document.getElementById('seleccion').innerHTML = textoAnterior + document.getElementById('editando').value + textoPosterior;
		editar = true;
	}
	</script>
</head>
<body>
	<div id="seleccion" onmouseup="sel();">
		texto que podra o no ser seleccionado. Al seleccionar devera ser convertido en una caja de texto para que sea editado.
	
	</div>
</body>
</html> 
El codigo esta siendo provado en FF y safari. Ten en cuenta que esta en fase de desarrollo y aun no empiezo a meterme en problemas con IE. Es mas, ni lo eh probado en IE y no se si funciona. Puedes usar el probador de codigos de caricatos. Selecciona una parte del texto y veras que se convierte en caja de texto para ser editado, Edita y presiona algo alejado del texto y veras que la caja de texto desaparece y en su lugar aparece el texto seleccionado. Ahora selecciona nuevamente un poco de texo, editalo y presiona sobre alguna otra parte del texto y veras el error.

Yo lo eh solucionado de esta manera:
1.- En cuanto el texto es impreso, elimino la función asignada al evento onmouseup de mi elemento texto de tal modo que no se ejecute y no me abra otra caja de texto.
2.- Uso setTimeout para volver a asignar la función al evento onmouseup cuando creo que es seguro de modo que cuando el texto sea seleccionado nuevamente me cree la caja de texto.

Un poco difícil de explicar. Acá mi solución:

Código HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>seleccion</title>
	<script type="text/javascript">
	var editar = true;
	function sel(){
		if(editar == true){
			var texto = document.getElementById('seleccion');
			var inicio = window.getSelection().anchorOffset;
			var Final = window.getSelection().focusOffset;
			var textoIni = texto.innerHTML;
			textoAnterior = textoIni.substr(0, inicio);
			textoPosterior =  textoIni.substr(Final);
			var cajaValue = window.getSelection().toString();
			var textoFn = textoAnterior + "<input type='text' id='editando' value='" + cajaValue + "' size='" + cajaValue.length + "' />" + textoPosterior;
			texto.innerHTML = textoFn;
			document.getElementById('editando').focus();
			document.getElementById('editando').select();
			document.getElementById('editando').onblur = imprimeTexto;
			editar = false;
		}
	}
	function imprimeTexto(){
		document.getElementById('seleccion').onmouseup="";
		setTimeout("document.getElementById('seleccion').onmouseup=sel",100);
		document.getElementById('seleccion').innerHTML = textoAnterior + document.getElementById('editando').value + textoPosterior;
		editar = true;
	}
	</script>
</head>
<body>
	<div id="seleccion" onmouseup="sel();">
		texto que podra o no ser seleccionado. Al seleccionar devera ser convertido en una caja de texto para que sea editado.
	
	</div>
</body>
</html> 
Nuevamente el código esta en fase de desarrollo, es un código muy rudimentario y escrito de una forma no muy recomendable pero que me sirve. Cuando esté terminada la fase rudimentaria empezaré a desarrollar con mejores practicas y todo. Lo hago así para mantener el código lo mas sencillo posible a la hora del desarrollo ya que es mas fácil de hacer el debug.

La pregunta es. Es esta la mejor forma de evitar el doble evento o hay una manera mejor de hacerlo?
__________________
twitter: @imbuzu
  #2 (permalink)  
Antiguo 27/07/2008, 16:20
Avatar de buzu  
Fecha de Ingreso: octubre-2006
Ubicación: San Francisco, CA
Mensajes: 2.168
Antigüedad: 17 años, 6 meses
Puntos: 122
Respuesta: Evitar captura de eventos simultaneos. Lo estoy haciendo bien?

WOW! Acabo de pensar en otra solución que a la vez me podría solucionar otro problema. La solución es simple, si la selección es mayor a una letra se crea la caja de texto, de otra manera no se muestra nada. Así si solo se hace click en el texto la selección no es menor a uno, ya que no hay nada seleccionado, y no se crea la caja de texto.

Acá el código a como lo tengo ahora.

Código HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>seleccion</title>
	<script type="text/javascript">
	var editar = true;
	function sel(){
		if(editar == true){
			var texto = document.getElementById('seleccion');
			var inicio = window.getSelection().anchorOffset;
			var Final = window.getSelection().focusOffset;
			var textoIni = texto.innerHTML;
			textoAnterior = textoIni.substr(0, inicio);
			textoPosterior =  textoIni.substr(Final);
			var cajaValue = window.getSelection().toString();
			if(cajaValue.length >= 1){
			var textoFn = textoAnterior + "<input type='text' id='editando' value='" + cajaValue + "' size='" + cajaValue.length + "' />" + textoPosterior;
			texto.innerHTML = textoFn;
			document.getElementById('editando').focus();
			document.getElementById('editando').select();
			document.getElementById('editando').onblur = imprimeTexto;
			editar = false;
			}
		}
	}
	function imprimeTexto(){
		//document.getElementById('seleccion').onmouseup="";
		//setTimeout("document.getElementById('seleccion').onmouseup=sel",100);
		document.getElementById('seleccion').innerHTML = textoAnterior + document.getElementById('editando').value + textoPosterior;
		editar = true;
	}
	</script>
</head>
<body>
	<div id="seleccion" onmouseup="sel();">
		texto que podra o no ser seleccionado. Al seleccionar devera ser convertido en una caja de texto para que sea editado.
	
	</div>
</body>
</html> 
El segundo problema que me podría solucionar esta opción(y fue precisamente buscando una solución a ese problema que se me ocurrió esta segunda solución) es dar la oportunidad al usuario de seleccionar otra parte de la pagina para ser editada en lugar de simplemente dar click para guardar los cambios.

PD. Eh notado algo curioso, si la selección la haces de izquierda a derecha el efecto funciona de perlas, pero si seleccionas de derecha a izquierda, el efecto hace algo curiosos. Es fácil de solucionar, pero se me hizo curiosos jaja.
__________________
twitter: @imbuzu

Última edición por buzu; 27/07/2008 a las 16:28
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 02:46.