31 de diciembre de 2019
:: ¿Qué son las Web beacons?
Las Web beacons o Web bugs son imágenes, inapreciables a la vista por su tamaño y color, que se descargan al visitar una web. Sin embargo estas imágenes están almacenadas en un sitio distinto y permiten al titular de este registrar la visita mediante la información que el navegador proporciona al descargar la imagen: IP, sistema operativo, versión de navegador, etcétera.
23 de diciembre de 2019
:: ¿Qué son las Flash Cookies?
Las Flash Cookies o Local Shared Objects son un tipo de cookies que pueden almacenar más información que las cookies tradicionales. Al no depender del navegador utilizado son más difíciles de localizar, visualizar o borrar y, por ejemplo pueden utilizarse para regenerar cookies estándar.
16 de diciembre de 2019
:: Alfresco. Compartir carpeta
Como prueba de concepto y a modo de recordatorio, si la opción Quick Share no está deshabilitada, podemos compartir un fichero por medio de una url.
En el caso de necesitar compartir una carpeta, la url de la misma se encuentra en los detalles de esta. Para ello los pasos a seguir serán los siguientes:
.- Sobre la carpeta que queremos compartir, pulsaremos en la opción: "Ver los detalles"
.- En los detalles de esta, disponemos de un enlace para compartir la página actual, y será este el que utilicemos
En el caso de necesitar compartir una carpeta, la url de la misma se encuentra en los detalles de esta. Para ello los pasos a seguir serán los siguientes:
.- Sobre la carpeta que queremos compartir, pulsaremos en la opción: "Ver los detalles"
.- En los detalles de esta, disponemos de un enlace para compartir la página actual, y será este el que utilicemos
10 de diciembre de 2019
:: Alfresco. Configuración Euskera
Como prueba de concepto, describiremos a continuación cómo configurar nuestro Alfresco 5.2 en Euskera.
.- Accederemos a la siguiente url para descargar los paquetes de idiomas disponibles:
http://alf-trans.ossportal.org/
.- En nuestro caso, descargaremos los ficheros "alfresco-eu.jar" y "share-eu.jar"
.- Copiaremos los ficheros en la carpeta "${alfresco}/tomcat/shared/lib", siendo ${alfresco} la ruta donde lo tengamos instalado
.- Reiniciaremos el servicio de Alfresco para que los cambios sean efectivos
Podemos comprobar el correcto funcionamiento si configuramos nuestro navegador (en el caso de que no lo tengamos) al Euskera.
.- Accederemos a la siguiente url para descargar los paquetes de idiomas disponibles:
http://alf-trans.ossportal.org/
.- En nuestro caso, descargaremos los ficheros "alfresco-eu.jar" y "share-eu.jar"
.- Copiaremos los ficheros en la carpeta "${alfresco}/tomcat/shared/lib", siendo ${alfresco} la ruta donde lo tengamos instalado
.- Reiniciaremos el servicio de Alfresco para que los cambios sean efectivos
Podemos comprobar el correcto funcionamiento si configuramos nuestro navegador (en el caso de que no lo tengamos) al Euskera.
5 de diciembre de 2019
:: Liferay no muestra literales de traducción
En nuestros desarrollos bajo el CMS Liferay, a la hora de internacionalizar literales obtenidos de un ficheros de traducciones:
LanguageUtil.get(portletConfig, locale, "literal-internacionalizable");
es posible que observemos que estos literales que deberían extraerse del fichero de traducciones oportuno, no se están recuperando. Si ocurre esto, tal vez en nuestro portlet, en el fichero: "portlet.xml" nos falte la siguiente línea:
<resource-bundle>content/Language</resource-bundle>
29 de noviembre de 2019
:: Wordpress. Deshabilitar el editor: "Gutenberg"
El editor de bloques denominado: "Gutenberg" que viene con la versión 5 de Wordpress, puede que de problemas para algunos usuarios.
Existen distintas formas de deshabilitarlo y recurrir de nuevo al editor clásico:
1.- Instalación del plugin "Editor Clásico"
2.- Instalación del plugin: "Disable Gutenberg"
3.- Deshabilitar el editor por código.
En este caso, deshabilitaremos el editor utilizando esta última opción. Para ello debemos añadir en el fichero: "functions.php" la siguiente línea:
De esta manera, a la hora de definir nuevas entradas en nuestro Wordpress, haremos uso del editor clásico.
Existen distintas formas de deshabilitarlo y recurrir de nuevo al editor clásico:
1.- Instalación del plugin "Editor Clásico"
2.- Instalación del plugin: "Disable Gutenberg"
3.- Deshabilitar el editor por código.
En este caso, deshabilitaremos el editor utilizando esta última opción. Para ello debemos añadir en el fichero: "functions.php" la siguiente línea:
add_filter('use_block_editor_for_post', '__return_false', 10);
De esta manera, a la hora de definir nuevas entradas en nuestro Wordpress, haremos uso del editor clásico.
25 de noviembre de 2019
:: Cambiar el puerto en XAMPP
Al montar un XAMPP en nuestro equipo, es posible que necesitemos modificar el puerto por el que responde el tomcat. Para llevar a cabo esta tarea debemos modificar los siguientes ficheros:
En este fichero los valores a modificar son:
http.conf
El fichero estará ubicado -en función de la carpeta donde hayamos realizado la instalación- en una ruta similar a la siguiente: "C:\xampp\apache\conf\htpd.conf"En este fichero los valores a modificar son:
“ServerName localhost:80” por “ServerName localhost:81”
“Listen 80” por “Listen 81”
“#Listen 12.34.56.78:80” por “#Listen 12.34.56.78:81”
httpd-ssl.conf
El fichero estará ubicado en: "C:\xampp\apache\conf\extra\httpd-ssl.conf"
Las modificaciones a realizar serán las siguientes:
“Listen 443” por “Listen 4430”
“” por “”
“ServerName www.example.com:443” por “ServerName www.example.com:4430”
Una vez realizados los cambios, procederemos a reiniciar el XAMPP para que estos se hagan efectivos.
18 de noviembre de 2019
:: Instalar tomcat8
Para llevar a cabo la instalación de tomcat8 en Windows, los pasos a seguir son los siguientes:
.- Descargaremos tomcat8 de la urtl: https://tomcat.apache.org/
.- Descomprimimos el fichero en una carpeta de nuestro equipo
.- Ejecutarmos el fichero startup.bat que aparece en la carpeta: "bin"
.- En el caso de que no nos arranque el tomcat podemos "matar" el proceso: "javaw"
.- En el fichero: "tomcat-users.xml" ubicado en la carpeta: "conf" debemos definir los roles de los usuarios con acceso a la gestión de tomcat.
Las entradas a definir serán las siguientes:
.- Accederemos a la siguiente url e indicaremos las credenciales que hemos definido para cada uno de los módulos:
http://localhost:8080/
.- Descargaremos tomcat8 de la urtl: https://tomcat.apache.org/
.- Descomprimimos el fichero en una carpeta de nuestro equipo
.- Ejecutarmos el fichero startup.bat que aparece en la carpeta: "bin"
.- En el caso de que no nos arranque el tomcat podemos "matar" el proceso: "javaw"
.- En el fichero: "tomcat-users.xml" ubicado en la carpeta: "conf" debemos definir los roles de los usuarios con acceso a la gestión de tomcat.
Las entradas a definir serán las siguientes:
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-status"/>
<user username="admin" password="calvo" roles="manager-gui, manager-script, manager-status, admin-gui"/>
.- Accederemos a la siguiente url e indicaremos las credenciales que hemos definido para cada uno de los módulos:
http://localhost:8080/
13 de noviembre de 2019
:: Accesibilidad. WCAG 2.0
Las pautas WCAG 2.0 se engloban en 4 principios básicos:
1.- Perceptible
La información y elementos de la interfaz deben ser presentados al usuario de forma que puedan percibirlos claramente.
- Debemos proporcionar alternativas textuales para todo contenido no textual, de manera que pueda modificarse y adaptarse a las necesidades de los usuarios: tamaño de letra, braille, voz,...
- Proporcionar alternativas sincronizadas para contenidos multimedia
- Crear contenidos que puedan presentarse de diversas maneras, sin perder la información y estructura
- Facilitar que los usuarios puedan ver y oir el contenido, incluyendo la separación entre el primer plano y fondo
2.- Operable
Los elementos de la interfaz de usuario y navegación deben ser operables fácilmente.
- Hacer que toda la funcionalidad esté disponible a través del teclado
- Proporcionar a los usuarios el tiempo suficiente para leer y utilizar el contenido
- No diseñar contenidos que puedan causar ataques epilépticos
- Proporcionar medios que sirvan de ayuda a los usuarios a la hora de navegar, localizar contenido y determinar dónde se encuentran.
3.- Comprensible
La información y el manejo de la interfaz de usuario deben ser comprensibles.
- Lograr que el contenido textual sea legible y comprensible
- Crear páginas web cuya apariencia y operabilidad sean predecibles
- Ayudar a los usuarios a evitar y corregir errores
4.- Robusto
El contenido debe ser lo suficientemente robusto como para ser interpretado de forma fiable por una variedad de aplicaciones de usuario y productos de apoyo.
- Maximizar la compatibilidad con agentes de usuarios actuales y futuros, así como con los productos de apoyo
1 de noviembre de 2019
:: jQuery. noConflict()
Como sabemos, jQuery utiliza el simbolo: "$"; sin embargo hay otros framworks javascript que hacen uso de este símbolo, por lo que si en nuestra aplicación utilizamos diferentes frameworks, estos podrían entrar en conflicto.
Para ello, en jQuery disponemos del método: noConflict();
En el siguiente ejemplo tras utilizar $.noConflict(); podremos utilizar la sintáxis: "jQuery" (sin hacer uso del atajo: "$"). Es decir, el método "$.noConflict()" devuelve una referencia a "jQuery"
Podemos guardar esta referencia en una variable, y utilizarla en lugar de la que devolvería por defecto: "jQuery"
Para ello, en jQuery disponemos del método: noConflict();
En el siguiente ejemplo tras utilizar $.noConflict(); podremos utilizar la sintáxis: "jQuery" (sin hacer uso del atajo: "$"). Es decir, el método "$.noConflict()" devuelve una referencia a "jQuery"
$.noConflict();
jQuery(document).ready(function(){
jQuery("button").click(function(){
jQuery("p").text("jQuery funciona!");
});
});
Podemos guardar esta referencia en una variable, y utilizarla en lugar de la que devolvería por defecto: "jQuery"
var jq = $.noConflict();
jq(document).ready(function(){
jq("button").click(function(){
jq("p").text("jQuery funciona!");
});
});
Si no queremos modificar esta referencia, una tercera alternativa, sería seguir utilizando: "$" en nuestras funciones, aunque fuera de ellas, tendríamos que utilizar la referencia: "jQuery"
$.noConflict();
jQuery(document).ready(function($){
$("button").click(function(){
$("p").text("jQuery funciona!");
});
});
25 de octubre de 2019
:: Accesibilidad. Pautas WCAG 1.0
WCAG 1.0 está compuesta por 14 pautas principales:
1.- Proporcionar alternativas equivalentes para el contenido sonoro y visual
Los textos alternativos al contenido visual o auditivo benefician a personas con alguna discapacidad visual o cognitiva, y a aquellos usuarios que deciden anular la descarga de imágenes y/o sonidos.
2.- No basarse sólo en el color
Los textos y gráficos deben comprenderse sin necesidad de ver los colores. El cumplimiento de esta pauta beneficia a personas con dificultades para ver los colores, y a usuarios que utilizan pantallas monocromáticas.
3.- Utilizar marcadores y hojas de estilo de manera correcta
El control de la presentación de los contenidos se debe realizar con hojas de estilo en vez de con elementos y atributos de presentación, para evitar tener dificultades con herramientas de apoyo utilizadas por algunos usuarios.
4.- Identificar el idioma utilizado
Implica usar marcadores que faciliten la pronunciación o interpretación de texto abreviado o extranjero. Se debe indicar el idioma predominante en cada página y marcar aquellas expresiones que se encuentren en otra lengua. De esta forma, los sintetizadores de voz son capaces de cambiar su pronunciación en función del idioma, siempre y cuando se usen los marcadores apropiados.
5.- Crear tablas que se transformen correctamente
Las tablas sólo deben utilizarse para marcar información tabular (tablas de datos). El uso de tablas con otros fines crea dificultades para los usuarios que usan lectores de pantalla.
De la misma manera, las tablas mal estructuradas (por ejemplo, sin encabezados ) dificultan la lectura a usuarios que utilizan lectores de pantalla.
6.- Asegurarse de que las páginas que incorporan nuevas tecnologías se transformen correctamente
Una página basada en tecnologías modernas tiene que ser accesible sobre navegadores antiguos.
7.- Asegurar que el usuario tiene el control sobre los cambios de contenidos
El movimiento de los objetos o páginas, parpadeo o actualización automática, deben ser controlados por el usuario. Las personas con discapacidades cognitivas, visuales o mptrices no pueden leer textos en movimiento o interactuar con objetos móviles.
8.- Asegurar la accesibilidad directa de las interfaces de usuario incrustadas
Cuando un objeto incrustado (Flash, Java) tiene su propia interfaz, ésta debe ser accesible. Si la interfaz del objeto incrustado no puede hacerse accesible, debe proporcionarse una solución alternativa accesible.
9.- Diseñar con independencia del dispositivo
Esta pauta establece que el usuario pueda interactuar con la aplicación de usuario o con el documento mediante dispositivos de entrada diversos: ratón, teclado, voz, ...
Si por ejemplo, un control de formulario sólo puede ser activado con un ratón u otro dispositivo apuntador, alguien que use la página con entrada de voz o teclado, no será capaz de completar el formulario.
10.- Utilizar soluciones provisionales
En muchos casos, las alternativas accesibles sólo son imprescindibles hasta que los antiguos navegadores y los productos de apoyo se actualicen y operen correctamente.
11.- Utilizar la tecnologíay pautas W3C
Cuando no se pueda usar una tecnología W3C, o al usarla se obtengan materiales que no se transformen correctamente, se debe proporcionar una versión alternativa. Se recomiendan las tecnologías W3C por incluir características accesibles, por estar desarrolladas en un proceso abierto consensuado y porque se utilizan como base de muchas legislaciones para crear contenidos accesibles.
12.- Proporcionar información de contexto y orientativa
Esta información ayuda al usuario a comprender páginas o elementos complejos. Se deben agrupar los elementos y ofrecer información contextual sobre la relación entre elementos.
13.- Proporcionar mecanismos claros de navegación
Estos mecanismos facilitan a todos los usuarios la búsqueda de aquella información que necesitan, por ejemplo: mapa web, ayuda, barras de navegación, etc.
14.- Asegurarse de que los documentos sean claros y sencillos
La información escrita puede ser difícil para personas con discapacidad cognitiva o con dificultad de aprendizaje, y para personas sordas o que hablan en una lengua extranjera.
1.- Proporcionar alternativas equivalentes para el contenido sonoro y visual
Los textos alternativos al contenido visual o auditivo benefician a personas con alguna discapacidad visual o cognitiva, y a aquellos usuarios que deciden anular la descarga de imágenes y/o sonidos.
2.- No basarse sólo en el color
Los textos y gráficos deben comprenderse sin necesidad de ver los colores. El cumplimiento de esta pauta beneficia a personas con dificultades para ver los colores, y a usuarios que utilizan pantallas monocromáticas.
3.- Utilizar marcadores y hojas de estilo de manera correcta
El control de la presentación de los contenidos se debe realizar con hojas de estilo en vez de con elementos y atributos de presentación, para evitar tener dificultades con herramientas de apoyo utilizadas por algunos usuarios.
4.- Identificar el idioma utilizado
Implica usar marcadores que faciliten la pronunciación o interpretación de texto abreviado o extranjero. Se debe indicar el idioma predominante en cada página y marcar aquellas expresiones que se encuentren en otra lengua. De esta forma, los sintetizadores de voz son capaces de cambiar su pronunciación en función del idioma, siempre y cuando se usen los marcadores apropiados.
5.- Crear tablas que se transformen correctamente
Las tablas sólo deben utilizarse para marcar información tabular (tablas de datos). El uso de tablas con otros fines crea dificultades para los usuarios que usan lectores de pantalla.
De la misma manera, las tablas mal estructuradas (por ejemplo, sin encabezados ) dificultan la lectura a usuarios que utilizan lectores de pantalla.
6.- Asegurarse de que las páginas que incorporan nuevas tecnologías se transformen correctamente
Una página basada en tecnologías modernas tiene que ser accesible sobre navegadores antiguos.
7.- Asegurar que el usuario tiene el control sobre los cambios de contenidos
El movimiento de los objetos o páginas, parpadeo o actualización automática, deben ser controlados por el usuario. Las personas con discapacidades cognitivas, visuales o mptrices no pueden leer textos en movimiento o interactuar con objetos móviles.
8.- Asegurar la accesibilidad directa de las interfaces de usuario incrustadas
Cuando un objeto incrustado (Flash, Java) tiene su propia interfaz, ésta debe ser accesible. Si la interfaz del objeto incrustado no puede hacerse accesible, debe proporcionarse una solución alternativa accesible.
9.- Diseñar con independencia del dispositivo
Esta pauta establece que el usuario pueda interactuar con la aplicación de usuario o con el documento mediante dispositivos de entrada diversos: ratón, teclado, voz, ...
Si por ejemplo, un control de formulario sólo puede ser activado con un ratón u otro dispositivo apuntador, alguien que use la página con entrada de voz o teclado, no será capaz de completar el formulario.
10.- Utilizar soluciones provisionales
En muchos casos, las alternativas accesibles sólo son imprescindibles hasta que los antiguos navegadores y los productos de apoyo se actualicen y operen correctamente.
11.- Utilizar la tecnologíay pautas W3C
Cuando no se pueda usar una tecnología W3C, o al usarla se obtengan materiales que no se transformen correctamente, se debe proporcionar una versión alternativa. Se recomiendan las tecnologías W3C por incluir características accesibles, por estar desarrolladas en un proceso abierto consensuado y porque se utilizan como base de muchas legislaciones para crear contenidos accesibles.
12.- Proporcionar información de contexto y orientativa
Esta información ayuda al usuario a comprender páginas o elementos complejos. Se deben agrupar los elementos y ofrecer información contextual sobre la relación entre elementos.
13.- Proporcionar mecanismos claros de navegación
Estos mecanismos facilitan a todos los usuarios la búsqueda de aquella información que necesitan, por ejemplo: mapa web, ayuda, barras de navegación, etc.
14.- Asegurarse de que los documentos sean claros y sencillos
La información escrita puede ser difícil para personas con discapacidad cognitiva o con dificultad de aprendizaje, y para personas sordas o que hablan en una lengua extranjera.
21 de octubre de 2019
:: jQuery. Funciones Callback
Javascript se ejecuta línea a línea; sin embargo -al trabajar con efectos- la siguiente línea de código podría ejecutarse antes de que finalizara el efecto, lo que podría ser fuente de errores.
Para evitar este caso, podemos crear una función "Callback", la cual es ejecutada después de que termine el efecto.
La sintáxis típica es: $(selector).hide(velocidad, funcionCallback);
En este caso, el "alert" se ejecuta una vez haya finalizado el efecto.
En el siguiente ejemplo - sin utilizar funciones "callback"- el "alert" se ejecuta antes de que finalice el efecto.
Para evitar este caso, podemos crear una función "Callback", la cual es ejecutada después de que termine el efecto.
La sintáxis típica es: $(selector).hide(velocidad, funcionCallback);
En este caso, el "alert" se ejecuta una vez haya finalizado el efecto.
$("button").click(function(){
$("p").hide("slow", function(){
alert("La línea se oculta ahora");
});
});
En el siguiente ejemplo - sin utilizar funciones "callback"- el "alert" se ejecuta antes de que finalice el efecto.
$("button").click(function(){
$("p").hide(1000);
alert("La línea se oculta ahora");
});
15 de octubre de 2019
:: Alfresco. Aumentar el número de categorías mostradas
En esta prueba de concepto, la situación es la siguiente:
Tenemos definidas más de 100 categorías, pero a la hora de editar las propiedades de un contenido "Classificable", en la lista de categorías no nos aparecen más de 100 categorías.
En este caso, el número de elementos a mostrar para las categorías, está definido en la vista denominada: "picker.inc.ftl" ubicada en la ruta: "{Alfresco}\tomcat\webapps\awe\WEB-INF\classes\alfresco\site-webscripts\org\alfresco\components\form\controls\common"
El parámetro que controla el número de elementos a mostrar es: "maxSearchResults": ${field.control.params.maxSearchResults!'100'}"
Para llevar a cabo la prueba, sustituiremos el valor: "100" por "5" y guardaremos la plantilla de freemaker (.ftl).
Como podemos ver en la siguiente captura de pantalla, el selector de categorías únicamente nos muestra 5 elementos; de esta manera, si necesitásemos mostrar más de 100 elementos, este sería el valor a modificar.
8 de octubre de 2019
:: Alfresco. Envío de notificaciones a un grupo
En esta ocasión -como prueba de concepto- lo que queremos hacer es enviar un correo electrónico al grupo de "Contabilidad", cada vez que se suba una nueva factura a Alfresco.
De esta manera, tendremos definido un grupo "Contabilidad" -compuesto por varios integrantes- a los que se les notificará por correo electrónico cada vez que se suba un documento a una determinada carpeta, por ejemplo: "Facturas".
Sobre la carpeta "Facturas" definiremos una regla de contenido, de forma que cada vez que se suba un nuevo documento, se ejecute un script, al que llamaremos: "notificarfactura.js".
El contenido de este javascript, sería algo similar a lo siguiente:
De esta manera, tendremos definido un grupo "Contabilidad" -compuesto por varios integrantes- a los que se les notificará por correo electrónico cada vez que se suba un documento a una determinada carpeta, por ejemplo: "Facturas".
Sobre la carpeta "Facturas" definiremos una regla de contenido, de forma que cada vez que se suba un nuevo documento, se ejecute un script, al que llamaremos: "notificarfactura.js".
El contenido de este javascript, sería algo similar a lo siguiente:
### Notificar con plantilla
function sendMail()
{
var mail = actions.create("mail");
mail.parameters.to_many = "GROUP_site_Contabilidad";
mail.parameters.subject = "Nueva factura disponible: " + document.name;
mail.parameters.template =
companyhome.childByNamePath("Data Dictionary/Email Templates/Notify Email Templates/notify_user_email.html.ftl");
mail.execute(document);
}
sendMail();
### Notificar sin plantilla
function sendMail()
{
var mail = actions.create("mail");
mail.parameters.to_many = "GROUP_site_Contabilidad";
mail.parameters.subject = "Nueva factura disponible: " + document.name;
mail.execute(document);
}
sendMail();
4 de octubre de 2019
:: CSS. Sustituir imagen por css
En alguna ocasión necesitamos cambiar una imagen por otra en nuestras maquetaciones web.
Existen distintas alternativas, pero una de ellas sería mediante el uso de CSS.
Por ejemplo, en un portal Liferay 6.2 al añadir el componente: "Búsqueda de contenido web", el aspecto del buscador sería el siguiente:
Para adaptarlo al diseño del portal, podríamos aplicar los siguientes estilos css, en los que se incluye la sustitución de la imagen "de la lupa", por una más acorde a la línea general del diseño:
Tras aplicar estos estilos el aspecto sería similar al siguiente:
Existen distintas alternativas, pero una de ellas sería mediante el uso de CSS.
Por ejemplo, en un portal Liferay 6.2 al añadir el componente: "Búsqueda de contenido web", el aspecto del buscador sería el siguiente:
Para adaptarlo al diseño del portal, podríamos aplicar los siguientes estilos css, en los que se incluye la sustitución de la imagen "de la lupa", por una más acorde a la línea general del diseño:
.portlet-journal-content-search input.lfr-search-keywords {
height: 61px;
line-height: 61px;
padding: 0;
width: 100%;
border-color: #e0e5e8;
text-indent: 10px;
}
.portlet-journal-content-search .lfr-search-button {
position: relative;
left: 0;
width: 80% !important;
padding-left: 115px;
height: 61px;
background: url(/netic360-theme/css/images/search-icon-big.png) scroll no-repeat center center white;
cursor: pointer;
background-color: #c30e2e;
top: -5px;
box-sizing:border-box;
overflow:hidden;
}
Tras aplicar estos estilos el aspecto sería similar al siguiente:
30 de septiembre de 2019
:: Liferay. Servir ficheros .xml
En Liferay 6.2 podemos configurar los ficheros que nos servirá, en lugar de descargarlos. Por ejemplo, ante la necesidad de servir un fichero .xml sin que se lo descargue, podemos revisar la línea siguiente, presente en el fichero "portal-ext.properties":
En esta línea añadiremos el mimetype del fichero que necesitamos. De esta manera, la línea quedará como sigue:
Será necesario reiniciar el servicio para que los cambios surtan efecto.
mime.types.content.disposition.inline=flv,gif,jpg,pdf,png,wmv
En esta línea añadiremos el mimetype del fichero que necesitamos. De esta manera, la línea quedará como sigue:
mime.types.content.disposition.inline=flv,gif,jpg,pdf,png,wmv,xml
Será necesario reiniciar el servicio para que los cambios surtan efecto.
24 de septiembre de 2019
:: Tip CSS. Ser específico
Cuando realizamos por ejemplo un desarrollo web, necesitamos hacer uso de CSS (Cascading Style Sheets) y es posible que en muchas ocasiones hayamos utilizado reglas "abreviadas";
Si queremos cambiar el color de fondo de un elemento, podríamos utilizar el siguiente código:
Esta versión abreviada, aunque nos ahorra tiempo, automáticamente se están definiendo estas otras propiedades:
Por lo tanto, la mejor opción sería ser lo más específico posible, en este caso:
background:red;
Esta versión abreviada, aunque nos ahorra tiempo, automáticamente se están definiendo estas otras propiedades:
background-color : red;
background-repeat : repeat;
background-origin : padding-box;
background-image : none;
background-position : 0% 0%;
background-size : auto auto;
background-clip : border-box;
background-attachment : scroll;
Por lo tanto, la mejor opción sería ser lo más específico posible, en este caso:
background-color:red;
18 de septiembre de 2019
:: Tip CSS. Regla para marcar lo que ocupa un elemento
Únicamente como un detalle para marcar lo que ocupa un elemento cuando estamos maquetando, podríamos aplicarle los estilos css siguientes.
De esta manera, nos ayudará a darnos cuenta de lo que realmente está sucediendo en nuestra maqueta.
De esta manera, nos ayudará a darnos cuenta de lo que realmente está sucediendo en nuestra maqueta.
outline: 2px dotted red
10 de septiembre de 2019
:: Velocity. Obtener la fecha y hora actual
Para obtener la fecha y hora actual en una plantilla Velocity, por ejemplo para mostrar el año de Copyright en un portal Liferay, el código es el mostrado a continuación:
Para mostrar el año actual, el marcado sería:
## Obtener fecha actual
#set ($fecha = $dateUtil)
#set ($fechaActual = $fecha.getCurrentDate())
#set ($anioActual = $fecha.getCurrentDate("yyyy", $locale))
Para mostrar el año actual, el marcado sería:
<div id="pie">
Todos los derechos reservados © $anioActual
</div>
6 de septiembre de 2019
:: Tip Alfresco. Aumentar el tiempo de sesión
En el caso de que necesitemos modificar el tiempo de sesión en Alfresco, esta tarea se realiza a nivel de: Tomcat, Alfresco y Share.
La línea a añadir es la siguiente:
Los ficheros a modificar son los siguientes:
Más información: https://community.alfresco.com/thread/205313-cambiar-tiempo-sesi%C3%B3n
La línea a añadir es la siguiente:
<session-timeout>20</session-timeout>
Los ficheros a modificar son los siguientes:
<alfresco_home>/tomcat/conf/web.xml
<alfresco_home>/tomcat/webapps/alfresco/WEB-INF/web.xml
<alfresco_home>/tomcat/webapps/share/WEB-INF/web.xml
</alfresco_home></alfresco_home></alfresco_home>
Más información: https://community.alfresco.com/thread/205313-cambiar-tiempo-sesi%C3%B3n
3 de septiembre de 2019
:: Liferay. PermissionChecker not initialized
Un error que se producía en un portlet desarrollado en Liferay 6.2, a la hora de consultar un campo personalizado, era el siguiente: "PermissionChecker not initialized"
Este error se lanzaba a la hora de consultar el valor del campo personalizado desde una tarea programada:
La solución a este problema, documentado en los foros de Liferay fue el siguiente:
Más información: https://liferay.dev/forums/-/message_boards/message/48763277
com.liferay.portal.kernel.messaging.MessageListenerException: java.lang.RuntimeException: com.liferay.portal.security.auth.PrincipalException: PermissionChecker not initialized at com.liferay.portal.kernel.scheduler.messaging.SchedulerEventMessageListenerWrapper.receive(SchedulerEventMessageListenerWrapper.java:86) at com.liferay.portal.kernel.messaging.InvokerMessageListener.receive(InvokerMessageListener.java:72) at com.liferay.portal.kernel.messaging.ParallelDestination$1.run(ParallelDestination.java:71) at com.liferay.portal.kernel.concurrent.ThreadPoolExecutor$WorkerTask._runTask(ThreadPoolExecutor.java:682) at com.liferay.portal.kernel.concurrent.ThreadPoolExecutor$WorkerTask.run(ThreadPoolExecutor.java:593) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.RuntimeException: com.liferay.portal.security.auth.PrincipalException: PermissionChecker not initialized at com.liferay.portlet.expando.model.impl.ExpandoBridgeImpl.getAttribute(ExpandoBridgeImpl.java:219) at com.liferay.portlet.expando.model.impl.ExpandoBridgeImpl.getAttribute(ExpandoBridgeImpl.java:199) at sun.reflect.GeneratedMethodAccessor6456.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.liferay.portal.kernel.bean.ClassLoaderBeanHandler.invoke(ClassLoaderBeanHandler.java:67) at com.sun.proxy.$Proxy1399.receive(Unknown Source) at com.liferay.portal.kernel.scheduler.messaging.SchedulerEventMessageListenerWrapper.receive(SchedulerEventMessageListenerWrapper.java:77) ... 5 more Caused by: com.liferay.portal.security.auth.PrincipalException: PermissionChecker not initialized at com.liferay.portal.service.BaseServiceImpl.getPermissionChecker(BaseServiceImpl.java:82) at com.liferay.portlet.expando.service.impl.ExpandoValueServiceImpl.getData(ExpandoValueServiceImpl.java:125) at sun.reflect.GeneratedMethodAccessor1874.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:115) at com.liferay.portal.spring.transaction.DefaultTransactionExecutor.execute(DefaultTransactionExecutor.java:62) at com.liferay.portal.spring.transaction.TransactionInterceptor.invoke(TransactionInterceptor.java:51) at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:111) at com.liferay.portal.spring.aop.ChainableMethodAdvice.invoke(ChainableMethodAdvice.java:56) at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:111) at com.liferay.portal.spring.aop.ChainableMethodAdvice.invoke(ChainableMethodAdvice.java:56) at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:111) at com.liferay.portal.spring.aop.ServiceBeanAopProxy.invoke(ServiceBeanAopProxy.java:175) at com.sun.proxy.$Proxy228.getData(Unknown Source) at com.liferay.portlet.expando.service.ExpandoValueServiceUtil.getData(ExpandoValueServiceUtil.java:107) at com.liferay.portlet.expando.model.impl.ExpandoBridgeImpl.getAttribute(ExpandoBridgeImpl.java:208) ... 14 more
Este error se lanzaba a la hora de consultar el valor del campo personalizado desde una tarea programada:
user.getExpandoBridge().getAttribute("nombre-del-campo-personalizado");
La solución a este problema, documentado en los foros de Liferay fue el siguiente:
try{ //Backup del permiso actual PermissionChecker permissionCheckerBackup= PermissionThreadLocal.getPermissionChecker(); //Recupera el valor del del campo personalizado PrincipalThreadLocal.setName(user.getUserId()); PermissionChecker permissionChecker; permissionChecker = PermissionCheckerFactoryUtil.create(user); PermissionThreadLocal.setPermissionChecker(permissionChecker); campoPersonalizado=(boolean) user.getExpandoBridge().getAttribute("nombre-del-campo-personalizado"); //Restablece el permiso inicial PermissionThreadLocal.setPermissionChecker(permissionCheckerBackup); }catch(Exception ex){ ex.printStackTrace(); }
Más información: https://liferay.dev/forums/-/message_boards/message/48763277
8 de julio de 2019
:: Tip Alfresco. Obtener la relación de documentos bloqueados
Para obtener la relación de documentos bloqueados en Alfresco, una forma sencilla de lograrlo es haciendo uso del buscador. En este debemos especificar lo siguiente:
ASPECT:"cm:lockable"
Tras la búsqueda, obtendremos un listado de todos aquellos documentos que se encuentran bloqueados por algún usuario.
10 de mayo de 2019
:: Tip. Obtener en C# el último fichero abierto en un "OpenFileDialog"
Únicamente a modo de recordatorio, cuando necesitemos en un "OpenFileDialog" recuerde la ruta a la carpeta que accedimos ultimamente, debemos utilizar: "System.Environment.GetFolderPath(Environment.SpecialFolder.MyComputer)"
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.MyComputer);
6 de abril de 2019
:: Tip Liferay. Redirigir a una página tras el login
En Liferay podemos configurar la página a la que debe ser redirigido el usuario tras el login, o bien a la que debe dirigirle cuando cierra la sesión.
Estas configuraciones se encuentran disponibles en: "Panel de control > Configuración > General"
El apartado en el que debemos fijarnos es el denominado: "Navegación"
En este punto podemos configurar:
Estas configuraciones se encuentran disponibles en: "Panel de control > Configuración > General"
El apartado en el que debemos fijarnos es el denominado: "Navegación"
En este punto podemos configurar:
- Url de inicio (página de entrada al portal)
- Página de entrada por defecto (página a la que será redirigido el usuario tras realizar el login)
- Página de salida por defecto (página a la que será redirigido el usuario tras cerrar la sesión)
31 de marzo de 2019
:: Tip. Alfresco en modo lectura
En el caso de que necesitemos ejecutar Alfresco en modo de sólo lectura, tendremos que modificar el fichero: "alfresco-global.properties"
En este añadiremos la siguiente línea:
En este añadiremos la siguiente línea:
server.allowWrite=false
De esta manera, no se podrían llevar a cabo operaciones de escritura sobre el repositorio de Alfresco.
25 de marzo de 2019
:: Integración Liferay y Alfresco
Los pasos a seguir para integrar Liferay y Alfresco a través del protocolo CMIS, son los siguientes:
1.- Modificaremos el fichero "portal-ext.properties" añadiendo las siguientes líneas:
### Integración con Alfresco
session.store.password=true
company.security.auth.type=screenName
2.- En el panel de administración web, seleccionaremos la entrada: "Documentos y Multimedia" y en el botón: "Añadir" seleccionaremos: "Repositorio"
3.- Cumplimentaremos el formulario que nos aparece con la siguiente información:
- Nombre
- Descripción
- Url de AtomPub
4.- La url de AtomPub la obtendremos de Alfresco, y será del tipo:
http://localhost:8383/alfresco/api/-default-/public/cmis/versions/1.1/atom
5.- Una vez definido este nuevo repositorio, podremos mostrarlo en la parte pública. Para ello, añadiremos un portlet "visor de documentos y multimedia" y lo configuraremos para que muestre la información pertinente.
Una vez configurado, en este visor tendremos la estructura de carpetas y documentos presentes en el repositorio de Alfresco.
NOTA: Para llevar a cabo esta integración, debemos tener el mismo usuario definido en Alfresco y en Liferay o bien tener configurado un sistema SSO (Single Sign On)
28 de febrero de 2019
:: Editor "nano". Cómo copiar y pegar
Únicamente a modo de recordatorio, en el editor de texto: "nano" los pasos para copiar y pegar texto son los siguientes:
1.- Pulsaremos: "Esc+A" y con las teclas del cursos seleccionaremos el texto que queremos copiar.
2.- Una vez hayamos finalizado con la selección pulsaremos: "Esc+6"
3.- Nos desplazaremos al punto donde deseamos pegar el texto seleccionado, y pulsaremos: "Crtl+U"
1.- Pulsaremos: "Esc+A" y con las teclas del cursos seleccionaremos el texto que queremos copiar.
2.- Una vez hayamos finalizado con la selección pulsaremos: "Esc+6"
3.- Nos desplazaremos al punto donde deseamos pegar el texto seleccionado, y pulsaremos: "Crtl+U"
15 de febrero de 2019
:: Extraer las páginas indexadas de un portal web
Aunque la manera más habitual para extraer las páginas indexadas de un portal web es recurrir a Google y ejecutar lo siguiente, existen otras opciones:
2.1.- Instalar la extensión "ginfinity" que nos mostrará un scroll infinito. Existe otra extensión denominada: Scrollsearch
2.2.- En Chrome ejecutamos: "site:dominio"
2.3.- Accedemos a ajustes de Chromey seleccionamos que nos muestre 100 resultados por página
2.4.- Instalamos la extensión: "linkklipper" que nos permitirá extraer la relación de url's de un sitio web
2.5.- En la configuración de esta extensión, indicamos la expresión regular que necesitemos
y pulsamos sobre el botón: "Extraer todos los enlaces"
Tras obtener el listado de url, por ejemplo en formato CSV, tendremos que filtrar estas.
site:dominio
Si necesitamos extraer un listado con las url's
indexadas, podemos optar por estas alternativas:
Utilizar un servicio externo
Existe una web en la que -indicando el dominio- nos devuelve un listado de las url indexadas http://intavant.com/tools/google-indexed-pages-extractor/Utilizar extensiones
Podemos realizar los siguientes pasos, haciendo uso de una serie de extensiones para obtener este listado:2.1.- Instalar la extensión "ginfinity" que nos mostrará un scroll infinito. Existe otra extensión denominada: Scrollsearch
2.2.- En Chrome ejecutamos: "site:dominio"
2.3.- Accedemos a ajustes de Chromey seleccionamos que nos muestre 100 resultados por página
2.4.- Instalamos la extensión: "linkklipper" que nos permitirá extraer la relación de url's de un sitio web
2.5.- En la configuración de esta extensión, indicamos la expresión regular que necesitemos
y pulsamos sobre el botón: "Extraer todos los enlaces"
Tras obtener el listado de url, por ejemplo en formato CSV, tendremos que filtrar estas.
11 de febrero de 2019
Esto es lo que pasa cuando respondes a un correo de spam
Correos electrónicos sospechosos: bonos de seguros no reclamados, cajas de seguridad con incrustaciones de diamantes, amigos cercanos abandonados en un país extranjero.
Todas estas cosas y más, aparecen en nuestras bandejas de entrada, y el procedimiento estándar es eliminarlos. ¿Pero qué pasa cuando respondes?
En este vídeo, James Veitch -escritor y humorista -, nos cuenta un hilarante intercambio de mensajes con un spammer que se ofreció a convencerlo de una buena oferta.
Otra forma de ver y tomarse el creciente problema del spam o correo no deseado.
Todas estas cosas y más, aparecen en nuestras bandejas de entrada, y el procedimiento estándar es eliminarlos. ¿Pero qué pasa cuando respondes?
En este vídeo, James Veitch -escritor y humorista -, nos cuenta un hilarante intercambio de mensajes con un spammer que se ofreció a convencerlo de una buena oferta.
Otra forma de ver y tomarse el creciente problema del spam o correo no deseado.
5 de febrero de 2019
:: Tip. Script en Groovy para consulta de propiedades de un tipo de datos de Alfresco
Únicamente a modo de apunte, haciendo uso de la herramienta CMIS Workbench podemos conectar con el repositorio de Alfresco. En este teníamos definidos una serie de datos personalizados, y necesitamos obtener los valores asociados a estos metadatos.
Un breve script que podemos ejecutar desde la consola de la herramienta, podría ser similar al siguiente:
Como salida obtendremos en la consola, diversa información sobre el nodo (uno específico) que estamos consultando.
Un breve script que podemos ejecutar desde la consola de la herramienta, podría ser similar al siguiente:
import org.apache.chemistry.opencmis.commons.*
import org.apache.chemistry.opencmis.commons.data.*
import org.apache.chemistry.opencmis.commons.enums.*
import org.apache.chemistry.opencmis.client.api.*
Document doc = (Document) session.getObject("d779ee5c-7aa0-46ab-a31f-d8340f9114d0;1.0");
println(doc.name);
println(doc.description);
println("");
println(doc.properties['id']);
println("");
println(doc.getPropertyValue('aso:fecha').format('DD/MM/YYYY'));
println(doc.getPropertyValue('aso:tema'));
println(doc.getPropertyValue('aso:organismo'));
Como salida obtendremos en la consola, diversa información sobre el nodo (uno específico) que estamos consultando.
29 de enero de 2019
:: Tip. Búsqueda por etiquetas en Alfresco
Si en nuestro gestor documental etiquetamos los documentos, podemos llevar a cabo búsquedas sobre estos, haciendo uso de las etiquetas. Para ello, en el buscador, debemos especificar:
Por ejemplo, para buscar los documentos que contengan la etiqueta "cmis", la búsqueda a realizar sería:
TAG:"nombre-de-la-etiqueta"
Por ejemplo, para buscar los documentos que contengan la etiqueta "cmis", la búsqueda a realizar sería:
TAG:"cmis"
18 de enero de 2019
:: CMIS Workbench. Certificado autofirmado
En este tip, cuando intentamos conectarnos por CMIS al repositorio de Alfresco con un certificado autofirmado, obtendremos un mensaje de error como el siguiente:
Para solventar este problema podemos deshabilitar los certificados, añadiendo la siguiente línea en el fichero: "workbench.bat"
Tras esta modificación, al probar de nuevo a conectarnos por CMIS, accederemos al repositorio.
Para solventar este problema podemos deshabilitar los certificados, añadiendo la siguiente línea en el fichero: "workbench.bat"
-Dcmis.workbench.acceptSelfSignedCertificates=true
De esta manera el fichero quedará así:
@echo off
rem Licensed to the Apache Software Foundation (ASF) under one or more
rem contributor license agreements. See the NOTICE file distributed with
rem this work for additional information regarding copyright ownership.
rem The ASF licenses this file to You under the Apache License, Version 2.0
rem (the "License"); you may not use this file except in compliance with
rem the License. You may obtain a copy of the License at
rem
rem http://www.apache.org/licenses/LICENSE-2.0
rem
rem Unless required by applicable law or agreed to in writing, software
rem distributed under the License is distributed on an "AS IS" BASIS,
rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rem See the License for the specific language governing permissions and
rem limitations under the License.
rem Version: 0.14.0 / Revision: 1741103 / Build: 2016-04-26T14:09:01-0700
cd %~dp0\lib
rem use variable CUSTOM_JAVA_OPTS to set additional JAVA options
rem uncomment the following lines to configure HTTP proxy
rem set http_proxy=http://:
rem set https_proxy=https://:
rem set no_proxy=localhost,127.0.0.0,.local
for /F "delims=/" %%x in ('"java -classpath .;* org.apache.chemistry.opencmis.workbench.ProxyDetector -j -s"') do set "JAVA_PROXY_CONF=%%x"
set JAVA_OPTS=%JAVA_PROXY_CONF% -Dcmis.workbench.acceptSelfSignedCertificates=true
start /B javaw %JAVA_OPTS% %CUSTOM_JAVA_OPTS% -classpath ".;*" org.apache.chemistry.opencmis.workbench.Workbench
Tras esta modificación, al probar de nuevo a conectarnos por CMIS, accederemos al repositorio.
13 de enero de 2019
:: ¿Qué son los "polyfill"?
En desarrollo web, "Polyfill" es un fragmento de código que proporciona una característica a los navegadores web que estos no soportan nativamente.
Por ejemplo, un "Polyfill" permite a los desarrolladores web utilizar una API, independientemente de si es compatible con un navegador, y normalmente con una sobrecarga mínima. Habitualmente comprueban si un navegador es compatible con una API y la utilizan -si está disponible-, o -en caso contrario- utilizan su propia implementación.
Un ejemplo de "polyfill" sería: sessionStorage, que permite guardar información localmente. Esta es una característica que está disponible a partir de IE8, pero si la necesitásemos para navegadores anteriores, la solución sería utilizar un "polyfill".
En resumen, el uso de "polyfills" nos aporta beneficios, al escribir código fuente compatible en todos los navegadores.
Más información: https://en.wikipedia.org/wiki/Polyfill_(programming)
Índice de polyfills:
https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills
Guía sobre como escribir polyfills:
http://addyosmani.com/blog/writing-polyfills/
Por ejemplo, un "Polyfill" permite a los desarrolladores web utilizar una API, independientemente de si es compatible con un navegador, y normalmente con una sobrecarga mínima. Habitualmente comprueban si un navegador es compatible con una API y la utilizan -si está disponible-, o -en caso contrario- utilizan su propia implementación.
Un ejemplo de "polyfill" sería: sessionStorage, que permite guardar información localmente. Esta es una característica que está disponible a partir de IE8, pero si la necesitásemos para navegadores anteriores, la solución sería utilizar un "polyfill".
En resumen, el uso de "polyfills" nos aporta beneficios, al escribir código fuente compatible en todos los navegadores.
Más información: https://en.wikipedia.org/wiki/Polyfill_(programming)
Índice de polyfills:
https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills
Guía sobre como escribir polyfills:
http://addyosmani.com/blog/writing-polyfills/
7 de enero de 2019
:: Condiciones Yoda
Las condiciones Yoda son una convención de programación que nos ayudará a evitar los típicos errores en la comprobación del valor de una variable en un condicional.
Utilizar la convención Yoda consistiría en modificar el código de esta manera:
Pero, ¿por qué deberíamos utilizar esta alternativa?. Es bastante habitual (en algunos lenguajes) cometer un error al realizar la comprobación del valor de una variable en un condicional:
En el caso anterior, estaríamos asignando el valor: 'Yoda' a la variable que hemos llamado: "variable". Este código no produciría ningún error, pero estaríamos asignando un valor a una variable que puede provocar errores en la lógica del programa.
Por el contrario, al utilizar una "condición Yoda", en el caso de cometer este error, el intérprete o compilador nos daría un error, lo que nos ayudaría a detectar el problema:
Más información: https://en.wikipedia.org/wiki/Yoda_conditions
if(variable=='Yoda')
{
//TODO
}
Utilizar la convención Yoda consistiría en modificar el código de esta manera:
if('Yoda'==variable)
{
//TODO
}
Pero, ¿por qué deberíamos utilizar esta alternativa?. Es bastante habitual (en algunos lenguajes) cometer un error al realizar la comprobación del valor de una variable en un condicional:
if(variable='Yoda')
{
//TODO
}
En el caso anterior, estaríamos asignando el valor: 'Yoda' a la variable que hemos llamado: "variable". Este código no produciría ningún error, pero estaríamos asignando un valor a una variable que puede provocar errores en la lógica del programa.
Por el contrario, al utilizar una "condición Yoda", en el caso de cometer este error, el intérprete o compilador nos daría un error, lo que nos ayudaría a detectar el problema:
if('Yoda'=variable)
{
//TODO
}
Las condiciones Yoda usar debes
Más información: https://en.wikipedia.org/wiki/Yoda_conditions
1 de enero de 2019
:: Portal de traducción automática: PTPLATA
Este traductor automático permite al usuario traducir textos y ficheros desde el castellano a los distintos idiomas de la UE y lengua cooficiales.
Aunque se trata de un traductor automático, la calidad de las traducciones se encuentra dentro de los umbrales de calidad marcados.
Para hacer uso del mismo es necesario tener un perfil de Administración Pública, registrándose en el Portal de Administración Electrónica.
Información de la noticia: https://goo.gl/7GsS7x
Información del traductor: https://goo.gl/TWQTVx
Aunque se trata de un traductor automático, la calidad de las traducciones se encuentra dentro de los umbrales de calidad marcados.
Para hacer uso del mismo es necesario tener un perfil de Administración Pública, registrándose en el Portal de Administración Electrónica.
Información de la noticia: https://goo.gl/7GsS7x
Información del traductor: https://goo.gl/TWQTVx
Suscribirse a:
Entradas (Atom)
:: Cookies de nuestra página web. ¿Para qué sirve cada una?
A menudo una pregunta que nos hacen es qué cookies se están utilizando en mi página y para qué sirven. Para ver las cookies, podemos selecci...
-
A veces necesitamos obtener las coordenadas geográficas (longitud y latitud) de una serie de direcciones. Una forma rápida de llevar a cabo ...
-
En multitud de ocasiones es útil obtener el modelo de datos de una aplicación para determinar las tablas, consultas, relaciones,... En es...
-
Para deshabilitar la opción de "crear sitio" a todos aquellos usuarios que no sean administradores, debemos seguir los pasos sig...