Javascript https://www.carloscarrascal.com/ es Bootstrap + Less + Gulp para Drupal 8 https://www.carloscarrascal.com/blog/bootstrap-less-gulp-para-drupal-8 <article data-history-node-id="33" class="node node--type-blog-post node--view-mode-rss group-one-column ds-2col-stacked-fluid clearfix"> <div class="group-header"> <div class="field field--name-node-title field--type-ds field--label-hidden field--item"><h1> Bootstrap + Less + Gulp para Drupal 8 </h1> </div> <div class="field field--name-node-post-date field--type-ds field--label-hidden field--item">Lunes, Octubre 16, 2017 - 21:19</div> </div> <div class="group-left"> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field--items"> <div class="field--item"><a href="/tags/d8" hreflang="es">D8</a></div> <div class="field--item"><a href="/tags/drupal" hreflang="es">Drupal</a></div> <div class="field--item"><a href="/tags/bootstrap" hreflang="es">Bootstrap</a></div> <div class="field--item"><a href="/tags/gulp" hreflang="es">Gulp</a></div> <div class="field--item"><a href="/tags/less" hreflang="es">less</a></div> <div class="field--item"><a href="/tags/javascript" hreflang="es">Javascript</a></div> </div> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p><a href="https://gulpjs.com/">Gulp.js</a> es un gestor de tareas en Javascript que nos va ayudar a automatizar tareas repetitivas en nuestro proyecto Drupal. Una de las que mas vamos a repetir mientras estamos desarrollando es compilar el tema para generar el <em>CSS</em> si estamos utilizando un preprocesador como <em>SASS</em> o <em>Less</em>, con el tema de Bootstrap, por ejemplo, o con nuestro propio tema '<em>custom</em>'.</p> <p>Añadir <em>Gulp</em> a nuestro tema para compilar nos proporciona unas cuantas ventajas, entre las que podemos destacar:</p> <ul><li>Recompilar el tema automáticamente cada vez que modificamos un archivo <em>less</em>.</li> <li>Y recargar automáticamente el navegador cuando cambia el <em>CSS</em>.</li> <li>Minificar el <em>CSS</em> para mejorar el rendimiento.</li> <li>Ejecutar test y chequear el código al compilar el tema, para controlar errores de sintaxis, estándares, etc.</li> <li>Gestionar dependencias y minificar nuestros ficheros <em>Javascript</em>.</li> <li>Realizar operaciones con ficheros: copiar, mover, borrar, etc.</li> </ul><p>Vamos a ver una forma sencilla y rápida que nos dará un buen punto de partida para comenzar a utilizar <em>Gulp</em> para compilar nuestro tema de Drupal 8 basado en <em>Bootstrap</em>. Yo estoy utilizando la versión normal que viene con Less por defecto. Si estáis usando <em>SASS</em> en vez de Less podéis darle un vistazo a <a href="http://www.abhishekanand.in/article/set-drupal-8-theme-gulp-bower-bootstrap-sass-fontawesome">este artículo</a> (en inglés).</p> <p>Si habéis seguido las instrucciones para crear un subtema de <em>Bootstrap</em>, ya tendréis una estructura parecida a esta:</p> <ul><li>DRUPAL_ROOT/themes/custom/vuestro_subtema <ul><li>less <ul><li>style.less &lt;-- Este el archivo principal Less para compilar el tema.</li> </ul></li> <li>css <ul><li>style.css &lt;-- Archivo CSS resultado de compilar el tema.</li> </ul></li> </ul></li> </ul><p>En este punto, y si no queremos complicarnos la vida, podremos compilar nuestro tema de forma sencilla con un comando llamando al compilador de Less:</p> <pre> lessc less/style.less &gt; css/style.css </pre> <p>Yo tenía esta línea metida en un script bash sencillo llamado <em>compile.sh</em>, y lo ejecutaba cuando necesitaba compilar, así:</p> <pre> sh ./compile.sh</pre> <p>Pero claro, si estáis leyendo es que os va la marcha, así que vamos a ver cómo montamos Gulp en un periquete. Primero vamos a necesitar crear en la raíz de nuestro tema (subtema si usais Bootstrap), un archivo package.json para controlar las dependencias de Npm. Será muy sencillo:</p> <pre> { "name": "nombre_del_tema", "version": "0.0.0", "description": "Paquete para compilar subtema de Bootstrap con Gulp", "author": "nombre<your name="">", "contributors": [ { "name": "nombre<your name="">", "email": "direccion@email.com<your email="">" } ], "dependencies": {}, "devDependencies": {}, "license": "Private" } </your></your></your></pre> <p>Obviamente vamos a necesitar tener instalado npm, ya que lo vamos a utilizar para instalar cómodamente todos los paquetes y dependencias que necesitamos.</p> <p>Primero instalamos <em>Gulp</em> como paquete global para no tener problemas con el ejecutable:</p> <pre> npm install -g gulp</pre> <p>Una vez instalado, desde la raíz de nuestro tema, instalamos las dependencias y le decimos a npm que las añada a nuestro fichero <em>package.json</em> con el parámetro <em>--save-dev</em>:</p> <pre> npm install gulp gulp-less gulp-livereload gulp-sourcemaps gulp-watch --save-dev</pre> <p>Después de ejecutar este comando deberíamos tener un directorio <em>node_modules</em> con los paquetes que acabamos de instalar:</p> <pre> ll node_modules/ total 0 drwxr-xr-x 12 charles staff 408 16 Oct 19:36 gulp drwxr-xr-x 8 charles staff 272 16 Oct 19:36 gulp-less drwxr-xr-x 11 charles staff 374 16 Oct 19:36 gulp-livereload drwxr-xr-x 8 charles staff 272 16 Oct 19:36 gulp-sourcemaps drwxr-xr-x 7 charles staff 238 16 Oct 19:36 gulp-watch</pre> <p>Y en nuestro archivo <em>package.json</em> se habrán incluido las dependencias (los números de versión pueden cambiar):</p> <pre> "devDependencies": { "gulp": "^3.9.1", "gulp-less": "^3.3.2", "gulp-livereload": "^3.8.1", "gulp-sourcemaps": "^2.6.1", "gulp-watch": "^4.3.11" }, </pre> <p>Ahora necesitamos crear el archivo de control para <em>Gulp</em>, llamado <em>gulpfile.js</em>, también en la raíz de nuestro tema, con lo básico para empezar a funcionar:</p> <pre> var gulp = require('gulp'); var less = require('gulp-less'); var watch = require('gulp-watch'); var livereload = require('gulp-livereload'); var sourcemaps = require('gulp-sourcemaps'); gulp.task('less', function () { gulp.src('less/style.less') .pipe(sourcemaps.init()) .pipe(less()) .pipe(sourcemaps.write('.')) .pipe(gulp.dest('css')) .pipe(livereload()); }); gulp.task('watch', function() { livereload.listen(); gulp.watch('less/*.less', ['less']); }); gulp.task('default', ['watch']); </pre> <p>Con esto deberíamos poder ejecutar dos comandos para compilar:</p> <pre> gulp less</pre> <p>Que simplemente compilará el tema creando los CSS dentro del directorio css, o también:</p> <pre> gulp watch</pre> <p>Que dejará el proceso corriendo, vigilando modificaciones en nuestros archivos less y recompilando el tema si detecta algún cambio. Este comando se ejecutará por defecto si solo hacemos:</p> <pre> gulp</pre> <p>Vamos a ver en detalle que hemos metido en este fichero de control de <em>Gulp</em>:</p> <ul><li>Las líneas <em>var</em> van a cargar las dependencias que necesitamos. <ul><li><strong>Gulp</strong> y <strong>gulp-less</strong>: Carga la libreria y la extension para less.</li> <li><strong>gulp-watch</strong>: Carga el módulo para vigilar los archivos del tema.</li> <li><strong>gulp-livereload</strong>: Carga el módulo <a href="http://livereload.com/">livereload</a> para automatizar la recarga del navegador. Para que funcione tenemos que instalar una <a href="http://livereload.com/extensions/">extensión del navegador</a>. Hay extensiones disponibles para Chrome, Firefox y Safari.</li> <li><strong>gulp-sourcemaps</strong>: Carga el paquete para generar sourcemaps de nuestros ficheros CSS. Tal como está configurado creará un fichero <em>.map</em> separado en el mismo directorio /css. Estos ficheros sirven para ayudar en la depuración de nuestros estilos.</li> </ul></li> <li>Tarea <strong>less</strong>: <ul><li>Compila el CSS, aplica el módulo de <em>livereload</em> y genera los sourcemaps necesarios.</li> </ul></li> <li>Tarea <strong>watch</strong>: <ul><li>Activa el <em>livereload</em> y vigila los archivos con extension <em>.less</em>, dentro de la carpeta less por si cambian, lo que recompilará el tema completo.</li> </ul></li> <li>Tarea <strong>default</strong>: <ul><li>Se ejecuta cuando corremos gulp sin parámetros, y por defecto lanzará la tarea <em>watch</em>.</li> </ul></li> </ul><p>Con estos sencillos pasos tendremos configurado <em>Gulp</em> en muy poco tiempo, y a partir de esta configuración inicial podremos ir ampliando e introducir otras mejoras o librerías en nuestro proyecto Drupal.</p> <p> </p> <h2>Referencias</h2> <ol><li><a href="https://eureka.ykyuen.info/2015/03/09/drupal-7-setup-bootstrap-3-theme-with-gulp-for-less-compilation/">DRUPAL 7 – SETUP BOOTSTRAP 3 THEME WITH GULP FOR LESS COMPILATION</a></li> <li><a href="http://www.abhishekanand.in/article/set-drupal-8-theme-gulp-bower-bootstrap-sass-fontawesome">Set up a Drupal 8 theme with Gulp, Bower, Bootstrap Sass, &amp; FontAwesome</a></li> <li><a href="http://brandonclapp.com/what-is-gulp-js-and-why-use-it/">What is gulp.js and why use it?</a></li> </ol></div> </div> <div class="group-footer"> <section> <h2>Añadir nuevo comentario</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=33&amp;2=comment&amp;3=comment" token="SOCxtNpb2aUdz8W91NLOhKstqWZQIwlggK7ehFpqvWc"></drupal-render-placeholder> </section> </div> </article> Mon, 16 Oct 2017 19:19:41 +0000 root 33 at https://www.carloscarrascal.com Eventos para cambios de visibilidad en JQuery https://www.carloscarrascal.com/blog/eventos-para-cambios-de-visibilidad-en-jquery <article data-history-node-id="22" class="node node--type-blog-post node--view-mode-rss group-one-column ds-2col-stacked-fluid clearfix"> <div class="group-header"> <div class="field field--name-node-title field--type-ds field--label-hidden field--item"><h1> Eventos para cambios de visibilidad en JQuery </h1> </div> <div class="field field--name-node-post-date field--type-ds field--label-hidden field--item">Jueves, Julio 6, 2017 - 23:02</div> </div> <div class="group-left"> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field--items"> <div class="field--item"><a href="/tags/jquery" hreflang="es">JQuery</a></div> <div class="field--item"><a href="/tags/javascript" hreflang="es">Javascript</a></div> </div> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p>Este artículo es básicamente una traducción de este original en inglés:</p> <p><a href="http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/" target="_blank">http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/</a></p> <p>En un caso bastante particular necesitaba detectar si cambiaba la visibilidad de un elemento del DOM que venia de una librería externa de JS. Después de dar algunas vueltas encontré una solución bastante elegante, publicada hace bastante tiempo. No he visto nada parecido en castellano, y hay algunos hilos en Stackoverflow, pero con soluciones bastante extrañas, así que lo publicaré aquí.</p> <p>Con este bloque de código Javascript podemos registrar los eventos 'hide' y 'show' con la función .on() de JQuery como hacemos con cualquiera de los eventos estándar, de forma que podemos ejecutar nuestro código cuando se produzcan.</p> <pre> (function ($) { $.each(['show', 'hide'], function (i, ev) { var el = $.fn[ev]; $.fn[ev] = function () { this.trigger(ev); return el.apply(this, arguments); }; }); })(jQuery); </pre> <p>Una vez incluyamos este código, podemos registar los eventos usando un selector, de la manera tradicional:</p> <pre> $('#foo').on('show', function() { console.log('#foo es visible'); }); $('#foo').on('hide', function() { console.log('#foo esta oculto'); });</pre> <p>El código del ejemplo completo sería algo así.</p> <h2>Código HTML</h2> <pre> &lt;button id="btnMostrar"&gt;Mostrar&lt;/button&gt; &lt;button id="btnOcultar"&gt;Ocultar&lt;/button&gt; &lt;div class="contenedor"&gt; &lt;div id="foo"&gt; Elemento #foo &lt;/div&gt; &lt;/div&gt; &lt;div id="console"&gt; &lt;/div&gt;</pre> <h2>Código CSS</h2> <pre> .contenedor { height:60px; margin:10px; } #foo { background-color:#eeeeee; width:150px; height:50px; text-align:center; font-size:20px; }</pre> <h2>Código Javascript</h2> <pre> // Codigo para registrar eventos hide y show (function ($) { $.each(['show', 'hide'], function (i, ev) { var el = $.fn[ev]; $.fn[ev] = function () { this.trigger(ev); return el.apply(this, arguments); }; }); })(jQuery); // Mostrar elemento #foo al hacer click en el boton mostrar $('#btnMostrar').click(function(){ $('#foo').show(); }); // Ocultar elemento #foo al hacer click el boton ocular $('#btnOcultar').click(function(){ $('#foo').hide(); }); // Añadimos evento para imprimir un mensaje al mostrar #foo $('#foo').on('show', function(){ $('#console').html( $('#console').html() + '#foo es visible'+ '&lt;br&gt;' ) }); // Añadimos evento para imprimir un mensaje al ocultar #foo $('#foo').on('hide', function(){ $('#console').html( $('#console').html() + '#foo esta oculto'+ '&lt;br&gt;' ) }); </pre> <h2>Ejemplo​</h2> <p> </p> <style type="text/css"> <!--/*--><![CDATA[/* ><!--*/ .contenedor { height:60px; margin:10px; } #foo { background-color:#eeeeee; width:150px; height:50px; text-align:center; font-size:20px; } /*--><!]]>*/ </style><script> <!--//--><![CDATA[// ><!-- (function ($) { $.each(['show', 'hide'], function (i, ev) { var el = $.fn[ev]; $.fn[ev] = function () { this.trigger(ev); return el.apply(this, arguments); }; }); })(jQuery); jQuery( document ).ready(function() { console.log( "ready!" ); // Mostrar elemento #foo al hacer click en el boton mostrar jQuery('#btnMostrar').click(function(){ jQuery('#foo').show(); }); // Ocultar elemento #foo al hacer click el boton ocular jQuery('#btnOcultar').click(function(){ jQuery('#foo').hide(); }); // Añadimos evento para imprimir un mensaje al mostrar #foo jQuery('#foo').on('show', function(){ jQuery('#console').html( jQuery('#console').html() + '#foo es visible'+ '<br>' ) }); // Añadimos evento para imprimir un mensaje al ocultar #foo jQuery('#foo').on('hide', function(){ jQuery('#console').html( jQuery('#console').html() + '#foo esta oculto'+ '<br>' ) }); }); //--><!]]> </script><p><button id="btnMostrar">Show</button><button id="btnOcultar">Hide</button></p> <div class="contenedor"> <div id="foo">Yo soy #foo</div> </div> <div id="console"> </div> </div> </div> <div class="group-footer"> <section> <h2>Añadir nuevo comentario</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=22&amp;2=comment&amp;3=comment" token="8G-0ziIYgIKVNZP_lsiweU7U_jtelpkeubzWPKGyBMY"></drupal-render-placeholder> </section> </div> </article> Thu, 06 Jul 2017 21:02:37 +0000 root 22 at https://www.carloscarrascal.com