Solo funciona con alerts
Resulta que tengo una web, que se genera mediante echo's de php, o sea, los controles no están en la página html/php como p.ej <INPUT id='nombre' ... /> sino que mediante php
se genera, tipo:
echo "<input id='" . $registro["nombre_campo"] . "' ... />";
Y así con todos, bueno, pues resulta que ha llegado un punto en que al rellenar una select (una lista), no me lo hace si no hay un alert, he intentado diferentes soluciones, pero no me resulta nada, decir antes que nada, que solo me pasa con las listas, con los textos no
hay ningún problema. El código en cuestión es este:
if ($registro2["idValorPermitido"]){
echo "var idEncontrado='" . $registro2["idValorPermitido"] . "';";
echo "var objeto=document.getElementById(nombre_id);";
echo "var tipo=objeto.type;";
echo "var bvalido=(tipo==='select-multiple');";
echo "alert(bvalido);";
echo "for(var d=0;d<10000;d++){}";
echo "if (bvalido){";
echo " for(var ni=0;ni<objeto.length;ni++){";
echo " var opción=objeto[ni];";
echo " if(opción.value===idEncontrado){";
echo " opción.selected=true;";
echo " }";
echo " }";
echo "}";
}
La línea del for "d<10000", ha sido un intento de emular una
"paradiña", pero no resulta, ni poniendo 1000000, y el alert que lo
antecede es el que hace, que las opciones se marquen cuando toca, si se
quita el alert, no marca ninguna.
¿Alguna idea?
Saludos y gracias.
P.D: He leído en la web, que tiene que ver con llamadas síncronas /
Asíncronas, pero claro, hablan de ajax / jquery, y lo mio es puto
javascript / php, por lo que si, el origen es el mismo problema, que es
una ejecución asíncrona, o sea, que no están sincronizados, no se espera
a tener cierta información para ejecutar la siguiente instrucción, el
for, que trata de simular la parada, era un intento de realizar algo
parecido a un sleep.
1 respuesta
Creo que acá hay una mezcla un poco extraña de lenguajes de programación. Php en su gran mayoría de los usos que se le dan genera código html. Encuentro que ese código javascript no corresponde que sea generado desde ese lugar si no que tiene que estar desde alguna librería con extensión js o en su defecto en el archivo html o php base que contiene esta ejecución.
Me disculparás pero en esta situación no entiendo mucho el contexto con el cual trabaja tu script para poder identificar la problemática aunque en muchos de estos problemas, la solución radica en ejecutar esta funcionalidad en un momento en el cual todos los elementos del dom se hayan ejecutado, de nada te servirá hacer una especie de sleep si aun el selector javascript no es capaz de encontrar los elementos que acabas de generar (puede ser que el código se ejecute antes de que crees los input).
Intenta ejecutar este código cuando tengas certeza de que ya se han generado los elementos (colocalo posterior a los input) y para el sleep que deseas hacer, averigua más sobre las funciones setTimeout o setInterval de javascript.
Las razones que te doy no son soluciones a tu problema, solo estoy intentando obtener información para entender la causa y así ayudarte posteriormente.
En la página no existe ninguna etiqueta html, se genera todo mediante parámetros que hay en una base de datos.
El problema viene, cuando en una lista ya existente, se trata de marcar los elementos que el usuario ha seleccionado y que se encuentran en la bbdd, el problema es que si pones un alert si que lo hace, pero si se lo quitas, no marca los que se han seleccionado. La lista y sus elementos ya están en pantalla cuando se ejecuta todo esto ...
Ya probé el setTimeout y el setInterval pero no me ha servido de nada, he reestructurado la funcionalidad dos o tres veces, pero nada,, la lista sigue sin marcarse ...
Es evidente que en principio, se supone, por los resultados que se obtiene que trata de marcar algo cuando aún no está completa la página,
Lo de separar la funcionalidad de marcado a una librería o a un script independiente, también lo he probado, de hecho es como lo tengo ahora, pero sigue pasando lo mismo ...
No hagas entonces la validación con javascript. Cuando por php tengas certeza de que el elemento está marcado desde la base de datos, le agregas la propiedad selected="selected" al option especifico
<option value="valor" selected="selected">Texto</option>
De esta forma aparecerá marcado por html sin necesidad de javascript
Ja ja ja ... si, si ... eso también lo he probado, de hecho es lo que estoy tratando de hacer ... Verás, como te he dicho he intentado ya unas cuantas cosas, la última ha sido volver a generar el objeto select con sus options, para hacer lo que tu dices, el tema es que dicho objeto de un div (esto lo he hecho así, para posicionarlo mejor en pantalla), pero claro, dicho div lo manipulo a través de javascript, o sea jquery mediante un
$('#capa_select').load('generar_elmento.php');
pero claro, tampoco me funciona si antes de llamar a ese php, no le pongo un alert, por lo que empiezo a estar un poco "desesperado", llevo ya unos días con este tema ...
¿se te ocurre algo?
Gracias.
Tendría que revisar más detalles de lo que estás haciendo, así puedo dar una respuesta certera a tu requerimiento.
¿Me podrías enviar el código al siguiente correo?
[email protected]
Te envio el código, en un fichero, tal y como me pedias, a ver si teniendo el código delante ves algo que yo no vea, ...
Está algo "sucio" por las pruebas que he ido haciendo, pero en el correo te explico algo mas ...
He revisado el código y tengo algunas observaciones con respecto a tu código:
No creo que sea optimo ni necesario generar código javascript por medio de php ya que esa mezcla de código hace que tu script sea imposible de mantener en el tiempo.
De la forma en la cual deseas trabajar haría una llamada con ajax para que sea posible marcar todos los elementos por javascript.
Si encuentras que este método es muy complicado o no te interesa realizar lo así lo trabajaría de la manera más fácil con php (aunque no es la mejor para realizar un buen mvc).
Cuando generes las listas es de suponer que lo haces con un bucle (en este caso lo ejemplificaré con un foreach)
$países=array();
$países[0]="Perú";
$países[1]="Argentina";
$países[2]="España";
$países[3]="Colombia";
echo "<select id="países" name="países">
foreach($países as $key=>$value){
//En caso de que sea la opción guardada desde la base, la marcamos como selected
if($desde_la_base->país==$key){
echo "<option value='".$key."'" selected="selected">".$value."</option>";
}else{
echo "<option value='".$key."'">".$value."</option>";
}
}
echo "</select>";
De esta forma automáticamente se validarán los campos en función de la información contenida en la base.
Si me consultas cual es la mejor opción, te recomiendo que utilices jquery y que trabajes con ajax, aunque la opción por php que te acabo de comentar es lo que tienes más a mano.
Vamos a ver ...
Si observas la función rellenar_select, hace lo que tu me comentas, o al menos debería hacerlo, pero lo hace solo si pones un alert:
function rellenar_select(pIdControl,pIdCaracteristica,pValoresPermitidos){
//alert('vengo a rellenar_select: ' + pIdControl + '-' + pIdCaracteristica + '-' +
pValoresPermitidos);
var prefijo='<?php echo $prefijo_id_capa_objeto; ?>';
var nombre_capa="#" + prefijo + pIdControl;
//Estas líneas deberían funcionar, pero son muy señoritas y solo funcionan con un alert.
var control=document.getElementById(pIdControl);
//var a_buscar;
/*for (var a=0;a<control.length;a++){
a_buscar=',' + control[a].value + ',';
if (pValoresPermitidos.indexOf(a_buscar)!==-1){
control[a].selected=true;
}
}*/
// Fin del comentario
//$(window).ready(function() { /* code here */
$(nombre_capa).load('pruebas.php');
//control[2].selected=true;
//control[2].selected=true;
//});
return;
}
Te explico la función, el primer parámetro indica el id de la select, el segundo parámetro es el id de una característica (que para el bucle no es necesario), y el tercer parámetro pValoresPermitidos, son todos los id que se deben seleccionar en la select. El bucle "for" es lo que hace en el select indicado (pIdControl) va recorriendo sus elementos y va mirando si su valor se corresponde con alguno de los valores seleccionados (pValoresPermitidos) y si es así lo marca ...
Pero no lo hace, si no le pones un alert.
La otra alternativa es la del jquery que me comentabas ... bueno pues está más abajo ... :
$(nombre_capa).load('pruebas.php');
donde nombre_capa, es el nombre de la capa donde se haya el "select" y el fichero pruebas.php, es el que debería generar toda la select de nuevo, exactamente como tu dices, marcando como selected las opciones que fueran necesarias (he obviado poner los parámetros a esa llamada, simplemente para hacer pruebas) ... de hecho ni llama, el contenido de pruebas.php, hay un simple
<?php
echo "hola";
?>
y ni siquiera lo hace ... He probado 3 o 4 alternativas y ninguna ha funcionado ...
si combino php y javascript / html, es porque todos los elementos se generan a través de los parámetros de una base de datos, posicionándose los elementos de igual manera. He querido hacerlo lo más automático posible para no tener que editar código fuente, y realizar el diseño y el mantenimiento por bbdd, y hasta ahora a funcionado todo ...
Me gustaría que me indicaras un ejemplo tipo ajax, aunque me parece el liarlo todo un poco mas, pero si funciona, pues funciona.
Saludos y gracias.
Cuando hablé de hacer el bucle estaba hablando de php no de javascript (la confusión entra al no tener delimitadas las actividades de ambos lenguajes).
Esta es la forma con la cual trabajaría para rellenar un campo select con jquery
De hecho no es liarlo al trabajar así con ajax, si no, separar los lenguajes y las capas de desarrollo que es lo mas eficiente para poder mantenerlo a futuro.
Tu desarrollo, a estas alturas, tendría que estar separado por capas, las que están desde el lado servidor (php + mysql) y que entregan información al lado cliente (javascript y html) lo cual se hace por medio de llamadas ajax tal cual se utiliza en muchos de los sitios web de primera línea.
En principio, está todo separado, a un lado php y al otro javascript/html, pero al quererlo hacer parametrizado es lo que tiene si quieres general el código html mediante php termina mezclándose ...
Estoy haciendo otra alternativa que se me ha ocurrido si no surte efecto, intentaré de hacerlo como indica el enlace que me has pasado, pero creo que tendría el mismo problema ...
Te cuento más tarde.
Saludos y gracias.
Quedo atento entonces a tu alternativa de desarrollo para que podamos seguir con la solución a tu problema.
La alternativa no ha funcionado.
La alternativa era suprimir todos los echo, y dejar solo el javascript ... pero sigue pasando lo mismo. Trataré de hacerlo como indica el enlace que me has pasado, aunque a simple vista no tengo mucha fe, ya que intuyo que no ralentiza la ejecución del código, por lo que el problema creo que persistirá ...
Yo lo que haría seria lo siguiente:
Primero trataría de limpiar muy bien el archivo donde va el código html.
Limpiar de php a no se que sea para mostrar el valor de una propiedad
en vez de hacer echo "<input type='text .... ...
Haz solo html <input type="text" name="nombre_campo" value="$propiedad->valor">
En el javascript averigua como recorrer los elementos del dom con javascript nativo (con document.getElementByTagName, byId etc o con un selector de jquery $("#id_del_campo)
Carga los comboboxes de la manera explicada con json y jquery para que mantengas las capas de presentación y de negocio separadas y tendría que funcionar, de verdad lo que intentas hacer lo hecho muchas veces pero siempre he trabajado en otra situación de capas lo que me hace muy difícil poder dar una solución en la situación de tu script.
Lo de hacer la asignación directamente al elemento <input type="text" name="nombre_campo" value="$propiedad->valor"> ... es imposible el elemento se genera al momento, dependiendo de unos parámetros de bbdd.
El for, de rellenar está hecho como dices con el document.getElementById, ahí ya se localiza los objetos selects, el problema es que la asignación NO QUEDA a menos que se le ponga un alert.
Lo único que no he probado a hacer, y que voy a hacer es cargar los listbox mediante json y jquery ... Lo que me hace "gracia", es que los demás elementos los <input> los "combobox" ... no solo los carga bien sino que incluso en el caso del combo, selecciona el elemento que toca ... el único problemático son los listbox ...
Si esto último no funciona, ya veremos que pasa ...
Te mantengo informado.
Buenísimo!!!
Adivina ... pasa lo mismo !!!
He quitado todo lo que había en la función rellenar_select ...
y he puesto:
var nombreControl='#' + pIdControl;
alert(nombreControl);
var miselect=$(nombreControl);
miselect.find('option').remove();
Y si lo borra pero solo si tiene el alert, puesto ...
A seguir investigando ...
En verdad... de todos los años que llevo trabajando en esto nunca, nunca me había topado con un caso mas extraño, donde un alert sea pseudo solución a una funcionalidad.
Bueno, pon en google "solo funciona con alert" y verás que no soy el único, aunque los demás lo han arreglado de una manera u otra ... y yo también acabaré solucionándolo no se como, pero lo haré.
Cierro, la pregunta.
De hecho, estoy modificando casi totalmente el código, tocando diversas funciones ... y dividiendo el código en más partes si cabe ...
El tema era que:
Imaginate dos partes, en la parte de arriba hay dos "div" con un montón de controles y un command-button, y en la parte de abajo pueden haber de 2 a n "div", dependiendo de valores de la primera parte, la de arriba, que puede decirse que es de "configuración" ...
¿Que pasaba? pues que cuando seleccionas un elemento de la lista, si existe información la visualiza en pantalla, y ejecuta el command-button, que es quien genera la parte inferior. En la parte de arriba nunca ha habido problemas, pero en la inferior, supongo, aunque es imposible saberlo a ciencia cierta, por la velocidad de ejecución, se trataba de incorporar datos antes de que existan los controles generados por el command-button, por eso, cuando pones un alert, hace que frene todo y de tiempo a que refresque la pantalla y se generen los controles.
Entonces lo que estoy haciendo es que la parte de configuración (la superior) se visualiza tal cual, ahora, pero la inferior, será el usuario quien deba pulsar el botón para que se generen los datos, y a medida que se generen los datos estoy tratando de que incorpore los datos si existen. Esta es una de las opciones que me dijiste tú, pero que no quería implementar porque me parece poco "elegante", quería tener la definición de la plantilla por un lado y la incorporación de datos por otro, pero viendo que no es posible, estoy tratando de realizarlo así.
Esto lo he decidido hacerlo así, porque con la llamada de jquery que te dije pasaba lo mismo.
No sé, si volveré a comentarte algo hoy o mañana, porque estoy modificando gran parte de código ...
Saludos y gracias. Seguimos en las otras preguntas.
- Compartir respuesta