Thursday, May 30, 2019

Blogger y los redireccionamientos personalizados

Una de las nuevas opciones para configurar Blogger que sólo podemos ver en la nueva interfaz es la llamada Errores y re-direccionamientos que se encuentra en el apartado Preferencias de búsqueda. Allí, junto con la opción de crear páginas de error personalizadas hay otra que se titula Re-direccionamiento personalizado ¿Qué es esto?

La ayuda de Blogger nos dice algunas cosas pero lo mejor es probar y ver que sale ... sin temor a destruir nada. Si hacemos click en Editar, veremos algo así:


Allí, nos dicen que debemos agregar dos direcciones ¿cuáles? ¿cómo? ¿para qué?

Lo que nos permite esta opción es redirigir una página interna a otra página interna con una particularidad, esa dirección puede no ser una página inexistente ¿Confuso? Veamos un ejemplo sencillo. Si tengo una página estática con datos referidos a mi perfil, ontacto o cualquier otra cosa cuya URL es:
http://miblog.blogspot.com/p/el-titulo-de-la-pagina.html
y quisiera que esa URL fuera más corta, más clara, más "linda" y llamarla, por ejemplo:
http://miblog.blogspot.com/perfil
bastaría colocar esos datos en la opción de Blogger para que cualquier enlace a miblog.blogspot.com/perfil se re-direccionará automáticamente a la página real sin ventanas de advertencia ni problemas ya que se trataría de un re-direccionamiento desde el mismo servidor.

¿Cómo colocaría esos datos?

En De pondría la dirección "falsa" como un path interno, sin el protocolo http ni el dominio ni el subdominio; antecediendo todo con una barra: /perfil

Y en A pondría la dirección "real" con el mismo criterio: /p/el-titulo-de-la-pagina.html

Luego, guardaría y listo. Al acceder al enlace indicado en De, se abriría la pagina indicada en A.

¿Cuántas re-direcciones pueden hacerse? No hay información al respecto pero, evidentemente, puede haber varias así que si queremos agregar otra, basta repetir los mismos pasos.

¿Qué diferencia hay entre marcar y desmarcar el cuadro Permanente? No tengo idea.

¿Para qué podría servir esto aparte de crear URLs más amigables?

Podría usarse para redirigir entradas viejas o desactualizadas a una nueva entrada; para redirigir entradas eliminadas ... quien sabe; la opción existe, funciona bien y cada uno sabrá sacarle provecho o descartarla.

Concretamente, en este blog, no existe esta URL:

http://vagabundia.blogspot.com/ejemplo

pero si se hace click allí, se abrirá la página a la que se re-direcciona.

Wednesday, May 29, 2019

La nueva interfaz de Blogger: Errores y demoras

Para quienes no usamos la nueva interfaz de Blogger porque no nos gusta, nos resulta muy incómoda o simplemente no queremos cambiar, este mes de mayo era clave y, si bien aún no ha terminado y la espada de Damocles sigue pendiendo sobre nuestras cabezas, tal vez podamos tener un tiempo de respiro extra ya que, curiosamente, el mensaje de Blogger indicando que el cambio sería forzoso a fines de este mes, ahora ha cambiado por otro indicando que eso ocurrirá "en los próximos meses" o sea ... vaya uno a saber cuando. Mañana, en julio, nunca ... con Blogger, no se sabe; lo temporal puede ser permanente y lo permanente puede ser efímero.


Aparentemente, lo que hay son muchos problemas no resueltos en esa interfaz que han obligado a Blogger a demorar el cambio programado. En este momento, en mi caso, la opción Descripción de búsqueda parece haber desaparecido y sin embargo ... allí está, en el código fuente pero oculta ¿por qué?


Hay otras opciones ocultas que jamás habia visto: Etiquetas de robots personalizados que no sé que puede significar:


Y Enlace permanente que parecería servir para cambiar la URL de la entrada algo que sería muy útil ya que muchas veces aparecen cortadas o son "feas":


Veremos, veremos, veremos o ... no veremos nada. Blogger es una caja de sorpresas.

Monday, May 27, 2019

Palabras animadas con CSS

Este es un efecto creado exclusivamente con CSS donde ciertas palabras se animan, "cayendo" ordenadamente y son reemplazadas por otras usando transiciones y animaciones. En el sitio d los desarrolladores hay varios ejemplos con variaciones pero, todos comparten la misma idea general. En principio, empezamos con el HTML, una serie de etiquetas SPAN dentro de un DIV:
<div class="rw-sentence">
<span>Un ejemplo</span>
<span>donde las palabras</span>
<span>se van cayendo:</span>
<div class="rw-words rw-words-1">
<span>uno</span>
<span>dos</span>
<!-- etc etc etc -->
<span>tres</span>
</div>
</div>
Eso es simple aunque si se coloca dentro de un psot de Blogegr, hay que tener cuidado con los saltos de línea.
Un ejemplodonde las palabrasse van cayendo:
unodostrescuatrocincoseis
Y claro, el CSS:
<style>
.rw-sentence { /* el DIV donde se verá el efecto */
margin: 0 auto;
text-align: left;
width: 400px;
}
.rw-sentence span { /* cada uno de los párrafs */
color: #AAA;
font-size: 30px;
}
.rw-words { /* las palabras que caen */
display: inline;
text-indent: 10px;
}
.rw-words-1 span { /* la primera palabra */
color: White;
position: absolute;
opacity: 0;
overflow: hidden;
/* la animación */
-moz-transform-origin: 10% 75%;
-webkit-transform-origin: 10% 75%;
-o-transform-origin: 10% 75%;
-ms-transform-origin: 10% 75%;
transform-origin: 10% 75%;
-moz-animation: rotateWord 18s linear infinite 0s;
-webkit-animation: rotateWord 18s linear infinite 0s;
-o-animation: rotateWord 18s linear infinite 0s;
-ms-animation: rotateWord 18s linear infinite 0s;
animation: rotateWord 18s linear infinite 0s;
}
/* la animación de las siguientes */
.rw-words span:nth-child(2) { /* la segunda */
color: Red;
-moz-animation-delay: 3s;
-webkit-animation-delay: 3s;
-o-animation-delay: 3s;
-ms-animation-delay: 3s;
animation-delay: 3s;
}
.rw-words span:nth-child(3) { /* la tercera */
color: Aqua;
-webkit-animation-delay: 6s;
-moz-animation-delay: 6s;
-o-animation-delay: 6s;
-ms-animation-delay: 6s;
animation-delay: 6s;
}
.rw-words span:nth-child(4) { /* la cuarta */
color: Bisque;
-moz-animation-delay: 9s;
-webkit-animation-delay: 9s;
-o-animation-delay: 9s;
-ms-animation-delay: 9s;
animation-delay: 9s;
}
.rw-words span:nth-child(5) { /* la la quinta */
color: CadetBlue;
-moz-animation-delay: 12s;
-webkit-animation-delay: 12s;
-o-animation-delay: 12s;
-ms-animation-delay: 12s;
animation-delay: 12s;
}
.rw-words span:nth-child(6) { /* la última */
color: Yellow;
-moz-animation-delay: 15s;
-webkit-animation-delay: 15s;
-o-animation-delay: 15s;
-ms-animation-delay: 15s;
animation-delay: 15s;
}
/* y las reglas de las animaciones para cada navegador */
@-moz-keyframes rotateWord { /* Firefox */
0% { opacity: 0; }
5% { opacity: 1; }
17% { opacity: 1; -moz-transform: rotate(0deg); }
19% { opacity: 1; -moz-transform: rotate(98deg); }
21% { opacity: 1; -moz-transform: rotate(86deg); }
23% { opacity: 1; -moz-transform: translateY(85px) rotate(83deg); }
25% { opacity: 0; -moz-transform: translateY(170px) rotate(80deg); }
80% { opacity: 0; }
100% { opacity: 0; }
}
@-webkit-keyframes rotateWord { /* Chrome/Safari */
0% { opacity: 0; }
5% { opacity: 1; }
17% { opacity: 1; -webkit-transform: rotate(0deg); }
19% { opacity: 1; -webkit-transform: rotate(98deg); }
21% { opacity: 1; -webkit-transform: rotate(86deg); }
23% { opacity: 1; -webkit-transform: translateY(85px) rotate(83deg); }
25% { opacity: 0; -webkit-transform: translateY(170px) rotate(80deg); }
80% { opacity: 0; }
100% { opacity: 0; }
}
@-o-keyframes rotateWord { /* Opera */
0% { opacity: 0; }
5% { opacity: 1; }
17% { opacity: 1; -o-transform: rotate(0deg); }
19% { opacity: 1; -o-transform: rotate(98deg); }
21% { opacity: 1; -o-transform: rotate(86deg); }
23% { opacity: 1; -o-transform: translateY(85px) rotate(83deg); }
25% { opacity: 0; -o-transform: translateY(170px) rotate(80deg); }
80% { opacity: 0; }
100% { opacity: 0; }
}
@-ms-keyframes rotateWord { /* IE IE9/10 */
0% { opacity: 0; }
5% { opacity: 1; }
17% { opacity: 1; -ms-transform: rotate(0deg); }
19% { opacity: 1; -ms-transform: rotate(98deg); }
21% { opacity: 1; -ms-transform: rotate(86deg); }
23% { opacity: 1; -ms-transform: translateY(85px) rotate(83deg); }
25% { opacity: 0; -ms-transform: translateY(170px) rotate(80deg); }
80% { opacity: 0; }
100% { opacity: 0; }
}
@keyframes rotateWord { /* genérica */
0% { opacity: 0; }
5% { opacity: 1; }
17% { opacity: 1; transform: rotate(0deg); }
19% { opacity: 1; transform: rotate(98deg); }
21% { opacity: 1; transform: rotate(86deg); }
23% { opacity: 1; transform: translateY(85px) rotate(83deg); }
25% { opacity: 0; transform: translateY(170px) rotate(80deg); }
80% { opacity: 0; }
100% { opacity: 0; }
}
</style>
REFERENCIAS:codrops

Thursday, May 23, 2019

ResizeBrowser: Una herramienta online

No es algo del otro mundo pero resizebrowser es una herramienta útil a la hora de verificar cómo se ve un sitio web en distintas resoluciones de pantalla ya que los avances que se ven en el tema monitores hacen que este sea un tema complicado. Antes era más fácil, 800x600 o 1024x640 y ahí se acababan las variantes pero hoy en día, las alternativas son múltiples y conviene verificar si lo que vemos es lo que otros verán.

Esto no significa que uno deba crear sitios para el 100% ya que sería casi imposible pero, siempre es bueno saber qué pasaría si ... y de ese modo decidir dónde estarán nuestros límites.

La herramienta funciona online y posee dos pestañas. La izquierda nos permite seleccionar las distintas resoluciones admitidas o agregar alguna personal y la superior usar un zoom y definir la proporción: 4:3, 16:10, 16:9 o móviles.


Luego, basta hacer click en cualquiera de los enlaces que se muestran de nodo gráfico, para que se abra el navegador en una nueva ventana, ya re-dimensionada y desde allí podemos navegar libremente o colocar la dirección URL del sitio que queremos verificar.

Wednesday, May 22, 2019

Animando listas con Stroll

stroll es un script experimental creado por Hakimel que no pretende tener ningún uso práctico, simplemente, se trata de un efecto visual que funcionará sólo en los navegadores más modernos ya que hace un uso intensivo de las nuevas propiedades de estilo tales como transiciones, transformaciones y perspectivas.

Lo que permite es aplicar una serie de efectos a las listas que utilizan la propiedad overflow para mostrar sólo una parte del contenido y que el resto sea accesible mediante el uso de una barra de scroll vertical.

No tiene muchas explicaciones y en realidad, no son necesarias, podemos descargar el demo desde github y allí tendremos todo lo necesario para aplicarlo en nuestros propios proyectos. Para eso, basta tener dos cosas: los estilos y el script.

Los estilos se encuentran en el archivo stroll.min.css o stroll.css (son iguales) y no es necesario agregarlos todos, basta seleccionar el efecto deseado y descartar el resto. Lo más simple es copiar las reglas y agregarlas a nuestra plantilla.

El script también tiene dos versiones stroll.min.js y stroll.js; podemos usar cualquiera de ellas y la agregamos como siempre, antes de </head>

¿Y cómo lo usamos? Basta colocar la lista dentro de algún DIV contenedor al que identificamos mediante un ID y luego, llamar a la función:
<div class="demo">
<ul class="zipper">
<li>uno</li>
<li>dos</li>
<li>tres</li>
</ul>
</div>
<script>stroll.bind('#demo ul');</script>
Todos los efectos funcionan de la misma manera y se distinguen estableciendo el atributo class en al etiqueta UL; en esta entrada, hay tres ejemplos distintos: curl, helix y zipper.

Un último detalle extra a tener en cuenta: establecer las propiedades mínimas de las etiquetas UL y LI de la lista a la que vamos a aplicar el efecto; un ejemplo:
#demo ul {
height: 280px;
list-style-type: none;
margin: 0;
overflow-x: hidden;
overflow-y: scroll;
padding: 0;
position: relative;
width: 190px;
}
#demo ul li {
background-color: #B0B9C1;
color: #000;
font-size: 20px;
padding: 10px;
position: relative;
z-index: 2;
}
#demo ul li:nth-child(odd) {
background-color:#EEE;
}

Monday, May 20, 2019

Simple menú desplegable con CSS

Este es un ejemplo sencillo para crear un menú desplegable que puede incluir submenús, que usa las posibilidades que nos brindan las nuevas propiedades del CSS3.

Como casi cualquier otro, el HTML se arma en una lista, utilizando etiquetas UL y LI que, se anidan si es que queremos crear un submenú. Esta sería una lista standard:
<ul class="mi-menu">
<li><a href="URL_enlace_1"> texto_enlace_1 </a></li>
<li><a href="URL_enlace_2"> texto_enlace_2 </a></li>
<li><a href="URL_enlace_3"> texto_enlace_3 </a></li>
</ul>
y si quisiéramos que uno de esos enlaces fuera un submenú:
<ul class="mi-menu">
<li><a href="URL_enlace_1"> texto_enlace_1 </a></li>
<li>
<a href="#"> texto_enlace_2 </a>
<ul>
<li><a href="URL_enlace_2.1"> texto_submenú_2.1 </a></li>
<li><a href="URL_enlace_2.2"> texto_submenú_2.2 </a></li>
<li><a href="URL_enlace_2.3"> texto_submenú_2.3 </a></li>
</ul>
</li>
<li><a href="URL_enlace_3"> texto_enlace_3 </a></li>
</ul>

Así como está, veríamos algo similar a esto:

Y ahora, el CSS que hará que esa lista se transforme en otra cosa:
<style type="text/css">
/* el menú en si mismo */
.mi-menu {
border-radius: 5px;
list-style-type: none;
margin: 0 auto; /* si queremos centrarlo */
padding: 0;
/* la altura y su ancho dependerán de los textos */
height: 40px;
width: 510px;
/* el color de fondo */
background: #555;
background: -moz-linear-gradient(#555,#222);
background: -webkit-linear-gradient(#555,#222);
background: -o-linear-gradient(#555,#222);
background: -ms-linear-gradient(#555,#222);
background: linear-gradient(#555,#222);
}

/* si es necesario, evitamos que Blogger de problemas con los saltos de línea cuando escribimos el HTML */
.mi-menu br { display:none; }

/* cada item del menu */
.mi-menu li {
display: block;
float: left; /* la lista se ve horizontal */
height: 40px;
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
.mi-menu li a {
border-left: 1px solid #000;
border-right: 1px solid #666;
color: #EEE;
display: block;
font-family: Tahoma;
font-size: 13px;
font-weight: bold;
line-height: 28px;
padding: 0 14px;
margin: 6px 0;
text-decoration: none;
/* animamos el cambio de color de los textos */
-webkit-transition: color .2s ease-in-out;
-moz-transition: color .2s ease-in-out;
-o-transition: color .2s ease-in-out;
-ms-transition: color .2s ease-in-out;
transition: color .2s ease-in-out;
}
/* eliminamos los bordes del primer y el último */
.mi-menu li:first-child a { border-left: none; }
.mi-menu li:last-child a{ border-right: none; }
/* efecto hover cambia el color */
.mi-menu li:hover > a { color: Crimson; }

/* los submenús */
.mi-menu ul {
border-radius: 0 0 5px 5px;
left: 0;
margin: 0;
opacity: 0; /* no son visibles */
position: absolute;
top: 40px; /* se ubican debajo del enlace principal */
/* el color de fondo */
background: #222;
background: -moz-linear-gradient(#222,#555);
background: -webkit-linear-gradient(#22,#555);
background: -o-linear-gradient(#222,#555);
background: -ms-linear-gradient(#222,#555);
background: linear-gradient(#222,#555);
/* animamos su visibildiad */
-moz-transition: opacity .25s ease .1s;
-webkit-transition: opacity .25s ease .1s;
-o-transition: opacity .25s ease .1s;
-ms-transition: opacity .25s ease .1s;
transition: opacity .25s ease .1s;
}
/* son visibes al poner el cursor encima */
.mi-menu li:hover > ul { opacity: 1; }

/* cada un ode los items de los submenús */
.mi-menu ul li {
height: 0; /* no son visibles */
overflow: hidden;
padding: 0;
/* animamos su visibildiad */
-moz-transition: height .25s ease .1s;
-webkit-transition: height .25s ease .1s;
-o-transition: height .25s ease .1s;
-ms-transition: height .25s ease .1s;
transition: height .25s ease .1s;
}
.mi-menu li:hover > ul li {
height: 36px; /* los mostramos */
overflow: visible;
padding: 0;
}
.mi-menu ul li a {
border: none;
border-bottom: 1px solid #111;
margin: 0;
/* el ancho dependerá de los textos a utilizar */
padding: 5px 20px;
width: 100px;
}
/* el último n otiene un borde */
.mi-menu ul li:last-child a { border: none; }

</style>
REFERENCIAS:designmodo.com

Saturday, May 18, 2019

Unos cuantos íconos especiales

Pictonic Icons
Contiene 266 íconos en formato PNG.
descargar


PW Drawn Icon Font
Contiene un archivo en formato TTF.
descargar

Friday, May 17, 2019

Iconos de tipo Glyphs

Glyphish
Contiene 201 íconos de distintos tamaños en formato PNG.
descargar

Pixicus
Contiene 106 íconos de distintos tamaños en formato PNG.
descargar

Mimiglyphs
Contiene 80 íconos de 16x16 en formato PNG.
descargar

Thursday, May 16, 2019

Crear un gadget de Facebook usando Json (3)

Voy a insistir en que la forma de mostrar los datos que leemos de un feed usando Json es subjetiva y podemos hacer casi cualquier cosa, sólo hay que saber cuáles son y aprender la forma de manipularlos, armando la salida de modo personal (más información: 1, 2)

En este último ejemplo, vamos a tratar de diferenciar el contenido y mostrarlo de distinto ¿Qué contenido? Por ejemplo trataremos a las imágenes que subimos a Facebook de modo diferenciado, mostrándolas más grandes o con un formato especial ¿Cómo podríamos hacer esto? leyendo el HTML y verificando la dirección URL de esas imágenes; una posibilidad:
var externo = elHtml.indexOf("safe_image.php");
La variable externo tendrá un valor mayor o igual a cero si dentro del contenido se encuentra ese texto que indica que la imagen no la hemos subido nosotros sino que es externa, ya sea porque lo que compartimos es un enlace o un video así que, si se trata de ese tipo de entradas, armaré un DIV de un tipo; por el contrario, si no se encuentra ese texto y hay una imagen, esa imagen la hemos subido nosotros y la URL es algo así:
https://fbcdn-photos-a.akamaihd.net/......./xxxxxxx_s.jpg
Donde el _s final indica que el tamaño de la imagen es pequeño (small) y es el dato que contiene el feed; mide 130 pixeles de ancho; si cambio _s por _n vería la imagen original con su tamaño normal, lo mismo si pasaría si usara _b..

Podría usar esas pero son muy grandes así que elegiré una intermedia y cambiare _s por _a que me dará una imagen de 180 pixeles de ancho.

¿Cómo haría eso? Por ejemplo, de este modo:
laImagen = laImagen.replace("_s.jpg","_a.jpg")
No son las únicas alternativas; _t es una miniatura de 75 pixeles, _o nos devuelve una imagen de 540 pixeles y _q o _x también tienen 180 pixeles ¿Por qué? No sé. Habrá que preguntarles a ellos.

Ahora que tengo todos los pedazos y un lio bárbaro en al cabeza, me dedico a armar la función y ver qué sale:
<,script type='text/javascript'>,
//<,![CDATA[

function extraer_imagen(htmltag) {
var s, a, b, c, d;
var imagen = "";
s = htmltag;
a = s.indexOf("<img");
b = s.indexOf("src=\"",a);
c = s.indexOf("\"",b+5);
d = s.substr(b+5,c-b-5);
if((a!=-1)&&(b!=-1)&&(c!=-1)&&(d!="")) {
imagen = d;
}
return imagen;
}

function feedFacebook(json) {
var entry, mensaje, enlace, elResumen, elHtml, externo, laImagen;
var salida = "";
for (var i = 0; i < json.responseData.feed.entries.length; i++) {
entry = json.responseData.feed.entries[i];

// los datos del feed
mensaje = entry.title;
enlace = entry.link;
elResumen = entry.contentSnippet;
elHtml = entry.content;

// los datos que verifico
externo = elHtml.indexOf("safe_image.php");
laImagen = extraer_imagen(elHtml);

// y voy armando la salida
salida += "<div class='cadaitem'>";

if(externo!=-1) {

// enlaces
salida += "<div class='titulo'><a href='" + enlace + "' target='_blank' >" + mensaje + "</a></div>";
salida += "<div class='contenido enlace'>";
salida += "<img src='" + laImagen + "'/>";
salida += "<p>" + elResumen + "</p>";
salida += "</div>";
salida += "<div class='clear'></div>";

} else {

// imágenes
salida += "<div class='contenido imagen'>";
if(laImagen) {
laImagen = laImagen.replace("_s.jpg","_a.jpg");
salida += "<a href='" + enlace + "' target='_blank'><img src='" + laImagen + "'/></a>";
if(mensaje) { salida += "<span>" + mensaje + "</span>"; }
if(elResumen) { salida += "<span>" + elResumen + "</span>"; }

}
salida += "</div>";

}
salida += "</div>";

}
document.getElementById('divFACEpage').innerHTML=salida;
}

//]]>,
<,/script>,
El resto es un poco de CSS:
<,style>,
#divFACEpage {
margin: 0 auto;
width: 250px;
}
.cadaitem {
background-color: #FFF;
font-family: Tahoma;
font-size: 13px;
margin-bottom: 5px;
}
.cadaitem .clear {
clear:both;
padding:10px;
}
.cadaitem .contenido.enlace {
width:250px;
}
.cadaitem .titulo {
overflow: hidden;
padding: 10px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
word-wrap: normal;
}
.cadaitem .titulo a {
color:DeepSkyBlue;
font-weight:bold;
}
.cadaitem .contenido.enlace img {
float: left;
max-width: 100px;
padding: 0 10px;
}
.cadaitem .contenido.enlace p {
color: #666;
float: right;
font-size: 11px;
overflow: hidden;
padding-right: 10px;
width: 120px;
word-wrap: break-word;
}
.cadaitem .contenido.imagen {
position:relative;
}
.cadaitem .contenido.imagen img {
display: block;
margin: 0 auto;
padding: 20px 0;
}
.cadaitem .contenido.imagen:hover span {
display: block;
}
.cadaitem .contenido.imagen span {
background-color: rgba(0, 0, 0, 0.5);
border-radius: 10px;
color: #FFF;
display: none;
font-size: 11px;
margin: 0 20px;
padding: 10px;
position: absolute;
text-align: center;
top:30%;
width: 200px;
}
<,/style>,

Wednesday, May 15, 2019

Crear un gadget de Facebook usando Json (2)

En la primera parte hablaba de crear un gadget a partir de los datos de un feed de Facebook pero ¿cómo se diseña el gadget? Tal como se diseña un post, usando HTML y haciendo que sea la función el que escriba esos códigos. Para esto no hay un solo método, hay muchas formas; yo uso siempre el mismo, creo una variable de texto, voy "sumando" las distintas etiquetas y cuando termina el bucle, la "escribo" en el DIV.

El resto, es subjetivo; me imagino un gadget que colocaré en la sidebar así que será "angosto" y estaría más interesado en mostrar imágenes que en mostrar textos así que, para complicarme la vida, debería "detectar" esas imágenes y separarlas de los textos. Usaré sólo cuatro datos: entry.title, entry.link, entry.content y entry.contentSnippet; no me meteré con la fecha que requiere códigos más largos para formatearlas de manera "razonable" y quisiera mantener todo lo más simple posible para concentrarme en lo que realmente me parece importante aunque, como dije, todo esto es absolutamente subjetivo y esa es justamente lo verdaderamente interesante de Json, que con los mismos datos, podemos armar cosas completamente distintas.

¿Por que no pensar primero el modelo que quisiera que se viera escribiendo el HTML tal como haría en una entrada? Un ejemplo:
<div class='cadaitem'>
<div class='titulo'>
<a href='URL_entrada' target='_blank' > ... el texto del mensaje ... </a>
</div>
<div class='contenido'>
<img src='URL_imagen'/>
<p> ... aquí pondría el resumen ... <p>
</div>
</div>
Bastaría establecer las reglas de estilo CSS para cada cosa u ordenarlas de cualquier otro modo y luego, usar eso en la función, agregando los datos correspondientes:
salida += "<div class='cadaitem'>";
salida += "<div class='titulo'>";
salida += "<a href='"+enlace+"' target='_blank' >"+mensaje+"</a>";
salida += "</div>";
salida += "<div class='contenido'>";
salida += "<img src='"+laImagen+"'/>";
salida += "<p>"+elResumen+"<p>";
salida += "</div>";
salida += "</div>";
Pero ... me falta laImagen; debo "encontrarla" dentro del contenido (entry.content) y para eso, usaré una función extra que es la misma que usamos en Blogger para detectar al primera imagen de las entradas:
function extraer_imagen(htmltag) {
var s, a, b, c, d;
var imagen = "";
s = htmltag;
a = s.indexOf("<img");
b = s.indexOf("src=\"",a);
c = s.indexOf("\"",b+5);
d = s.substr(b+5,c-b-5);
if((a!=-1)&&(b!=-1)&&(c!=-1)&&(d!="")) {
imagen = d;
}
return imagen;
}
Así que en mi función, la variable laImagen será:
var elHtml = entry.content;
var laImagen = extraer_imagen(elHtml);
o directamente:
laImagen = extraer_imagen(entry.content);

Monday, May 13, 2019

Crear un gadget de Facebook usando Json (1)

Muchas veces hablamos de los feeds de un sitio web ¿que son? En realidad, nada especial, son, como todo lo que vemos en internet, archivos de alguna clase, una serie de "números" ordenados de alguna forma que los navegadores interpretan y nos muestran de acuerdo a ciertas reglas universales; el resultado, será una imagen, un video, un texto o ... un feed.

Ese "orden" en que está escrito, define su contenido. Un feed es un archivo de tipo XML, es decir, un texto con etiquetas especiales que es generado por el servidor (Blogger, YouTube, Twitter o cualquier otro) y que contiene los datos de nuestro blog o de un sitio determinado; bien podría decirse que es un "resumen" del contenido de un sitio que nos permite acceder a esa información y visualizarla directamente en el navegador o, lo que es más común, utilizando algún software especial.

Si colocamos la URL de un feed en la mayoría de los navegadores, estos lo interpretarán y mostrarán su contenido como si fuera una página web minimizada. Chrome, por el contrario, mostrará su código, es decir, el texto del archivo cosa que también podemos ver en todos los otros, si les solicitamos ver el código fuente de la pagina.

Si hacemos eso, veremos una serie de etiquetas que dependerán del formato de ese archivo de feeds ya que hay varios sistemas (Atom, RSS2) algunos más simples y otros mucho más complejos pero, lo básico es siempre similar. Cada entrada se encuentra contenida entre las etiquetas <item> </item> o <entry> </entry> dentro de la cual hay otras con el título, la fecha, el autor, etc.
<entry>
<title> xxxxxxx </title>
<link> xxxxxxx </link>
<published> xxxxxxx </published>
<content> xxxxxxx </content>
</entry>
Todo es teoria ya que, en realidad, si bien hay una cierta normalización de esos datos, cada sistema puede (y lo hace) agregar etiquetas o atributos especiales; por eso es que muchos de ellos incluyen documentación extra donde nos dicen cuáles son los datos y cómo debemos interpretarlos. Para eso, para interpretarlos, se usan diferentes lenguajes; en Blogger, las cosas no son tan fáciles ya que sólo podemos usar JavaScript que tiene sus limitaciones y es ahí donde entra a jugar el misterioso Json que es una palabrita que vemos constantemente y a través de la cual se arman la gran mayoría de los gadgets que utilizamos.

En este caso, podríamos decir que Json que no es otra cosa que un ese mismo archivo de feeds, "re-armado" con un formato diferente adaptado, justamente, para que podamos leerlo con JavaScript. Cuando solicitamos que se cargue un archivo de feeds en formato Json, lo que obenemos es una serie de variables ordenadas con el contenido y leerlas es fácil, el problema está en "saber" cuales son esas variables ya que pueden ser muy variadas.

Una herramienta que ayuda en este asunto es el llamado Google Ajax Feed API ya que nos simplifica la tarea, interpretando los datos de los distintos feeds y enviándonos datos que tienen siempre la misma estructura por lo tanto, podemos leer cualquier feed y mostrarlo como se nos de la gana.

Vamos a ver un ejemplo concreto, intentaremos mostrar nuestra página de Facebook ya que esta, dispone de un feed ¿cuál es? algo como esto:
https://www.facebook.com/feeds/page.php?format=atom10&id=XXXXXXXXXX
donde XXXXXXXXXX es el ID de nuestra página que es el que nos muestra el navegador cuando entramos en ella:
https://www.facebook.com/pages/Vagabundia/215401628483231
https://www.facebook.com/pages/Gem-BLOG/395197195477
¿No tiene un ID y sólo tiene un nombre? busquen el emlace a Notificaciones que se ve en la parte superior y copien el enlace; el ID son los números que siguen a id=:
http://www.facebook.com/Infinitos.Magazine
http://www.facebook.com/notifications?id=151205601565278
Vamos al grano. Necesitamos el script que tiene dos partes, la llamada al API de Google y una función que interpretará y mostrará los datos en un DIV con cierto ID. La función la ponemos en cualquier parte, por ejemplo, antes de </head>:
<,script type='text/javascript'>,
//<,![CDATA[
function feedFacebook(json) {
var entry, mensaje, enlace, elResumen;
var salida = "";
for (var i = 0; i < json.responseData.feed.entries.length; i++) {
entry = json.responseData.feed.entries[i];
var mensaje = entry.title;
var enlace = entry.link;
var elResumen = entry.contentSnippet;
salida += "<p>" ;
salida += mensaje + "<br/>";
salida += enlace + "<br/>";
salida += elResumen + "<br/>";
salida += "</p>";
}
document.getElementById('divFACEpage').innerHTML=salida;
}
//]]>,
<,/script>,
Luego, donde queramos que se muestre el resultado, un DIV vacío:
<div id="divFACEpage"></div>
Y debajo, el script que llama al API de Google:
<,script type='text/javascript'>,
//<,![CDATA[
var URLFEED = "https://www.facebook.com/feeds/page.php?format=atom10&id=XXXXXXXXXX";
var NUMFEED = 5;
var archivofeeds = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num="+NUMFEED+"&output=json&q="+encodeURIComponent(URLFEED)+"&callback=feedFacebook";
var nuevo = document.createElement('script');
nuevo.setAttribute('type', 'text/javascript');
nuevo.setAttribute('src', archivofeeds);
document.getElementsByTagName('head')[0].appendChild(nuevo);
//]]>,
<,/script>,
¿Qué hace esta última? cargar el script con el API de Google indicándole la dirección del feed (URLFEED), la cantidad de entradas que queremos leer (NUMFEED) y el nombre de la función que interpretará esos datos (callback=feedFacebook)

Justamente, es esta función lo que hará la diferencia ya que, los datos serán siempre los mismos y lo que luego variará es la forma en que los mostremos. La función es un bucle que va leyendo item por item guardándolos en una variable a la que llamamos entry; como esos datos son un array, accedemos a ellos con el nombre de la variable, un punto y el nombre del dato en si mismo. El API nos dará los siguiente datos:

entry.title es el título del item (el título de una entrada de un blog o, en este caso, el mensaje que hayamos agregado) y corresponde al contenido de la etiqueta <title>
entry.link es la dirección URL de ese item y corresponde al contenido de la etiqueta <link>
entry.content es el contenido HTML de la entrada, etiquetas <content> <summary> o <description>
entry.contentSnippet es un resumen de ese mismo contenido, en formato de texto plano, es decir, sin etiquetas HTML
entry.publishedDate es la fecha en un formato similar a este "20 May 2019 10:20:30 -0300"
entry.author es el nombre del autor y en este ejemplo no existe
entry.description es un texto adicional o subtítulo que tampoco existe
entry.categories es la lista de etiquetas que tampoco existe

En este ejemplo, simplemente guardamos algunos de esos datos en otras variables y los mostramos así nomás, uno debajo del otro; el mensaje, la URL y el resumen:

Obviamente, nada especial pero, en realidad, eso es todo lo que necesitamos; sabiendo cuales son los datos, podemos armar nuestros propios gadgets, diseñando el formato en que quisiéramos mostrarlos.

Notas desde el navegador

El artículo de Jose Jesus Perez Aguinaga llamado One line browser notepad me llamó la atención, no sólo por lo original de la idea sino por el grado de participación y aportes de los lectores, algo que, no suele ser habitual en estos tiempos donde sólo vale la inmediatez y la "practicidad" de las cosas.

Seguramente, no es algo que maraville ya que es posible que haya decenas de sistemas similares pero, no deja de ser interesante ya que demuestra dos cosas: que siempre se puede darle una vuelta de tuerca más a algo y que vale la pena hacerlo.

La idea es simple; usar el navegador para tomar notas rápidas sin necesidad de agregar plugins o aplicaciones extras, valiéndose sólo de un bookmarklet, algo que puede ser agregado a los marcadores.

¿Cómo funcionaría? Basta abrir una ventana o pestaña y escribir lo siguiente en la barra de direcciones:
data:text/html, <html contenteditable>
Haciendo eso, la ventana se convertirá en un editor de textos sencillo donde podremos escribir cualquier cosa. Bastaría guardarla así en los marcadores para no tener que tipear eso cada vez que lo necesitemos.

De ahí en más, comenzaron a aparecer variaciones de todo tipo:
data:text/html, <textarea style="font-size: 1.5em; width: 100%; height: 100%; border: none; outline: none" autofocus />

data:text/html, <body contenteditable style="font-size:2rem;line-height:1.4;max-width:60rem;margin:0 auto;padding:4rem;">

data:text/html, <title>Text Editor</title><body contenteditable style="font-size:2rem;line-height:1.4;max-width:60rem;margin:0 auto;padding:4rem;">

data:text/html;charset=utf-8, <html contenteditable>

data:text/html;charset=utf-8, <title>TextEditor</title><body contenteditable style="font-size:2rem;line-height:1.4;max-width:60rem;margin:0 auto;padding:4rem;" spellcheck="false">

data:text/html;charset=utf-8, <title>TextEditor</title><body contenteditable style="font-size:2rem;font-family:monaco;line-height:1.4;max-width:60rem;margin:0 auto;padding:4rem;" spellcheck="false"><h1>Text Editor</h1><p>Start Here.

data:text/html, <style>html,body{margin: 0; padding: 0;}</style><textarea style="font-size: 1.5em; line-height: 1.5em; background: %23000; color: %23EEE; width: 100%; height: 100%; border: none; outline: none; margin: 0; padding: 90px;" autofocus placeholder="empezar a escribir" />

data:text/html,<pre onkeyup="(function(d,t){d[t]('iframe')[0].contentDocument.body.innerHTML = d[t]('pre')[0].textContent;})(document,'getElementsByTagName')" style="width:100%;height:48%;white-space:pre-wrap;overflow:auto;" contenteditable></pre><iframe style="width:100%;height:48%">
Una vez que terminamos de escribir, sólo necesitamos guardar el resultado como haríamos con cualquier página web.

Incluso hay quien llevó la idea al extremo de crear un bookmarklet que guarda cualquier contenido seleccionado.

Saturday, May 11, 2019

Cuatro packs de íconos y herramientas

Nixus
Contiene 180 íconos de 32x32, 48x48 y 64x64, en formato PNG.
descargar

iconSweets
Contiene 1 archivo en formato PSD.
descargar

Sanscons
Contiene más de 5000 íconos en formato GIF y PNG.
descargar

Iconic
Un sistema completo con íconos en distintos formatos y heramientas varias.
descargar

Thursday, May 9, 2019

Sobre reglas y diversidades

Cuando la w3.org dice que hay etiquetas y atributos que son obsoletos y que no deben usarse, sólo expresa un deseo ya que los navegadores siguen y seguirán soportando TODAS las etiquetas que existen y por lo tanto, este tipo de información que a algunos les parece mandatorio, no pasa de ser una sugerencia porque, como en muchos otros casos, la distancia entre la teoría y la práctica puede ser enorme.

La realidad indica que la w3.org dispone cosas y los navegadores hacen lo que quieren o lo que pueden. Si eso es malo o bueno carece de importancia y es discutible, lo cierto es que las reglas y las leyes sólo tienen sentido cuando existe alguien que pueda obligar a aplicarlas, caso contrario, sólo son palabras.

En la web, eso tiene una variante, las reglas sirven si nos sirven ya que es un tema donde no intervienen ni la moral ni la ética y donde todo lo que funciona bien está bien aunque pueda ser mejorado.

Validar el HTML es la forma de saber si una página cumple con los estándares del W3C pero ¿hay alguna relación entre validar el HTML de un sitio y su posicionamiento en los buscadores?

Algunos afirman que SI pero, Google responde NO:



"Muchos sitios web pueden tener código inválido pero verse correctamente porque muchos navegadores actuales hacen un buen trabajo a la hora de tratar con código deficiente. Así que no es tan importante que el código sea absolutamente perfecto, sino que la página se muestre correctamente a los usuarios en general ... Google puede entender y manejar páginas que son perfectas gramaticalmente hablando y con un código HTML perfectamente correcto, y también puede entender las que son un poco más informales. Porque básicamente entiende sobre qué trata la página."

¿Acaso esto significa que podemos hacer cualquier cosa? Mi respuesta es SI PERO NO.

¿Cuál es el sentido de una página web? Que, tal como dice Google, "se muestre correctamente a los usuarios en general", a la mayor parte de ellos, sea cual sea el navegador que utilicen.

¿Esto es posible? Mi respuesta es la misma: SI PERO NO.

El 100% es un lindo numero pero es un valor excesivo e inalcanzable a menos que se sacrifique tantas cosas que la web se transforme en uniforme y la medida a tener en cuenta sea siempre el navegador menos versátil, la resolución de pantalla más chica, la conexión más lenta, la imaginación más escasa.

Cada uno deberá evaluar qué quiere, a quién se dirige y tomar decisiones. Decisiones que tendrán consecuencias. Tal cosa no se verá tan bien en tal navegador y tal otra tendrá que ser adaptada, retorcida o desestimada. Eso, no es ni un pecado ni un error, es aprender a manejarse dentro de los límites de la realidad, sin falsearla. No hay ningún motivo para tratar de imponer reglas que no son tales sino sólo gustos subjetivos.

Nada es perfecto, nada es universal. Si algo ha enseñado la famosa globalización es justamente lo inverso; que el mundo del futuro (si es que existe) no será único sino una suma de diversidades infinitas.

Wednesday, May 8, 2019

Slider Kit: Un plugin multifuncional para jQuery

Este plugin para jQuery es imposible de explicar detalladamente porque posee tal cantidad de opciones que resulta imposible enumerarlas. Se trata de Slider Kit y lo podemos descargar desde lo descargamos desde Google Codes.

Su característica principal es que el plugin reune en si mismo una serie de características que normalmente requieren el uso de varios scripts; genera slideshows, galerías de distinto tipo, carruseles de imágenes, pestañas, sliders de contenido, etc; y todo eso lo hace de manera modular, con un CSS básico que podemos personalizar a gusto y agregando características avanzadas tales como el control de los elementos con la rueda del ratón y animaciones de diferente tipo.

Aunque no lo he probado en todos los navegadores, dicen que funciona en todos, incluyendo Internet Explorer 8.

Como cualquier otro de estos scripts, debemos agregar los archivos antes de </head> ya sea con archivos externos o copaindo su contenido en la plantilla misma:
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js' type='text/javascript' />
<script type="text/javascript" src="URL_jquery.sliderkit.1.4.min.js />
<script src='URL_jquery.easing.1.3.js' type='text/javascript />
<script type="text/javascript" src="URL_jquery.mousewheel.min.js />
Luego, dependiendo de qué queremos utilizar, llamamos a las funciones; por ejemplo:
<script type="text/javascript">
jQuery(window).load(function(){
jQuery(".newslider-vertical").sliderkit({shownavitems:3,verticalnav:true,navitemshover:true});
jQuery(".tabs-standard").sliderkit({auto:false,tabs:true,mousewheel:true,circular:true,panelfx:"none"});
// agregamos todas las funciones que vayamos a necesitar
});
</script>
y por último, el CSS, que, tal como dije antes, podemos personalizar aunque para empezar, conviene que utilicemos las reglas de estilo por defecto y luego, ir probando.


La descarga incluye mucha información detallada y ejemplos así que es una buena opción para simplificar scripts ya que la forma de armar los contenidos es muy similar y cuando se entiende su funcionamiento, termina siendo sencillo generar cosas diferentes, sin restricciones en cuanto a la cantidad que pueden ser agregadas en una misma página.

Monday, May 6, 2019

Reglas, sugerencias, un poco de todo

La llamada Google HTML/CSS Style Guide es eso; un documento de Google que intenta definir algunas reglas a seguir cuando se escriben códigos HTML o CSS cuyo objetivo es ayudar a quienes lo leen o deben interpretarlo.

La guia es una mezcla de sugerencias validas y subjetivas por lo tanto, cada uno debería "filtrarla" y tener en cuenta aquellas cosas que se adapten a su modo de trabajo y descartar las otras. La base de todo esto es la accesibilidad es decir, que nosotros mismos entendamos qué estamos escribiendo y lo hagamos siempre del mismo modo para que resulte sencillo modificarlo en el futuro.

La paradoja del documento de Google es que ellos no aplican lo que predican ya que las páginas que crean los servicios que administran suelen ser engendros irracionales sin pies ni cabeza. Ni hablar de Blogger o de sus plantillas !!!

De todos modos, acá hay algunas sugerencias a tener en cuenta que no son novedad pero tal vez valga la pena repetir.

1 Usar las etiquetas HTML correctas ya que cada una de ellas ha sido creada con un propósito.

A es un enlace por lo tanto; es mejor poner:
<a href="UNA_URL">un enlace</a>
que:
<div onclick="abrir('UNA_URL');">un enlace</a>
H1 H2 H3 etc son encabezados; el número (1 a 6) no existe para indicar su tamaño sino para indicar su importancia. Una página web sólo debería tener una etiqueta H1 y esa etiqueta debería ser el título. Si hay subtítulos se usa H2 y no hay que abusar de ellos; si los títulos son elementos intrascendentes (por ejemplo los títulos de la sidebar de Blogger) estos no deberían tener una etiqueta de encabezado y si la tienen, jamás deberían ser encabezados "superiores" al título del blog o al título de la entrada.

P es un párrafo (un texto) así que escribir:
<p><img src="UNA_IMAGEN" /></p>
no tiene mucho sentido.

2 Toda etiqueta IMG debería tener un atributo alt que indique el contenido alternativo pero, lo mismo debería hacerse con videos o cualquier otro tipo de contenido multimedia.

3 Las reglas del HTML5 dicen que ya no es necesario agregar el atributo type en hojas de estilo y scripts a menos que el tipo no sea el usual (CSS y JavaScript) por lo tanto, se sugiere que en lugar de esto:
<link rel="stylesheet" href="archivo.css" type="text/css" />
<script src="archivo.js" type="text/javascript"></script>
se use:
<link rel="stylesheet" href="archivo.css" />
<script src="archivo.js"></script>
ya que es algo que funcionará en cualquier navegador y en cualquier página, aún cuando no sea HTML5.

4 Agregar siempre un punto y coma final a cualquier propiedad de CSS aún cuando no sea "obligatoria" es algo que evitará errores futuros.

Suele verse esto:
.ejemplo {
text-align: center
}
que funciona perfectamente pero, en algún momento le agregamos alguna otra propiedad:
.ejemplo {
text-align: center
color: red;
}
y ya no funcionará porque nos hemos olvidado de agregarle el punto y coma final.

5 Indentar el código siempre es buena idea porque permite visualizar qué cosa esta dentro de que otra y de ese modo comprender cómo se verán afectados los contenidos. Ellos recomiendan usar dos espacios y evitar el uso de la tecla TAB (cosa con la que yo estoy de acuerdo) pero, es algo que queda criterio de cada uno:
<div>
<p> algo </p>
<ul>
<li> item </li>
<li> item </li>
<li> item </li>
</ul>
<div>
<!-- OTRA COSA -->
</div>
</div>
Minimizar quitando espacios o indentaciones debería estar reservado sólo a aquellos códigos que estemos completamente seguros que no vamos a editar jamás.

Por el contrario, se recomienda minimizar ciertas cosas, por ejemplo, eliminar las comillas innecesarias en las direcciones URL:
background: url("UNA_IMAGEN") no-repeat 0 0 transparent;
se puede escribir:
background: url(UNA_IMAGEN) no-repeat 0 0 transparent;
usar tres caracteres de color cuando es posible:
color: #FFF;
en lugar de:
color: #FFFFFF;
eliminar la unidad cuando el valor es cero:
margin: 0;
en lugar de:
margin: 0px;
eliminar el cero cuando se usan valores decimales:
font-size: .8em;
en lugar de:
font-size: 0.8em;
6 Una última recomendación que desconocía y habría que verificar y evaluar: omitir el protocolo (http:, https:) en las direcciones URL de los archivos externos a menos que ese protocolo sea absolutamente necesario; en lugar de:
background: url(https://lh5.googleusercontent.com/xxxxxxx/imagen.jpg);
usar:
background: url(//lh5.googleusercontent.com/xxxxxxx/imagen.jpg);
Si optamos por esto, hay que tener en cuenta que la URL debe comenzar con //

En resumen: conviene leerlo, "masticarlo", aplicar aquello que nos parezca razonable y descartar el resto. Como siempre, sólo debe primar el sentido común y no aceptar todo lo que se diga como si fuera una verdad revelada e incontrovertible, lo diga quien lo diga.

Saturday, May 4, 2019

Comentarios: Borrar o marcar como spam

Tanto en el escritorio normal como en el nuevo, los comentarios se encuentran divididos en tres secciones: Publicados, Esperando moderación y Spam. Las dos primeras nos dan tres opciones:
  • Suprimir el contenido borra el texto pero lo deja publicado, informando que "Un administrador del blog ha eliminado esta entrada."
  • Suprimir lo borra por completo
  • Span lo envia a la pestaña correspondiente


Lo que comentan en The Real Blogger Status es, justamente, cuál debería ser el proceso lógico para que este filtro de spam funcione de manera razonable y, de esa manera, beneficiarnos todos.

Como todo sistema que intenta controlar el spam, debe ser "entrenado" y somos nosotros quienes debemos hacer eso. Para eso, lo recomendable no es borrar el spam sino, marcarlo primero; de esta manera, Blogger va acumulando información y el sistema tiende a mejorar con el tiempo.

Esto es importante hacerlo tanto con los comentarios publicados como con aquellos que están en moderación. Por el contrario, todos aquellos que aparecen por error en la pestaña Spam deben ser desmarcados con el botón correspondiente e inmediatamente serán publicados. Esto, es algo habitual ya que, si el comentario posee varios enlaces o enlaces a algún sitio considerado "peligroso", puede ser malinterpretado.

Thursday, May 2, 2019

Un espacio hace la diferencia

Todos sabemos que los caracteres espacio son importantes; separan las palabras y evitar que eso que escribimosseaungalimatíasilegible.

En CSS pasa lo mismo, no tanto porque no pueda leerse eso que escribimos sino porque al no estar donde deben estar, el resultado es un error. El caso típico es el de la propiedad background; si escribimos esto:
background:#FFF url(una_imagen)no-repeat left top;
en Intenet Explorer no se verá la imagen y no es un error del navegador, es que lo hemos escrito mal, sin dejar el espacio entre el cierre del paréntesis y la palabra no-repeat

Pero no sólo se producen errores en tal o cual navegador, es algo que podría ocurrir en todos si, por ejemplo, queremos poner una regla de estilo para que una etiqueta span tenga un determinado formato (color rojo en este caso):
<div id="demo" class="ejemplo">
.......
un texto cualquiera <span>esto en rojo</span> un texto cualquiera.
.......
</div>
¿Cuál sería la regla de estilo?
#demo.ejemplo span { color:#F00; }
o
#demo .ejemplo span { color:#F00; }
Si usamos la primera, todo estará bien; si usamos la segunda, no pasará nada. Esto, se debe a que el espacio indica "algo".

Maecenas porta felis pharetra diam suscipit id vehicula urna ullamcorper. Aenean a interdum nibh. Nam enim nunc, aliquet et egestas vitae cras amet.

En la primer, traducida al español, se indica que en el elemento cuyo ID es demo y cuya clase es ejemplo, las etiquetas SPAN interiores son de color rojo. Por eso, no hay un espacio intermedio.

En la segunda decimos que en el elemento cuyo ID es demo, en toda etiqueta interna que sea de la clase ejemplo, las etiquetas SPAN internas serán de color rojo; el HTML debería tener esta estructura:
<div id="demo">
.......
<div class="ejemplo">
un texto cualquiera <span>esto en rojo</span> un texto cualquiera.
</div>
.......
<div class="otra">
un texto cualquiera <span>esto no será de color rojo</span> un texto cualquiera.
</div>
.......
</div>

Maecenas porta felis pharetra diam suscipit id vehicula urna ullamcorper. Aenean a interdum nibh. Nam enim nunc, aliquet et egestas vitae cras amet.

Maecenas porta felis pharetra diam suscipit id vehicula urna ullamcorper. Aenean a interdum nibh. Nam enim nunc, aliquet et egestas vitae cras amet.

Por supuesto, la primera parece redundante y no siempre es necesario escribirlas de ese modo indicando el ID y la clase; estas dos reglas también harían lo mismo en el primer ejemplo:
#demo span { color:#F00; }
.ejemplo span { color:#F00; }
y esta haría lo mismo en el segundo ejemplo:
.ejemplo span { color:#F00; }
No todo funcionará igual, las reglas también dependen de lo que se llama prioridad por lo que ciertas definiciones no son tenidas en cuenta ya que hay otras que indican lo contrario y para el navegador, son más "importantes". Un ejemplo, si tuviera estas tres:
#demo.ejemplo span { color:#F00; } /* color rojo */
#demo span { color:#FF0; } /* color amarillo */
.ejemplo span { color:#0F0; } /* color verde */
el SPAN se vería de color rojo pese a que las otras dos reglas dicen lo contrario; si elimino la primera ser vería amarillo así que si quisiera que se viera verde, sólo debería incluir la última o agregar la palabra !important a alguna de ellas para forzar al navegador a prestar atención.

Maecenas porta felis pharetra diam suscipit id vehicula urna ullamcorper. Aenean a interdum nibh. Nam enim nunc, aliquet et egestas vitae cras amet.