Acceder a elementos de un iframe que carga contenido remoto

El otro día estaba trasteando con unos experimentos, y me topé con que necesitaba cargar un iframe (si, un iframe a estas alturas) en un sitio web. Os cuento la situación y como pensaba resolverlo. Tenemos un sitio web y queremos cargar en una de nuestras páginas, un formulario que creamos en otra, para ello lo vamos a cargar en un iframe. Hasta ahora tan simple como pasarle la URL al tag iframe. En mi caso, dependiendo un enlace pulsado en la primera página (el “padre”) quería que en un formulario del iframe se auto seleccionara un valor de un combo. Página padre: JavaScript var iframe = document.getElementById( "idIframe" ); var ifrDocument = iframe.contentDocument || iframe.contentWindow.document; var selectElement = ifrDocument .getElementById( "mySelect" ); selectElement.selectedIndex = *El valor que necesitaba* 12345 var iframe = document.getElementById( "idIframe" );var ifrDocument = iframe.contentDocument || iframe.contentWindow.document;var selectElement = ifrDocument .getElementById( "mySelect" ); selectElement.selectedIndex = *El valor que necesitaba* Con ese código javascript puedo inicializar por defecto el valor del combo del iframe desde la página padre. No hay mucho problema hasta aquí. Pero ¿Qué pasaría si ese iframe viene de un sitio remoto? Pues que debido a las políticas modernas de seguridad de los navegadores, no podemos modificar elementos de otra página que son cargados de un iframe (y me parece totalmente lógico). Sin embargo, si tenemos acceso a esa página que vamos a cargar en el iframe, ( la que está en otro dominio/protocolo/puerto.. y que por tanto nos bloquea el navegador por motivos de seguridad ) El dicho error de seguridad es este: <span class="pln">SecurityError: Blocked a frame with origin "http://www.&lt;domain&gt;.com" from accessing a cross-origin frame. </span> 12 <span class="pln">SecurityError: Blocked a frame with origin "http://www.&lt;domain&gt;.com" from accessing a cross-origin frame.</span> Para que podamos seguir interactuando con esa página, necesitamos permisos de edición a la misma, ya que necesitaremos añadir cierto código javascript, como muestro a continuación: Página principal: <span class="kwd">var</span><span class="pln"> iframe </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'iframeId'</span><span class="pun">);</span><span class="pln"> iframe</span><span class="pun">.</span><span class="pln">contentWindow</span><span class="pun">.</span><span class="pln">postMessage</span><span class="pun">(Objeto/Variable a enviar</span><span class="pun">,</span> <span class="str">'*'</span><span class="pun">);</span> 12 <span class="kwd">var</span><span class="pln"> iframe </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'iframeId'</span><span class="pun">);</span><span class="pln">iframe</span><span class="pun">.</span><span class="pln">contentWindow</span><span class="pun">.</span><span class="pln">postMessage</span><span class="pun">(Objeto/Variable a enviar</span><span class="pun">,</span> <span class="str">'*'</span><span class="pun">);</span> Página que vamos a cargar en el iframe: <span class="pln">window</span><span class="pun">.</span><span class="pln">addEventListener</span><span class="pun">(</span><span class="str">'message'</span><span class="pun">,</span> <span class="kwd">function</span><span class="pun">(</span><span class="kwd">event</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">event</span><span class="pun">.</span><span class="pln">data</span><span class="pun">);</span> <span class="pun">});</span> 123 <span class="pln">window</span><span class="pun">.</span><span class="pln">addEventListener</span><span class="pun">(</span><span class="str">'message'</span><span class="pun">,</span> <span class="kwd">function</span><span class="pun">(</span><span class="kwd">event</span><span class="pun">)</span> <span class="pun">{</span><span class="pln">        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">event</span><span class="pun">.</span><span class="pln">data</span><span class="pun">);</span><span class="pun">});</span> El objeto event.data es el objeto que ha recibido (y por tanto hemos enviado) desde...

Read More
Familiar Game Jam #5 – Sevilla. Tema: “Deconstrucción no es destrucción”
nov09

Familiar Game Jam #5 – Sevilla. Tema: “Deconstrucción no es destrucción”

Antes de que pase más tiempo, me gustaría escribir unas líneas sobre la Familiar Game Jam que se hizo en Sevilla el fin de semana del 23 al 25 de Octubre, patrocinada por Genera Games. Fue mi primer Game Jam, a la que me presenté presencialmente con un buen amigo con el que ya había trasteado en el mundo del desarrollo de videojuegos. Sin mucha información entramos de rebote en un nuevo local que consiguieron habilitar para 12 personas más, y sin poder asistir a la charla de inicio porque por trabajo nos retrasamos, llegamos sin saber que íbamos a encontrarnos a ese local, con el portátil preparado en la mochila (El local era una de las aulas de la academia AulaArcade). En fin, con muchas ganas nos instalamos en el aula y por suerte decidí mirar el tema de la jam en la web (ya había sido revelado),  hasta ese momento nuestras fuentes nos habían dicho que el tema era “Construcción” (Esto se debe a que construcción y de-construcción mientras hablamos, no es tan fácil de diferenciar). Una vez saltado ese primer obstáculo. Decidimos ir dándole vueltas al juego que queríamos hacer en esas siguiente 48 horas, y para ser sinceros ya habíamos pensado que íbamos a orientar un juego tipo Shoot ’em up al tema en cuestión (dentro de lo humanamente posible) ya que fuimos 2 programadores sin mucha habilidad de sonido ni de gráficos y vimos un objetivo realista. Eso sí, allí nos asignaron un músci, en nuestro caso Beni, que hizo un genial trabajo que ha gustado a todo el mundo. El tema que nos quema El tema era “Deconstrucción no es destrucción“, contamos hasta 10 para que se nos pasaran las ganas de cerrar los portátiles e irnos, pero al final decidimos quedarnos y darle unas vueltas a ver si podríamos enlazar el tema de alguna manera con nuestro “matamarcianos“. Finalmente le dimos al tema y al juego esta orientación: Un juego matamarcianos en el que te basas en energía (combustible) para disparar y para usar tu habilidad especial. Para recargar esa energía, tienes que entrar en un modo deconstruido del juego, el que digamos es principalmente un modo “gráficamente” deconstruido, pasando a ver variables del juego en vivo, logs, fake-sprites simulando el tamaño de la memoria. Intentamos que ese modo cumpliera con la definición de deconstrucción ayudando al jugador a analizar cada parte del juego: fondo, los paths que siguen los enemigos, variables de sus posiciones, etc… El juego Finalmente, conseguimos hacer a tiempo algo justito como un boceto-idea de lo que queríamos desarrollar, y la verdad quedamos bastante contentos aunque nos hubiera gustado dejar algo...

Read More
Invitar a usuarios de tu aplicación a votarla
sep07

Invitar a usuarios de tu aplicación a votarla

Hace tiempo dí con un snippet para aplicaciones Android que se encargaba de lanzar un dialogo invitando al usuario a puntuar tu aplicación, a hacerlo más tarde o simplemente no hacerlo. El snippet controla el número de días a esperar antes de que aparezca la modal y el número de ejecuciones, y es tan simple como incluir la clase java que os dejo a continuación y añadir la siguiente línea en el onCreate de nuestra Activity principal: Java AppRater.app_launched(this); 1 AppRater.app_launched(this); Si queremos ver la modal sin esperar esos días para ver como queda, pruebas, etc, podemos usar esto en vez de la línea anterior: Java AppRater.showRateDialog(this, null); 1 AppRater.showRateDialog(this, null); El snippet propiamente peca de usar algunos literales a fuego (en inglés) por lo que os recomiendo hacer uso de vuestros propios strings definidios en los ficheros strings.xml para que sea totalmente multilenguaje. El sinppet completo aquí: public class AppRater { private final static String APP_TITLE = "YOUR-APP-NAME"; private final static String APP_PNAME = "YOUR-PACKAGE-NAME"; private final static int DAYS_UNTIL_PROMPT = 3; private final static int LAUNCHES_UNTIL_PROMPT = 7; public static void app_launched(Context mContext) { SharedPreferences prefs = mContext.getSharedPreferences("apprater", 0); if (prefs.getBoolean("dontshowagain", false)) { return ; } SharedPreferences.Editor editor = prefs.edit(); // Increment launch counter long launch_count = prefs.getLong("launch_count", 0) + 1; editor.putLong("launch_count", launch_count); // Get date of first launch Long date_firstLaunch = prefs.getLong("date_firstlaunch", 0); if (date_firstLaunch == 0) { date_firstLaunch = System.currentTimeMillis(); editor.putLong("date_firstlaunch", date_firstLaunch); } // Wait at least n days before opening if (launch_count >= LAUNCHES_UNTIL_PROMPT) { if (System.currentTimeMillis() >= date_firstLaunch + (DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000)) { showRateDialog(mContext, editor); } } editor.commit(); } public static void showRateDialog(final Context mContext, final SharedPreferences.Editor editor) { final Dialog dialog = new Dialog(mContext); dialog.setTitle("Rate " + APP_TITLE); LinearLayout ll = new LinearLayout(mContext); ll.setOrientation(LinearLayout.VERTICAL); TextView tv = new TextView(mContext); tv.setText("If you enjoy using " + APP_TITLE + ", please take a moment to rate it. Thanks for your support!"); tv.setWidth(240); tv.setPadding(4, 0, 4, 10); ll.addView(tv); Button b1 = new Button(mContext); b1.setText("Rate " + APP_TITLE); b1.setOnClickListener(new OnClickListener() { public void onClick(View v) { mContext.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + APP_PNAME))); dialog.dismiss(); } }); ll.addView(b1); Button b2 = new Button(mContext); b2.setText("Remind me later"); b2.setOnClickListener(new OnClickListener() { public void onClick(View v) { dialog.dismiss(); } }); ll.addView(b2); Button b3 = new Button(mContext); b3.setText("No, thanks"); b3.setOnClickListener(new OnClickListener() { public void onClick(View v) { if (editor != null) { editor.putBoolean("dontshowagain", true); editor.commit(); } dialog.dismiss(); } }); ll.addView(b3); dialog.setContentView(ll); dialog.show(); } } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 public class AppRater {    private final static String APP_TITLE = "YOUR-APP-NAME";    private final static String APP_PNAME = "YOUR-PACKAGE-NAME";        private final static int DAYS_UNTIL_PROMPT = 3;    private final static int LAUNCHES_UNTIL_PROMPT = 7;        public static void app_launched(Context mContext)...

Read More
Crear icono de todos los tamaños online
sep02

Crear icono de todos los tamaños online

Os voy a hablar de una web: http://makeappicon.com/ , que te proporciona la descarga de iconos para todos los tamaños disponibles del sistema Android (y de iOS, sea dicho de paso) a partir de una imagen que subas. Os dejo un par de imágenes de ejemplo con un icono de ejemplo. Tan sólo tenemos que arrastrar el icono que queremos a la tostadora y automáticamente la imagen será subida y procesada en el servidor para devolvernos el pack de iconos listo para descargar (con preview incluída). Por supuesto es gratis.  ...

Read More
Obtener Idioma en Android (Locale)
ago13

Obtener Idioma en Android (Locale)

Para obtener el idioma de nuestra aplicación Android, podemos usar la clase Locale. Algunos ejemplos de código y su salida. Locale.getDefault().toString(); -> en_US // El locale actual del usuario Locale.getDefault().getDisplayName().toString(); -> Thai (Thailand,TH) //Nombre del idioma Locale.getDefault().getLanguage().toString(); -> th //Código del idioma Locale.getDefault().getDisplayLanguage().toString(); -> Thai //Nombre del idioma Locale.getDefault().getCountry().toString(); -> TH //Código del País Locale.getDefault().getDisplayCountry().toString(); -> Thailand //Nombre del país 123456 Locale.getDefault().toString(); -> en_US // El locale actual del usuarioLocale.getDefault().getDisplayName().toString(); -> Thai (Thailand,TH) //Nombre del idiomaLocale.getDefault().getLanguage().toString(); -> th //Código del idiomaLocale.getDefault().getDisplayLanguage().toString(); -> Thai //Nombre del idiomaLocale.getDefault().getCountry().toString(); -> TH //Código del PaísLocale.getDefault().getDisplayCountry().toString(); -> Thailand //Nombre del país Además de eso, la clase Locale tiene más utilidades para  otros casos (monedas.....

Read More