{
    "componentChunkName": "component---node-modules-gatsby-theme-try-ghost-src-templates-post-js",
    "path": "/jquery-basics-i/",
    "result": {"data":{"ghostPost":{"id":"Ghost__Post__5a81da9b8cda356bbe9bbe20","title":"jQuery Basics I","slug":"jquery-basics-i","featured":false,"feature_image":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/jquery-logo.png","excerpt":"Empecemos con los básicos de jQuery. jQuery nos permite manejar el DOM de una\nmanera dinámica, hacer peticiones, manipular datos..... y de una manera muy\nsencilla, y realmente podemos hacer casi de todo, iremos viendo un poco de todo\nen varios post.\nPrimero vamos con un ejemplo sencillo\n\nEjemplo de uso básico de jQuery\n<!DOCTYPE html>\n<html lang=\"es\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"Content-type\" content=\"text/html\">\n    <title>Leccion 01</title>\n    <script src=\"lib/jqu","custom_excerpt":null,"visibility":"public","created_at_pretty":"12 Feb 2018","published_at_pretty":"20 Feb 2018","updated_at_pretty":"20 Feb 2018","created_at":"2018-02-12T19:19:07.000+01:00","published_at":"2018-02-20T12:34:20.000+01:00","updated_at":"2018-02-20T12:34:20.000+01:00","meta_title":null,"meta_description":null,"og_description":null,"og_image":null,"og_title":null,"twitter_description":null,"twitter_image":null,"twitter_title":null,"authors":[{"slug":"jlgarcia","url":"https://jlgarcia.fulldev.ninja/author/jlgarcia/","name":"Juan Luis Garcia Aparicio","bio":null,"cover_image":null,"profile_image":"https://jlgarcia.fulldev.ninja/assets/images/2017/12/Perfil.jpg","location":null,"website":null,"twitter":null,"facebook":null,"meta_title":null,"meta_description":null,"coverImageSharp":null,"profileImageSharp":null}],"primary_author":{"slug":"jlgarcia","url":"https://jlgarcia.fulldev.ninja/author/jlgarcia/","name":"Juan Luis Garcia Aparicio","bio":null,"cover_image":null,"profile_image":"https://jlgarcia.fulldev.ninja/assets/images/2017/12/Perfil.jpg","location":null,"website":null,"twitter":null,"facebook":null,"meta_title":null,"meta_description":null,"coverImageSharp":null,"profileImageSharp":{"base":"Perfil.jpg","publicURL":"/static/b0de6281fb28a266510b3b09b9243e5a/Perfil.jpg","imageMeta":{"width":307,"height":307},"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAUDBAb/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAGzw6zC6zHn+cLYP//EAB0QAAICAQUAAAAAAAAAAAAAAAEDAAIEEyEiIzL/2gAIAQEAAQUCifca8KgcKWVfUpkHsG5pxX//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAdEAACAgEFAAAAAAAAAAAAAAAAARARcQISIUFR/9oACAEBAAY/AhU88xkb7N06a8P/xAAcEAEAAwEAAwEAAAAAAAAAAAABABEhMUFRYXH/2gAIAQEAAT8hR2pq40aqb+xIAeXibhW9JXr8joF4TBcSNe0//9oADAMBAAIAAwAAABDzDwD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhUTFhcfD/2gAIAQEAAT8QyItrELaTlatLwU63MvEW6vUNdy4LZQDn7iVApV9VLtANdWwKkuYq4Er1VZ//2Q==","aspectRatio":1,"src":"/static/b0de6281fb28a266510b3b09b9243e5a/31709/Perfil.jpg","srcSet":"/static/b0de6281fb28a266510b3b09b9243e5a/f340b/Perfil.jpg 28w,\n/static/b0de6281fb28a266510b3b09b9243e5a/22d64/Perfil.jpg 55w,\n/static/b0de6281fb28a266510b3b09b9243e5a/31709/Perfil.jpg 110w,\n/static/b0de6281fb28a266510b3b09b9243e5a/aa249/Perfil.jpg 165w,\n/static/b0de6281fb28a266510b3b09b9243e5a/0dc33/Perfil.jpg 220w,\n/static/b0de6281fb28a266510b3b09b9243e5a/60667/Perfil.jpg 307w","srcWebp":"/static/b0de6281fb28a266510b3b09b9243e5a/8678c/Perfil.webp","srcSetWebp":"/static/b0de6281fb28a266510b3b09b9243e5a/59cda/Perfil.webp 28w,\n/static/b0de6281fb28a266510b3b09b9243e5a/7da75/Perfil.webp 55w,\n/static/b0de6281fb28a266510b3b09b9243e5a/8678c/Perfil.webp 110w,\n/static/b0de6281fb28a266510b3b09b9243e5a/f282e/Perfil.webp 165w,\n/static/b0de6281fb28a266510b3b09b9243e5a/a7b21/Perfil.webp 220w,\n/static/b0de6281fb28a266510b3b09b9243e5a/f59af/Perfil.webp 307w","sizes":"(max-width: 110px) 100vw, 110px"}}}},"primary_tag":{"slug":"jquery","url":"https://jlgarcia.fulldev.ninja/tag/jquery/","name":"jquery","visibility":"public","feature_image":null,"description":null,"meta_title":null,"meta_description":null,"featureImageSharp":null},"tags":[{"slug":"jquery","url":"https://jlgarcia.fulldev.ninja/tag/jquery/","name":"jquery","visibility":"public","feature_image":null,"description":null,"meta_title":null,"meta_description":null,"featureImageSharp":null}],"plaintext":"Empecemos con los básicos de jQuery. jQuery nos permite manejar el DOM de una\nmanera dinámica, hacer peticiones, manipular datos..... y de una manera muy\nsencilla, y realmente podemos hacer casi de todo, iremos viendo un poco de todo\nen varios post.\nPrimero vamos con un ejemplo sencillo\n\nEjemplo de uso básico de jQuery\n<!DOCTYPE html>\n<html lang=\"es\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"Content-type\" content=\"text/html\">\n    <title>Leccion 01</title>\n    <script src=\"lib/jquery-3.3.1.min.js\"></script>\n</head>\n<style>\n    .textoVerde {\n        color: green;\n    }\n</style>\n\n<body>\n\n    <ul>\n        <li>Hola 1</li>\n        <li>Hola 2</li>\n        <li>Hola 3</li>\n    </ul>\n\n    <ul>\n            <li>Negrita</li>\n            <li>Negrita 2</li>\n            <li>Negrita 3</li>\n        </ul>\n\n    <script>\n        jQuery('ul').addClass('textoVerde');\n\n        jQuery('ul').css('font-weight','bold')\n    </script>\n\n\n</body>\n<script></script>\n\n</html>\n\n\nComo véis tenemos un html básico con dos listas, y en ellas cambiamos\nproopiedades, añadimos una clase css en una de las funciones de jQuery y en la\notra le añadimos un estilo de css directamente, esto seria lo mismo que tener un\nhtml de esta forma\n\n<!DOCTYPE html>\n<html lang=\"es\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"Content-type\" content=\"text/html\">\n    <title>Leccion 01</title>\n    <script src=\"lib/jquery-3.3.1.min.js\"></script>\n</head>\n<style>\n    .textoVerde {\n        color: green;\n    }\n</style>\n\n<body>\n\n    <ul class=\"textoVerde\">\n        <li>Hola 1</li>\n        <li>Hola 2</li>\n        <li>Hola 3</li>\n    </ul>\n\n    <ul style=\"font-weight:bold;\">\n            <li>Negrita</li>\n            <li>Negrita 2</li>\n            <li>Negrita 3</li>\n        </ul>\n\n    <script>\n        //jQuery('ul').addClass('textoVerde');\n\n        //jQuery('ul').css('font-weight','bold')\n    </script>\n\n\n</body>\n\n</html>\n\n\nSi os fijáis hemos comentado los métodos de jQuery y hemos puesto directamente\nen uno la clase y en el otro un estilo de css.\n\nEsperando a que la página esté cargada para ejecutar algo\nAlgunas veces tenemos en distintos lugares ciertas funciones o variables, esto\nnos puede dar problemas en lenguajes como html ya que el lenguaje es\ninterpretado de arriba hacia abajo es posible que estemos ejecutando un cambio\nen un elemento que todavía no ha sido leído por el interprete por lo que el\ncambio no se producirá, para ello jQuery nos proveé de el método ready que nos\npermite esperar hasta que algo haya sido cargado o leído completamente, veamoslo\ncon un ejemplo.\n\nSi nosotros pusieramos los métodos anteriormente mencionados en el header, por\nejemplo, no se produciría ningún cambio en la página (si no os fiáis de mi\nprobarlo ;) ), pero si por lo que fuera tenemos que cargar algo en el header lo\npodríamos hacer de esta forma\n\n<script>\n    $(document).ready(function() {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n</script>\n\n\nMetiendo nuestro código dentro de la función o método anterior, todo se\nejecutará tras la carga de la página o documento completo.\njQuery nos da una forma más corta para hacer lo mismo:\n\n<script>\n    $(function() {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n</script>\n\n\nEsto es lo mismo que lo anterior, y si pensamos en las arrow functions todavía\npodemos ahorrarnos algo más:\n\n<script>\n    $(() => {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n</script>\n\n\nLas tres son la misma función, solo que como es algo muy habitual de usar, le\nhan dado algo de azúcar sintactico para hacer más cómodo su uso.\n\nTrabajando con selectores y otras cosas\nVamos a ver un ejemplo cortito de uso de algunas funciones para añadir, eliminar\nclases y atributos a elementos del DOM\n\n<script>\n\n\t$(\"img\")\n\t\t.attr(\"src\",\"img/photo2.jpg\")\n\t\t.removeClass('img-circle')\n\t\t.addClass('img-thumbnail');\n\n</script>\n\n\nEsto lo que hace es: primero cambia el atributo src de la imagen, segundo\nelimina la clase img-circle y tercero añade la clase img-thumbnail\n\nEstas son algunas de las cosas más básicas que podemos ir haciendo con jQuery,\niré haciendo más post de jQuery con ejemplos de uso. Nos vemos en el siguiente,\nun abrazooorrrr","html":"<!--kg-card-begin: markdown--><p>Empecemos con los básicos de jQuery. jQuery nos permite manejar el DOM de una manera dinámica, hacer peticiones, manipular datos..... y de una manera muy sencilla, y realmente podemos hacer casi de todo, iremos viendo un poco de todo en varios post.<br>\nPrimero vamos con un ejemplo sencillo</p>\n<h2 id=\"ejemplodeusobsicodejquery\">Ejemplo de uso básico de jQuery</h2>\n<pre><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;es&quot;&gt;\n\n&lt;head&gt;\n    &lt;meta charset=&quot;UTF-8&quot;&gt;\n    &lt;meta http-equiv=&quot;Content-type&quot; content=&quot;text/html&quot;&gt;\n    &lt;title&gt;Leccion 01&lt;/title&gt;\n    &lt;script src=&quot;lib/jquery-3.3.1.min.js&quot;&gt;&lt;/script&gt;\n&lt;/head&gt;\n&lt;style&gt;\n    .textoVerde {\n        color: green;\n    }\n&lt;/style&gt;\n\n&lt;body&gt;\n\n    &lt;ul&gt;\n        &lt;li&gt;Hola 1&lt;/li&gt;\n        &lt;li&gt;Hola 2&lt;/li&gt;\n        &lt;li&gt;Hola 3&lt;/li&gt;\n    &lt;/ul&gt;\n\n    &lt;ul&gt;\n            &lt;li&gt;Negrita&lt;/li&gt;\n            &lt;li&gt;Negrita 2&lt;/li&gt;\n            &lt;li&gt;Negrita 3&lt;/li&gt;\n        &lt;/ul&gt;\n\n    &lt;script&gt;\n        jQuery('ul').addClass('textoVerde');\n\n        jQuery('ul').css('font-weight','bold')\n    &lt;/script&gt;\n\n\n&lt;/body&gt;\n&lt;script&gt;&lt;/script&gt;\n\n&lt;/html&gt;\n</code></pre>\n<p>Como véis tenemos un html básico con dos listas, y en ellas cambiamos proopiedades, añadimos una clase css en una de las funciones de jQuery y en la otra le añadimos un estilo de css directamente, esto seria lo mismo que tener un html de esta forma</p>\n<pre><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;es&quot;&gt;\n\n&lt;head&gt;\n    &lt;meta charset=&quot;UTF-8&quot;&gt;\n    &lt;meta http-equiv=&quot;Content-type&quot; content=&quot;text/html&quot;&gt;\n    &lt;title&gt;Leccion 01&lt;/title&gt;\n    &lt;script src=&quot;lib/jquery-3.3.1.min.js&quot;&gt;&lt;/script&gt;\n&lt;/head&gt;\n&lt;style&gt;\n    .textoVerde {\n        color: green;\n    }\n&lt;/style&gt;\n\n&lt;body&gt;\n\n    &lt;ul class=&quot;textoVerde&quot;&gt;\n        &lt;li&gt;Hola 1&lt;/li&gt;\n        &lt;li&gt;Hola 2&lt;/li&gt;\n        &lt;li&gt;Hola 3&lt;/li&gt;\n    &lt;/ul&gt;\n\n    &lt;ul style=&quot;font-weight:bold;&quot;&gt;\n            &lt;li&gt;Negrita&lt;/li&gt;\n            &lt;li&gt;Negrita 2&lt;/li&gt;\n            &lt;li&gt;Negrita 3&lt;/li&gt;\n        &lt;/ul&gt;\n\n    &lt;script&gt;\n        //jQuery('ul').addClass('textoVerde');\n\n        //jQuery('ul').css('font-weight','bold')\n    &lt;/script&gt;\n\n\n&lt;/body&gt;\n\n&lt;/html&gt;\n</code></pre>\n<p>Si os fijáis hemos comentado los métodos de jQuery y hemos puesto directamente en uno la clase y en el otro un estilo de css.</p>\n<h2 id=\"esperandoaquelapginaestcargadaparaejecutaralgo\">Esperando a que la página esté cargada para ejecutar algo</h2>\n<p>Algunas veces tenemos en distintos lugares ciertas funciones o variables, esto nos puede dar problemas en lenguajes como html ya que el lenguaje es interpretado de arriba hacia abajo es posible que estemos ejecutando un cambio en un elemento que todavía no ha sido leído por el interprete por lo que el cambio no se producirá, para ello jQuery nos proveé de el método <strong>ready</strong> que nos permite esperar hasta que algo haya sido cargado o leído completamente, veamoslo con un ejemplo.</p>\n<p>Si nosotros pusieramos los métodos anteriormente mencionados en el <em>header</em>, por ejemplo, no se produciría ningún cambio en la página (si no os fiáis de mi probarlo ;) ), pero si por lo que fuera tenemos que cargar algo en el header lo podríamos hacer de esta forma</p>\n<pre><code>&lt;script&gt;\n    $(document).ready(function() {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n&lt;/script&gt;\n</code></pre>\n<p>Metiendo nuestro código dentro de la función o método anterior, todo se ejecutará tras la carga de la página o <em>documento</em> completo.<br>\njQuery nos da una forma más corta para hacer lo mismo:</p>\n<pre><code>&lt;script&gt;\n    $(function() {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n&lt;/script&gt;\n</code></pre>\n<p>Esto es lo mismo que lo anterior, y si pensamos en las <strong>arrow functions</strong> todavía podemos ahorrarnos algo más:</p>\n<pre><code>&lt;script&gt;\n    $(() =&gt; {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n&lt;/script&gt;\n</code></pre>\n<p>Las tres son la misma función, solo que como es algo muy habitual de usar, le han dado algo de <em>azúcar sintactico</em> para hacer más cómodo su uso.</p>\n<h3 id=\"trabajandoconselectoresyotrascosas\">Trabajando con selectores y otras cosas</h3>\n<p>Vamos a ver un ejemplo cortito de uso de algunas funciones para añadir, eliminar clases y atributos a elementos del DOM</p>\n<pre><code>&lt;script&gt;\n\n\t$(&quot;img&quot;)\n\t\t.attr(&quot;src&quot;,&quot;img/photo2.jpg&quot;)\n\t\t.removeClass('img-circle')\n\t\t.addClass('img-thumbnail');\n\n&lt;/script&gt;\n</code></pre>\n<p>Esto lo que hace es: primero cambia el atributo <em>src</em> de la imagen, segundo elimina la clase <em>img-circle</em> y tercero añade la clase <em>img-thumbnail</em></p>\n<p>Estas son algunas de las cosas más básicas que podemos ir haciendo con jQuery, iré haciendo más post de jQuery con ejemplos de uso. Nos vemos en el siguiente, un abrazooorrrr</p>\n<!--kg-card-end: markdown-->","url":"https://jlgarcia.fulldev.ninja/jquery-basics-i/","canonical_url":null,"uuid":"09e07f3e-e198-4216-b950-9b024c3142e4","codeinjection_foot":null,"codeinjection_head":null,"codeinjection_styles":null,"comment_id":"5a81da9b8cda356bbe9bbe20","reading_time":3,"send_email_when_published":false,"email_subject":null,"childHtmlRehype":{"html":"<!--kg-card-begin: markdown--><p>Empecemos con los básicos de jQuery. jQuery nos permite manejar el DOM de una manera dinámica, hacer peticiones, manipular datos..... y de una manera muy sencilla, y realmente podemos hacer casi de todo, iremos viendo un poco de todo en varios post.<br>\nPrimero vamos con un ejemplo sencillo</p>\n<h2 id=\"ejemplodeusobsicodejquery\">Ejemplo de uso básico de jQuery</h2>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;!DOCTYPE html>\n&#x3C;html lang=\"es\">\n\n&#x3C;head>\n    &#x3C;meta charset=\"UTF-8\">\n    &#x3C;meta http-equiv=\"Content-type\" content=\"text/html\">\n    &#x3C;title>Leccion 01&#x3C;/title>\n    &#x3C;script src=\"lib/jquery-3.3.1.min.js\">&#x3C;/script>\n&#x3C;/head>\n&#x3C;style>\n    .textoVerde {\n        color: green;\n    }\n&#x3C;/style>\n\n&#x3C;body>\n\n    &#x3C;ul>\n        &#x3C;li>Hola 1&#x3C;/li>\n        &#x3C;li>Hola 2&#x3C;/li>\n        &#x3C;li>Hola 3&#x3C;/li>\n    &#x3C;/ul>\n\n    &#x3C;ul>\n            &#x3C;li>Negrita&#x3C;/li>\n            &#x3C;li>Negrita 2&#x3C;/li>\n            &#x3C;li>Negrita 3&#x3C;/li>\n        &#x3C;/ul>\n\n    &#x3C;script>\n        jQuery('ul').addClass('textoVerde');\n\n        jQuery('ul').css('font-weight','bold')\n    &#x3C;/script>\n\n\n&#x3C;/body>\n&#x3C;script>&#x3C;/script>\n\n&#x3C;/html>\n</code></pre></div>\n<p>Como véis tenemos un html básico con dos listas, y en ellas cambiamos proopiedades, añadimos una clase css en una de las funciones de jQuery y en la otra le añadimos un estilo de css directamente, esto seria lo mismo que tener un html de esta forma</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;!DOCTYPE html>\n&#x3C;html lang=\"es\">\n\n&#x3C;head>\n    &#x3C;meta charset=\"UTF-8\">\n    &#x3C;meta http-equiv=\"Content-type\" content=\"text/html\">\n    &#x3C;title>Leccion 01&#x3C;/title>\n    &#x3C;script src=\"lib/jquery-3.3.1.min.js\">&#x3C;/script>\n&#x3C;/head>\n&#x3C;style>\n    .textoVerde {\n        color: green;\n    }\n&#x3C;/style>\n\n&#x3C;body>\n\n    &#x3C;ul class=\"textoVerde\">\n        &#x3C;li>Hola 1&#x3C;/li>\n        &#x3C;li>Hola 2&#x3C;/li>\n        &#x3C;li>Hola 3&#x3C;/li>\n    &#x3C;/ul>\n\n    &#x3C;ul style=\"font-weight:bold;\">\n            &#x3C;li>Negrita&#x3C;/li>\n            &#x3C;li>Negrita 2&#x3C;/li>\n            &#x3C;li>Negrita 3&#x3C;/li>\n        &#x3C;/ul>\n\n    &#x3C;script>\n        //jQuery('ul').addClass('textoVerde');\n\n        //jQuery('ul').css('font-weight','bold')\n    &#x3C;/script>\n\n\n&#x3C;/body>\n\n&#x3C;/html>\n</code></pre></div>\n<p>Si os fijáis hemos comentado los métodos de jQuery y hemos puesto directamente en uno la clase y en el otro un estilo de css.</p>\n<h2 id=\"esperandoaquelapginaestcargadaparaejecutaralgo\">Esperando a que la página esté cargada para ejecutar algo</h2>\n<p>Algunas veces tenemos en distintos lugares ciertas funciones o variables, esto nos puede dar problemas en lenguajes como html ya que el lenguaje es interpretado de arriba hacia abajo es posible que estemos ejecutando un cambio en un elemento que todavía no ha sido leído por el interprete por lo que el cambio no se producirá, para ello jQuery nos proveé de el método <strong>ready</strong> que nos permite esperar hasta que algo haya sido cargado o leído completamente, veamoslo con un ejemplo.</p>\n<p>Si nosotros pusieramos los métodos anteriormente mencionados en el <em>header</em>, por ejemplo, no se produciría ningún cambio en la página (si no os fiáis de mi probarlo ;) ), pero si por lo que fuera tenemos que cargar algo en el header lo podríamos hacer de esta forma</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;script>\n    $(document).ready(function() {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n&#x3C;/script>\n</code></pre></div>\n<p>Metiendo nuestro código dentro de la función o método anterior, todo se ejecutará tras la carga de la página o <em>documento</em> completo.<br>\njQuery nos da una forma más corta para hacer lo mismo:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;script>\n    $(function() {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n&#x3C;/script>\n</code></pre></div>\n<p>Esto es lo mismo que lo anterior, y si pensamos en las <strong>arrow functions</strong> todavía podemos ahorrarnos algo más:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;script>\n    $(() => {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n&#x3C;/script>\n</code></pre></div>\n<p>Las tres son la misma función, solo que como es algo muy habitual de usar, le han dado algo de <em>azúcar sintactico</em> para hacer más cómodo su uso.</p>\n<h3 id=\"trabajandoconselectoresyotrascosas\">Trabajando con selectores y otras cosas</h3>\n<p>Vamos a ver un ejemplo cortito de uso de algunas funciones para añadir, eliminar clases y atributos a elementos del DOM</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;script>\n\n\t$(\"img\")\n\t\t.attr(\"src\",\"img/photo2.jpg\")\n\t\t.removeClass('img-circle')\n\t\t.addClass('img-thumbnail');\n\n&#x3C;/script>\n</code></pre></div>\n<p>Esto lo que hace es: primero cambia el atributo <em>src</em> de la imagen, segundo elimina la clase <em>img-circle</em> y tercero añade la clase <em>img-thumbnail</em></p>\n<p>Estas son algunas de las cosas más básicas que podemos ir haciendo con jQuery, iré haciendo más post de jQuery con ejemplos de uso. Nos vemos en el siguiente, un abrazooorrrr</p>\n<!--kg-card-end: markdown-->","htmlAst":{"type":"root","children":[{"type":"comment","value":"kg-card-begin: markdown"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Empecemos con los básicos de jQuery. jQuery nos permite manejar el DOM de una manera dinámica, hacer peticiones, manipular datos..... y de una manera muy sencilla, y realmente podemos hacer casi de todo, iremos viendo un poco de todo en varios post."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPrimero vamos con un ejemplo sencillo"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"ejemplodeusobsicodejquery"},"children":[{"type":"text","value":"Ejemplo de uso básico de jQuery"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<!DOCTYPE html>\n<html lang=\"es\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"Content-type\" content=\"text/html\">\n    <title>Leccion 01</title>\n    <script src=\"lib/jquery-3.3.1.min.js\"></script>\n</head>\n<style>\n    .textoVerde {\n        color: green;\n    }\n</style>\n\n<body>\n\n    <ul>\n        <li>Hola 1</li>\n        <li>Hola 2</li>\n        <li>Hola 3</li>\n    </ul>\n\n    <ul>\n            <li>Negrita</li>\n            <li>Negrita 2</li>\n            <li>Negrita 3</li>\n        </ul>\n\n    <script>\n        jQuery('ul').addClass('textoVerde');\n\n        jQuery('ul').css('font-weight','bold')\n    </script>\n\n\n</body>\n<script></script>\n\n</html>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como véis tenemos un html básico con dos listas, y en ellas cambiamos proopiedades, añadimos una clase css en una de las funciones de jQuery y en la otra le añadimos un estilo de css directamente, esto seria lo mismo que tener un html de esta forma"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<!DOCTYPE html>\n<html lang=\"es\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"Content-type\" content=\"text/html\">\n    <title>Leccion 01</title>\n    <script src=\"lib/jquery-3.3.1.min.js\"></script>\n</head>\n<style>\n    .textoVerde {\n        color: green;\n    }\n</style>\n\n<body>\n\n    <ul class=\"textoVerde\">\n        <li>Hola 1</li>\n        <li>Hola 2</li>\n        <li>Hola 3</li>\n    </ul>\n\n    <ul style=\"font-weight:bold;\">\n            <li>Negrita</li>\n            <li>Negrita 2</li>\n            <li>Negrita 3</li>\n        </ul>\n\n    <script>\n        //jQuery('ul').addClass('textoVerde');\n\n        //jQuery('ul').css('font-weight','bold')\n    </script>\n\n\n</body>\n\n</html>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si os fijáis hemos comentado los métodos de jQuery y hemos puesto directamente en uno la clase y en el otro un estilo de css."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"esperandoaquelapginaestcargadaparaejecutaralgo"},"children":[{"type":"text","value":"Esperando a que la página esté cargada para ejecutar algo"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Algunas veces tenemos en distintos lugares ciertas funciones o variables, esto nos puede dar problemas en lenguajes como html ya que el lenguaje es interpretado de arriba hacia abajo es posible que estemos ejecutando un cambio en un elemento que todavía no ha sido leído por el interprete por lo que el cambio no se producirá, para ello jQuery nos proveé de el método "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"ready"}]},{"type":"text","value":" que nos permite esperar hasta que algo haya sido cargado o leído completamente, veamoslo con un ejemplo."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si nosotros pusieramos los métodos anteriormente mencionados en el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"header"}]},{"type":"text","value":", por ejemplo, no se produciría ningún cambio en la página (si no os fiáis de mi probarlo ;) ), pero si por lo que fuera tenemos que cargar algo en el header lo podríamos hacer de esta forma"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<script>\n    $(document).ready(function() {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n</script>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Metiendo nuestro código dentro de la función o método anterior, todo se ejecutará tras la carga de la página o "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"documento"}]},{"type":"text","value":" completo."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\njQuery nos da una forma más corta para hacer lo mismo:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<script>\n    $(function() {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n</script>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Esto es lo mismo que lo anterior, y si pensamos en las "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"arrow functions"}]},{"type":"text","value":" todavía podemos ahorrarnos algo más:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<script>\n    $(() => {\n        $('ul').addClass('textoVerde');\n        $('ul').css('font-weight','bold')\n    });\n</script>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Las tres son la misma función, solo que como es algo muy habitual de usar, le han dado algo de "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"azúcar sintactico"}]},{"type":"text","value":" para hacer más cómodo su uso."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"trabajandoconselectoresyotrascosas"},"children":[{"type":"text","value":"Trabajando con selectores y otras cosas"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vamos a ver un ejemplo cortito de uso de algunas funciones para añadir, eliminar clases y atributos a elementos del DOM"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<script>\n\n\t$(\"img\")\n\t\t.attr(\"src\",\"img/photo2.jpg\")\n\t\t.removeClass('img-circle')\n\t\t.addClass('img-thumbnail');\n\n</script>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Esto lo que hace es: primero cambia el atributo "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"src"}]},{"type":"text","value":" de la imagen, segundo elimina la clase "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"img-circle"}]},{"type":"text","value":" y tercero añade la clase "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"img-thumbnail"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Estas son algunas de las cosas más básicas que podemos ir haciendo con jQuery, iré haciendo más post de jQuery con ejemplos de uso. Nos vemos en el siguiente, un abrazooorrrr"}]},{"type":"text","value":"\n"},{"type":"comment","value":"kg-card-end: markdown"}],"data":{"quirksMode":false}},"tableOfContents":[{"id":"ejemplodeusobsicodejquery","heading":"Ejemplo de uso básico de jQuery"},{"id":"esperandoaquelapginaestcargadaparaejecutaralgo","heading":"Esperando a que la página esté cargada para ejecutar algo","items":[{"id":"trabajandoconselectoresyotrascosas","heading":"Trabajando con selectores y otras cosas"}]}]},"featureImageSharp":{"base":"jquery-logo.png","publicURL":"/static/d41803bc36890b1c71051dc26c29c3ea/jquery-logo.png","imageMeta":{"width":665,"height":405},"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABwklEQVQoz2MQVjYkGzFgFRVRMRJVNSZOs4oRCCkbQYTE1Iz55XW5pLWA+iGmiAGRmrEolDQCCgopGcA0A1lK+iBSGSTKIamhZGhv4ugH1M8np8Mrp8MlrckuocYjq80qpsonr8srqy0CsgyoWclASM1UwMBZSNuaX05HxdghJD5r2tzFK9Zuzi6ptXALdPCJ8I9KzStvtPMOr2npNXLwySiqDoxJ55TUYAA6mNcjDYgE3JPYZfUiErMvXr4Wn1kcnpR7+tzlgqrmJavWX7p6Y+vu/Zu276lp69tz4OiUOYuAXgC6kUFEXofHJ4cruonPO4tLwXDyjPn17f1ADRs2b+/tn7pqzYbuvsmbN2/r7J3c1jlBXtN05uyFhvbenFKaQP0MYK8aCtiFs2s7WHsEz1uySkBRX0nfWt3Oj986WNEnWdAmWNw2WM0rQdQ6UMgmWNjcR1DRAOZnSNzIaQrJaUtpmYurmwgpGQJDm0fZRMDInUfHQcDQhV/fhUfLTkDfCSgioOcoAosXWDyrGAORoKI+0CdAU0ExpGwgqqAjqqgnoqArqqgLYijqAv0IZOBMJBD3wEwExz/IXCMUNv4URiQCANQ+lfCXnaknAAAAAElFTkSuQmCC","aspectRatio":1.6455696202531647,"src":"/static/d41803bc36890b1c71051dc26c29c3ea/d5882/jquery-logo.png","srcSet":"/static/d41803bc36890b1c71051dc26c29c3ea/bcfcb/jquery-logo.png 260w,\n/static/d41803bc36890b1c71051dc26c29c3ea/19d75/jquery-logo.png 520w,\n/static/d41803bc36890b1c71051dc26c29c3ea/d5882/jquery-logo.png 665w","srcWebp":"/static/d41803bc36890b1c71051dc26c29c3ea/20521/jquery-logo.webp","srcSetWebp":"/static/d41803bc36890b1c71051dc26c29c3ea/dc8f3/jquery-logo.webp 260w,\n/static/d41803bc36890b1c71051dc26c29c3ea/2db4b/jquery-logo.webp 520w,\n/static/d41803bc36890b1c71051dc26c29c3ea/20521/jquery-logo.webp 665w","sizes":"(max-width: 665px) 100vw, 665px"}}}},"prev":{"id":"Ghost__Post__5a8c07c98cda356bbe9bbe44","title":"jQuery Slideshow","slug":"jquery-slideshow","featured":false,"feature_image":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/jquery-logo-1.png","excerpt":"Vamos con un ejemplo de creación de un Slideshow muy simple en jQuery. Lo\nprimero de todo es generarnos la estructura del proyecto, cada uno que la haga\ncomo quiera, yo tengo algo así\n\n\nEn mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado\nal index.html al igual que jQuery. También he creado mi propio fichero de estilo \nstyle.css y lo he añadido, quedando todo de esta manera:\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;","custom_excerpt":null,"visibility":"public","created_at_pretty":"20 Feb 2018","published_at_pretty":"22 Feb 2018","updated_at_pretty":"22 Feb 2018","created_at":"2018-02-20T12:34:33.000+01:00","published_at":"2018-02-22T14:10:51.000+01:00","updated_at":"2018-02-22T14:10:51.000+01:00","meta_title":null,"meta_description":null,"og_description":null,"og_image":null,"og_title":null,"twitter_description":null,"twitter_image":null,"twitter_title":null,"authors":[{"slug":"jlgarcia","url":"https://jlgarcia.fulldev.ninja/author/jlgarcia/","name":"Juan Luis Garcia Aparicio","bio":null,"cover_image":null,"profile_image":"https://jlgarcia.fulldev.ninja/assets/images/2017/12/Perfil.jpg","location":null,"website":null,"twitter":null,"facebook":null,"meta_title":null,"meta_description":null,"coverImageSharp":null,"profileImageSharp":null}],"primary_author":{"slug":"jlgarcia","url":"https://jlgarcia.fulldev.ninja/author/jlgarcia/","name":"Juan Luis Garcia Aparicio","bio":null,"cover_image":null,"profile_image":"https://jlgarcia.fulldev.ninja/assets/images/2017/12/Perfil.jpg","location":null,"website":null,"twitter":null,"facebook":null,"meta_title":null,"meta_description":null,"coverImageSharp":null,"profileImageSharp":{"base":"Perfil.jpg","publicURL":"/static/b0de6281fb28a266510b3b09b9243e5a/Perfil.jpg","imageMeta":{"width":307,"height":307},"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAUDBAb/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAGzw6zC6zHn+cLYP//EAB0QAAICAQUAAAAAAAAAAAAAAAEDAAIEEyEiIzL/2gAIAQEAAQUCifca8KgcKWVfUpkHsG5pxX//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAdEAACAgEFAAAAAAAAAAAAAAAAARARcQISIUFR/9oACAEBAAY/AhU88xkb7N06a8P/xAAcEAEAAwEAAwEAAAAAAAAAAAABABEhMUFRYXH/2gAIAQEAAT8hR2pq40aqb+xIAeXibhW9JXr8joF4TBcSNe0//9oADAMBAAIAAwAAABDzDwD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhUTFhcfD/2gAIAQEAAT8QyItrELaTlatLwU63MvEW6vUNdy4LZQDn7iVApV9VLtANdWwKkuYq4Er1VZ//2Q==","aspectRatio":1,"src":"/static/b0de6281fb28a266510b3b09b9243e5a/31709/Perfil.jpg","srcSet":"/static/b0de6281fb28a266510b3b09b9243e5a/f340b/Perfil.jpg 28w,\n/static/b0de6281fb28a266510b3b09b9243e5a/22d64/Perfil.jpg 55w,\n/static/b0de6281fb28a266510b3b09b9243e5a/31709/Perfil.jpg 110w,\n/static/b0de6281fb28a266510b3b09b9243e5a/aa249/Perfil.jpg 165w,\n/static/b0de6281fb28a266510b3b09b9243e5a/0dc33/Perfil.jpg 220w,\n/static/b0de6281fb28a266510b3b09b9243e5a/60667/Perfil.jpg 307w","srcWebp":"/static/b0de6281fb28a266510b3b09b9243e5a/8678c/Perfil.webp","srcSetWebp":"/static/b0de6281fb28a266510b3b09b9243e5a/59cda/Perfil.webp 28w,\n/static/b0de6281fb28a266510b3b09b9243e5a/7da75/Perfil.webp 55w,\n/static/b0de6281fb28a266510b3b09b9243e5a/8678c/Perfil.webp 110w,\n/static/b0de6281fb28a266510b3b09b9243e5a/f282e/Perfil.webp 165w,\n/static/b0de6281fb28a266510b3b09b9243e5a/a7b21/Perfil.webp 220w,\n/static/b0de6281fb28a266510b3b09b9243e5a/f59af/Perfil.webp 307w","sizes":"(max-width: 110px) 100vw, 110px"}}}},"primary_tag":{"slug":"jquery","url":"https://jlgarcia.fulldev.ninja/tag/jquery/","name":"jquery","visibility":"public","feature_image":null,"description":null,"meta_title":null,"meta_description":null,"featureImageSharp":null},"tags":[{"slug":"jquery","url":"https://jlgarcia.fulldev.ninja/tag/jquery/","name":"jquery","visibility":"public","feature_image":null,"description":null,"meta_title":null,"meta_description":null,"featureImageSharp":null}],"plaintext":"Vamos con un ejemplo de creación de un Slideshow muy simple en jQuery. Lo\nprimero de todo es generarnos la estructura del proyecto, cada uno que la haga\ncomo quiera, yo tengo algo así\n\n\nEn mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado\nal index.html al igual que jQuery. También he creado mi propio fichero de estilo \nstyle.css y lo he añadido, quedando todo de esta manera:\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n    <title>Ninja_slider</title>\n\n    <script src=\"https://code.jquery.com/jquery-3.3.1.min.js\"></script>\n\n    <link rel=\"stylesheet\" href=\"css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n    \n</head>\n<body>\n    \n</body>\n</html>\n\n\nLo siguiente es añadir donde estará el slider en el body de la página\n\n<body>\n\n    <div class=\"container\" align=\"center\">\n        <h1>Ninja-Slider</h1>\n        <hr>\n\n        <div class=\"ninjaSlider\"></div>\n\n    </div>\n    \n</body>\n\n\nNuestro slider como os podéis imaginar estará en el div con la clase ninjaSlider\n, y esto es todo por el momento en el html, ahora vamos a nuestro css para darle\nun poco de estilo y que se vea algo en la página. Le daremos un tamaño y un\ncolor de fondo para ir viendo algo.\n\n.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\toverflow: hidden;\n\tmargin-bottom: 10px;\n}\n\n\nQuedando así\n\n\nBien ahora vamos a crear un fichero js donde meteremos toda la lógica de\nfuncionamiento de nuestro slider. Tener en cuenta que la idea es hacerlo estilo\nplugin, es decir que este encapsulado para poder usarlo en cualquiera de\nnuestros proyectos.\nBien lo primero como hemos comentado es crearnos el fichero js y meterlo en la\ncarpeta correspondiente, lo siguiente son las imágenes para que slider tenga\nalgo que mostrar, entonces buscamos unas cuantas imágenes, yo me he descargado 4\ny las metemos en la carpeta img.\n\nUna vez que tenemos las imagenes ya podemos empezar, con el js. Creamos una\nfunción anónima que se ejecute nada más cargar el js en el HTML:\n\n(function(){\n    //Aqui dentro meteríamos todo el código.\n})();\n\n\nVamos a empezar por algo sencillo, que es recibir las imagenes desde el html que\nes desde donde nos las mandarían si pensamos que este es un plugin. Estas\nimágenes las incluiremos en una lista, es decir, dentro de un ul de html.\nPero antes de hacer esto, pensemos...¿cómo hacemos para pasar los datos que\nnecesitemos a nuestro plugin?, fácil, por parámetros le pasamos un objecto que\ntenga las modificaciones que queramos hacer.\nPrimero creemos un método, que será el que realmente configure e inicie nuestro\nslider\n\n(function(){\n    $.ninjaShow = function(config){\n    \n    }\n})();\n\n\nAqui hemos añadido la función ninjaShow a jQuery, por lo que la podemos llamar\ndesde cualquier sitio desde el que podamos llamar a jQuery. A esta función le\npasamos por parámetro un objeto config que tendrá todos los cambios sobre la\nconfiguración por defecto que establezcamos.\nContinuemos añadiendo lógica para nuestras imagenes, suponiendo que nos indiquen\ncuales son las imágenes a través del objeto config, podemos tener nuestras\nimagenes bajo la propiedad images dentro del objeto config. Hagamos una prueba\npara que veáis de lo que estoy hablando, nos vamos a nuestro index.html y\nañadimos lo siguiente al final (pero siempre dentro del body)\n\n<!-- añadimos nuestro js al html -->\n<script src=\"js/slider.js\"></script>\n<script>\n\t//Llamamos a nuestra función pasandole un objeto con la propiedad images\n\t$.ninjaShow({\n\n        images:['img/ninja1.jpg','img/ninja2.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n\t});\n\n</script>\n</body>\n\n\nY luego en nuestro fichero js, ponemos un log para ver que estamos recibiendo.\n\n(function(){\n\n    $.ninjaShow = function( config ){\n\n        console.log(config);\n    }\n\n})();\n\n\nSi guardamos y miramos la consola al ejecutar nuestro index.html, veremos algo\ncomo lo siguiente\n\n\nEs decir, un objeto con la propiedad images y dentro de esta un array con la\ndirección donde estan nuestras imágenes.\nEntonces ya tenemos nuestras imágenes, ahora creemos la lista con ellas.\n\n(function(){\n\n    $.ninjaShow = function( config ){\n                //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n\n            //Abrimos la lista\n            var imgList = \"<ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '<li><img src=\"'+ img +'\"</li>';\n            })\n            //Cerramos la lista\n            imgList += \"</ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(\".ninjaSlider\").append(imgList);\n    }\n\n})();\n\n\nSi ejecutamos nuestro index.html veremos algo similar a esto:\n\n\n\nAhora mismo no vemos casi nada, ¿verdad?, vamos a modificar un poco el estilo\npara que veamos que realmente las cosas estan donde deben estar. Nos vamos a\nnuestro style.css y lo dejamos así\n\n.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\t/* overflow: hidden; */\n\tmargin-bottom: 10px;\n}\n\n.ninjaSlider ul{\n\tpadding: 0;\n\tlist-style-type: none;\n\tmargin-left: 0px;\n\tdisplay: flex;\n}\n\n\nAhora si veríamos algo aunque solo sean las imágenes\n\n\nPero si miramos el código fuente de la página deberíamos ver algo como esto:\n\n\nYa tenemos nuestra lista de imágenes, y las vemos porque hemos cambiado la\npropiedad overflow de css, la configuración correcta sería descomentado la línea\ny dejandola así\n\noverflow: hidden;\n\n\nPero la hemos comentado para explicar que es lo que vamos a hacer para ir\ncambiando de imágenes.\nSi os fijáis las imágenes estan configuradas en una linea horizontal, una al\nlado de otra, lo que haremos será ir moviendo el interior del contenedor en esa\nlinea horizontal, modificando el margin-left, es decir, supongamos que nuestro \nmargin-left en nuestra primera imagen es 0 y tenemos imágenes con un ancho de\n600, pues lo que haríamos para movernos entre las imágenes sería ir modificando\nel margin-left en conjuntos de 600, es decir, la siguiente imagen tendria un\nmargen de -600, la siguiente de -1200... y el - es necesario porque nuestro\nslide se movera de izquierda a derecha y como os podréis imaginar para que\nfuncione en este ejemplo es necesario que el ancho de las imágenes sea el mismo\no muy parecido (podríamos manejar el ancho de cada li dentro de la lista pero\nprefiero dejar el código más claro).\nCreo que está más o menos explicado el concepto de lo que queremos hacer, veamos\ncomo lo hacemos\n\n //Variable de ayuda para gestionar la posicion\n var position = 0;\n //Numero de imagenes para controlar\n var images = config.images.length;\n\n //intervalo en el que se cambia la imagen\n var interval = setInterval(function(){\n   move();\n }, 1400);\n\n function move(){\n//Cada vez que pase por aqui aumentamos la posicion       \n   position++;\n\n//Si la posicion es igual o mayor que la cantidad de imagenes\n//ponemos position a 0\n   if (position >= images ){\n        position = 0\n   }\n\n//Por ultimo movemos el margen según la posición en grupos de 600\n   $(\".ninjaSlider ul\").animate({\n     marginLeft: position * -600\n   },400);\n\n\nPor último descomentamos el overflow:hidden en el fichero css y listo, ya lo\ntenemos\n\n\n\nYa tenemos nuestro slide funcionando, en este punto podríamos añadir más\nfuncionalidad, que tuviera los puntitos típicos que te indican en que slide te\nencuentras y que puedes pulsar para moverte de uno a otro, o parar el slide por\nejemplo. Eso lo haremos más adelante en algún post posterior ahora quería solo\nmostrar como podríamos hacer lo más básico de un slide, ahora lo ultimo que\nharemos será añadir un par de cosas al js para que se vaya pareciendo más a un\nplugin y podamos personalizarlo un poco más.\n\nSi miramos el código detenidamente y pensamos un poco que cosas podrían ser\nsusceptibles de cambiar, podrían ser:\n\n * El ancho básico de las imágenes para ir moviendo el slide.\n * La clase o id del slider (podriamos tener mas de uno por ejemplo)\n * El intervalo de transición de las imágenes.\n\nEstos son algunos de los cambios que se me han ocurrido con el código que\ntenemos actualmente podríamos tener más seguramente. Por el momento vamos a\npreparar esos.\nPara empezar tenemos que plantearnos cuales son obligatorios y cuales podrían\ntener una configuración por defecto. Las imágenes deben ser obligatorias, por\neso hemos puesto el control antes que nos lanzaría una alerta si no se pasa\nninguna imagen, y a lo mejor el nombre del id del slide y el resto podemos tener\nvalores por defecto si no nos lo pasan por parámetro.\nPara ellos basta con usar el método extend de jQuery sobre el objeto que se pasa\npor parámetro\n\n$.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n\nEste método lo que hace es sobreescribir el objeto local, que sería el primero\n(el que está entre { }) con el que se pasa por parámetro, pero solo las\npropiedades con el mismo nombre, es decir, no elimina el objeto por otro, es\ncomo si cambiaramos las propiedades que coincidan por las nuevas que se pasan\npor parámetro.\nY ahora simplemente es cambiar los elementos que tenemos puestos a mano como \n\".ninjaslider\" por la propiedad correspondiente y listo, ya tendríamos preparado\nel código como si fuera un plugin quedando así (dejo comentado el código)\n\n//Función anonima\n(function(){\n\n    $.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n            //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n            \n            //Comprobamos que nos han pasado un nombre para slider\n            if (config.slideName == \"\"){\n                alert(\"Falta el nombre o id donde estará el slider\")\n                return\n            }\n\n            //Abrimos la lista\n            var imgList = \"<ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '<li><img src=\"'+ img +'\"</li>';\n            })\n            //Cerramos la lista\n            imgList += \"</ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(config.slideName).append(imgList);\n\n            //Variable de ayuda para gestionar la posicion\n            var position = 0;\n            //Numero de imagenes para controlar\n            var images = config.images.length;\n\n            //intervalo en el que se cambia la imagen\n            var interval = setInterval(function(){\n                move();\n            }, config.timeTransition);\n\n            function move(){\n                \n                position++;\n\n                if (position >= images ){\n                    position = 0\n                }\n\n                $(config.slideName + \" ul\").animate({\n                    marginLeft: position * - config.width\n                },400);\n            }\n    }\n\n})();\n\n\nComo véis ahora tenemos config.algo por todas partes. Y para usarlo nos vamos a\nnuestro index.html y añadimos las propiedades necesarias:\n\n<script>\n\t\n\t$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n</script>\n\n\nY podríamos como he comentado, crear más sliders simplemente creando el\nelemento, dandole un nombre y crear un nuevo ninjaShow\n\n$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n    \n$.ninjaShow({\n        slideName: \".ninjaSlider2\",\n        ancho: 600,\n        timeTransition: 1200,\n        images:['img/ninja4.jpg','img/ninja1.jpg','img/ninja3.jpg'],\n});\n\n\n\n\nComo véis ahora es muy sencillo crear sliders básicos con este código. En algún\npost posterior mejoraremos este slider para que tenga más funcionalidades, esto\nes básicamente para que veamos un poco como podemos trabajar con jQuery para\nhacer todo lo que queramos con el DOM.\n\nSin mucho más nos vemos en el siguiente, un abrazooorrrr.","html":"<!--kg-card-begin: markdown--><p>Vamos con un ejemplo de creación de un <strong>Slideshow</strong> muy simple en jQuery. Lo primero de todo es generarnos la estructura del proyecto, cada uno que la haga como quiera, yo tengo algo así<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/folders.JPG\" alt=\"folders\"></p>\n<p>En mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado al index.html al igual que <strong>jQuery</strong>. También he creado mi propio fichero de estilo <strong>style.css</strong> y lo he añadido, quedando todo de esta manera:</p>\n<pre><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;en&quot;&gt;\n&lt;head&gt;\n    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;\n    &lt;title&gt;Ninja_slider&lt;/title&gt;\n\n    &lt;script src=&quot;https://code.jquery.com/jquery-3.3.1.min.js&quot;&gt;&lt;/script&gt;\n\n    &lt;link rel=&quot;stylesheet&quot; href=&quot;css/bootstrap.min.css&quot;&gt;\n    &lt;link rel=&quot;stylesheet&quot; href=&quot;css/style.css&quot;&gt;\n    \n&lt;/head&gt;\n&lt;body&gt;\n    \n&lt;/body&gt;\n&lt;/html&gt;\n</code></pre>\n<p>Lo siguiente es añadir donde estará el slider en el <strong>body</strong> de la página</p>\n<pre><code>&lt;body&gt;\n\n    &lt;div class=&quot;container&quot; align=&quot;center&quot;&gt;\n        &lt;h1&gt;Ninja-Slider&lt;/h1&gt;\n        &lt;hr&gt;\n\n        &lt;div class=&quot;ninjaSlider&quot;&gt;&lt;/div&gt;\n\n    &lt;/div&gt;\n    \n&lt;/body&gt;\n</code></pre>\n<p>Nuestro slider como os podéis imaginar estará en el <em>div</em> con la clase <em>ninjaSlider</em>, y esto es todo por el momento en el html, ahora vamos a nuestro <em>css</em> para darle un poco de estilo y que se vea algo en la página. Le daremos un tamaño y un color de fondo para ir viendo algo.</p>\n<pre><code>.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\toverflow: hidden;\n\tmargin-bottom: 10px;\n}\n</code></pre>\n<p>Quedando así<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/background.JPG\" alt=\"background\"></p>\n<p>Bien ahora vamos a crear un fichero <em>js</em> donde meteremos toda la lógica de funcionamiento de nuestro slider. Tener en cuenta que la idea es hacerlo estilo plugin, es decir que este encapsulado para poder usarlo en cualquiera de nuestros proyectos.<br>\nBien lo primero como hemos comentado es crearnos el fichero <em>js</em> y meterlo en la carpeta correspondiente, lo siguiente son las imágenes para que slider tenga algo que mostrar, entonces buscamos unas cuantas imágenes, yo me he descargado 4 y las metemos en la carpeta <em>img</em>.</p>\n<p>Una vez que tenemos las imagenes ya podemos empezar, con el js. Creamos una función anónima que se ejecute nada más cargar el js en el HTML:</p>\n<pre><code>(function(){\n    //Aqui dentro meteríamos todo el código.\n})();\n</code></pre>\n<p>Vamos a empezar por algo sencillo, que es recibir las imagenes desde el html que es desde donde nos las mandarían si pensamos que este es un plugin. Estas imágenes las incluiremos en una lista, es decir, dentro de un <em>ul</em> de html.<br>\nPero antes de hacer esto, pensemos...¿cómo hacemos para pasar los datos que necesitemos a nuestro plugin?, fácil, por parámetros le pasamos un <em>objecto</em> que tenga las modificaciones que queramos hacer.<br>\nPrimero creemos un método, que será el que realmente configure e inicie nuestro slider</p>\n<pre><code>(function(){\n    $.ninjaShow = function(config){\n    \n    }\n})();\n</code></pre>\n<p>Aqui hemos añadido la función <em>ninjaShow</em> a jQuery, por lo que la podemos llamar desde cualquier sitio desde el que podamos llamar a jQuery. A esta función le pasamos por parámetro un objeto <em>config</em> que tendrá todos los cambios sobre la configuración por defecto que establezcamos.<br>\nContinuemos añadiendo lógica para nuestras imagenes, suponiendo que nos indiquen cuales son las imágenes a través del objeto <em>config</em>, podemos tener nuestras imagenes bajo la propiedad <em>images</em> dentro del objeto <em>config</em>. Hagamos una prueba para que veáis de lo que estoy hablando, nos vamos a nuestro <em>index.html</em> y añadimos lo siguiente al final (pero siempre dentro del <em>body</em>)</p>\n<pre><code>&lt;!-- añadimos nuestro js al html --&gt;\n&lt;script src=&quot;js/slider.js&quot;&gt;&lt;/script&gt;\n&lt;script&gt;\n\t//Llamamos a nuestra función pasandole un objeto con la propiedad images\n\t$.ninjaShow({\n\n        images:['img/ninja1.jpg','img/ninja2.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n\t});\n\n&lt;/script&gt;\n&lt;/body&gt;\n</code></pre>\n<p>Y luego en nuestro fichero <em>js</em>, ponemos un log para ver que estamos recibiendo.</p>\n<pre><code>(function(){\n\n    $.ninjaShow = function( config ){\n\n        console.log(config);\n    }\n\n})();\n</code></pre>\n<p>Si guardamos y miramos la consola al ejecutar nuestro <em>index.html</em>, veremos algo como lo siguiente<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/images.JPG\" alt=\"images\"></p>\n<p>Es decir, un objeto con la propiedad <em>images</em> y dentro de esta un array con la dirección donde estan nuestras imágenes.<br>\nEntonces ya tenemos nuestras imágenes, ahora creemos la lista con ellas.</p>\n<pre><code>(function(){\n\n    $.ninjaShow = function( config ){\n                //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(&quot;Necesitamos alguna imagen para mostrar&quot;);\n                return;\n            }\n\n            //Abrimos la lista\n            var imgList = &quot;&lt;ul&gt;&quot;;\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=&gt;{\n                imgList += '&lt;li&gt;&lt;img src=&quot;'+ img +'&quot;&lt;/li&gt;';\n            })\n            //Cerramos la lista\n            imgList += &quot;&lt;/ul&gt;&quot;;\n            \n            //Adjuntamos la lista al contenedor\n            $(&quot;.ninjaSlider&quot;).append(imgList);\n    }\n\n})();\n</code></pre>\n<p>Si ejecutamos nuestro <em>index.html</em> veremos algo similar a esto:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example.JPG\" alt=\"example\"></p>\n<p>Ahora mismo no vemos casi nada, ¿verdad?, vamos a modificar un poco el estilo para que veamos que realmente las cosas estan donde deben estar. Nos vamos a nuestro <em>style.css</em> y lo dejamos así</p>\n<pre><code>.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\t/* overflow: hidden; */\n\tmargin-bottom: 10px;\n}\n\n.ninjaSlider ul{\n\tpadding: 0;\n\tlist-style-type: none;\n\tmargin-left: 0px;\n\tdisplay: flex;\n}\n</code></pre>\n<p>Ahora si veríamos algo aunque solo sean las imágenes<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example2.JPG\" alt=\"example2\"></p>\n<p>Pero si miramos el código fuente de la página deberíamos ver algo como esto:<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example3.JPG\" alt=\"example3\"></p>\n<p>Ya tenemos nuestra lista de imágenes, y las vemos porque hemos cambiado la propiedad <em>overflow</em> de css, la configuración correcta sería descomentado la línea y dejandola así</p>\n<pre><code>overflow: hidden;\n</code></pre>\n<p>Pero la hemos comentado para explicar que es lo que vamos a hacer para ir cambiando de imágenes.<br>\nSi os fijáis las imágenes estan configuradas en una linea horizontal, una al lado de otra, lo que haremos será ir moviendo el interior del contenedor en esa linea horizontal, modificando el <em>margin-left</em>, es decir, supongamos que nuestro <em>margin-left</em> en nuestra primera imagen es 0 y tenemos imágenes con un ancho de 600, pues lo que haríamos para movernos entre las imágenes sería ir modificando el <em>margin-left</em> en conjuntos de 600, es decir, la siguiente imagen tendria un margen de <strong>-600</strong>, la siguiente de <strong>-1200</strong>... y el <em>-</em> es necesario porque nuestro slide se movera de izquierda a derecha y como os podréis imaginar para que funcione en este ejemplo es necesario que el ancho de las imágenes sea el mismo o muy parecido (podríamos manejar el ancho de cada <em>li</em> dentro de la lista pero prefiero dejar el código más claro).<br>\nCreo que está más o menos explicado el concepto de lo que queremos hacer, veamos como lo hacemos</p>\n<pre><code> //Variable de ayuda para gestionar la posicion\n var position = 0;\n //Numero de imagenes para controlar\n var images = config.images.length;\n\n //intervalo en el que se cambia la imagen\n var interval = setInterval(function(){\n   move();\n }, 1400);\n\n function move(){\n//Cada vez que pase por aqui aumentamos la posicion       \n   position++;\n\n//Si la posicion es igual o mayor que la cantidad de imagenes\n//ponemos position a 0\n   if (position &gt;= images ){\n        position = 0\n   }\n\n//Por ultimo movemos el margen según la posición en grupos de 600\n   $(&quot;.ninjaSlider ul&quot;).animate({\n     marginLeft: position * -600\n   },400);\n</code></pre>\n<p>Por último descomentamos el <em>overflow:hidden</em> en el fichero <em>css</em> y listo, ya lo tenemos</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/slideExample.gif\" alt=\"slideExample\"></p>\n<p>Ya tenemos nuestro slide funcionando, en este punto podríamos añadir más funcionalidad, que tuviera los puntitos típicos que te indican en que slide te encuentras y que puedes pulsar para moverte de uno a otro, o parar el slide por ejemplo. Eso lo haremos más adelante en algún post posterior ahora quería solo mostrar como podríamos hacer lo más básico de un slide, ahora lo ultimo que haremos será añadir un par de cosas al <em>js</em> para que se vaya pareciendo más a un plugin y podamos personalizarlo un poco más.</p>\n<p>Si miramos el código detenidamente y pensamos un poco que cosas podrían ser susceptibles de cambiar, podrían ser:</p>\n<ul>\n<li>El ancho básico de las imágenes para ir moviendo el slide.</li>\n<li>La clase o id del slider (podriamos tener mas de uno por ejemplo)</li>\n<li>El intervalo de transición de las imágenes.</li>\n</ul>\n<p>Estos son algunos de los cambios que se me han ocurrido con el código que tenemos actualmente podríamos tener más seguramente. Por el momento vamos a preparar esos.<br>\nPara empezar tenemos que plantearnos cuales son obligatorios y cuales podrían tener una configuración por defecto. Las imágenes deben ser obligatorias, por eso hemos puesto el control antes que nos lanzaría una alerta si no se pasa ninguna imagen, y a lo mejor el nombre del id del slide y el resto podemos tener valores por defecto si no nos lo pasan por parámetro.<br>\nPara ellos basta con usar el método <em>extend</em> de jQuery sobre el objeto que se pasa por parámetro</p>\n<pre><code>$.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: &quot;&quot;,\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n</code></pre>\n<p>Este método lo que hace es sobreescribir el objeto local, que sería el primero (el que está entre <em>{ }</em>) con el que se pasa por parámetro, pero solo las propiedades con el mismo nombre, es decir, no elimina el objeto por otro, es como si cambiaramos las propiedades que coincidan por las nuevas que se pasan por parámetro.<br>\nY ahora simplemente es cambiar los elementos que tenemos puestos a mano como <em>&quot;.ninjaslider&quot;</em> por la propiedad correspondiente y listo, ya tendríamos preparado el código como si fuera un plugin quedando así (dejo comentado el código)</p>\n<pre><code>//Función anonima\n(function(){\n\n    $.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: &quot;&quot;,\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n            //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(&quot;Necesitamos alguna imagen para mostrar&quot;);\n                return;\n            }\n            \n            //Comprobamos que nos han pasado un nombre para slider\n            if (config.slideName == &quot;&quot;){\n                alert(&quot;Falta el nombre o id donde estará el slider&quot;)\n                return\n            }\n\n            //Abrimos la lista\n            var imgList = &quot;&lt;ul&gt;&quot;;\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=&gt;{\n                imgList += '&lt;li&gt;&lt;img src=&quot;'+ img +'&quot;&lt;/li&gt;';\n            })\n            //Cerramos la lista\n            imgList += &quot;&lt;/ul&gt;&quot;;\n            \n            //Adjuntamos la lista al contenedor\n            $(config.slideName).append(imgList);\n\n            //Variable de ayuda para gestionar la posicion\n            var position = 0;\n            //Numero de imagenes para controlar\n            var images = config.images.length;\n\n            //intervalo en el que se cambia la imagen\n            var interval = setInterval(function(){\n                move();\n            }, config.timeTransition);\n\n            function move(){\n                \n                position++;\n\n                if (position &gt;= images ){\n                    position = 0\n                }\n\n                $(config.slideName + &quot; ul&quot;).animate({\n                    marginLeft: position * - config.width\n                },400);\n            }\n    }\n\n})();\n</code></pre>\n<p>Como véis ahora tenemos <em>config.algo</em> por todas partes. Y para usarlo nos vamos a nuestro <em>index.html</em> y añadimos las propiedades necesarias:</p>\n<pre><code>&lt;script&gt;\n\t\n\t$.ninjaShow({\n        slideName: &quot;.ninjaSlider&quot;,\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n&lt;/script&gt;\n</code></pre>\n<p>Y podríamos como he comentado, crear más sliders simplemente creando el elemento, dandole un nombre y crear un nuevo <em>ninjaShow</em></p>\n<pre><code>$.ninjaShow({\n        slideName: &quot;.ninjaSlider&quot;,\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n    \n$.ninjaShow({\n        slideName: &quot;.ninjaSlider2&quot;,\n        ancho: 600,\n        timeTransition: 1200,\n        images:['img/ninja4.jpg','img/ninja1.jpg','img/ninja3.jpg'],\n});\n</code></pre>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/2Sliders.JPG\" alt=\"2Sliders\"></p>\n<p>Como véis ahora es muy sencillo crear sliders básicos con este código. En algún post posterior mejoraremos este slider para que tenga más funcionalidades, esto es básicamente para que veamos un poco como podemos trabajar con jQuery para hacer todo lo que queramos con el DOM.</p>\n<p>Sin mucho más nos vemos en el siguiente, un abrazooorrrr.</p>\n<!--kg-card-end: markdown-->","url":"https://jlgarcia.fulldev.ninja/jquery-slideshow/","canonical_url":null,"uuid":"3b1de9f2-e3a4-45a7-a056-dc806e105a19","codeinjection_foot":null,"codeinjection_head":null,"codeinjection_styles":null,"comment_id":"5a8c07c98cda356bbe9bbe44","reading_time":8,"send_email_when_published":false,"email_subject":null,"childHtmlRehype":{"html":"<!--kg-card-begin: markdown--><p>Vamos con un ejemplo de creación de un <strong>Slideshow</strong> muy simple en jQuery. Lo primero de todo es generarnos la estructura del proyecto, cada uno que la haga como quiera, yo tengo algo así<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/folders.JPG\" alt=\"folders\"></p>\n<p>En mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado al index.html al igual que <strong>jQuery</strong>. También he creado mi propio fichero de estilo <strong>style.css</strong> y lo he añadido, quedando todo de esta manera:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;!DOCTYPE html>\n&#x3C;html lang=\"en\">\n&#x3C;head>\n    &#x3C;meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n    &#x3C;title>Ninja_slider&#x3C;/title>\n\n    &#x3C;script src=\"https://code.jquery.com/jquery-3.3.1.min.js\">&#x3C;/script>\n\n    &#x3C;link rel=\"stylesheet\" href=\"css/bootstrap.min.css\">\n    &#x3C;link rel=\"stylesheet\" href=\"css/style.css\">\n    \n&#x3C;/head>\n&#x3C;body>\n    \n&#x3C;/body>\n&#x3C;/html>\n</code></pre></div>\n<p>Lo siguiente es añadir donde estará el slider en el <strong>body</strong> de la página</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;body>\n\n    &#x3C;div class=\"container\" align=\"center\">\n        &#x3C;h1>Ninja-Slider&#x3C;/h1>\n        &#x3C;hr>\n\n        &#x3C;div class=\"ninjaSlider\">&#x3C;/div>\n\n    &#x3C;/div>\n    \n&#x3C;/body>\n</code></pre></div>\n<p>Nuestro slider como os podéis imaginar estará en el <em>div</em> con la clase <em>ninjaSlider</em>, y esto es todo por el momento en el html, ahora vamos a nuestro <em>css</em> para darle un poco de estilo y que se vea algo en la página. Le daremos un tamaño y un color de fondo para ir viendo algo.</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\toverflow: hidden;\n\tmargin-bottom: 10px;\n}\n</code></pre></div>\n<p>Quedando así<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/background.JPG\" alt=\"background\"></p>\n<p>Bien ahora vamos a crear un fichero <em>js</em> donde meteremos toda la lógica de funcionamiento de nuestro slider. Tener en cuenta que la idea es hacerlo estilo plugin, es decir que este encapsulado para poder usarlo en cualquiera de nuestros proyectos.<br>\nBien lo primero como hemos comentado es crearnos el fichero <em>js</em> y meterlo en la carpeta correspondiente, lo siguiente son las imágenes para que slider tenga algo que mostrar, entonces buscamos unas cuantas imágenes, yo me he descargado 4 y las metemos en la carpeta <em>img</em>.</p>\n<p>Una vez que tenemos las imagenes ya podemos empezar, con el js. Creamos una función anónima que se ejecute nada más cargar el js en el HTML:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(function(){\n    //Aqui dentro meteríamos todo el código.\n})();\n</code></pre></div>\n<p>Vamos a empezar por algo sencillo, que es recibir las imagenes desde el html que es desde donde nos las mandarían si pensamos que este es un plugin. Estas imágenes las incluiremos en una lista, es decir, dentro de un <em>ul</em> de html.<br>\nPero antes de hacer esto, pensemos...¿cómo hacemos para pasar los datos que necesitemos a nuestro plugin?, fácil, por parámetros le pasamos un <em>objecto</em> que tenga las modificaciones que queramos hacer.<br>\nPrimero creemos un método, que será el que realmente configure e inicie nuestro slider</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(function(){\n    $.ninjaShow = function(config){\n    \n    }\n})();\n</code></pre></div>\n<p>Aqui hemos añadido la función <em>ninjaShow</em> a jQuery, por lo que la podemos llamar desde cualquier sitio desde el que podamos llamar a jQuery. A esta función le pasamos por parámetro un objeto <em>config</em> que tendrá todos los cambios sobre la configuración por defecto que establezcamos.<br>\nContinuemos añadiendo lógica para nuestras imagenes, suponiendo que nos indiquen cuales son las imágenes a través del objeto <em>config</em>, podemos tener nuestras imagenes bajo la propiedad <em>images</em> dentro del objeto <em>config</em>. Hagamos una prueba para que veáis de lo que estoy hablando, nos vamos a nuestro <em>index.html</em> y añadimos lo siguiente al final (pero siempre dentro del <em>body</em>)</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;!-- añadimos nuestro js al html -->\n&#x3C;script src=\"js/slider.js\">&#x3C;/script>\n&#x3C;script>\n\t//Llamamos a nuestra función pasandole un objeto con la propiedad images\n\t$.ninjaShow({\n\n        images:['img/ninja1.jpg','img/ninja2.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n\t});\n\n&#x3C;/script>\n&#x3C;/body>\n</code></pre></div>\n<p>Y luego en nuestro fichero <em>js</em>, ponemos un log para ver que estamos recibiendo.</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(function(){\n\n    $.ninjaShow = function( config ){\n\n        console.log(config);\n    }\n\n})();\n</code></pre></div>\n<p>Si guardamos y miramos la consola al ejecutar nuestro <em>index.html</em>, veremos algo como lo siguiente<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/images.JPG\" alt=\"images\"></p>\n<p>Es decir, un objeto con la propiedad <em>images</em> y dentro de esta un array con la dirección donde estan nuestras imágenes.<br>\nEntonces ya tenemos nuestras imágenes, ahora creemos la lista con ellas.</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(function(){\n\n    $.ninjaShow = function( config ){\n                //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n\n            //Abrimos la lista\n            var imgList = \"&#x3C;ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '&#x3C;li>&#x3C;img src=\"'+ img +'\"&#x3C;/li>';\n            })\n            //Cerramos la lista\n            imgList += \"&#x3C;/ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(\".ninjaSlider\").append(imgList);\n    }\n\n})();\n</code></pre></div>\n<p>Si ejecutamos nuestro <em>index.html</em> veremos algo similar a esto:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example.JPG\" alt=\"example\"></p>\n<p>Ahora mismo no vemos casi nada, ¿verdad?, vamos a modificar un poco el estilo para que veamos que realmente las cosas estan donde deben estar. Nos vamos a nuestro <em>style.css</em> y lo dejamos así</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\t/* overflow: hidden; */\n\tmargin-bottom: 10px;\n}\n\n.ninjaSlider ul{\n\tpadding: 0;\n\tlist-style-type: none;\n\tmargin-left: 0px;\n\tdisplay: flex;\n}\n</code></pre></div>\n<p>Ahora si veríamos algo aunque solo sean las imágenes<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example2.JPG\" alt=\"example2\"></p>\n<p>Pero si miramos el código fuente de la página deberíamos ver algo como esto:<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example3.JPG\" alt=\"example3\"></p>\n<p>Ya tenemos nuestra lista de imágenes, y las vemos porque hemos cambiado la propiedad <em>overflow</em> de css, la configuración correcta sería descomentado la línea y dejandola así</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">overflow: hidden;\n</code></pre></div>\n<p>Pero la hemos comentado para explicar que es lo que vamos a hacer para ir cambiando de imágenes.<br>\nSi os fijáis las imágenes estan configuradas en una linea horizontal, una al lado de otra, lo que haremos será ir moviendo el interior del contenedor en esa linea horizontal, modificando el <em>margin-left</em>, es decir, supongamos que nuestro <em>margin-left</em> en nuestra primera imagen es 0 y tenemos imágenes con un ancho de 600, pues lo que haríamos para movernos entre las imágenes sería ir modificando el <em>margin-left</em> en conjuntos de 600, es decir, la siguiente imagen tendria un margen de <strong>-600</strong>, la siguiente de <strong>-1200</strong>... y el <em>-</em> es necesario porque nuestro slide se movera de izquierda a derecha y como os podréis imaginar para que funcione en este ejemplo es necesario que el ancho de las imágenes sea el mismo o muy parecido (podríamos manejar el ancho de cada <em>li</em> dentro de la lista pero prefiero dejar el código más claro).<br>\nCreo que está más o menos explicado el concepto de lo que queremos hacer, veamos como lo hacemos</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> //Variable de ayuda para gestionar la posicion\n var position = 0;\n //Numero de imagenes para controlar\n var images = config.images.length;\n\n //intervalo en el que se cambia la imagen\n var interval = setInterval(function(){\n   move();\n }, 1400);\n\n function move(){\n//Cada vez que pase por aqui aumentamos la posicion       \n   position++;\n\n//Si la posicion es igual o mayor que la cantidad de imagenes\n//ponemos position a 0\n   if (position >= images ){\n        position = 0\n   }\n\n//Por ultimo movemos el margen según la posición en grupos de 600\n   $(\".ninjaSlider ul\").animate({\n     marginLeft: position * -600\n   },400);\n</code></pre></div>\n<p>Por último descomentamos el <em>overflow:hidden</em> en el fichero <em>css</em> y listo, ya lo tenemos</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/slideExample.gif\" alt=\"slideExample\"></p>\n<p>Ya tenemos nuestro slide funcionando, en este punto podríamos añadir más funcionalidad, que tuviera los puntitos típicos que te indican en que slide te encuentras y que puedes pulsar para moverte de uno a otro, o parar el slide por ejemplo. Eso lo haremos más adelante en algún post posterior ahora quería solo mostrar como podríamos hacer lo más básico de un slide, ahora lo ultimo que haremos será añadir un par de cosas al <em>js</em> para que se vaya pareciendo más a un plugin y podamos personalizarlo un poco más.</p>\n<p>Si miramos el código detenidamente y pensamos un poco que cosas podrían ser susceptibles de cambiar, podrían ser:</p>\n<ul>\n<li>El ancho básico de las imágenes para ir moviendo el slide.</li>\n<li>La clase o id del slider (podriamos tener mas de uno por ejemplo)</li>\n<li>El intervalo de transición de las imágenes.</li>\n</ul>\n<p>Estos son algunos de los cambios que se me han ocurrido con el código que tenemos actualmente podríamos tener más seguramente. Por el momento vamos a preparar esos.<br>\nPara empezar tenemos que plantearnos cuales son obligatorios y cuales podrían tener una configuración por defecto. Las imágenes deben ser obligatorias, por eso hemos puesto el control antes que nos lanzaría una alerta si no se pasa ninguna imagen, y a lo mejor el nombre del id del slide y el resto podemos tener valores por defecto si no nos lo pasan por parámetro.<br>\nPara ellos basta con usar el método <em>extend</em> de jQuery sobre el objeto que se pasa por parámetro</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n</code></pre></div>\n<p>Este método lo que hace es sobreescribir el objeto local, que sería el primero (el que está entre <em>{ }</em>) con el que se pasa por parámetro, pero solo las propiedades con el mismo nombre, es decir, no elimina el objeto por otro, es como si cambiaramos las propiedades que coincidan por las nuevas que se pasan por parámetro.<br>\nY ahora simplemente es cambiar los elementos que tenemos puestos a mano como <em>\".ninjaslider\"</em> por la propiedad correspondiente y listo, ya tendríamos preparado el código como si fuera un plugin quedando así (dejo comentado el código)</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">//Función anonima\n(function(){\n\n    $.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n            //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n            \n            //Comprobamos que nos han pasado un nombre para slider\n            if (config.slideName == \"\"){\n                alert(\"Falta el nombre o id donde estará el slider\")\n                return\n            }\n\n            //Abrimos la lista\n            var imgList = \"&#x3C;ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '&#x3C;li>&#x3C;img src=\"'+ img +'\"&#x3C;/li>';\n            })\n            //Cerramos la lista\n            imgList += \"&#x3C;/ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(config.slideName).append(imgList);\n\n            //Variable de ayuda para gestionar la posicion\n            var position = 0;\n            //Numero de imagenes para controlar\n            var images = config.images.length;\n\n            //intervalo en el que se cambia la imagen\n            var interval = setInterval(function(){\n                move();\n            }, config.timeTransition);\n\n            function move(){\n                \n                position++;\n\n                if (position >= images ){\n                    position = 0\n                }\n\n                $(config.slideName + \" ul\").animate({\n                    marginLeft: position * - config.width\n                },400);\n            }\n    }\n\n})();\n</code></pre></div>\n<p>Como véis ahora tenemos <em>config.algo</em> por todas partes. Y para usarlo nos vamos a nuestro <em>index.html</em> y añadimos las propiedades necesarias:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;script>\n\t\n\t$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n&#x3C;/script>\n</code></pre></div>\n<p>Y podríamos como he comentado, crear más sliders simplemente creando el elemento, dandole un nombre y crear un nuevo <em>ninjaShow</em></p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n    \n$.ninjaShow({\n        slideName: \".ninjaSlider2\",\n        ancho: 600,\n        timeTransition: 1200,\n        images:['img/ninja4.jpg','img/ninja1.jpg','img/ninja3.jpg'],\n});\n</code></pre></div>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/2Sliders.JPG\" alt=\"2Sliders\"></p>\n<p>Como véis ahora es muy sencillo crear sliders básicos con este código. En algún post posterior mejoraremos este slider para que tenga más funcionalidades, esto es básicamente para que veamos un poco como podemos trabajar con jQuery para hacer todo lo que queramos con el DOM.</p>\n<p>Sin mucho más nos vemos en el siguiente, un abrazooorrrr.</p>\n<!--kg-card-end: markdown-->","htmlAst":{"type":"root","children":[{"type":"comment","value":"kg-card-begin: markdown"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vamos con un ejemplo de creación de un "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Slideshow"}]},{"type":"text","value":" muy simple en jQuery. Lo primero de todo es generarnos la estructura del proyecto, cada uno que la haga como quiera, yo tengo algo así"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/folders.JPG","alt":"folders"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"En mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado al index.html al igual que "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"jQuery"}]},{"type":"text","value":". También he creado mi propio fichero de estilo "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"style.css"}]},{"type":"text","value":" y lo he añadido, quedando todo de esta manera:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n    <title>Ninja_slider</title>\n\n    <script src=\"https://code.jquery.com/jquery-3.3.1.min.js\"></script>\n\n    <link rel=\"stylesheet\" href=\"css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n    \n</head>\n<body>\n    \n</body>\n</html>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Lo siguiente es añadir donde estará el slider en el "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"body"}]},{"type":"text","value":" de la página"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<body>\n\n    <div class=\"container\" align=\"center\">\n        <h1>Ninja-Slider</h1>\n        <hr>\n\n        <div class=\"ninjaSlider\"></div>\n\n    </div>\n    \n</body>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Nuestro slider como os podéis imaginar estará en el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"div"}]},{"type":"text","value":" con la clase "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"ninjaSlider"}]},{"type":"text","value":", y esto es todo por el momento en el html, ahora vamos a nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"css"}]},{"type":"text","value":" para darle un poco de estilo y que se vea algo en la página. Le daremos un tamaño y un color de fondo para ir viendo algo."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":".ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\toverflow: hidden;\n\tmargin-bottom: 10px;\n}\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Quedando así"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/background.JPG","alt":"background"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Bien ahora vamos a crear un fichero "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"js"}]},{"type":"text","value":" donde meteremos toda la lógica de funcionamiento de nuestro slider. Tener en cuenta que la idea es hacerlo estilo plugin, es decir que este encapsulado para poder usarlo en cualquiera de nuestros proyectos."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nBien lo primero como hemos comentado es crearnos el fichero "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"js"}]},{"type":"text","value":" y meterlo en la carpeta correspondiente, lo siguiente son las imágenes para que slider tenga algo que mostrar, entonces buscamos unas cuantas imágenes, yo me he descargado 4 y las metemos en la carpeta "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"img"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Una vez que tenemos las imagenes ya podemos empezar, con el js. Creamos una función anónima que se ejecute nada más cargar el js en el HTML:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"(function(){\n    //Aqui dentro meteríamos todo el código.\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vamos a empezar por algo sencillo, que es recibir las imagenes desde el html que es desde donde nos las mandarían si pensamos que este es un plugin. Estas imágenes las incluiremos en una lista, es decir, dentro de un "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"ul"}]},{"type":"text","value":" de html."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPero antes de hacer esto, pensemos...¿cómo hacemos para pasar los datos que necesitemos a nuestro plugin?, fácil, por parámetros le pasamos un "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"objecto"}]},{"type":"text","value":" que tenga las modificaciones que queramos hacer."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPrimero creemos un método, que será el que realmente configure e inicie nuestro slider"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"(function(){\n    $.ninjaShow = function(config){\n    \n    }\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Aqui hemos añadido la función "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"ninjaShow"}]},{"type":"text","value":" a jQuery, por lo que la podemos llamar desde cualquier sitio desde el que podamos llamar a jQuery. A esta función le pasamos por parámetro un objeto "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"config"}]},{"type":"text","value":" que tendrá todos los cambios sobre la configuración por defecto que establezcamos."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nContinuemos añadiendo lógica para nuestras imagenes, suponiendo que nos indiquen cuales son las imágenes a través del objeto "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"config"}]},{"type":"text","value":", podemos tener nuestras imagenes bajo la propiedad "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"images"}]},{"type":"text","value":" dentro del objeto "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"config"}]},{"type":"text","value":". Hagamos una prueba para que veáis de lo que estoy hablando, nos vamos a nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"index.html"}]},{"type":"text","value":" y añadimos lo siguiente al final (pero siempre dentro del "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"body"}]},{"type":"text","value":")"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<!-- añadimos nuestro js al html -->\n<script src=\"js/slider.js\"></script>\n<script>\n\t//Llamamos a nuestra función pasandole un objeto con la propiedad images\n\t$.ninjaShow({\n\n        images:['img/ninja1.jpg','img/ninja2.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n\t});\n\n</script>\n</body>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y luego en nuestro fichero "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"js"}]},{"type":"text","value":", ponemos un log para ver que estamos recibiendo."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"(function(){\n\n    $.ninjaShow = function( config ){\n\n        console.log(config);\n    }\n\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si guardamos y miramos la consola al ejecutar nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"index.html"}]},{"type":"text","value":", veremos algo como lo siguiente"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/images.JPG","alt":"images"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Es decir, un objeto con la propiedad "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"images"}]},{"type":"text","value":" y dentro de esta un array con la dirección donde estan nuestras imágenes."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nEntonces ya tenemos nuestras imágenes, ahora creemos la lista con ellas."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"(function(){\n\n    $.ninjaShow = function( config ){\n                //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n\n            //Abrimos la lista\n            var imgList = \"<ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '<li><img src=\"'+ img +'\"</li>';\n            })\n            //Cerramos la lista\n            imgList += \"</ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(\".ninjaSlider\").append(imgList);\n    }\n\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si ejecutamos nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"index.html"}]},{"type":"text","value":" veremos algo similar a esto:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example.JPG","alt":"example"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ahora mismo no vemos casi nada, ¿verdad?, vamos a modificar un poco el estilo para que veamos que realmente las cosas estan donde deben estar. Nos vamos a nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"style.css"}]},{"type":"text","value":" y lo dejamos así"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":".ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\t/* overflow: hidden; */\n\tmargin-bottom: 10px;\n}\n\n.ninjaSlider ul{\n\tpadding: 0;\n\tlist-style-type: none;\n\tmargin-left: 0px;\n\tdisplay: flex;\n}\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ahora si veríamos algo aunque solo sean las imágenes"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example2.JPG","alt":"example2"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Pero si miramos el código fuente de la página deberíamos ver algo como esto:"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example3.JPG","alt":"example3"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ya tenemos nuestra lista de imágenes, y las vemos porque hemos cambiado la propiedad "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"overflow"}]},{"type":"text","value":" de css, la configuración correcta sería descomentado la línea y dejandola así"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"overflow: hidden;\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Pero la hemos comentado para explicar que es lo que vamos a hacer para ir cambiando de imágenes."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nSi os fijáis las imágenes estan configuradas en una linea horizontal, una al lado de otra, lo que haremos será ir moviendo el interior del contenedor en esa linea horizontal, modificando el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"margin-left"}]},{"type":"text","value":", es decir, supongamos que nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"margin-left"}]},{"type":"text","value":" en nuestra primera imagen es 0 y tenemos imágenes con un ancho de 600, pues lo que haríamos para movernos entre las imágenes sería ir modificando el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"margin-left"}]},{"type":"text","value":" en conjuntos de 600, es decir, la siguiente imagen tendria un margen de "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"-600"}]},{"type":"text","value":", la siguiente de "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"-1200"}]},{"type":"text","value":"... y el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"-"}]},{"type":"text","value":" es necesario porque nuestro slide se movera de izquierda a derecha y como os podréis imaginar para que funcione en este ejemplo es necesario que el ancho de las imágenes sea el mismo o muy parecido (podríamos manejar el ancho de cada "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"li"}]},{"type":"text","value":" dentro de la lista pero prefiero dejar el código más claro)."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nCreo que está más o menos explicado el concepto de lo que queremos hacer, veamos como lo hacemos"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":" //Variable de ayuda para gestionar la posicion\n var position = 0;\n //Numero de imagenes para controlar\n var images = config.images.length;\n\n //intervalo en el que se cambia la imagen\n var interval = setInterval(function(){\n   move();\n }, 1400);\n\n function move(){\n//Cada vez que pase por aqui aumentamos la posicion       \n   position++;\n\n//Si la posicion es igual o mayor que la cantidad de imagenes\n//ponemos position a 0\n   if (position >= images ){\n        position = 0\n   }\n\n//Por ultimo movemos el margen según la posición en grupos de 600\n   $(\".ninjaSlider ul\").animate({\n     marginLeft: position * -600\n   },400);\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Por último descomentamos el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"overflow:hidden"}]},{"type":"text","value":" en el fichero "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"css"}]},{"type":"text","value":" y listo, ya lo tenemos"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/slideExample.gif","alt":"slideExample"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ya tenemos nuestro slide funcionando, en este punto podríamos añadir más funcionalidad, que tuviera los puntitos típicos que te indican en que slide te encuentras y que puedes pulsar para moverte de uno a otro, o parar el slide por ejemplo. Eso lo haremos más adelante en algún post posterior ahora quería solo mostrar como podríamos hacer lo más básico de un slide, ahora lo ultimo que haremos será añadir un par de cosas al "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"js"}]},{"type":"text","value":" para que se vaya pareciendo más a un plugin y podamos personalizarlo un poco más."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si miramos el código detenidamente y pensamos un poco que cosas podrían ser susceptibles de cambiar, podrían ser:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"El ancho básico de las imágenes para ir moviendo el slide."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"La clase o id del slider (podriamos tener mas de uno por ejemplo)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"El intervalo de transición de las imágenes."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Estos son algunos de los cambios que se me han ocurrido con el código que tenemos actualmente podríamos tener más seguramente. Por el momento vamos a preparar esos."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPara empezar tenemos que plantearnos cuales son obligatorios y cuales podrían tener una configuración por defecto. Las imágenes deben ser obligatorias, por eso hemos puesto el control antes que nos lanzaría una alerta si no se pasa ninguna imagen, y a lo mejor el nombre del id del slide y el resto podemos tener valores por defecto si no nos lo pasan por parámetro."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPara ellos basta con usar el método "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"extend"}]},{"type":"text","value":" de jQuery sobre el objeto que se pasa por parámetro"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"$.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Este método lo que hace es sobreescribir el objeto local, que sería el primero (el que está entre "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"{ }"}]},{"type":"text","value":") con el que se pasa por parámetro, pero solo las propiedades con el mismo nombre, es decir, no elimina el objeto por otro, es como si cambiaramos las propiedades que coincidan por las nuevas que se pasan por parámetro."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nY ahora simplemente es cambiar los elementos que tenemos puestos a mano como "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\".ninjaslider\""}]},{"type":"text","value":" por la propiedad correspondiente y listo, ya tendríamos preparado el código como si fuera un plugin quedando así (dejo comentado el código)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"//Función anonima\n(function(){\n\n    $.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n            //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n            \n            //Comprobamos que nos han pasado un nombre para slider\n            if (config.slideName == \"\"){\n                alert(\"Falta el nombre o id donde estará el slider\")\n                return\n            }\n\n            //Abrimos la lista\n            var imgList = \"<ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '<li><img src=\"'+ img +'\"</li>';\n            })\n            //Cerramos la lista\n            imgList += \"</ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(config.slideName).append(imgList);\n\n            //Variable de ayuda para gestionar la posicion\n            var position = 0;\n            //Numero de imagenes para controlar\n            var images = config.images.length;\n\n            //intervalo en el que se cambia la imagen\n            var interval = setInterval(function(){\n                move();\n            }, config.timeTransition);\n\n            function move(){\n                \n                position++;\n\n                if (position >= images ){\n                    position = 0\n                }\n\n                $(config.slideName + \" ul\").animate({\n                    marginLeft: position * - config.width\n                },400);\n            }\n    }\n\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como véis ahora tenemos "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"config.algo"}]},{"type":"text","value":" por todas partes. Y para usarlo nos vamos a nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"index.html"}]},{"type":"text","value":" y añadimos las propiedades necesarias:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<script>\n\t\n\t$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n</script>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y podríamos como he comentado, crear más sliders simplemente creando el elemento, dandole un nombre y crear un nuevo "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"ninjaShow"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n    \n$.ninjaShow({\n        slideName: \".ninjaSlider2\",\n        ancho: 600,\n        timeTransition: 1200,\n        images:['img/ninja4.jpg','img/ninja1.jpg','img/ninja3.jpg'],\n});\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/2Sliders.JPG","alt":"2Sliders"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como véis ahora es muy sencillo crear sliders básicos con este código. En algún post posterior mejoraremos este slider para que tenga más funcionalidades, esto es básicamente para que veamos un poco como podemos trabajar con jQuery para hacer todo lo que queramos con el DOM."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Sin mucho más nos vemos en el siguiente, un abrazooorrrr."}]},{"type":"text","value":"\n"},{"type":"comment","value":"kg-card-end: markdown"}],"data":{"quirksMode":false}},"tableOfContents":[]},"featureImageSharp":{"base":"jquery-logo-1.png","publicURL":"/static/d41803bc36890b1c71051dc26c29c3ea/jquery-logo-1.png","imageMeta":{"width":665,"height":405},"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABwklEQVQoz2MQVjYkGzFgFRVRMRJVNSZOs4oRCCkbQYTE1Iz55XW5pLWA+iGmiAGRmrEolDQCCgopGcA0A1lK+iBSGSTKIamhZGhv4ugH1M8np8Mrp8MlrckuocYjq80qpsonr8srqy0CsgyoWclASM1UwMBZSNuaX05HxdghJD5r2tzFK9Zuzi6ptXALdPCJ8I9KzStvtPMOr2npNXLwySiqDoxJ55TUYAA6mNcjDYgE3JPYZfUiErMvXr4Wn1kcnpR7+tzlgqrmJavWX7p6Y+vu/Zu276lp69tz4OiUOYuAXgC6kUFEXofHJ4cruonPO4tLwXDyjPn17f1ADRs2b+/tn7pqzYbuvsmbN2/r7J3c1jlBXtN05uyFhvbenFKaQP0MYK8aCtiFs2s7WHsEz1uySkBRX0nfWt3Oj986WNEnWdAmWNw2WM0rQdQ6UMgmWNjcR1DRAOZnSNzIaQrJaUtpmYurmwgpGQJDm0fZRMDInUfHQcDQhV/fhUfLTkDfCSgioOcoAosXWDyrGAORoKI+0CdAU0ExpGwgqqAjqqgnoqArqqgLYijqAv0IZOBMJBD3wEwExz/IXCMUNv4URiQCANQ+lfCXnaknAAAAAElFTkSuQmCC","aspectRatio":1.6355140186915889,"src":"/static/d41803bc36890b1c71051dc26c29c3ea/d5882/jquery-logo-1.png","srcSet":"/static/d41803bc36890b1c71051dc26c29c3ea/847ef/jquery-logo-1.png 175w,\n/static/d41803bc36890b1c71051dc26c29c3ea/91cba/jquery-logo-1.png 350w,\n/static/d41803bc36890b1c71051dc26c29c3ea/d5882/jquery-logo-1.png 665w","srcWebp":"/static/d41803bc36890b1c71051dc26c29c3ea/20521/jquery-logo-1.webp","srcSetWebp":"/static/d41803bc36890b1c71051dc26c29c3ea/9fca7/jquery-logo-1.webp 175w,\n/static/d41803bc36890b1c71051dc26c29c3ea/37a4e/jquery-logo-1.webp 350w,\n/static/d41803bc36890b1c71051dc26c29c3ea/20521/jquery-logo-1.webp 665w","sizes":"(max-width: 665px) 100vw, 665px"}}}},"next":{"id":"Ghost__Post__5a3a19cf84f3c8302096922d","title":"MongoDB Ninja(IV): Index Ninja","slug":"mongodb-ninja-iv-index-ninja","featured":false,"feature_image":"https://jlgarcia.fulldev.ninja/assets/images/2017/12/MongoBanner.png","excerpt":"Hablemos más profundamente sobre los índices,\n\n¿Qué son los índices?\nLos índices son una forma muy eficiente de buscar los datos por un valor\nespecífico y nos evita tener que recorrer toda la colección en busca de un dato\nespecífico.\nLos índices en las bases de datos tradicionales se basan en Binary Tree Sort, y\nMongo también.\nVeamos de una forma muy resumida como funcionaría este tipo de algoritmo.\n\nBinary Tree Sort\nPara que nos hagamos una idea, es un tipo específico de ordenación que tiene\nes","custom_excerpt":null,"visibility":"public","created_at_pretty":"20 Dec 2017","published_at_pretty":"23 Dec 2017","updated_at_pretty":"19 Jan 2018","created_at":"2017-12-20T09:05:35.000+01:00","published_at":"2017-12-23T20:59:52.000+01:00","updated_at":"2018-01-19T14:06:31.000+01:00","meta_title":"Mongo DB Ninja(IV): Index Ninja","meta_description":"Veamos en profundidad todo el poder que nos ofrece MongoDB gracias a la indexación avanzada.","og_description":null,"og_image":null,"og_title":null,"twitter_description":null,"twitter_image":null,"twitter_title":null,"authors":[{"slug":"jlgarcia","url":"https://jlgarcia.fulldev.ninja/author/jlgarcia/","name":"Juan Luis Garcia Aparicio","bio":null,"cover_image":null,"profile_image":"https://jlgarcia.fulldev.ninja/assets/images/2017/12/Perfil.jpg","location":null,"website":null,"twitter":null,"facebook":null,"meta_title":null,"meta_description":null,"coverImageSharp":null,"profileImageSharp":null}],"primary_author":{"slug":"jlgarcia","url":"https://jlgarcia.fulldev.ninja/author/jlgarcia/","name":"Juan Luis Garcia Aparicio","bio":null,"cover_image":null,"profile_image":"https://jlgarcia.fulldev.ninja/assets/images/2017/12/Perfil.jpg","location":null,"website":null,"twitter":null,"facebook":null,"meta_title":null,"meta_description":null,"coverImageSharp":null,"profileImageSharp":{"base":"Perfil.jpg","publicURL":"/static/b0de6281fb28a266510b3b09b9243e5a/Perfil.jpg","imageMeta":{"width":307,"height":307},"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAUDBAb/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAGzw6zC6zHn+cLYP//EAB0QAAICAQUAAAAAAAAAAAAAAAEDAAIEEyEiIzL/2gAIAQEAAQUCifca8KgcKWVfUpkHsG5pxX//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAdEAACAgEFAAAAAAAAAAAAAAAAARARcQISIUFR/9oACAEBAAY/AhU88xkb7N06a8P/xAAcEAEAAwEAAwEAAAAAAAAAAAABABEhMUFRYXH/2gAIAQEAAT8hR2pq40aqb+xIAeXibhW9JXr8joF4TBcSNe0//9oADAMBAAIAAwAAABDzDwD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhUTFhcfD/2gAIAQEAAT8QyItrELaTlatLwU63MvEW6vUNdy4LZQDn7iVApV9VLtANdWwKkuYq4Er1VZ//2Q==","aspectRatio":1,"src":"/static/b0de6281fb28a266510b3b09b9243e5a/31709/Perfil.jpg","srcSet":"/static/b0de6281fb28a266510b3b09b9243e5a/f340b/Perfil.jpg 28w,\n/static/b0de6281fb28a266510b3b09b9243e5a/22d64/Perfil.jpg 55w,\n/static/b0de6281fb28a266510b3b09b9243e5a/31709/Perfil.jpg 110w,\n/static/b0de6281fb28a266510b3b09b9243e5a/aa249/Perfil.jpg 165w,\n/static/b0de6281fb28a266510b3b09b9243e5a/0dc33/Perfil.jpg 220w,\n/static/b0de6281fb28a266510b3b09b9243e5a/60667/Perfil.jpg 307w","srcWebp":"/static/b0de6281fb28a266510b3b09b9243e5a/8678c/Perfil.webp","srcSetWebp":"/static/b0de6281fb28a266510b3b09b9243e5a/59cda/Perfil.webp 28w,\n/static/b0de6281fb28a266510b3b09b9243e5a/7da75/Perfil.webp 55w,\n/static/b0de6281fb28a266510b3b09b9243e5a/8678c/Perfil.webp 110w,\n/static/b0de6281fb28a266510b3b09b9243e5a/f282e/Perfil.webp 165w,\n/static/b0de6281fb28a266510b3b09b9243e5a/a7b21/Perfil.webp 220w,\n/static/b0de6281fb28a266510b3b09b9243e5a/f59af/Perfil.webp 307w","sizes":"(max-width: 110px) 100vw, 110px"}}}},"primary_tag":{"slug":"mongodb","url":"https://jlgarcia.fulldev.ninja/tag/mongodb/","name":"mongodb","visibility":"public","feature_image":null,"description":"Convirtamonos en Ninjas de la mejor base de datos NoSql, MongoDB","meta_title":"MongoDD Ninja","meta_description":"Convirtamonos en Ninjas de la mejor base de datos NoSql, MongoDB, viendo desde lo básica hasta métodos de indexación avanzada.","featureImageSharp":null},"tags":[{"slug":"mongodb","url":"https://jlgarcia.fulldev.ninja/tag/mongodb/","name":"mongodb","visibility":"public","feature_image":null,"description":"Convirtamonos en Ninjas de la mejor base de datos NoSql, MongoDB","meta_title":"MongoDD Ninja","meta_description":"Convirtamonos en Ninjas de la mejor base de datos NoSql, MongoDB, viendo desde lo básica hasta métodos de indexación avanzada.","featureImageSharp":null}],"plaintext":"Hablemos más profundamente sobre los índices,\n\n¿Qué son los índices?\nLos índices son una forma muy eficiente de buscar los datos por un valor\nespecífico y nos evita tener que recorrer toda la colección en busca de un dato\nespecífico.\nLos índices en las bases de datos tradicionales se basan en Binary Tree Sort, y\nMongo también.\nVeamos de una forma muy resumida como funcionaría este tipo de algoritmo.\n\nBinary Tree Sort\nPara que nos hagamos una idea, es un tipo específico de ordenación que tiene\nesta pinta\n\n\n\nSupongamos entonces que buscamos el número 10, en la búsqueda lo que hace es\ncomprobar los números en la posición en la que está y sigue estos pasos:\n\n * ¿El número que busco es menor que 8? No.\n * ¿Está entre 8 - 12? Sí. Paso la búsqueda por la rama central.\n\nBásicamente sigue este orden:\n\n * Si es menor que el número más a la izquierda pasamos la búsqueda por la rama\n   que esté más a la izquierda.\n * Si está entre números lo mando por la rama que comprenda esos números.\n * Si el número es mayor que el número que esta más a la derecha envío la\n   búsqueda por la rama que está más a la derecha.\n\nY así con tantos niveles como tenga el árbol. Aunque en conjunto pueda ser algo\nmás complicado que esto, pero esta es la teoría fundamental de este algoritmo de\nordenación/búsqueda. Por dar un dato extra la fórmula de lo que tarda en la\nbúsqueda sería:\n\nO(log(n))\n\n\nCreo que no tengo la capacidad para explicar bien la fórmula, tenéis un montón\nde información al respecto por internet. Info\n[https://es.khanacademy.org/computing/computer-science/algorithms/asymptotic-notation/a/big-o-notation]\n\nY, ¿que hace la indexación con este algoritmo?...a parte de ordenar los datos de\nesa manera, intenta que un bloque de números entre en un sector del disco, lo\nque hace que en una sola pasada sea capaz de leer todos los números de un bloque\ny así en conjunto se consigue que la búsqueda de elementos sea realmente rápida.\n\nY después de comentar sobre BTS (Binary Tree Search) continuemos hablando de los\níndices.\n\nTipos de índices\nAhora viene el cambio de concepto, ya hemos visto en post anteriores como se\nhacian los índices, digamos, simples\n\ndb.collectionName.createIndex({nombreDelCampo: Ascendente/descendente})\n\ndb.heros.createIndex({money:1})\n\n\nEstos son los índices más habituales y son los que usan BTS realmente, pero\ntenemos otros 2 tipos de índices que no usan este mecanismo de ordenación:\n\n * Full text Index: Indices de texto libre. Nos permite buscar el texto que hay\n   en los documentos, es una búsqueda tipo Google. Al generar este tipo de\n   índice crea una base de datos grande con todos los documentos de tipo texto\n   (según los criterios que indiquemos) y a la hora de buscar nos muestras los\n   elementos por relevancia (cuanto más aparezca la palabra que buscamos en el\n   documento, más relevante se vuelve)\n * Geospatial Index: Indices de búsqueda geoespacial, que nos permiten manejar\n   datos geográficos, latitudes y longitudes pero no solo puntos si no, nos\n   permiten hacer búsquedas por zonas (en plan datos a mi alrededor o a X Km o\n   si tengo por ejemplo una línea de las de Google maps ruta/origen/destino\n   podríamos buscar lo que está cerca de la línea). Esto se vuelve muy útil para\n   aplicaciones móviles por ejemplo.\n\nFull text Index\nPrimero veamos como crear este tipo de índice:\n\ndb.nameCollection.createIndex({\"fieldName\": \"text\"})\n\ndb.heros.createIndex({ name: \"text\"})\n\n\nSi os fijáis un poco, se crean de la misma forma que habitualmente, solo que en\nlugar de indicarle la dirección del índice(ascendente/descendente con +/-1) lo\nque hacemos es indicarle que es de tipo text.\nEsto nos crea una especie de índice invertido, en el que en lugar de indexar al\nestilo \"esta palabra está en todos estos documentos\", lo que hace es darle la\nvuelta, es decir, este documento tiene estas palabras.\nSi hacemos la prueba con el campo name de nuestra colección (sé que no tiene\nsentido es un campo muy pequeño pero para hacer las pruebas nos vale) y\nmostramos los índices:\n\ndb.heros.getIndexes()\n\n\n\n\nVemos como cambia bastante la configuración de uno a otro (el de arriba sería el\nnormal que hicimos con el campo money y el de abajo sería el nuevo).\nPara hacer la prueba vamos a cambiarle el nombre a Batman por un párrafo de\ntexto como este:\n\n\"Hero can be anyone. Even a man knowing something as simple and reassuring as\nputting a coat around a young boy shoulders to let him know the world hadn't\nended.\"\n\nPara hacerlo, ya sabéis con:\n\ndb.heros.update({_id:ObjectId(\"59e1ff63c5662c1d57baf715\")},{$set: {name:\"Hero can be anyone. Even a man knowing something as simple and reassuring as putting a coat around a young boy shoulders to let him know the world hadn't ended.\"}})\n\n\nPerfecto, y ahora para buscar en este formato:\n\ndb.collectionName.find({$text: {$search: \"\"}})\n\n\nDentro del habitual find para filtrar tenemos:\n\n * $text: Con esto le indicamos que haga una búsqueda de tipo texto.\n * $search: Con search lo que hacemos es indicarle que busque por algo.\n\nHagamos alguna búsqueda para ver que pasa:\n\ndb.heros.find({$text: {$search: \"coat\"}}).pretty()\n\n\n\n\nComo véis lo encuentra sin problemas. Las búsquedas de este tipo en mongo\nparecen ser bastante inteligentes, ignoran las típicas palabras comodines como\npueden ser en ingles un \"a\" o \"the\" y se centra en el resto, también busca por\nraiz de palabra, es decir, por palabras que contengan la palabra que estamos\nbuscando (OJO tienen que ser palabras en sí y no mezclas de comodines como \nsome..), por ejemplo:\n\ndb.heros.find({$text: {$search: \"put\"}}).pretty()\n\n\n\nUn detalle es que el crea el índice en un idioma específico, por eso puede\nignorar ciertas palabras (están soportados la mayoría de los idiomas) y en el\ncaso de que no se le indicara el idioma en el índice, este seguiría siendo\nfuncional pero no tan efectivo ya que nos metería palabras innecesarias en las\nbúsquedas pero a grandes rasgos funcionaría perfectamente.\n\nComo extra comentar que las búsquedas son caseInsensitive, es decir, ignora si\nla palabra está en mayúsculas o en minúsculas y también ignora los acentos\n(ambas opciones son modificables y lo veremos más abajo)\n\nImportanto datos\nAntes de continuar necesitamos una colección con algo más de información, para\nello nos vamos a descargar una de ejemplo oficial de Mongo desde:\nAQUI\n[https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json] \n(recomiendo botón derecho- guardar como)\n\nAhora vamos a importarla, para ello nos salimos fuera de la shell de mongo y en\nla misma ruta donde hacíamos\n\nbin/mongo\n\n\nEjecutamos lo siguiente\n\n./mongoimport -c collectionTest -d databaseTest ../primer-dataset.json\n\n\nSi no esta en esa ruta, buscar el ejecutable mongoimport, y lo que hacemos es\nmeter los datos dentro de una colección nombre collectionTest que a su vez\nestará dentro de una base de datos llamada databaseTest (lo último es el fichero\nJSON que nos hemos descargado)\n\nVeamos como son los documentos que tiene esta colección, usamos:\n\ndb.collectionTest.findOne()\n\n\nY veremos algo similar a esto:\n\n\n\nTenemos coordenadas, que nos serán útiles cuando trabajemos con los índices\ngeoespaciales, y tenemos varios campos de texto como \"street\", \"name\" o\n\"cuisine\". Con esto lo que vamos a ver es como podemos gestionar nuestros\níndices para que diferencie la importancia de unos campos de texto u otros y así\npoder hacer nuestras búsquedas más eficaces. Para ello tenemos la propiedad\nweights , que mejor que explicarlo creo que es verlo en un ejemplo de uso:\n\ndb.collectionTest.createIndex({name: \"text\",\"address.street\": \"text\",cuisine: \"text\"},{weights:{name: 5, cuisine: 8, \"address.street\": 10}})\n\n\nSi os fijáis hemos creado un índice con los tres campos que he comentado antes,\ny a continuación le he puesto unos pesos específicos a cada uno, cuanto más alto\nmás importante es el campo. OJO para los subdocumentos es necesario poner\ncomillas a los nombres de los campos en este caso sería el campo address:{\nstreet}.\nHe puesto esos números pensando qué a lo hora de buscar un restaurante a no ser\nque busques un restaurante en concreto con el nombre exacto, sueles buscar una\ncalle a ver que tiene, o lo mejor buscas por un tipo de cocina, pero esto es\nsolo un ejemplo podéis usar la lógica que más os guste. En una aplicación en\nproducción esto habrá que pensarlo más detenidamente.\n\nBueno ahora vamos a probar una búsqueda, y para que sea más visual vamos a\nsolicitarle a Mongo que nos añada una puntuación a la búsqueda. Lo más fácil es\nverlo con un ejemplo:\n\ndb.collectionTest.find({$text: {$search: \"irish\"}},{score: {$meta: \"textScore\"}, name:1, cuisine:1, \"address.street\":1,_id:0}).sort({score:{$meta: \"textScore\"}})\n\n\nVayamos por orden:\n\n * $text:{$search: \"irish\"}: Esto ya lo hemos visto que es la palabra por la que\n   estamos buscando.\n * score: {$meta: \"textScore\"}: Aquí le indicamos que nos genere un campo con la\n   puntuación del texto.\n * name:1, cuisine:1, \"address.street\":1,_id:0: Si os acordáis de esto, le\n   estamos diciendo los campos que queremos ver para que no nos saque todos,\n   name, cuisine y address.street, y ademas que nos quite el _id que nos\n   molesta.\n * sort({score:{$meta: \"textScore\"}}): Por último le decimos que nos ordene los\n   resultados por la puntuación que ha recibido.\n\nAl ejecutarlo obtenemos esto:\n\n\n\nVemos que obtenemos varios resultados (si escribimos it nos saldrán más) y que\nempiezan por 12.55 de puntuación. En este caso la puntuación es debida a que\nviene en cuisine y que ocupa gran parte del campo name si os fijáis va bajando\nla puntuación siempre que el campo name tiene más palabras(y no son comodines\ncomo The o a). Como detalle haceros a la idea de que estamos filtrando unos\n25000 documentos que yo creo que no está nada mal lo que tarda en devolver los\nresultados\n\nBueno supongo que váis viendo un poco como funcionan las búsquedas de texto.\nHabréis visto que en el campo street no tenemos coincidiencias, vamos a buscar\nalgo relacionado con una calle.\n\ndb.collectionTest.find({$text: {$search: \"Jamaica\"}},{score: {$meta: \"textScore\"}, name:1, cuisine:1, \"address.street\":1,_id:0}).sort({score:{$meta: \"textScore\"}})\n\n\n\n\nVeis que sigue el mismo concepto pero esta vez con la calle y el nombre. Estas\nbúsquedas las podemos hacer tan complicadas como queramos igual que el resto que\nya vimos anteriormente.\n\nComo extra recalcar que podemos:\n\n * Modificar el lenguaje del índice con $language: Idioma, por ejemplo\n\n$languaje: Spanish\n\n\n * Indicarle que sea $caseSensitive:\n\n$caseSensitive: True (default false)\n\n\n * Soportar acentos con $diacriticSensitive:\n\n$diacriticSensitive: True (default false)\n\n\nCreo que con esto es suficiente para que se entienda como funcionan los Full\ntext index y podáis hacer los vuestros según requiera vuestra aplicación. Ahora\nempecemos con los Indices Geoespaciales\n\nGeospatial Index\nEn Mongo tenemos dos tipos de índices Geoespaciales:\n\n * 2d: Basicamente representa una cuadrícula sobre un plano, pensado para\n   superficies pequeñas, por ejemplo un campo de fútbol. También si no tenemos\n   pensado usar geoJSON o nos da igual la curvatura de la tierra.\n   \n   \n * 2dsphere: El caso contrario, es decir, situamos cosas sobre la tierra. Este\n   es el más común realmente. Esta basado en el estandar WGS 84, un estandar que\n   intenta simular en una espera a la tierra.\n   \n   \n\nLas posiciones en cualquier mapa están representadas por unas coordenadas, estas\ncoordenadas están representadas en:\n\n * Latitud: Distancia desde el Ecuador al norte y al sur. De 0 a 90 al norte, de\n   0 a -90 al sur.\n   \n   \n * Longitud: Distancia desde el Meridiano de Greenwich (seían los 0 Grados).\n   Para localizaciones al este sería de 0 a 180 y para localizaciones al oeste\n   de 0 a -180\n   \n   \n\nOJO las coordenadas en MongoDB se guardan Longitud/Latitud y en Google Maps\nLatitud/Longitud\n\nBien ya sabemos un poco de que hablamos, ahora veamos como crear un índice de\neste tipo:\n\ndb.collectionName.createIndex({campo_localización: \"2dsphere\"})\n\n\n(Como véis siempre tiene el mismo estilo la creación de índices) Por si acaso no\nlo imagináis ya, el campo de localización tiene ser unas coordenadas o datos al\nestilo GeoJSON [http://geojson.org/]\n\nVamos a crear un índice con los datos de las coordenadas que tenemos en la\ncolección que usamos antes, para ello basta con crear el índice:\n\ndb.collectionTest.createIndex({\"address.coord\": \"2dsphere\"})\n\n\nYa tenemos nuestro índice creado, ahora vamos a ver como es uno de nuestros\nelementos con coordenadas\n\ndb.collectionTest.findOne()\n\n\n\n\nY por si acaso nos vamos a ir a Google Maps a comprobar los datos, OJO recordad\nque están al revés\n\n\n\nCoincide con nuestra calle ¿no?. Bueno pues ahora vamos a probar a buscar por\ncoordenadas directamente, es decir, que me muestre quien contiene la coordenada\nque pasamos. OJO la búsqueda que vamos a realizar ahora lo que hace es buscar\ndocumentos que contengan esa coordenada, si tuvieramos una base de datos con las\ncoordenadas de los paises enteros podríamos sacar el pais al que pertenece\n\ndb.collectionTest.find(\n    {\"address.coord\":\n        {$geoIntersects:\n            {$geometry:\n                {type: \"Point\", coordinates: [-73.9549067, 40.6971322]}}}},{\"name\":1}).pretty()\n\n\nVeamos que estamos pidiendo aqui:\n\n * address.coord: Esta es fácil le indicamos donde queremos que busque.\n * geoIntersects: Es uno de los operadores para buscar con los índices\n   Geoespaciales (tener en cuenta que todo esto esta más pensado para documentos\n   tipo GeoJSON). En este caso lo que hace es buscar geometrias que se crucen\n   con la coordenada que le indiquemos. Veremos alguno más, tenemos 4 distintos. \n   Geospatial query operators\n   [https://docs.mongodb.com/manual/geospatial-queries/#geospatial-query-operators]\n * geometry: Propiedad para indicarle lo que queremos buscar.\n * type: Dentro de type le indicamos el tipo de coordenadas que le vamos a\n   buscar, siempre pensando en formato GeoJSON. En este caso hemos puesto un\n   tipo \"Punto\". Existen varios distintos, lo mejor es que los veáis en la\n   documentación: GeoJSON Objects\n   [https://docs.mongodb.com/manual/reference/geojson/]\n * coordinates y name: Básicamente son las coordenadas por las que queremos\n   buscar y lo que queremos que nos devuelva.\n\nEn este caso la búsqueda parece que es sobre una ubicación específica porque no\ntenemos coordenadas al estilo \"Polígono\", pero es más que nada para que veamos\nque funciona bien. Al ejecutarlo vemos que nos devuelve el restaurante que\nhabíamos seleccionado\n\n\n\nProbemos ahora algo con algo más de \"chicha\", vamos a buscar restaurantes que\nestén a unos 500 metros del que hemos seleccionado antes. Para ello en lugar de\nusar el operador geoIntersect vamos a usar el operador near\n\ndb.collectionTest.find({\n    \"address.coord\":{\n        $near:{\n            $geometry:{\n                type: \"Point\", \n                coordinates: [-73.9549067, 40.6971322]},\n                $maxDistance: 500\n                }\n              }\n     },{\"name\":1})\n\n\nComo propiedad extra que no habíamos visto antes tenemos $maxDistance, en la\ncual indicamos una distancia máxima en metros.\n\n\n\nHe cogido las coordenadas de los dos primeros restaurantes y si las ponemos en \nGoogle Maps (recordemos que tenemos que invertir las coordenadas ya que google\nlas guarda al revés), y esto es lo que aparece\n\n\n\nComo véis está a menos de 500 metros, por lo que podemos confirmar que realmente\nfunciona.\n\nAhora pensemos en otro escenario, las aplicaciones móviles, en la mayoria de los\ncasos cuando buscamos lo que tenemos alrededor en el mapa lo que queremos ver es\nque se vé en la pantalla, es decir, que hay en la cuadrícula del mapa que estoy\nmostrando. Esto también lo podemos hacer con MongoDB, solo tenemos que indicarle\ncuales son las coordenadas que se están mostrando actualmente.\n\ndb.collectionTest.find({\"address.coord\":{\n        $geoWithin: {\n            $geometry:{\n                type: \"Polygon\", \n                coordinates:[\n                    [[-73,40],\n                    [-75,40],\n                    [-75,42],\n                    [-73,42],\n                    [-73,40]]]}}}},\n                    {\"name\":1,\"address.coord\":1,\"_id\":0})\n\n\nSi os fijáis en la query hemos cambiado la propiedad a geoWithin, es decir, lo\nque esté dentro de esa zona, y le pasamos un polígono, con 5 coordenadas\n(imagináos que es una línea que vamos dibujando, que empieza en un punto y tiene\nque acabar en el mismo punto, por eso son 5 ;) )\nAquí tendríamos una cuadrícula que sería más o menos esta zona\n\n\n\nSi la ejecutamos veremos que nos saca un montón de coincidencias que son las que\nestán dentro de esa zona (que yo diría que son todos jejeje)\n\n\n\nSi por ejemplo contamos los elementos:\n\ndb.collectionTest.find({\"address.coord\":{$geoWithin: {$geometry:{type: \"Polygon\", coordinates:[[[-73,40],[-75,40],[-75,42],[-73,42],[-73,40]]]}}}},{\"name\":1,\"address.coord\":1,\"_id\":0}).count()\n\n\nNos salen:\n\n\n\nVamos a probar a cambiar, todas las coordenadas -73 por -74 y así comprobamos\ncomo nos filtra de verdad:\n\ndb.collectionTest.find({\"address.coord\":{$geoWithin: {$geometry:{type: \"Polygon\", coordinates:[[[-74,40],[-75,40],[-75,42],[-74,42],[-74,40]]]}}}},{\"name\":1,\"address.coord\":1,\"_id\":0})\n\n\nSi ejecutamos vemos como todos los documentos empiezan a partir de la longitud\n-74\n\n\n\nSi contamos ahora los documentos tenemos\n\n\n\nComo vemos realmente si nos está filtrando por una zona en específico. Esto es\nun ejemplo de algunas cosas típicas que podemos necesitar hacer.\n\nSubiendo de nivel\nBien ahora subamos un poco más el nivel, vamos a ver como podemos programar\ndirectamente en la consola de MongoDB, en este ejemplo que vamos a ver\nseguiremos usando los índices geoespaciales porque son los últimos que hemos\nvisto, pero tener en cuenta que se podría hacer como queráis.\n\nLo que vamos hacer va a ser recorrer todos los restaurantes que tenemos en la\ncolección de test que estamos usando y vamos a ponerles una propiedad nueva\nindicando cual es el primer restaurante que esté a menos 500 mt (si hay alguno\nclaro).\n\nUna cosa muy interesante y util en mongo es que podemos usar variables.....y\nbueno podemos usar un estilo de programación similar al de JavaScript. Entonces\npara este ejemplo vamos a usar el siguiente código (podéis copiar y pegar ;) )\n\nvar restaurants = db.collectionTest.find()\n\nwhile(restaurants.hasNext()){\n\n    var rest = restaurants.next();\n    var coords = rest.address.coord;\n    \n    if (coords != \"\"){\n        var neighbour = db.collectionTest.find({\"address.coord\":{$near:\n            {$geometry:{type: \"Point\", coordinates: coords},$maxDistance: 500}}}).skip(1).limit(1);\n    \n        if (neighbour[0] != undefined){\n            var neigh = neighbour[0];\n\n            db.collectionTest.update({\"_id\": rest._id},\n                {$set: {\n                    \"address.neighbour\": neigh.name \n                }}\n            );\n        } \n    \n    }\n}\n\n\nEn general supongo que más o menos se entiende el código (y no está con la\nintención de ser el mejor ni el más bonito solo es un ejemplo) pero por si acaso\nvoy a explicarlo paso a paso.\n\nLo primero almacenamos todos nuestros documentos en una variable, se podría\nhaber limitado la cantidad o cualquier cosa que se os ocurra pero así\ncomprobamos lo que tarda en modificarnos mas de 25000 documentos.\n\nvar restaurants = db.collectionTest.find()\n\n\nY a continuación por ejemplo haremos un bucle while recorriendo los documentos\nque tenemos almacenados en la variable restaurants\n\nwhile(restaurants.hasNext()){\n\n\nAlmacenamos el documento en cuestión y las coordenadas de que tiene ese\ndocumento:\n\nvar rest = restaurants.next();\nvar coords = rest.address.coord;\n\n\nTenemos algunos documentos que tienen la propiedad coord vacía por lo que lo\ncomprobamos\n\nif (coords != \"\"){\n\n\nLo siguiente será buscar cuál es el restaurante más cercano, sin ser el propio\nrestaurante propietario de esas coordenadas, al buscar por coordenadas nos\nidentifica el primero como el propio restaurante, por eso ignoramos el primer\nresultado. Y como solo queremos encontrar uno de \"los vecinos\" limitamos la\nbúsqueda a 1\n\n var neighbour = db.collectionTest.find({\n     \"address.coord\":{\n         $near:{\n             $geometry:{\n                 type: \"Point\",\n                 coordinates: coords}\n                 ,$maxDistance: 500}}}).skip(1).limit(1);\n\n\nComo es posible que no tengamos nungún documento(restaurante) a menos de 500\nmetros tenemos que comprobar antes de hacer nada para que el proceso continue\n\nif (neighbour[0] != undefined){\n\n\nY por último actualizamos el restaurante usando el \"_id\" añadiendole la\npropiedad \"address.neighbour\" con el nombre del restaurante vecino\n\ndb.collectionTest.update({\"_id\": rest._id},\n                {$set: {\n                    \"address.neighbour\": neigh.name \n                }}\n            );\n\n\nEl proceso tardará un rato, y una vez terminado, si buscamos algún documento\n\ndb.collectionTest.findOne({},{\"name\":1,\"address\":1,\"_id\":0})\n\n\nVeremos como nos ha añadido una nueva propiedad con el nombre de algún\nrestaurante cercano\n\n\n\nEsto es solo un pequeño ejemplo de lo que podemos hacer con MongoDB, podemos\ncomplicar las búsquedas tanto como queramos (aunque lo suyo es que una parte lo\nhiciera nuestra app no la base de datos sola ;) )\n\nEspero que con este post seais capaces de mejorar vuestros índices y hacer que\nvuestras búsquedas en vuestras bases de datos MongoDB sean mucho más eficientes.\nDe momento vamos a dejar el tema de los índices, lo próximo que veremos será el \nAggregation Framework, si no sabéis lo que es no os preocupeis lo veremos en\ndetalle. Nos veeemoosssss un abrazooorrrrrr","html":"<!--kg-card-begin: markdown--><p>Hablemos más profundamente sobre los índices,</p>\n<h2 id=\"qusonlosndices\">¿Qué son los índices?</h2>\n<p>Los índices son una forma muy eficiente de buscar los datos por un valor específico y nos evita tener que recorrer toda la colección en busca de un dato específico.<br>\nLos índices en las bases de datos tradicionales se basan en <strong>Binary Tree Sort</strong>, y Mongo también.<br>\nVeamos de una forma muy resumida como funcionaría este tipo de algoritmo.</p>\n<h2 id=\"binarytreesort\">Binary Tree Sort</h2>\n<p>Para que nos hagamos una idea, es un tipo específico de ordenación que tiene esta pinta</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-16-a-las-9.04.36.png\" alt=\"Binary Tree Sort\"></p>\n<p>Supongamos entonces que buscamos el número 10, en la búsqueda lo que hace es comprobar los números en la posición en la que está y sigue estos pasos:</p>\n<ul>\n<li>¿El número que busco es menor que 8? No.</li>\n<li>¿Está entre 8 - 12? Sí. Paso la búsqueda por la rama central.</li>\n</ul>\n<p>Básicamente sigue este orden:</p>\n<ul>\n<li>Si es menor que el número más a la izquierda pasamos la búsqueda por la rama que esté más a la izquierda.</li>\n<li>Si está entre números lo mando por la rama que comprenda esos números.</li>\n<li>Si el número es mayor que el número que esta más a la derecha envío la búsqueda por la rama que está más a la derecha.</li>\n</ul>\n<p>Y así con tantos niveles como tenga el árbol. Aunque en conjunto pueda ser algo más complicado que esto, pero esta es la teoría fundamental de este algoritmo de ordenación/búsqueda. Por dar un dato extra la fórmula de lo que tarda en la búsqueda sería:</p>\n<pre><code>O(log(n))\n</code></pre>\n<p>Creo que no tengo la capacidad para explicar bien la fórmula, tenéis un montón de información al respecto por internet. <a href=\"https://es.khanacademy.org/computing/computer-science/algorithms/asymptotic-notation/a/big-o-notation\">Info</a></p>\n<p>Y, ¿que hace la indexación con este algoritmo?...a parte de ordenar los datos de esa manera, intenta que un bloque de números entre en un sector del disco, lo que hace que en una sola pasada sea capaz de leer todos los números de un bloque y así en conjunto se consigue que la búsqueda de elementos sea realmente rápida.</p>\n<p>Y después de comentar sobre BTS (Binary Tree Search) continuemos hablando de los índices.</p>\n<h2 id=\"tiposdendices\">Tipos de índices</h2>\n<p>Ahora viene el cambio de concepto, ya hemos visto en post anteriores como se hacian los índices, digamos, <strong>simples</strong></p>\n<pre><code>db.collectionName.createIndex({nombreDelCampo: Ascendente/descendente})\n\ndb.heros.createIndex({money:1})\n</code></pre>\n<p>Estos son los índices más habituales y son los que usan <strong>BTS</strong> realmente, pero tenemos otros 2 tipos de índices que no usan este mecanismo de ordenación:</p>\n<ul>\n<li><strong>Full text Index</strong>: Indices de texto libre. Nos permite buscar el texto que hay en los documentos, es una búsqueda tipo Google. Al generar este tipo de índice crea una base de datos grande con todos los documentos de tipo texto (según los criterios que indiquemos) y a la hora de buscar nos muestras los elementos por relevancia (cuanto más aparezca la palabra que buscamos en el documento, más relevante se vuelve)</li>\n<li><strong>Geospatial Index</strong>: Indices de búsqueda geoespacial, que nos permiten manejar datos geográficos, latitudes y longitudes pero no solo puntos si no, nos permiten hacer búsquedas por zonas (en plan datos a mi alrededor o a X Km o si tengo por ejemplo una línea de las de Google maps ruta/origen/destino podríamos buscar lo que está cerca de la línea). Esto se vuelve muy útil para aplicaciones móviles por ejemplo.</li>\n</ul>\n<h2 id=\"fulltextindex\">Full text Index</h2>\n<p>Primero veamos como crear este tipo de índice:</p>\n<pre><code>db.nameCollection.createIndex({&quot;fieldName&quot;: &quot;text&quot;})\n\ndb.heros.createIndex({ name: &quot;text&quot;})\n</code></pre>\n<p>Si os fijáis un poco, se crean de la misma forma que habitualmente, solo que en lugar de indicarle la dirección del índice(ascendente/descendente con +/-1) lo que hacemos es indicarle que es de tipo <strong>text</strong>.<br>\nEsto nos crea una especie de índice invertido, en el que en lugar de indexar al estilo &quot;esta palabra está en todos estos documentos&quot;, lo que hace es darle la vuelta, es decir, este documento tiene estas palabras.<br>\nSi hacemos la prueba con el campo name de nuestra colección (sé que no tiene sentido es un campo muy pequeño pero para hacer las pruebas nos vale) y mostramos los índices:</p>\n<pre><code>db.heros.getIndexes()\n</code></pre>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-8.45.23.png\" alt=\"full text index example\"></p>\n<p>Vemos como cambia bastante la configuración de uno a otro (el de arriba sería el normal que hicimos con el campo money y el de abajo sería el nuevo).<br>\nPara hacer la prueba vamos a cambiarle el nombre a Batman por un párrafo de texto como este:</p>\n<p><em>&quot;Hero can be anyone. Even a man knowing something as simple and reassuring as putting a coat around a young boy shoulders to let him know the world hadn't ended.&quot;</em></p>\n<p>Para hacerlo, ya sabéis con:</p>\n<pre><code>db.heros.update({_id:ObjectId(&quot;59e1ff63c5662c1d57baf715&quot;)},{$set: {name:&quot;Hero can be anyone. Even a man knowing something as simple and reassuring as putting a coat around a young boy shoulders to let him know the world hadn't ended.&quot;}})\n</code></pre>\n<p>Perfecto, y ahora para buscar en este formato:</p>\n<pre><code>db.collectionName.find({$text: {$search: &quot;&quot;}})\n</code></pre>\n<p>Dentro del habitual find para filtrar tenemos:</p>\n<ul>\n<li><strong>$text</strong>: Con esto le indicamos que haga una búsqueda de tipo texto.</li>\n<li><strong>$search</strong>: Con search lo que hacemos es indicarle que busque por algo.</li>\n</ul>\n<p>Hagamos alguna búsqueda para ver que pasa:</p>\n<pre><code>db.heros.find({$text: {$search: &quot;coat&quot;}}).pretty()\n</code></pre>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-9.02.28.png\" alt=\"full text index example2\"></p>\n<p>Como véis lo encuentra sin problemas. Las búsquedas de este tipo en mongo parecen ser bastante inteligentes, ignoran las típicas palabras comodines como pueden ser en ingles un <em>&quot;a&quot;</em> o <em>&quot;the&quot;</em> y se centra en el resto, también busca por raiz de palabra, es decir, por palabras que contengan la palabra que estamos buscando (OJO tienen que ser palabras en sí y no mezclas de comodines como <em>some..</em>), por ejemplo:</p>\n<p>db.heros.find({$text: {$search: &quot;put&quot;}}).pretty()</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-9.07.04.png\" alt=\"full text index example3\"></p>\n<p>Un detalle es que el crea el índice en un idioma específico, por eso puede ignorar ciertas palabras (están soportados la mayoría de los idiomas) y en el caso de que no se le indicara el idioma en el índice, este seguiría siendo funcional pero no tan efectivo ya que nos metería palabras innecesarias en las búsquedas pero a grandes rasgos funcionaría perfectamente.</p>\n<p>Como extra comentar que las búsquedas son <strong>caseInsensitive</strong>, es decir, ignora si la palabra está en mayúsculas o en minúsculas y también ignora los acentos (ambas opciones son modificables y lo veremos más abajo)</p>\n<h3 id=\"importantodatos\">Importanto datos</h3>\n<p>Antes de continuar necesitamos una colección con algo más de información, para ello nos vamos a descargar una de ejemplo oficial de Mongo desde:<br>\n<a href=\"https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json\">AQUI</a> (recomiendo botón derecho- guardar como)</p>\n<p>Ahora vamos a importarla, para ello nos salimos fuera de la shell de mongo y en la misma ruta donde hacíamos</p>\n<pre><code>bin/mongo\n</code></pre>\n<p>Ejecutamos lo siguiente</p>\n<pre><code>./mongoimport -c collectionTest -d databaseTest ../primer-dataset.json\n</code></pre>\n<p>Si no esta en esa ruta, buscar el ejecutable <strong>mongoimport</strong>, y lo que hacemos es meter los datos dentro de una colección nombre <em>collectionTest</em> que a su vez estará dentro de una base de datos llamada <em>databaseTest</em> (lo último es el fichero JSON que nos hemos descargado)</p>\n<p>Veamos como son los documentos que tiene esta colección, usamos:</p>\n<pre><code>db.collectionTest.findOne()\n</code></pre>\n<p>Y veremos algo similar a esto:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-21.59.54.png\" alt=\"mongoImport\"></p>\n<p>Tenemos coordenadas, que nos serán útiles cuando trabajemos con los índices geoespaciales, y tenemos varios campos de texto como &quot;street&quot;, &quot;name&quot; o &quot;cuisine&quot;. Con esto lo que vamos a ver es como podemos gestionar nuestros índices para que diferencie la importancia de unos campos de texto u otros y así poder hacer nuestras búsquedas más eficaces. Para ello tenemos la propiedad weights , que mejor que explicarlo creo que es verlo en un ejemplo de uso:</p>\n<pre><code>db.collectionTest.createIndex({name: &quot;text&quot;,&quot;address.street&quot;: &quot;text&quot;,cuisine: &quot;text&quot;},{weights:{name: 5, cuisine: 8, &quot;address.street&quot;: 10}})\n</code></pre>\n<p>Si os fijáis hemos creado un índice con los tres campos que he comentado antes, y a continuación le he puesto unos pesos específicos a cada uno, cuanto más alto más importante es el campo. <strong>OJO para los subdocumentos es necesario poner comillas a los nombres de los campos en este caso sería el campo address:{ street}.</strong><br>\nHe puesto esos números pensando qué a lo hora de buscar un restaurante a no ser que busques un restaurante en concreto con el nombre exacto, sueles buscar una calle a ver que tiene, o lo mejor buscas por un tipo de cocina, pero esto es solo un ejemplo podéis usar la lógica que más os guste. En una aplicación en producción esto habrá que pensarlo más detenidamente.</p>\n<p>Bueno ahora vamos a probar una búsqueda, y para que sea más visual vamos a solicitarle a Mongo que nos añada una puntuación a la búsqueda. Lo más fácil es verlo con un ejemplo:</p>\n<pre><code>db.collectionTest.find({$text: {$search: &quot;irish&quot;}},{score: {$meta: &quot;textScore&quot;}, name:1, cuisine:1, &quot;address.street&quot;:1,_id:0}).sort({score:{$meta: &quot;textScore&quot;}})\n</code></pre>\n<p>Vayamos por orden:</p>\n<ul>\n<li><strong>$text:{$search: &quot;irish&quot;}</strong>: Esto ya lo hemos visto que es la palabra por la que estamos buscando.</li>\n<li><strong>score: {$meta: &quot;textScore&quot;}</strong>: Aquí le indicamos que nos genere un campo con la puntuación del texto.</li>\n<li><strong>name:1, cuisine:1, &quot;address.street&quot;:1,_id:0</strong>: Si os acordáis de esto, le estamos diciendo los campos que queremos ver para que no nos saque todos, name, cuisine y address.street, y ademas que nos quite el _id que nos molesta.</li>\n<li><strong>sort({score:{$meta: &quot;textScore&quot;}})</strong>: Por último le decimos que nos ordene los resultados por la puntuación que ha recibido.</li>\n</ul>\n<p>Al ejecutarlo obtenemos esto:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-20-a-las-9.26.25.png\" alt=\"Example textScore\"></p>\n<p>Vemos que obtenemos varios resultados (si escribimos it nos saldrán más) y que empiezan por 12.55 de puntuación. En este caso la puntuación es debida a que viene en cuisine y que ocupa gran parte del campo name si os fijáis va bajando la puntuación siempre que el campo name tiene más palabras(y no son comodines como The o a). Como detalle haceros a la idea de que estamos filtrando unos 25000 documentos que yo creo que no está nada mal lo que tarda en devolver los resultados</p>\n<p>Bueno supongo que váis viendo un poco como funcionan las búsquedas de texto. Habréis visto que en el campo street no tenemos coincidiencias, vamos a buscar algo relacionado con una calle.</p>\n<pre><code>db.collectionTest.find({$text: {$search: &quot;Jamaica&quot;}},{score: {$meta: &quot;textScore&quot;}, name:1, cuisine:1, &quot;address.street&quot;:1,_id:0}).sort({score:{$meta: &quot;textScore&quot;}})\n</code></pre>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-20-a-las-9.29.56.png\" alt=\"Example textScore\"></p>\n<p>Veis que sigue el mismo concepto pero esta vez con la calle y el nombre. Estas búsquedas las podemos hacer tan complicadas como queramos igual que el resto que ya vimos anteriormente.</p>\n<p>Como extra recalcar que podemos:</p>\n<ul>\n<li>Modificar el lenguaje del índice con <strong>$language: Idioma</strong>, por ejemplo</li>\n</ul>\n<pre><code>$languaje: Spanish\n</code></pre>\n<ul>\n<li>Indicarle que sea <strong>$caseSensitive</strong>:</li>\n</ul>\n<pre><code>$caseSensitive: True (default false)\n</code></pre>\n<ul>\n<li>Soportar acentos con <strong>$diacriticSensitive</strong>:</li>\n</ul>\n<pre><code>$diacriticSensitive: True (default false)\n</code></pre>\n<p>Creo que con esto es suficiente para que se entienda como funcionan los <em><strong>Full text index</strong></em> y podáis hacer los vuestros según requiera vuestra aplicación. Ahora empecemos con los <em><strong>Indices Geoespaciales</strong></em></p>\n<h2 id=\"geospatialindex\">Geospatial Index</h2>\n<p>En Mongo tenemos dos tipos de índices <em>Geoespaciales</em>:</p>\n<ul>\n<li>\n<p><strong>2d</strong>: Basicamente representa una cuadrícula sobre un plano, pensado para superficies pequeñas, por ejemplo un campo de fútbol. También si no tenemos pensado usar geoJSON o nos da igual la curvatura de la tierra.</p>\n</li>\n<li>\n<p><strong>2dsphere</strong>: El caso contrario, es decir, situamos cosas sobre la tierra. Este es el más común realmente. Esta basado en el estandar <em>WGS 84</em>, un estandar que intenta simular en una espera a la tierra.</p>\n</li>\n</ul>\n<p>Las posiciones en cualquier mapa están representadas por unas <em><strong>coordenadas</strong></em>, estas coordenadas están representadas en:</p>\n<ul>\n<li>\n<p><strong>Latitud</strong>: Distancia desde el Ecuador al norte y al sur. De 0 a 90 al norte, de 0 a -90 al sur.</p>\n</li>\n<li>\n<p><strong>Longitud</strong>: Distancia desde el <em><strong>Meridiano de Greenwich</strong></em> (seían los 0 Grados). Para localizaciones al este sería de 0 a 180 y para localizaciones al oeste de 0 a -180</p>\n</li>\n</ul>\n<p><strong>OJO las coordenadas en MongoDB se guardan Longitud/Latitud y en Google Maps Latitud/Longitud</strong></p>\n<p>Bien ya sabemos un poco de que hablamos, ahora veamos como crear un índice de este tipo:</p>\n<pre><code>db.collectionName.createIndex({campo_localización: &quot;2dsphere&quot;})\n</code></pre>\n<p>(Como véis siempre tiene el mismo estilo la creación de índices) Por si acaso no lo imagináis ya, el campo de localización tiene ser unas <strong>coordenadas</strong> o datos al estilo <strong><a href=\"http://geojson.org/\">GeoJSON</a></strong></p>\n<p>Vamos a crear un índice con los datos de las coordenadas que tenemos en la colección que usamos antes, para ello basta con crear el índice:</p>\n<pre><code>db.collectionTest.createIndex({&quot;address.coord&quot;: &quot;2dsphere&quot;})\n</code></pre>\n<p>Ya tenemos nuestro índice creado, ahora vamos a ver como es uno de nuestros elementos con coordenadas</p>\n<pre><code>db.collectionTest.findOne()\n</code></pre>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-22-a-las-21.22.08.png\" alt=\"Document Example\"></p>\n<p>Y por si acaso nos vamos a ir a Google Maps a comprobar los datos, <strong>OJO recordad que están al revés</strong></p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-22-a-las-21.23.32.png\" alt=\"Google Maps Check\"></p>\n<p>Coincide con nuestra calle ¿no?. Bueno pues ahora vamos a probar a buscar por coordenadas directamente, es decir, que me muestre quien contiene la coordenada que pasamos. <strong>OJO la búsqueda que vamos a realizar ahora lo que hace es buscar documentos que contengan esa coordenada, si tuvieramos una base de datos con las coordenadas de los paises enteros podríamos sacar el pais al que pertenece</strong></p>\n<pre><code>db.collectionTest.find(\n    {&quot;address.coord&quot;:\n        {$geoIntersects:\n            {$geometry:\n                {type: &quot;Point&quot;, coordinates: [-73.9549067, 40.6971322]}}}},{&quot;name&quot;:1}).pretty()\n</code></pre>\n<p>Veamos que estamos pidiendo aqui:</p>\n<ul>\n<li><strong>address.coord</strong>: Esta es fácil le indicamos donde queremos que busque.</li>\n<li><strong>geoIntersects</strong>: Es uno de los operadores para buscar con los índices Geoespaciales (tener en cuenta que todo esto esta más pensado para documentos tipo <em>GeoJSON</em>). En este caso lo que hace es buscar geometrias que se crucen con la coordenada que le indiquemos. Veremos alguno más, tenemos 4 distintos. <a href=\"https://docs.mongodb.com/manual/geospatial-queries/#geospatial-query-operators\">Geospatial query operators</a></li>\n<li><strong>geometry</strong>: Propiedad para indicarle lo que queremos buscar.</li>\n<li><strong>type</strong>: Dentro de type le indicamos el tipo de coordenadas que le vamos a buscar, siempre pensando en formato GeoJSON. En este caso hemos puesto un tipo &quot;Punto&quot;. Existen varios distintos, lo mejor es que los veáis en la documentación: <a href=\"https://docs.mongodb.com/manual/reference/geojson/\">GeoJSON Objects</a></li>\n<li><strong>coordinates y name</strong>: Básicamente son las coordenadas por las que queremos buscar y lo que queremos que nos devuelva.</li>\n</ul>\n<p>En este caso la búsqueda parece que es sobre una ubicación específica porque no tenemos coordenadas al estilo <em>&quot;Polígono&quot;</em>, pero es más que nada para que veamos que funciona bien. Al ejecutarlo vemos que nos devuelve el restaurante que habíamos seleccionado</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-24-a-las-9.33.48.png\" alt=\"Search Example\"></p>\n<p>Probemos ahora algo con algo más de &quot;chicha&quot;, vamos a buscar restaurantes que estén a unos 500 metros del que hemos seleccionado antes. Para ello en lugar de usar el operador <em>geoIntersect</em> vamos a usar el operador <em>near</em></p>\n<pre><code>db.collectionTest.find({\n    &quot;address.coord&quot;:{\n        $near:{\n            $geometry:{\n                type: &quot;Point&quot;, \n                coordinates: [-73.9549067, 40.6971322]},\n                $maxDistance: 500\n                }\n              }\n     },{&quot;name&quot;:1})\n</code></pre>\n<p>Como propiedad extra que no habíamos visto antes tenemos <strong>$maxDistance</strong>, en la cual indicamos una distancia máxima en metros.</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-24-a-las-9.34.27.png\" alt=\"Search Example with Metres\"></p>\n<p>He cogido las coordenadas de los dos primeros restaurantes y si las ponemos en <strong>Google Maps</strong> (recordemos que tenemos que invertir las coordenadas ya que google las guarda al revés), y esto es lo que aparece</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-9.21.20.png\" alt=\"Google Maps 500 mt example\"></p>\n<p>Como véis está a menos de 500 metros, por lo que podemos confirmar que realmente funciona.</p>\n<p>Ahora pensemos en otro escenario, las aplicaciones móviles, en la mayoria de los casos cuando buscamos lo que tenemos alrededor en el mapa lo que queremos ver es que se vé en la pantalla, es decir, que hay en la cuadrícula del mapa que estoy mostrando. Esto también lo podemos hacer con MongoDB, solo tenemos que indicarle cuales son las coordenadas que se están mostrando actualmente.</p>\n<pre><code>db.collectionTest.find({&quot;address.coord&quot;:{\n        $geoWithin: {\n            $geometry:{\n                type: &quot;Polygon&quot;, \n                coordinates:[\n                    [[-73,40],\n                    [-75,40],\n                    [-75,42],\n                    [-73,42],\n                    [-73,40]]]}}}},\n                    {&quot;name&quot;:1,&quot;address.coord&quot;:1,&quot;_id&quot;:0})\n</code></pre>\n<p>Si os fijáis en la query hemos cambiado la propiedad a <strong>geoWithin</strong>, es decir, lo que esté dentro de esa zona, y le pasamos un polígono, con 5 coordenadas (imagináos que es una línea que vamos dibujando, que empieza en un punto y tiene que acabar en el mismo punto, por eso son 5 ;) )<br>\nAquí tendríamos una cuadrícula que sería más o menos esta zona</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.02.34.png\" alt=\"Polygon Google Maps\"></p>\n<p>Si la ejecutamos veremos que nos saca un montón de coincidencias que son las que están dentro de esa zona (que yo diría que son todos jejeje)</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.06.42.png\" alt=\"Polygon Example Query\"></p>\n<p>Si por ejemplo contamos los elementos:</p>\n<pre><code>db.collectionTest.find({&quot;address.coord&quot;:{$geoWithin: {$geometry:{type: &quot;Polygon&quot;, coordinates:[[[-73,40],[-75,40],[-75,42],[-73,42],[-73,40]]]}}}},{&quot;name&quot;:1,&quot;address.coord&quot;:1,&quot;_id&quot;:0}).count()\n</code></pre>\n<p>Nos salen:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.09.53.png\" alt=\"Count Query\"></p>\n<p>Vamos a probar a cambiar, todas las coordenadas -73 por -74 y así comprobamos como nos filtra de verdad:</p>\n<pre><code>db.collectionTest.find({&quot;address.coord&quot;:{$geoWithin: {$geometry:{type: &quot;Polygon&quot;, coordinates:[[[-74,40],[-75,40],[-75,42],[-74,42],[-74,40]]]}}}},{&quot;name&quot;:1,&quot;address.coord&quot;:1,&quot;_id&quot;:0})\n</code></pre>\n<p>Si ejecutamos vemos como todos los documentos empiezan a partir de la longitud -74</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.11.24.png\" alt=\"Query with long -74\"></p>\n<p>Si contamos ahora los documentos tenemos</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.12.48.png\" alt=\"Query -74 count\"></p>\n<p>Como vemos realmente si nos está filtrando por una zona en específico. Esto es un ejemplo de algunas cosas típicas que podemos necesitar hacer.</p>\n<h2 id=\"subiendodenivel\">Subiendo de nivel</h2>\n<p>Bien ahora subamos un poco más el nivel, vamos a ver como podemos programar directamente en la consola de MongoDB, en este ejemplo que vamos a ver seguiremos usando los índices <em>geoespaciales</em> porque son los últimos que hemos visto, pero tener en cuenta que se podría hacer como queráis.</p>\n<p>Lo que vamos hacer va a ser recorrer todos los restaurantes que tenemos en la colección de test que estamos usando y vamos a ponerles una propiedad nueva indicando cual es el primer restaurante que esté a menos 500 mt (si hay alguno claro).</p>\n<p>Una cosa muy interesante y util en mongo es que podemos usar variables.....y bueno podemos usar un estilo de programación similar al de <em>JavaScript</em>. Entonces para este ejemplo vamos a usar el siguiente código (podéis copiar y pegar ;) )</p>\n<pre><code>var restaurants = db.collectionTest.find()\n\nwhile(restaurants.hasNext()){\n\n    var rest = restaurants.next();\n    var coords = rest.address.coord;\n    \n    if (coords != &quot;&quot;){\n        var neighbour = db.collectionTest.find({&quot;address.coord&quot;:{$near:\n            {$geometry:{type: &quot;Point&quot;, coordinates: coords},$maxDistance: 500}}}).skip(1).limit(1);\n    \n        if (neighbour[0] != undefined){\n            var neigh = neighbour[0];\n\n            db.collectionTest.update({&quot;_id&quot;: rest._id},\n                {$set: {\n                    &quot;address.neighbour&quot;: neigh.name \n                }}\n            );\n        } \n    \n    }\n}\n</code></pre>\n<p>En general supongo que más o menos se entiende el código (y no está con la intención de ser el mejor ni el más bonito solo es un ejemplo) pero por si acaso voy a explicarlo paso a paso.</p>\n<p>Lo primero almacenamos todos nuestros documentos en una variable, se podría haber limitado la cantidad o cualquier cosa que se os ocurra pero así comprobamos lo que tarda en modificarnos mas de 25000 documentos.</p>\n<pre><code>var restaurants = db.collectionTest.find()\n</code></pre>\n<p>Y a continuación por ejemplo haremos un bucle while recorriendo los documentos que tenemos almacenados en la variable <em>restaurants</em></p>\n<pre><code>while(restaurants.hasNext()){\n</code></pre>\n<p>Almacenamos el documento en cuestión y las coordenadas de que tiene ese documento:</p>\n<pre><code>var rest = restaurants.next();\nvar coords = rest.address.coord;\n</code></pre>\n<p>Tenemos algunos documentos que tienen la propiedad <em>coord</em> vacía por lo que lo comprobamos</p>\n<pre><code>if (coords != &quot;&quot;){\n</code></pre>\n<p>Lo siguiente será buscar cuál es el restaurante más cercano, sin ser el propio restaurante propietario de esas coordenadas, al buscar por coordenadas nos identifica el primero como el propio restaurante, por eso ignoramos el primer resultado. Y como solo queremos encontrar uno de <em>&quot;los vecinos&quot;</em> limitamos la búsqueda a 1</p>\n<pre><code> var neighbour = db.collectionTest.find({\n     &quot;address.coord&quot;:{\n         $near:{\n             $geometry:{\n                 type: &quot;Point&quot;,\n                 coordinates: coords}\n                 ,$maxDistance: 500}}}).skip(1).limit(1);\n</code></pre>\n<p>Como es posible que no tengamos nungún documento(restaurante) a menos de 500 metros tenemos que comprobar antes de hacer nada para que el proceso continue</p>\n<pre><code>if (neighbour[0] != undefined){\n</code></pre>\n<p>Y por último actualizamos el restaurante usando el <em>&quot;_id&quot;</em> añadiendole la propiedad <em>&quot;address.neighbour&quot;</em> con el nombre del restaurante vecino</p>\n<pre><code>db.collectionTest.update({&quot;_id&quot;: rest._id},\n                {$set: {\n                    &quot;address.neighbour&quot;: neigh.name \n                }}\n            );\n</code></pre>\n<p>El proceso tardará un rato, y una vez terminado, si buscamos algún documento</p>\n<pre><code>db.collectionTest.findOne({},{&quot;name&quot;:1,&quot;address&quot;:1,&quot;_id&quot;:0})\n</code></pre>\n<p>Veremos como nos ha añadido una nueva propiedad con el nombre de algún restaurante cercano</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-28-a-las-17.49.58.png\" alt=\"Neighbour restaurant's\"></p>\n<p>Esto es solo un pequeño ejemplo de lo que podemos hacer con MongoDB, podemos complicar las búsquedas tanto como queramos (aunque lo suyo es que una parte lo hiciera nuestra app no la base de datos sola ;) )</p>\n<p>Espero que con este post seais capaces de mejorar vuestros índices y hacer que vuestras búsquedas en vuestras bases de datos MongoDB sean mucho más eficientes. De momento vamos a dejar el tema de los índices, lo próximo que veremos será el <strong>Aggregation Framework</strong>, si no sabéis lo que es no os preocupeis lo veremos en detalle. Nos veeemoosssss un abrazooorrrrrr</p>\n<!--kg-card-end: markdown-->","url":"https://jlgarcia.fulldev.ninja/mongodb-ninja-iv-index-ninja/","canonical_url":null,"uuid":"45e90e60-7350-484d-8e27-36d2cb4cf334","codeinjection_foot":null,"codeinjection_head":null,"codeinjection_styles":null,"comment_id":"5a3a19cf84f3c8302096922d","reading_time":14,"send_email_when_published":false,"email_subject":null,"childHtmlRehype":{"html":"<!--kg-card-begin: markdown--><p>Hablemos más profundamente sobre los índices,</p>\n<h2 id=\"qusonlosndices\">¿Qué son los índices?</h2>\n<p>Los índices son una forma muy eficiente de buscar los datos por un valor específico y nos evita tener que recorrer toda la colección en busca de un dato específico.<br>\nLos índices en las bases de datos tradicionales se basan en <strong>Binary Tree Sort</strong>, y Mongo también.<br>\nVeamos de una forma muy resumida como funcionaría este tipo de algoritmo.</p>\n<h2 id=\"binarytreesort\">Binary Tree Sort</h2>\n<p>Para que nos hagamos una idea, es un tipo específico de ordenación que tiene esta pinta</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-16-a-las-9.04.36.png\" alt=\"Binary Tree Sort\"></p>\n<p>Supongamos entonces que buscamos el número 10, en la búsqueda lo que hace es comprobar los números en la posición en la que está y sigue estos pasos:</p>\n<ul>\n<li>¿El número que busco es menor que 8? No.</li>\n<li>¿Está entre 8 - 12? Sí. Paso la búsqueda por la rama central.</li>\n</ul>\n<p>Básicamente sigue este orden:</p>\n<ul>\n<li>Si es menor que el número más a la izquierda pasamos la búsqueda por la rama que esté más a la izquierda.</li>\n<li>Si está entre números lo mando por la rama que comprenda esos números.</li>\n<li>Si el número es mayor que el número que esta más a la derecha envío la búsqueda por la rama que está más a la derecha.</li>\n</ul>\n<p>Y así con tantos niveles como tenga el árbol. Aunque en conjunto pueda ser algo más complicado que esto, pero esta es la teoría fundamental de este algoritmo de ordenación/búsqueda. Por dar un dato extra la fórmula de lo que tarda en la búsqueda sería:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">O(log(n))\n</code></pre></div>\n<p>Creo que no tengo la capacidad para explicar bien la fórmula, tenéis un montón de información al respecto por internet. <a href=\"https://es.khanacademy.org/computing/computer-science/algorithms/asymptotic-notation/a/big-o-notation\">Info</a></p>\n<p>Y, ¿que hace la indexación con este algoritmo?...a parte de ordenar los datos de esa manera, intenta que un bloque de números entre en un sector del disco, lo que hace que en una sola pasada sea capaz de leer todos los números de un bloque y así en conjunto se consigue que la búsqueda de elementos sea realmente rápida.</p>\n<p>Y después de comentar sobre BTS (Binary Tree Search) continuemos hablando de los índices.</p>\n<h2 id=\"tiposdendices\">Tipos de índices</h2>\n<p>Ahora viene el cambio de concepto, ya hemos visto en post anteriores como se hacian los índices, digamos, <strong>simples</strong></p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionName.createIndex({nombreDelCampo: Ascendente/descendente})\n\ndb.heros.createIndex({money:1})\n</code></pre></div>\n<p>Estos son los índices más habituales y son los que usan <strong>BTS</strong> realmente, pero tenemos otros 2 tipos de índices que no usan este mecanismo de ordenación:</p>\n<ul>\n<li><strong>Full text Index</strong>: Indices de texto libre. Nos permite buscar el texto que hay en los documentos, es una búsqueda tipo Google. Al generar este tipo de índice crea una base de datos grande con todos los documentos de tipo texto (según los criterios que indiquemos) y a la hora de buscar nos muestras los elementos por relevancia (cuanto más aparezca la palabra que buscamos en el documento, más relevante se vuelve)</li>\n<li><strong>Geospatial Index</strong>: Indices de búsqueda geoespacial, que nos permiten manejar datos geográficos, latitudes y longitudes pero no solo puntos si no, nos permiten hacer búsquedas por zonas (en plan datos a mi alrededor o a X Km o si tengo por ejemplo una línea de las de Google maps ruta/origen/destino podríamos buscar lo que está cerca de la línea). Esto se vuelve muy útil para aplicaciones móviles por ejemplo.</li>\n</ul>\n<h2 id=\"fulltextindex\">Full text Index</h2>\n<p>Primero veamos como crear este tipo de índice:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.nameCollection.createIndex({\"fieldName\": \"text\"})\n\ndb.heros.createIndex({ name: \"text\"})\n</code></pre></div>\n<p>Si os fijáis un poco, se crean de la misma forma que habitualmente, solo que en lugar de indicarle la dirección del índice(ascendente/descendente con +/-1) lo que hacemos es indicarle que es de tipo <strong>text</strong>.<br>\nEsto nos crea una especie de índice invertido, en el que en lugar de indexar al estilo \"esta palabra está en todos estos documentos\", lo que hace es darle la vuelta, es decir, este documento tiene estas palabras.<br>\nSi hacemos la prueba con el campo name de nuestra colección (sé que no tiene sentido es un campo muy pequeño pero para hacer las pruebas nos vale) y mostramos los índices:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.heros.getIndexes()\n</code></pre></div>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-8.45.23.png\" alt=\"full text index example\"></p>\n<p>Vemos como cambia bastante la configuración de uno a otro (el de arriba sería el normal que hicimos con el campo money y el de abajo sería el nuevo).<br>\nPara hacer la prueba vamos a cambiarle el nombre a Batman por un párrafo de texto como este:</p>\n<p><em>\"Hero can be anyone. Even a man knowing something as simple and reassuring as putting a coat around a young boy shoulders to let him know the world hadn't ended.\"</em></p>\n<p>Para hacerlo, ya sabéis con:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.heros.update({_id:ObjectId(\"59e1ff63c5662c1d57baf715\")},{$set: {name:\"Hero can be anyone. Even a man knowing something as simple and reassuring as putting a coat around a young boy shoulders to let him know the world hadn't ended.\"}})\n</code></pre></div>\n<p>Perfecto, y ahora para buscar en este formato:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionName.find({$text: {$search: \"\"}})\n</code></pre></div>\n<p>Dentro del habitual find para filtrar tenemos:</p>\n<ul>\n<li><strong>$text</strong>: Con esto le indicamos que haga una búsqueda de tipo texto.</li>\n<li><strong>$search</strong>: Con search lo que hacemos es indicarle que busque por algo.</li>\n</ul>\n<p>Hagamos alguna búsqueda para ver que pasa:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.heros.find({$text: {$search: \"coat\"}}).pretty()\n</code></pre></div>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-9.02.28.png\" alt=\"full text index example2\"></p>\n<p>Como véis lo encuentra sin problemas. Las búsquedas de este tipo en mongo parecen ser bastante inteligentes, ignoran las típicas palabras comodines como pueden ser en ingles un <em>\"a\"</em> o <em>\"the\"</em> y se centra en el resto, también busca por raiz de palabra, es decir, por palabras que contengan la palabra que estamos buscando (OJO tienen que ser palabras en sí y no mezclas de comodines como <em>some..</em>), por ejemplo:</p>\n<p>db.heros.find({$text: {$search: \"put\"}}).pretty()</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-9.07.04.png\" alt=\"full text index example3\"></p>\n<p>Un detalle es que el crea el índice en un idioma específico, por eso puede ignorar ciertas palabras (están soportados la mayoría de los idiomas) y en el caso de que no se le indicara el idioma en el índice, este seguiría siendo funcional pero no tan efectivo ya que nos metería palabras innecesarias en las búsquedas pero a grandes rasgos funcionaría perfectamente.</p>\n<p>Como extra comentar que las búsquedas son <strong>caseInsensitive</strong>, es decir, ignora si la palabra está en mayúsculas o en minúsculas y también ignora los acentos (ambas opciones son modificables y lo veremos más abajo)</p>\n<h3 id=\"importantodatos\">Importanto datos</h3>\n<p>Antes de continuar necesitamos una colección con algo más de información, para ello nos vamos a descargar una de ejemplo oficial de Mongo desde:<br>\n<a href=\"https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json\">AQUI</a> (recomiendo botón derecho- guardar como)</p>\n<p>Ahora vamos a importarla, para ello nos salimos fuera de la shell de mongo y en la misma ruta donde hacíamos</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">bin/mongo\n</code></pre></div>\n<p>Ejecutamos lo siguiente</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">./mongoimport -c collectionTest -d databaseTest ../primer-dataset.json\n</code></pre></div>\n<p>Si no esta en esa ruta, buscar el ejecutable <strong>mongoimport</strong>, y lo que hacemos es meter los datos dentro de una colección nombre <em>collectionTest</em> que a su vez estará dentro de una base de datos llamada <em>databaseTest</em> (lo último es el fichero JSON que nos hemos descargado)</p>\n<p>Veamos como son los documentos que tiene esta colección, usamos:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.findOne()\n</code></pre></div>\n<p>Y veremos algo similar a esto:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-21.59.54.png\" alt=\"mongoImport\"></p>\n<p>Tenemos coordenadas, que nos serán útiles cuando trabajemos con los índices geoespaciales, y tenemos varios campos de texto como \"street\", \"name\" o \"cuisine\". Con esto lo que vamos a ver es como podemos gestionar nuestros índices para que diferencie la importancia de unos campos de texto u otros y así poder hacer nuestras búsquedas más eficaces. Para ello tenemos la propiedad weights , que mejor que explicarlo creo que es verlo en un ejemplo de uso:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.createIndex({name: \"text\",\"address.street\": \"text\",cuisine: \"text\"},{weights:{name: 5, cuisine: 8, \"address.street\": 10}})\n</code></pre></div>\n<p>Si os fijáis hemos creado un índice con los tres campos que he comentado antes, y a continuación le he puesto unos pesos específicos a cada uno, cuanto más alto más importante es el campo. <strong>OJO para los subdocumentos es necesario poner comillas a los nombres de los campos en este caso sería el campo address:{ street}.</strong><br>\nHe puesto esos números pensando qué a lo hora de buscar un restaurante a no ser que busques un restaurante en concreto con el nombre exacto, sueles buscar una calle a ver que tiene, o lo mejor buscas por un tipo de cocina, pero esto es solo un ejemplo podéis usar la lógica que más os guste. En una aplicación en producción esto habrá que pensarlo más detenidamente.</p>\n<p>Bueno ahora vamos a probar una búsqueda, y para que sea más visual vamos a solicitarle a Mongo que nos añada una puntuación a la búsqueda. Lo más fácil es verlo con un ejemplo:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.find({$text: {$search: \"irish\"}},{score: {$meta: \"textScore\"}, name:1, cuisine:1, \"address.street\":1,_id:0}).sort({score:{$meta: \"textScore\"}})\n</code></pre></div>\n<p>Vayamos por orden:</p>\n<ul>\n<li><strong>$text:{$search: \"irish\"}</strong>: Esto ya lo hemos visto que es la palabra por la que estamos buscando.</li>\n<li><strong>score: {$meta: \"textScore\"}</strong>: Aquí le indicamos que nos genere un campo con la puntuación del texto.</li>\n<li><strong>name:1, cuisine:1, \"address.street\":1,_id:0</strong>: Si os acordáis de esto, le estamos diciendo los campos que queremos ver para que no nos saque todos, name, cuisine y address.street, y ademas que nos quite el _id que nos molesta.</li>\n<li><strong>sort({score:{$meta: \"textScore\"}})</strong>: Por último le decimos que nos ordene los resultados por la puntuación que ha recibido.</li>\n</ul>\n<p>Al ejecutarlo obtenemos esto:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-20-a-las-9.26.25.png\" alt=\"Example textScore\"></p>\n<p>Vemos que obtenemos varios resultados (si escribimos it nos saldrán más) y que empiezan por 12.55 de puntuación. En este caso la puntuación es debida a que viene en cuisine y que ocupa gran parte del campo name si os fijáis va bajando la puntuación siempre que el campo name tiene más palabras(y no son comodines como The o a). Como detalle haceros a la idea de que estamos filtrando unos 25000 documentos que yo creo que no está nada mal lo que tarda en devolver los resultados</p>\n<p>Bueno supongo que váis viendo un poco como funcionan las búsquedas de texto. Habréis visto que en el campo street no tenemos coincidiencias, vamos a buscar algo relacionado con una calle.</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.find({$text: {$search: \"Jamaica\"}},{score: {$meta: \"textScore\"}, name:1, cuisine:1, \"address.street\":1,_id:0}).sort({score:{$meta: \"textScore\"}})\n</code></pre></div>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-20-a-las-9.29.56.png\" alt=\"Example textScore\"></p>\n<p>Veis que sigue el mismo concepto pero esta vez con la calle y el nombre. Estas búsquedas las podemos hacer tan complicadas como queramos igual que el resto que ya vimos anteriormente.</p>\n<p>Como extra recalcar que podemos:</p>\n<ul>\n<li>Modificar el lenguaje del índice con <strong>$language: Idioma</strong>, por ejemplo</li>\n</ul>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$languaje: Spanish\n</code></pre></div>\n<ul>\n<li>Indicarle que sea <strong>$caseSensitive</strong>:</li>\n</ul>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$caseSensitive: True (default false)\n</code></pre></div>\n<ul>\n<li>Soportar acentos con <strong>$diacriticSensitive</strong>:</li>\n</ul>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$diacriticSensitive: True (default false)\n</code></pre></div>\n<p>Creo que con esto es suficiente para que se entienda como funcionan los <em><strong>Full text index</strong></em> y podáis hacer los vuestros según requiera vuestra aplicación. Ahora empecemos con los <em><strong>Indices Geoespaciales</strong></em></p>\n<h2 id=\"geospatialindex\">Geospatial Index</h2>\n<p>En Mongo tenemos dos tipos de índices <em>Geoespaciales</em>:</p>\n<ul>\n<li>\n<p><strong>2d</strong>: Basicamente representa una cuadrícula sobre un plano, pensado para superficies pequeñas, por ejemplo un campo de fútbol. También si no tenemos pensado usar geoJSON o nos da igual la curvatura de la tierra.</p>\n</li>\n<li>\n<p><strong>2dsphere</strong>: El caso contrario, es decir, situamos cosas sobre la tierra. Este es el más común realmente. Esta basado en el estandar <em>WGS 84</em>, un estandar que intenta simular en una espera a la tierra.</p>\n</li>\n</ul>\n<p>Las posiciones en cualquier mapa están representadas por unas <em><strong>coordenadas</strong></em>, estas coordenadas están representadas en:</p>\n<ul>\n<li>\n<p><strong>Latitud</strong>: Distancia desde el Ecuador al norte y al sur. De 0 a 90 al norte, de 0 a -90 al sur.</p>\n</li>\n<li>\n<p><strong>Longitud</strong>: Distancia desde el <em><strong>Meridiano de Greenwich</strong></em> (seían los 0 Grados). Para localizaciones al este sería de 0 a 180 y para localizaciones al oeste de 0 a -180</p>\n</li>\n</ul>\n<p><strong>OJO las coordenadas en MongoDB se guardan Longitud/Latitud y en Google Maps Latitud/Longitud</strong></p>\n<p>Bien ya sabemos un poco de que hablamos, ahora veamos como crear un índice de este tipo:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionName.createIndex({campo_localización: \"2dsphere\"})\n</code></pre></div>\n<p>(Como véis siempre tiene el mismo estilo la creación de índices) Por si acaso no lo imagináis ya, el campo de localización tiene ser unas <strong>coordenadas</strong> o datos al estilo <strong><a href=\"http://geojson.org/\">GeoJSON</a></strong></p>\n<p>Vamos a crear un índice con los datos de las coordenadas que tenemos en la colección que usamos antes, para ello basta con crear el índice:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.createIndex({\"address.coord\": \"2dsphere\"})\n</code></pre></div>\n<p>Ya tenemos nuestro índice creado, ahora vamos a ver como es uno de nuestros elementos con coordenadas</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.findOne()\n</code></pre></div>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-22-a-las-21.22.08.png\" alt=\"Document Example\"></p>\n<p>Y por si acaso nos vamos a ir a Google Maps a comprobar los datos, <strong>OJO recordad que están al revés</strong></p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-22-a-las-21.23.32.png\" alt=\"Google Maps Check\"></p>\n<p>Coincide con nuestra calle ¿no?. Bueno pues ahora vamos a probar a buscar por coordenadas directamente, es decir, que me muestre quien contiene la coordenada que pasamos. <strong>OJO la búsqueda que vamos a realizar ahora lo que hace es buscar documentos que contengan esa coordenada, si tuvieramos una base de datos con las coordenadas de los paises enteros podríamos sacar el pais al que pertenece</strong></p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.find(\n    {\"address.coord\":\n        {$geoIntersects:\n            {$geometry:\n                {type: \"Point\", coordinates: [-73.9549067, 40.6971322]}}}},{\"name\":1}).pretty()\n</code></pre></div>\n<p>Veamos que estamos pidiendo aqui:</p>\n<ul>\n<li><strong>address.coord</strong>: Esta es fácil le indicamos donde queremos que busque.</li>\n<li><strong>geoIntersects</strong>: Es uno de los operadores para buscar con los índices Geoespaciales (tener en cuenta que todo esto esta más pensado para documentos tipo <em>GeoJSON</em>). En este caso lo que hace es buscar geometrias que se crucen con la coordenada que le indiquemos. Veremos alguno más, tenemos 4 distintos. <a href=\"https://docs.mongodb.com/manual/geospatial-queries/#geospatial-query-operators\">Geospatial query operators</a></li>\n<li><strong>geometry</strong>: Propiedad para indicarle lo que queremos buscar.</li>\n<li><strong>type</strong>: Dentro de type le indicamos el tipo de coordenadas que le vamos a buscar, siempre pensando en formato GeoJSON. En este caso hemos puesto un tipo \"Punto\". Existen varios distintos, lo mejor es que los veáis en la documentación: <a href=\"https://docs.mongodb.com/manual/reference/geojson/\">GeoJSON Objects</a></li>\n<li><strong>coordinates y name</strong>: Básicamente son las coordenadas por las que queremos buscar y lo que queremos que nos devuelva.</li>\n</ul>\n<p>En este caso la búsqueda parece que es sobre una ubicación específica porque no tenemos coordenadas al estilo <em>\"Polígono\"</em>, pero es más que nada para que veamos que funciona bien. Al ejecutarlo vemos que nos devuelve el restaurante que habíamos seleccionado</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-24-a-las-9.33.48.png\" alt=\"Search Example\"></p>\n<p>Probemos ahora algo con algo más de \"chicha\", vamos a buscar restaurantes que estén a unos 500 metros del que hemos seleccionado antes. Para ello en lugar de usar el operador <em>geoIntersect</em> vamos a usar el operador <em>near</em></p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.find({\n    \"address.coord\":{\n        $near:{\n            $geometry:{\n                type: \"Point\", \n                coordinates: [-73.9549067, 40.6971322]},\n                $maxDistance: 500\n                }\n              }\n     },{\"name\":1})\n</code></pre></div>\n<p>Como propiedad extra que no habíamos visto antes tenemos <strong>$maxDistance</strong>, en la cual indicamos una distancia máxima en metros.</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-24-a-las-9.34.27.png\" alt=\"Search Example with Metres\"></p>\n<p>He cogido las coordenadas de los dos primeros restaurantes y si las ponemos en <strong>Google Maps</strong> (recordemos que tenemos que invertir las coordenadas ya que google las guarda al revés), y esto es lo que aparece</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-9.21.20.png\" alt=\"Google Maps 500 mt example\"></p>\n<p>Como véis está a menos de 500 metros, por lo que podemos confirmar que realmente funciona.</p>\n<p>Ahora pensemos en otro escenario, las aplicaciones móviles, en la mayoria de los casos cuando buscamos lo que tenemos alrededor en el mapa lo que queremos ver es que se vé en la pantalla, es decir, que hay en la cuadrícula del mapa que estoy mostrando. Esto también lo podemos hacer con MongoDB, solo tenemos que indicarle cuales son las coordenadas que se están mostrando actualmente.</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.find({\"address.coord\":{\n        $geoWithin: {\n            $geometry:{\n                type: \"Polygon\", \n                coordinates:[\n                    [[-73,40],\n                    [-75,40],\n                    [-75,42],\n                    [-73,42],\n                    [-73,40]]]}}}},\n                    {\"name\":1,\"address.coord\":1,\"_id\":0})\n</code></pre></div>\n<p>Si os fijáis en la query hemos cambiado la propiedad a <strong>geoWithin</strong>, es decir, lo que esté dentro de esa zona, y le pasamos un polígono, con 5 coordenadas (imagináos que es una línea que vamos dibujando, que empieza en un punto y tiene que acabar en el mismo punto, por eso son 5 ;) )<br>\nAquí tendríamos una cuadrícula que sería más o menos esta zona</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.02.34.png\" alt=\"Polygon Google Maps\"></p>\n<p>Si la ejecutamos veremos que nos saca un montón de coincidencias que son las que están dentro de esa zona (que yo diría que son todos jejeje)</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.06.42.png\" alt=\"Polygon Example Query\"></p>\n<p>Si por ejemplo contamos los elementos:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.find({\"address.coord\":{$geoWithin: {$geometry:{type: \"Polygon\", coordinates:[[[-73,40],[-75,40],[-75,42],[-73,42],[-73,40]]]}}}},{\"name\":1,\"address.coord\":1,\"_id\":0}).count()\n</code></pre></div>\n<p>Nos salen:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.09.53.png\" alt=\"Count Query\"></p>\n<p>Vamos a probar a cambiar, todas las coordenadas -73 por -74 y así comprobamos como nos filtra de verdad:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.find({\"address.coord\":{$geoWithin: {$geometry:{type: \"Polygon\", coordinates:[[[-74,40],[-75,40],[-75,42],[-74,42],[-74,40]]]}}}},{\"name\":1,\"address.coord\":1,\"_id\":0})\n</code></pre></div>\n<p>Si ejecutamos vemos como todos los documentos empiezan a partir de la longitud -74</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.11.24.png\" alt=\"Query with long -74\"></p>\n<p>Si contamos ahora los documentos tenemos</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.12.48.png\" alt=\"Query -74 count\"></p>\n<p>Como vemos realmente si nos está filtrando por una zona en específico. Esto es un ejemplo de algunas cosas típicas que podemos necesitar hacer.</p>\n<h2 id=\"subiendodenivel\">Subiendo de nivel</h2>\n<p>Bien ahora subamos un poco más el nivel, vamos a ver como podemos programar directamente en la consola de MongoDB, en este ejemplo que vamos a ver seguiremos usando los índices <em>geoespaciales</em> porque son los últimos que hemos visto, pero tener en cuenta que se podría hacer como queráis.</p>\n<p>Lo que vamos hacer va a ser recorrer todos los restaurantes que tenemos en la colección de test que estamos usando y vamos a ponerles una propiedad nueva indicando cual es el primer restaurante que esté a menos 500 mt (si hay alguno claro).</p>\n<p>Una cosa muy interesante y util en mongo es que podemos usar variables.....y bueno podemos usar un estilo de programación similar al de <em>JavaScript</em>. Entonces para este ejemplo vamos a usar el siguiente código (podéis copiar y pegar ;) )</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">var restaurants = db.collectionTest.find()\n\nwhile(restaurants.hasNext()){\n\n    var rest = restaurants.next();\n    var coords = rest.address.coord;\n    \n    if (coords != \"\"){\n        var neighbour = db.collectionTest.find({\"address.coord\":{$near:\n            {$geometry:{type: \"Point\", coordinates: coords},$maxDistance: 500}}}).skip(1).limit(1);\n    \n        if (neighbour[0] != undefined){\n            var neigh = neighbour[0];\n\n            db.collectionTest.update({\"_id\": rest._id},\n                {$set: {\n                    \"address.neighbour\": neigh.name \n                }}\n            );\n        } \n    \n    }\n}\n</code></pre></div>\n<p>En general supongo que más o menos se entiende el código (y no está con la intención de ser el mejor ni el más bonito solo es un ejemplo) pero por si acaso voy a explicarlo paso a paso.</p>\n<p>Lo primero almacenamos todos nuestros documentos en una variable, se podría haber limitado la cantidad o cualquier cosa que se os ocurra pero así comprobamos lo que tarda en modificarnos mas de 25000 documentos.</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">var restaurants = db.collectionTest.find()\n</code></pre></div>\n<p>Y a continuación por ejemplo haremos un bucle while recorriendo los documentos que tenemos almacenados en la variable <em>restaurants</em></p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">while(restaurants.hasNext()){\n</code></pre></div>\n<p>Almacenamos el documento en cuestión y las coordenadas de que tiene ese documento:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">var rest = restaurants.next();\nvar coords = rest.address.coord;\n</code></pre></div>\n<p>Tenemos algunos documentos que tienen la propiedad <em>coord</em> vacía por lo que lo comprobamos</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">if (coords != \"\"){\n</code></pre></div>\n<p>Lo siguiente será buscar cuál es el restaurante más cercano, sin ser el propio restaurante propietario de esas coordenadas, al buscar por coordenadas nos identifica el primero como el propio restaurante, por eso ignoramos el primer resultado. Y como solo queremos encontrar uno de <em>\"los vecinos\"</em> limitamos la búsqueda a 1</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> var neighbour = db.collectionTest.find({\n     \"address.coord\":{\n         $near:{\n             $geometry:{\n                 type: \"Point\",\n                 coordinates: coords}\n                 ,$maxDistance: 500}}}).skip(1).limit(1);\n</code></pre></div>\n<p>Como es posible que no tengamos nungún documento(restaurante) a menos de 500 metros tenemos que comprobar antes de hacer nada para que el proceso continue</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">if (neighbour[0] != undefined){\n</code></pre></div>\n<p>Y por último actualizamos el restaurante usando el <em>\"_id\"</em> añadiendole la propiedad <em>\"address.neighbour\"</em> con el nombre del restaurante vecino</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.update({\"_id\": rest._id},\n                {$set: {\n                    \"address.neighbour\": neigh.name \n                }}\n            );\n</code></pre></div>\n<p>El proceso tardará un rato, y una vez terminado, si buscamos algún documento</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">db.collectionTest.findOne({},{\"name\":1,\"address\":1,\"_id\":0})\n</code></pre></div>\n<p>Veremos como nos ha añadido una nueva propiedad con el nombre de algún restaurante cercano</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-28-a-las-17.49.58.png\" alt=\"Neighbour restaurant&#x27;s\"></p>\n<p>Esto es solo un pequeño ejemplo de lo que podemos hacer con MongoDB, podemos complicar las búsquedas tanto como queramos (aunque lo suyo es que una parte lo hiciera nuestra app no la base de datos sola ;) )</p>\n<p>Espero que con este post seais capaces de mejorar vuestros índices y hacer que vuestras búsquedas en vuestras bases de datos MongoDB sean mucho más eficientes. De momento vamos a dejar el tema de los índices, lo próximo que veremos será el <strong>Aggregation Framework</strong>, si no sabéis lo que es no os preocupeis lo veremos en detalle. Nos veeemoosssss un abrazooorrrrrr</p>\n<!--kg-card-end: markdown-->","htmlAst":{"type":"root","children":[{"type":"comment","value":"kg-card-begin: markdown"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Hablemos más profundamente sobre los índices,"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"qusonlosndices"},"children":[{"type":"text","value":"¿Qué son los índices?"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Los índices son una forma muy eficiente de buscar los datos por un valor específico y nos evita tener que recorrer toda la colección en busca de un dato específico."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nLos índices en las bases de datos tradicionales se basan en "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Binary Tree Sort"}]},{"type":"text","value":", y Mongo también."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nVeamos de una forma muy resumida como funcionaría este tipo de algoritmo."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"binarytreesort"},"children":[{"type":"text","value":"Binary Tree Sort"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Para que nos hagamos una idea, es un tipo específico de ordenación que tiene esta pinta"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-16-a-las-9.04.36.png","alt":"Binary Tree Sort"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Supongamos entonces que buscamos el número 10, en la búsqueda lo que hace es comprobar los números en la posición en la que está y sigue estos pasos:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"¿El número que busco es menor que 8? No."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"¿Está entre 8 - 12? Sí. Paso la búsqueda por la rama central."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Básicamente sigue este orden:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Si es menor que el número más a la izquierda pasamos la búsqueda por la rama que esté más a la izquierda."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Si está entre números lo mando por la rama que comprenda esos números."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Si el número es mayor que el número que esta más a la derecha envío la búsqueda por la rama que está más a la derecha."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y así con tantos niveles como tenga el árbol. Aunque en conjunto pueda ser algo más complicado que esto, pero esta es la teoría fundamental de este algoritmo de ordenación/búsqueda. Por dar un dato extra la fórmula de lo que tarda en la búsqueda sería:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"O(log(n))\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Creo que no tengo la capacidad para explicar bien la fórmula, tenéis un montón de información al respecto por internet. "},{"type":"element","tagName":"a","properties":{"href":"https://es.khanacademy.org/computing/computer-science/algorithms/asymptotic-notation/a/big-o-notation"},"children":[{"type":"text","value":"Info"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y, ¿que hace la indexación con este algoritmo?...a parte de ordenar los datos de esa manera, intenta que un bloque de números entre en un sector del disco, lo que hace que en una sola pasada sea capaz de leer todos los números de un bloque y así en conjunto se consigue que la búsqueda de elementos sea realmente rápida."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y después de comentar sobre BTS (Binary Tree Search) continuemos hablando de los índices."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"tiposdendices"},"children":[{"type":"text","value":"Tipos de índices"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ahora viene el cambio de concepto, ya hemos visto en post anteriores como se hacian los índices, digamos, "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"simples"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionName.createIndex({nombreDelCampo: Ascendente/descendente})\n\ndb.heros.createIndex({money:1})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Estos son los índices más habituales y son los que usan "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"BTS"}]},{"type":"text","value":" realmente, pero tenemos otros 2 tipos de índices que no usan este mecanismo de ordenación:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Full text Index"}]},{"type":"text","value":": Indices de texto libre. Nos permite buscar el texto que hay en los documentos, es una búsqueda tipo Google. Al generar este tipo de índice crea una base de datos grande con todos los documentos de tipo texto (según los criterios que indiquemos) y a la hora de buscar nos muestras los elementos por relevancia (cuanto más aparezca la palabra que buscamos en el documento, más relevante se vuelve)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Geospatial Index"}]},{"type":"text","value":": Indices de búsqueda geoespacial, que nos permiten manejar datos geográficos, latitudes y longitudes pero no solo puntos si no, nos permiten hacer búsquedas por zonas (en plan datos a mi alrededor o a X Km o si tengo por ejemplo una línea de las de Google maps ruta/origen/destino podríamos buscar lo que está cerca de la línea). Esto se vuelve muy útil para aplicaciones móviles por ejemplo."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"fulltextindex"},"children":[{"type":"text","value":"Full text Index"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Primero veamos como crear este tipo de índice:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.nameCollection.createIndex({\"fieldName\": \"text\"})\n\ndb.heros.createIndex({ name: \"text\"})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si os fijáis un poco, se crean de la misma forma que habitualmente, solo que en lugar de indicarle la dirección del índice(ascendente/descendente con +/-1) lo que hacemos es indicarle que es de tipo "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"text"}]},{"type":"text","value":"."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nEsto nos crea una especie de índice invertido, en el que en lugar de indexar al estilo \"esta palabra está en todos estos documentos\", lo que hace es darle la vuelta, es decir, este documento tiene estas palabras."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nSi hacemos la prueba con el campo name de nuestra colección (sé que no tiene sentido es un campo muy pequeño pero para hacer las pruebas nos vale) y mostramos los índices:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.heros.getIndexes()\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-8.45.23.png","alt":"full text index example"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vemos como cambia bastante la configuración de uno a otro (el de arriba sería el normal que hicimos con el campo money y el de abajo sería el nuevo)."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPara hacer la prueba vamos a cambiarle el nombre a Batman por un párrafo de texto como este:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\"Hero can be anyone. Even a man knowing something as simple and reassuring as putting a coat around a young boy shoulders to let him know the world hadn't ended.\""}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Para hacerlo, ya sabéis con:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.heros.update({_id:ObjectId(\"59e1ff63c5662c1d57baf715\")},{$set: {name:\"Hero can be anyone. Even a man knowing something as simple and reassuring as putting a coat around a young boy shoulders to let him know the world hadn't ended.\"}})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Perfecto, y ahora para buscar en este formato:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionName.find({$text: {$search: \"\"}})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Dentro del habitual find para filtrar tenemos:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"$text"}]},{"type":"text","value":": Con esto le indicamos que haga una búsqueda de tipo texto."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"$search"}]},{"type":"text","value":": Con search lo que hacemos es indicarle que busque por algo."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Hagamos alguna búsqueda para ver que pasa:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.heros.find({$text: {$search: \"coat\"}}).pretty()\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-9.02.28.png","alt":"full text index example2"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como véis lo encuentra sin problemas. Las búsquedas de este tipo en mongo parecen ser bastante inteligentes, ignoran las típicas palabras comodines como pueden ser en ingles un "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\"a\""}]},{"type":"text","value":" o "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\"the\""}]},{"type":"text","value":" y se centra en el resto, también busca por raiz de palabra, es decir, por palabras que contengan la palabra que estamos buscando (OJO tienen que ser palabras en sí y no mezclas de comodines como "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"some.."}]},{"type":"text","value":"), por ejemplo:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"db.heros.find({$text: {$search: \"put\"}}).pretty()"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-9.07.04.png","alt":"full text index example3"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Un detalle es que el crea el índice en un idioma específico, por eso puede ignorar ciertas palabras (están soportados la mayoría de los idiomas) y en el caso de que no se le indicara el idioma en el índice, este seguiría siendo funcional pero no tan efectivo ya que nos metería palabras innecesarias en las búsquedas pero a grandes rasgos funcionaría perfectamente."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como extra comentar que las búsquedas son "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"caseInsensitive"}]},{"type":"text","value":", es decir, ignora si la palabra está en mayúsculas o en minúsculas y también ignora los acentos (ambas opciones son modificables y lo veremos más abajo)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"importantodatos"},"children":[{"type":"text","value":"Importanto datos"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Antes de continuar necesitamos una colección con algo más de información, para ello nos vamos a descargar una de ejemplo oficial de Mongo desde:"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"a","properties":{"href":"https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json"},"children":[{"type":"text","value":"AQUI"}]},{"type":"text","value":" (recomiendo botón derecho- guardar como)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ahora vamos a importarla, para ello nos salimos fuera de la shell de mongo y en la misma ruta donde hacíamos"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"bin/mongo\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ejecutamos lo siguiente"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"./mongoimport -c collectionTest -d databaseTest ../primer-dataset.json\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si no esta en esa ruta, buscar el ejecutable "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"mongoimport"}]},{"type":"text","value":", y lo que hacemos es meter los datos dentro de una colección nombre "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"collectionTest"}]},{"type":"text","value":" que a su vez estará dentro de una base de datos llamada "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"databaseTest"}]},{"type":"text","value":" (lo último es el fichero JSON que nos hemos descargado)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Veamos como son los documentos que tiene esta colección, usamos:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.findOne()\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y veremos algo similar a esto:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-17-a-las-21.59.54.png","alt":"mongoImport"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Tenemos coordenadas, que nos serán útiles cuando trabajemos con los índices geoespaciales, y tenemos varios campos de texto como \"street\", \"name\" o \"cuisine\". Con esto lo que vamos a ver es como podemos gestionar nuestros índices para que diferencie la importancia de unos campos de texto u otros y así poder hacer nuestras búsquedas más eficaces. Para ello tenemos la propiedad weights , que mejor que explicarlo creo que es verlo en un ejemplo de uso:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.createIndex({name: \"text\",\"address.street\": \"text\",cuisine: \"text\"},{weights:{name: 5, cuisine: 8, \"address.street\": 10}})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si os fijáis hemos creado un índice con los tres campos que he comentado antes, y a continuación le he puesto unos pesos específicos a cada uno, cuanto más alto más importante es el campo. "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"OJO para los subdocumentos es necesario poner comillas a los nombres de los campos en este caso sería el campo address:{ street}."}]},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nHe puesto esos números pensando qué a lo hora de buscar un restaurante a no ser que busques un restaurante en concreto con el nombre exacto, sueles buscar una calle a ver que tiene, o lo mejor buscas por un tipo de cocina, pero esto es solo un ejemplo podéis usar la lógica que más os guste. En una aplicación en producción esto habrá que pensarlo más detenidamente."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Bueno ahora vamos a probar una búsqueda, y para que sea más visual vamos a solicitarle a Mongo que nos añada una puntuación a la búsqueda. Lo más fácil es verlo con un ejemplo:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.find({$text: {$search: \"irish\"}},{score: {$meta: \"textScore\"}, name:1, cuisine:1, \"address.street\":1,_id:0}).sort({score:{$meta: \"textScore\"}})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vayamos por orden:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"$text:{$search: \"irish\"}"}]},{"type":"text","value":": Esto ya lo hemos visto que es la palabra por la que estamos buscando."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"score: {$meta: \"textScore\"}"}]},{"type":"text","value":": Aquí le indicamos que nos genere un campo con la puntuación del texto."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"name:1, cuisine:1, \"address.street\":1,_id:0"}]},{"type":"text","value":": Si os acordáis de esto, le estamos diciendo los campos que queremos ver para que no nos saque todos, name, cuisine y address.street, y ademas que nos quite el _id que nos molesta."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"sort({score:{$meta: \"textScore\"}})"}]},{"type":"text","value":": Por último le decimos que nos ordene los resultados por la puntuación que ha recibido."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Al ejecutarlo obtenemos esto:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-20-a-las-9.26.25.png","alt":"Example textScore"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vemos que obtenemos varios resultados (si escribimos it nos saldrán más) y que empiezan por 12.55 de puntuación. En este caso la puntuación es debida a que viene en cuisine y que ocupa gran parte del campo name si os fijáis va bajando la puntuación siempre que el campo name tiene más palabras(y no son comodines como The o a). Como detalle haceros a la idea de que estamos filtrando unos 25000 documentos que yo creo que no está nada mal lo que tarda en devolver los resultados"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Bueno supongo que váis viendo un poco como funcionan las búsquedas de texto. Habréis visto que en el campo street no tenemos coincidiencias, vamos a buscar algo relacionado con una calle."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.find({$text: {$search: \"Jamaica\"}},{score: {$meta: \"textScore\"}, name:1, cuisine:1, \"address.street\":1,_id:0}).sort({score:{$meta: \"textScore\"}})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-20-a-las-9.29.56.png","alt":"Example textScore"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Veis que sigue el mismo concepto pero esta vez con la calle y el nombre. Estas búsquedas las podemos hacer tan complicadas como queramos igual que el resto que ya vimos anteriormente."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como extra recalcar que podemos:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Modificar el lenguaje del índice con "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"$language: Idioma"}]},{"type":"text","value":", por ejemplo"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"$languaje: Spanish\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Indicarle que sea "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"$caseSensitive"}]},{"type":"text","value":":"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"$caseSensitive: True (default false)\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Soportar acentos con "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"$diacriticSensitive"}]},{"type":"text","value":":"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"$diacriticSensitive: True (default false)\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Creo que con esto es suficiente para que se entienda como funcionan los "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Full text index"}]}]},{"type":"text","value":" y podáis hacer los vuestros según requiera vuestra aplicación. Ahora empecemos con los "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Indices Geoespaciales"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"geospatialindex"},"children":[{"type":"text","value":"Geospatial Index"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"En Mongo tenemos dos tipos de índices "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"Geoespaciales"}]},{"type":"text","value":":"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"2d"}]},{"type":"text","value":": Basicamente representa una cuadrícula sobre un plano, pensado para superficies pequeñas, por ejemplo un campo de fútbol. También si no tenemos pensado usar geoJSON o nos da igual la curvatura de la tierra."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"2dsphere"}]},{"type":"text","value":": El caso contrario, es decir, situamos cosas sobre la tierra. Este es el más común realmente. Esta basado en el estandar "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"WGS 84"}]},{"type":"text","value":", un estandar que intenta simular en una espera a la tierra."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Las posiciones en cualquier mapa están representadas por unas "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"coordenadas"}]}]},{"type":"text","value":", estas coordenadas están representadas en:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Latitud"}]},{"type":"text","value":": Distancia desde el Ecuador al norte y al sur. De 0 a 90 al norte, de 0 a -90 al sur."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Longitud"}]},{"type":"text","value":": Distancia desde el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Meridiano de Greenwich"}]}]},{"type":"text","value":" (seían los 0 Grados). Para localizaciones al este sería de 0 a 180 y para localizaciones al oeste de 0 a -180"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"OJO las coordenadas en MongoDB se guardan Longitud/Latitud y en Google Maps Latitud/Longitud"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Bien ya sabemos un poco de que hablamos, ahora veamos como crear un índice de este tipo:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionName.createIndex({campo_localización: \"2dsphere\"})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"(Como véis siempre tiene el mismo estilo la creación de índices) Por si acaso no lo imagináis ya, el campo de localización tiene ser unas "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"coordenadas"}]},{"type":"text","value":" o datos al estilo "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"http://geojson.org/"},"children":[{"type":"text","value":"GeoJSON"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vamos a crear un índice con los datos de las coordenadas que tenemos en la colección que usamos antes, para ello basta con crear el índice:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.createIndex({\"address.coord\": \"2dsphere\"})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ya tenemos nuestro índice creado, ahora vamos a ver como es uno de nuestros elementos con coordenadas"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.findOne()\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-22-a-las-21.22.08.png","alt":"Document Example"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y por si acaso nos vamos a ir a Google Maps a comprobar los datos, "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"OJO recordad que están al revés"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-22-a-las-21.23.32.png","alt":"Google Maps Check"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Coincide con nuestra calle ¿no?. Bueno pues ahora vamos a probar a buscar por coordenadas directamente, es decir, que me muestre quien contiene la coordenada que pasamos. "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"OJO la búsqueda que vamos a realizar ahora lo que hace es buscar documentos que contengan esa coordenada, si tuvieramos una base de datos con las coordenadas de los paises enteros podríamos sacar el pais al que pertenece"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.find(\n    {\"address.coord\":\n        {$geoIntersects:\n            {$geometry:\n                {type: \"Point\", coordinates: [-73.9549067, 40.6971322]}}}},{\"name\":1}).pretty()\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Veamos que estamos pidiendo aqui:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"address.coord"}]},{"type":"text","value":": Esta es fácil le indicamos donde queremos que busque."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"geoIntersects"}]},{"type":"text","value":": Es uno de los operadores para buscar con los índices Geoespaciales (tener en cuenta que todo esto esta más pensado para documentos tipo "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"GeoJSON"}]},{"type":"text","value":"). En este caso lo que hace es buscar geometrias que se crucen con la coordenada que le indiquemos. Veremos alguno más, tenemos 4 distintos. "},{"type":"element","tagName":"a","properties":{"href":"https://docs.mongodb.com/manual/geospatial-queries/#geospatial-query-operators"},"children":[{"type":"text","value":"Geospatial query operators"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"geometry"}]},{"type":"text","value":": Propiedad para indicarle lo que queremos buscar."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"type"}]},{"type":"text","value":": Dentro de type le indicamos el tipo de coordenadas que le vamos a buscar, siempre pensando en formato GeoJSON. En este caso hemos puesto un tipo \"Punto\". Existen varios distintos, lo mejor es que los veáis en la documentación: "},{"type":"element","tagName":"a","properties":{"href":"https://docs.mongodb.com/manual/reference/geojson/"},"children":[{"type":"text","value":"GeoJSON Objects"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"coordinates y name"}]},{"type":"text","value":": Básicamente son las coordenadas por las que queremos buscar y lo que queremos que nos devuelva."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"En este caso la búsqueda parece que es sobre una ubicación específica porque no tenemos coordenadas al estilo "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\"Polígono\""}]},{"type":"text","value":", pero es más que nada para que veamos que funciona bien. Al ejecutarlo vemos que nos devuelve el restaurante que habíamos seleccionado"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-24-a-las-9.33.48.png","alt":"Search Example"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Probemos ahora algo con algo más de \"chicha\", vamos a buscar restaurantes que estén a unos 500 metros del que hemos seleccionado antes. Para ello en lugar de usar el operador "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"geoIntersect"}]},{"type":"text","value":" vamos a usar el operador "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"near"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.find({\n    \"address.coord\":{\n        $near:{\n            $geometry:{\n                type: \"Point\", \n                coordinates: [-73.9549067, 40.6971322]},\n                $maxDistance: 500\n                }\n              }\n     },{\"name\":1})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como propiedad extra que no habíamos visto antes tenemos "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"$maxDistance"}]},{"type":"text","value":", en la cual indicamos una distancia máxima en metros."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-24-a-las-9.34.27.png","alt":"Search Example with Metres"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"He cogido las coordenadas de los dos primeros restaurantes y si las ponemos en "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Google Maps"}]},{"type":"text","value":" (recordemos que tenemos que invertir las coordenadas ya que google las guarda al revés), y esto es lo que aparece"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-9.21.20.png","alt":"Google Maps 500 mt example"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como véis está a menos de 500 metros, por lo que podemos confirmar que realmente funciona."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ahora pensemos en otro escenario, las aplicaciones móviles, en la mayoria de los casos cuando buscamos lo que tenemos alrededor en el mapa lo que queremos ver es que se vé en la pantalla, es decir, que hay en la cuadrícula del mapa que estoy mostrando. Esto también lo podemos hacer con MongoDB, solo tenemos que indicarle cuales son las coordenadas que se están mostrando actualmente."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.find({\"address.coord\":{\n        $geoWithin: {\n            $geometry:{\n                type: \"Polygon\", \n                coordinates:[\n                    [[-73,40],\n                    [-75,40],\n                    [-75,42],\n                    [-73,42],\n                    [-73,40]]]}}}},\n                    {\"name\":1,\"address.coord\":1,\"_id\":0})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si os fijáis en la query hemos cambiado la propiedad a "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"geoWithin"}]},{"type":"text","value":", es decir, lo que esté dentro de esa zona, y le pasamos un polígono, con 5 coordenadas (imagináos que es una línea que vamos dibujando, que empieza en un punto y tiene que acabar en el mismo punto, por eso son 5 ;) )"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nAquí tendríamos una cuadrícula que sería más o menos esta zona"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.02.34.png","alt":"Polygon Google Maps"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si la ejecutamos veremos que nos saca un montón de coincidencias que son las que están dentro de esa zona (que yo diría que son todos jejeje)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.06.42.png","alt":"Polygon Example Query"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si por ejemplo contamos los elementos:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.find({\"address.coord\":{$geoWithin: {$geometry:{type: \"Polygon\", coordinates:[[[-73,40],[-75,40],[-75,42],[-73,42],[-73,40]]]}}}},{\"name\":1,\"address.coord\":1,\"_id\":0}).count()\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Nos salen:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.09.53.png","alt":"Count Query"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vamos a probar a cambiar, todas las coordenadas -73 por -74 y así comprobamos como nos filtra de verdad:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.find({\"address.coord\":{$geoWithin: {$geometry:{type: \"Polygon\", coordinates:[[[-74,40],[-75,40],[-75,42],[-74,42],[-74,40]]]}}}},{\"name\":1,\"address.coord\":1,\"_id\":0})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si ejecutamos vemos como todos los documentos empiezan a partir de la longitud -74"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.11.24.png","alt":"Query with long -74"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si contamos ahora los documentos tenemos"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-25-a-las-10.12.48.png","alt":"Query -74 count"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como vemos realmente si nos está filtrando por una zona en específico. Esto es un ejemplo de algunas cosas típicas que podemos necesitar hacer."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"subiendodenivel"},"children":[{"type":"text","value":"Subiendo de nivel"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Bien ahora subamos un poco más el nivel, vamos a ver como podemos programar directamente en la consola de MongoDB, en este ejemplo que vamos a ver seguiremos usando los índices "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"geoespaciales"}]},{"type":"text","value":" porque son los últimos que hemos visto, pero tener en cuenta que se podría hacer como queráis."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Lo que vamos hacer va a ser recorrer todos los restaurantes que tenemos en la colección de test que estamos usando y vamos a ponerles una propiedad nueva indicando cual es el primer restaurante que esté a menos 500 mt (si hay alguno claro)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Una cosa muy interesante y util en mongo es que podemos usar variables.....y bueno podemos usar un estilo de programación similar al de "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"JavaScript"}]},{"type":"text","value":". Entonces para este ejemplo vamos a usar el siguiente código (podéis copiar y pegar ;) )"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"var restaurants = db.collectionTest.find()\n\nwhile(restaurants.hasNext()){\n\n    var rest = restaurants.next();\n    var coords = rest.address.coord;\n    \n    if (coords != \"\"){\n        var neighbour = db.collectionTest.find({\"address.coord\":{$near:\n            {$geometry:{type: \"Point\", coordinates: coords},$maxDistance: 500}}}).skip(1).limit(1);\n    \n        if (neighbour[0] != undefined){\n            var neigh = neighbour[0];\n\n            db.collectionTest.update({\"_id\": rest._id},\n                {$set: {\n                    \"address.neighbour\": neigh.name \n                }}\n            );\n        } \n    \n    }\n}\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"En general supongo que más o menos se entiende el código (y no está con la intención de ser el mejor ni el más bonito solo es un ejemplo) pero por si acaso voy a explicarlo paso a paso."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Lo primero almacenamos todos nuestros documentos en una variable, se podría haber limitado la cantidad o cualquier cosa que se os ocurra pero así comprobamos lo que tarda en modificarnos mas de 25000 documentos."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"var restaurants = db.collectionTest.find()\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y a continuación por ejemplo haremos un bucle while recorriendo los documentos que tenemos almacenados en la variable "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"restaurants"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"while(restaurants.hasNext()){\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Almacenamos el documento en cuestión y las coordenadas de que tiene ese documento:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"var rest = restaurants.next();\nvar coords = rest.address.coord;\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Tenemos algunos documentos que tienen la propiedad "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"coord"}]},{"type":"text","value":" vacía por lo que lo comprobamos"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"if (coords != \"\"){\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Lo siguiente será buscar cuál es el restaurante más cercano, sin ser el propio restaurante propietario de esas coordenadas, al buscar por coordenadas nos identifica el primero como el propio restaurante, por eso ignoramos el primer resultado. Y como solo queremos encontrar uno de "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\"los vecinos\""}]},{"type":"text","value":" limitamos la búsqueda a 1"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":" var neighbour = db.collectionTest.find({\n     \"address.coord\":{\n         $near:{\n             $geometry:{\n                 type: \"Point\",\n                 coordinates: coords}\n                 ,$maxDistance: 500}}}).skip(1).limit(1);\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como es posible que no tengamos nungún documento(restaurante) a menos de 500 metros tenemos que comprobar antes de hacer nada para que el proceso continue"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"if (neighbour[0] != undefined){\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y por último actualizamos el restaurante usando el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\"_id\""}]},{"type":"text","value":" añadiendole la propiedad "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\"address.neighbour\""}]},{"type":"text","value":" con el nombre del restaurante vecino"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.update({\"_id\": rest._id},\n                {$set: {\n                    \"address.neighbour\": neigh.name \n                }}\n            );\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"El proceso tardará un rato, y una vez terminado, si buscamos algún documento"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"db.collectionTest.findOne({},{\"name\":1,\"address\":1,\"_id\":0})\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Veremos como nos ha añadido una nueva propiedad con el nombre de algún restaurante cercano"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2017/10/Captura-de-pantalla-2017-10-28-a-las-17.49.58.png","alt":"Neighbour restaurant's"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Esto es solo un pequeño ejemplo de lo que podemos hacer con MongoDB, podemos complicar las búsquedas tanto como queramos (aunque lo suyo es que una parte lo hiciera nuestra app no la base de datos sola ;) )"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Espero que con este post seais capaces de mejorar vuestros índices y hacer que vuestras búsquedas en vuestras bases de datos MongoDB sean mucho más eficientes. De momento vamos a dejar el tema de los índices, lo próximo que veremos será el "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Aggregation Framework"}]},{"type":"text","value":", si no sabéis lo que es no os preocupeis lo veremos en detalle. Nos veeemoosssss un abrazooorrrrrr"}]},{"type":"text","value":"\n"},{"type":"comment","value":"kg-card-end: markdown"}],"data":{"quirksMode":false}},"tableOfContents":[{"id":"qusonlosndices","heading":"¿Qué son los índices?"},{"id":"binarytreesort","heading":"Binary Tree Sort"},{"id":"tiposdendices","heading":"Tipos de índices"},{"id":"fulltextindex","heading":"Full text Index","items":[{"id":"importantodatos","heading":"Importanto datos"}]},{"id":"geospatialindex","heading":"Geospatial Index"},{"id":"subiendodenivel","heading":"Subiendo de nivel"}]},"featureImageSharp":{"base":"MongoBanner.png","publicURL":"/static/e2d851a4e8d17762251ac236e48b5140/MongoBanner.png","imageMeta":{"width":510,"height":261},"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAACEElEQVQoz11STW8SURSdn+SiBoRhGOaTYSiCtR98t0hbhaIFagrWSimVFqqpFbdN9C+4Nd2Ybk3/iEk3GONi3vHdV1DSxcl9c+e9c8+590pWNDQyDBmmKTN+ngKzMCfRnoHI2zKbwR+OJ5LJyRIlDc6KwgRxVJ5eFpiS6lYQqh74hztFvUn8KRlc2fKFzZyDIMwIr8QJdTMgyAxOQtD4dyqpYTXvopCNoZhzoRkPCEwz/IzOtqN49EYiq+5Igb7vY83nVZx9OMGrvSZ6vdcYDA7R7bbRO+rg+HAbrRdL+NjfxPuDNWSySTx6HMfCYhyJpM38gXskxJPIZiwdZs5iGNnMAjY2Cyiv51BcXUalWsL5+RDb9WfI5xIoZKLIpR1kV2w8TFm4vPyG8XiMm5sb7LYbLBSe4wqjsmdZ3L8VYhHDL3oS0f3CcjQWFhA5bks3ZW4/CCXi48pcXF19x1ZtHf3jLru+/oF4wvgtWXbIo77ZMYUp6hxa7TpOuNX9zi63P8CbTgv1RkWcSbmq+UQBx42gsVPD5y8XGH06Y08rJd7TwC+JK6EJMd5UUsbWSmkM373FKUe9WeGxj+HpEbq9Pey8rAn1t3dpKAGUN/IsX1yi/GQo/1eDdolXVoXNZMrmUYU7r6G6VRbTduf1mZW6jYp6n1QLQfSPCL9Ods6bkhKmq0MgVXSZSO/sJxGxmXf9v1BbiUoJyKuGAAAAAElFTkSuQmCC","aspectRatio":1.9444444444444444,"src":"/static/e2d851a4e8d17762251ac236e48b5140/8d82d/MongoBanner.png","srcSet":"/static/e2d851a4e8d17762251ac236e48b5140/847ef/MongoBanner.png 175w,\n/static/e2d851a4e8d17762251ac236e48b5140/91cba/MongoBanner.png 350w,\n/static/e2d851a4e8d17762251ac236e48b5140/8d82d/MongoBanner.png 510w","srcWebp":"/static/e2d851a4e8d17762251ac236e48b5140/23d6c/MongoBanner.webp","srcSetWebp":"/static/e2d851a4e8d17762251ac236e48b5140/9fca7/MongoBanner.webp 175w,\n/static/e2d851a4e8d17762251ac236e48b5140/37a4e/MongoBanner.webp 350w,\n/static/e2d851a4e8d17762251ac236e48b5140/23d6c/MongoBanner.webp 510w","sizes":"(max-width: 510px) 100vw, 510px"}}}},"allGhostPost":{"edges":[{"node":{"id":"Ghost__Post__5a8c07c98cda356bbe9bbe44","title":"jQuery Slideshow","slug":"jquery-slideshow","featured":false,"feature_image":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/jquery-logo-1.png","excerpt":"Vamos con un ejemplo de creación de un Slideshow muy simple en jQuery. Lo\nprimero de todo es generarnos la estructura del proyecto, cada uno que la haga\ncomo quiera, yo tengo algo así\n\n\nEn mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado\nal index.html al igual que jQuery. También he creado mi propio fichero de estilo \nstyle.css y lo he añadido, quedando todo de esta manera:\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html;","custom_excerpt":null,"visibility":"public","created_at_pretty":"20 Feb 2018","published_at_pretty":"22 Feb 2018","updated_at_pretty":"22 Feb 2018","created_at":"2018-02-20T12:34:33.000+01:00","published_at":"2018-02-22T14:10:51.000+01:00","updated_at":"2018-02-22T14:10:51.000+01:00","meta_title":null,"meta_description":null,"og_description":null,"og_image":null,"og_title":null,"twitter_description":null,"twitter_image":null,"twitter_title":null,"authors":[{"slug":"jlgarcia","url":"https://jlgarcia.fulldev.ninja/author/jlgarcia/","name":"Juan Luis Garcia Aparicio","bio":null,"cover_image":null,"profile_image":"https://jlgarcia.fulldev.ninja/assets/images/2017/12/Perfil.jpg","location":null,"website":null,"twitter":null,"facebook":null,"meta_title":null,"meta_description":null,"coverImageSharp":null,"profileImageSharp":null}],"primary_author":{"slug":"jlgarcia","url":"https://jlgarcia.fulldev.ninja/author/jlgarcia/","name":"Juan Luis Garcia Aparicio","bio":null,"cover_image":null,"profile_image":"https://jlgarcia.fulldev.ninja/assets/images/2017/12/Perfil.jpg","location":null,"website":null,"twitter":null,"facebook":null,"meta_title":null,"meta_description":null,"coverImageSharp":null,"profileImageSharp":{"base":"Perfil.jpg","publicURL":"/static/b0de6281fb28a266510b3b09b9243e5a/Perfil.jpg","imageMeta":{"width":307,"height":307},"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAUDBAb/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAGzw6zC6zHn+cLYP//EAB0QAAICAQUAAAAAAAAAAAAAAAEDAAIEEyEiIzL/2gAIAQEAAQUCifca8KgcKWVfUpkHsG5pxX//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAdEAACAgEFAAAAAAAAAAAAAAAAARARcQISIUFR/9oACAEBAAY/AhU88xkb7N06a8P/xAAcEAEAAwEAAwEAAAAAAAAAAAABABEhMUFRYXH/2gAIAQEAAT8hR2pq40aqb+xIAeXibhW9JXr8joF4TBcSNe0//9oADAMBAAIAAwAAABDzDwD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhUTFhcfD/2gAIAQEAAT8QyItrELaTlatLwU63MvEW6vUNdy4LZQDn7iVApV9VLtANdWwKkuYq4Er1VZ//2Q==","aspectRatio":1,"src":"/static/b0de6281fb28a266510b3b09b9243e5a/31709/Perfil.jpg","srcSet":"/static/b0de6281fb28a266510b3b09b9243e5a/f340b/Perfil.jpg 28w,\n/static/b0de6281fb28a266510b3b09b9243e5a/22d64/Perfil.jpg 55w,\n/static/b0de6281fb28a266510b3b09b9243e5a/31709/Perfil.jpg 110w,\n/static/b0de6281fb28a266510b3b09b9243e5a/aa249/Perfil.jpg 165w,\n/static/b0de6281fb28a266510b3b09b9243e5a/0dc33/Perfil.jpg 220w,\n/static/b0de6281fb28a266510b3b09b9243e5a/60667/Perfil.jpg 307w","srcWebp":"/static/b0de6281fb28a266510b3b09b9243e5a/8678c/Perfil.webp","srcSetWebp":"/static/b0de6281fb28a266510b3b09b9243e5a/59cda/Perfil.webp 28w,\n/static/b0de6281fb28a266510b3b09b9243e5a/7da75/Perfil.webp 55w,\n/static/b0de6281fb28a266510b3b09b9243e5a/8678c/Perfil.webp 110w,\n/static/b0de6281fb28a266510b3b09b9243e5a/f282e/Perfil.webp 165w,\n/static/b0de6281fb28a266510b3b09b9243e5a/a7b21/Perfil.webp 220w,\n/static/b0de6281fb28a266510b3b09b9243e5a/f59af/Perfil.webp 307w","sizes":"(max-width: 110px) 100vw, 110px"}}}},"primary_tag":{"slug":"jquery","url":"https://jlgarcia.fulldev.ninja/tag/jquery/","name":"jquery","visibility":"public","feature_image":null,"description":null,"meta_title":null,"meta_description":null,"featureImageSharp":null},"tags":[{"slug":"jquery","url":"https://jlgarcia.fulldev.ninja/tag/jquery/","name":"jquery","visibility":"public","feature_image":null,"description":null,"meta_title":null,"meta_description":null,"featureImageSharp":null}],"plaintext":"Vamos con un ejemplo de creación de un Slideshow muy simple en jQuery. Lo\nprimero de todo es generarnos la estructura del proyecto, cada uno que la haga\ncomo quiera, yo tengo algo así\n\n\nEn mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado\nal index.html al igual que jQuery. También he creado mi propio fichero de estilo \nstyle.css y lo he añadido, quedando todo de esta manera:\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n    <title>Ninja_slider</title>\n\n    <script src=\"https://code.jquery.com/jquery-3.3.1.min.js\"></script>\n\n    <link rel=\"stylesheet\" href=\"css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n    \n</head>\n<body>\n    \n</body>\n</html>\n\n\nLo siguiente es añadir donde estará el slider en el body de la página\n\n<body>\n\n    <div class=\"container\" align=\"center\">\n        <h1>Ninja-Slider</h1>\n        <hr>\n\n        <div class=\"ninjaSlider\"></div>\n\n    </div>\n    \n</body>\n\n\nNuestro slider como os podéis imaginar estará en el div con la clase ninjaSlider\n, y esto es todo por el momento en el html, ahora vamos a nuestro css para darle\nun poco de estilo y que se vea algo en la página. Le daremos un tamaño y un\ncolor de fondo para ir viendo algo.\n\n.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\toverflow: hidden;\n\tmargin-bottom: 10px;\n}\n\n\nQuedando así\n\n\nBien ahora vamos a crear un fichero js donde meteremos toda la lógica de\nfuncionamiento de nuestro slider. Tener en cuenta que la idea es hacerlo estilo\nplugin, es decir que este encapsulado para poder usarlo en cualquiera de\nnuestros proyectos.\nBien lo primero como hemos comentado es crearnos el fichero js y meterlo en la\ncarpeta correspondiente, lo siguiente son las imágenes para que slider tenga\nalgo que mostrar, entonces buscamos unas cuantas imágenes, yo me he descargado 4\ny las metemos en la carpeta img.\n\nUna vez que tenemos las imagenes ya podemos empezar, con el js. Creamos una\nfunción anónima que se ejecute nada más cargar el js en el HTML:\n\n(function(){\n    //Aqui dentro meteríamos todo el código.\n})();\n\n\nVamos a empezar por algo sencillo, que es recibir las imagenes desde el html que\nes desde donde nos las mandarían si pensamos que este es un plugin. Estas\nimágenes las incluiremos en una lista, es decir, dentro de un ul de html.\nPero antes de hacer esto, pensemos...¿cómo hacemos para pasar los datos que\nnecesitemos a nuestro plugin?, fácil, por parámetros le pasamos un objecto que\ntenga las modificaciones que queramos hacer.\nPrimero creemos un método, que será el que realmente configure e inicie nuestro\nslider\n\n(function(){\n    $.ninjaShow = function(config){\n    \n    }\n})();\n\n\nAqui hemos añadido la función ninjaShow a jQuery, por lo que la podemos llamar\ndesde cualquier sitio desde el que podamos llamar a jQuery. A esta función le\npasamos por parámetro un objeto config que tendrá todos los cambios sobre la\nconfiguración por defecto que establezcamos.\nContinuemos añadiendo lógica para nuestras imagenes, suponiendo que nos indiquen\ncuales son las imágenes a través del objeto config, podemos tener nuestras\nimagenes bajo la propiedad images dentro del objeto config. Hagamos una prueba\npara que veáis de lo que estoy hablando, nos vamos a nuestro index.html y\nañadimos lo siguiente al final (pero siempre dentro del body)\n\n<!-- añadimos nuestro js al html -->\n<script src=\"js/slider.js\"></script>\n<script>\n\t//Llamamos a nuestra función pasandole un objeto con la propiedad images\n\t$.ninjaShow({\n\n        images:['img/ninja1.jpg','img/ninja2.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n\t});\n\n</script>\n</body>\n\n\nY luego en nuestro fichero js, ponemos un log para ver que estamos recibiendo.\n\n(function(){\n\n    $.ninjaShow = function( config ){\n\n        console.log(config);\n    }\n\n})();\n\n\nSi guardamos y miramos la consola al ejecutar nuestro index.html, veremos algo\ncomo lo siguiente\n\n\nEs decir, un objeto con la propiedad images y dentro de esta un array con la\ndirección donde estan nuestras imágenes.\nEntonces ya tenemos nuestras imágenes, ahora creemos la lista con ellas.\n\n(function(){\n\n    $.ninjaShow = function( config ){\n                //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n\n            //Abrimos la lista\n            var imgList = \"<ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '<li><img src=\"'+ img +'\"</li>';\n            })\n            //Cerramos la lista\n            imgList += \"</ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(\".ninjaSlider\").append(imgList);\n    }\n\n})();\n\n\nSi ejecutamos nuestro index.html veremos algo similar a esto:\n\n\n\nAhora mismo no vemos casi nada, ¿verdad?, vamos a modificar un poco el estilo\npara que veamos que realmente las cosas estan donde deben estar. Nos vamos a\nnuestro style.css y lo dejamos así\n\n.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\t/* overflow: hidden; */\n\tmargin-bottom: 10px;\n}\n\n.ninjaSlider ul{\n\tpadding: 0;\n\tlist-style-type: none;\n\tmargin-left: 0px;\n\tdisplay: flex;\n}\n\n\nAhora si veríamos algo aunque solo sean las imágenes\n\n\nPero si miramos el código fuente de la página deberíamos ver algo como esto:\n\n\nYa tenemos nuestra lista de imágenes, y las vemos porque hemos cambiado la\npropiedad overflow de css, la configuración correcta sería descomentado la línea\ny dejandola así\n\noverflow: hidden;\n\n\nPero la hemos comentado para explicar que es lo que vamos a hacer para ir\ncambiando de imágenes.\nSi os fijáis las imágenes estan configuradas en una linea horizontal, una al\nlado de otra, lo que haremos será ir moviendo el interior del contenedor en esa\nlinea horizontal, modificando el margin-left, es decir, supongamos que nuestro \nmargin-left en nuestra primera imagen es 0 y tenemos imágenes con un ancho de\n600, pues lo que haríamos para movernos entre las imágenes sería ir modificando\nel margin-left en conjuntos de 600, es decir, la siguiente imagen tendria un\nmargen de -600, la siguiente de -1200... y el - es necesario porque nuestro\nslide se movera de izquierda a derecha y como os podréis imaginar para que\nfuncione en este ejemplo es necesario que el ancho de las imágenes sea el mismo\no muy parecido (podríamos manejar el ancho de cada li dentro de la lista pero\nprefiero dejar el código más claro).\nCreo que está más o menos explicado el concepto de lo que queremos hacer, veamos\ncomo lo hacemos\n\n //Variable de ayuda para gestionar la posicion\n var position = 0;\n //Numero de imagenes para controlar\n var images = config.images.length;\n\n //intervalo en el que se cambia la imagen\n var interval = setInterval(function(){\n   move();\n }, 1400);\n\n function move(){\n//Cada vez que pase por aqui aumentamos la posicion       \n   position++;\n\n//Si la posicion es igual o mayor que la cantidad de imagenes\n//ponemos position a 0\n   if (position >= images ){\n        position = 0\n   }\n\n//Por ultimo movemos el margen según la posición en grupos de 600\n   $(\".ninjaSlider ul\").animate({\n     marginLeft: position * -600\n   },400);\n\n\nPor último descomentamos el overflow:hidden en el fichero css y listo, ya lo\ntenemos\n\n\n\nYa tenemos nuestro slide funcionando, en este punto podríamos añadir más\nfuncionalidad, que tuviera los puntitos típicos que te indican en que slide te\nencuentras y que puedes pulsar para moverte de uno a otro, o parar el slide por\nejemplo. Eso lo haremos más adelante en algún post posterior ahora quería solo\nmostrar como podríamos hacer lo más básico de un slide, ahora lo ultimo que\nharemos será añadir un par de cosas al js para que se vaya pareciendo más a un\nplugin y podamos personalizarlo un poco más.\n\nSi miramos el código detenidamente y pensamos un poco que cosas podrían ser\nsusceptibles de cambiar, podrían ser:\n\n * El ancho básico de las imágenes para ir moviendo el slide.\n * La clase o id del slider (podriamos tener mas de uno por ejemplo)\n * El intervalo de transición de las imágenes.\n\nEstos son algunos de los cambios que se me han ocurrido con el código que\ntenemos actualmente podríamos tener más seguramente. Por el momento vamos a\npreparar esos.\nPara empezar tenemos que plantearnos cuales son obligatorios y cuales podrían\ntener una configuración por defecto. Las imágenes deben ser obligatorias, por\neso hemos puesto el control antes que nos lanzaría una alerta si no se pasa\nninguna imagen, y a lo mejor el nombre del id del slide y el resto podemos tener\nvalores por defecto si no nos lo pasan por parámetro.\nPara ellos basta con usar el método extend de jQuery sobre el objeto que se pasa\npor parámetro\n\n$.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n\nEste método lo que hace es sobreescribir el objeto local, que sería el primero\n(el que está entre { }) con el que se pasa por parámetro, pero solo las\npropiedades con el mismo nombre, es decir, no elimina el objeto por otro, es\ncomo si cambiaramos las propiedades que coincidan por las nuevas que se pasan\npor parámetro.\nY ahora simplemente es cambiar los elementos que tenemos puestos a mano como \n\".ninjaslider\" por la propiedad correspondiente y listo, ya tendríamos preparado\nel código como si fuera un plugin quedando así (dejo comentado el código)\n\n//Función anonima\n(function(){\n\n    $.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n            //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n            \n            //Comprobamos que nos han pasado un nombre para slider\n            if (config.slideName == \"\"){\n                alert(\"Falta el nombre o id donde estará el slider\")\n                return\n            }\n\n            //Abrimos la lista\n            var imgList = \"<ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '<li><img src=\"'+ img +'\"</li>';\n            })\n            //Cerramos la lista\n            imgList += \"</ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(config.slideName).append(imgList);\n\n            //Variable de ayuda para gestionar la posicion\n            var position = 0;\n            //Numero de imagenes para controlar\n            var images = config.images.length;\n\n            //intervalo en el que se cambia la imagen\n            var interval = setInterval(function(){\n                move();\n            }, config.timeTransition);\n\n            function move(){\n                \n                position++;\n\n                if (position >= images ){\n                    position = 0\n                }\n\n                $(config.slideName + \" ul\").animate({\n                    marginLeft: position * - config.width\n                },400);\n            }\n    }\n\n})();\n\n\nComo véis ahora tenemos config.algo por todas partes. Y para usarlo nos vamos a\nnuestro index.html y añadimos las propiedades necesarias:\n\n<script>\n\t\n\t$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n</script>\n\n\nY podríamos como he comentado, crear más sliders simplemente creando el\nelemento, dandole un nombre y crear un nuevo ninjaShow\n\n$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n    \n$.ninjaShow({\n        slideName: \".ninjaSlider2\",\n        ancho: 600,\n        timeTransition: 1200,\n        images:['img/ninja4.jpg','img/ninja1.jpg','img/ninja3.jpg'],\n});\n\n\n\n\nComo véis ahora es muy sencillo crear sliders básicos con este código. En algún\npost posterior mejoraremos este slider para que tenga más funcionalidades, esto\nes básicamente para que veamos un poco como podemos trabajar con jQuery para\nhacer todo lo que queramos con el DOM.\n\nSin mucho más nos vemos en el siguiente, un abrazooorrrr.","html":"<!--kg-card-begin: markdown--><p>Vamos con un ejemplo de creación de un <strong>Slideshow</strong> muy simple en jQuery. Lo primero de todo es generarnos la estructura del proyecto, cada uno que la haga como quiera, yo tengo algo así<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/folders.JPG\" alt=\"folders\"></p>\n<p>En mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado al index.html al igual que <strong>jQuery</strong>. También he creado mi propio fichero de estilo <strong>style.css</strong> y lo he añadido, quedando todo de esta manera:</p>\n<pre><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;en&quot;&gt;\n&lt;head&gt;\n    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;\n    &lt;title&gt;Ninja_slider&lt;/title&gt;\n\n    &lt;script src=&quot;https://code.jquery.com/jquery-3.3.1.min.js&quot;&gt;&lt;/script&gt;\n\n    &lt;link rel=&quot;stylesheet&quot; href=&quot;css/bootstrap.min.css&quot;&gt;\n    &lt;link rel=&quot;stylesheet&quot; href=&quot;css/style.css&quot;&gt;\n    \n&lt;/head&gt;\n&lt;body&gt;\n    \n&lt;/body&gt;\n&lt;/html&gt;\n</code></pre>\n<p>Lo siguiente es añadir donde estará el slider en el <strong>body</strong> de la página</p>\n<pre><code>&lt;body&gt;\n\n    &lt;div class=&quot;container&quot; align=&quot;center&quot;&gt;\n        &lt;h1&gt;Ninja-Slider&lt;/h1&gt;\n        &lt;hr&gt;\n\n        &lt;div class=&quot;ninjaSlider&quot;&gt;&lt;/div&gt;\n\n    &lt;/div&gt;\n    \n&lt;/body&gt;\n</code></pre>\n<p>Nuestro slider como os podéis imaginar estará en el <em>div</em> con la clase <em>ninjaSlider</em>, y esto es todo por el momento en el html, ahora vamos a nuestro <em>css</em> para darle un poco de estilo y que se vea algo en la página. Le daremos un tamaño y un color de fondo para ir viendo algo.</p>\n<pre><code>.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\toverflow: hidden;\n\tmargin-bottom: 10px;\n}\n</code></pre>\n<p>Quedando así<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/background.JPG\" alt=\"background\"></p>\n<p>Bien ahora vamos a crear un fichero <em>js</em> donde meteremos toda la lógica de funcionamiento de nuestro slider. Tener en cuenta que la idea es hacerlo estilo plugin, es decir que este encapsulado para poder usarlo en cualquiera de nuestros proyectos.<br>\nBien lo primero como hemos comentado es crearnos el fichero <em>js</em> y meterlo en la carpeta correspondiente, lo siguiente son las imágenes para que slider tenga algo que mostrar, entonces buscamos unas cuantas imágenes, yo me he descargado 4 y las metemos en la carpeta <em>img</em>.</p>\n<p>Una vez que tenemos las imagenes ya podemos empezar, con el js. Creamos una función anónima que se ejecute nada más cargar el js en el HTML:</p>\n<pre><code>(function(){\n    //Aqui dentro meteríamos todo el código.\n})();\n</code></pre>\n<p>Vamos a empezar por algo sencillo, que es recibir las imagenes desde el html que es desde donde nos las mandarían si pensamos que este es un plugin. Estas imágenes las incluiremos en una lista, es decir, dentro de un <em>ul</em> de html.<br>\nPero antes de hacer esto, pensemos...¿cómo hacemos para pasar los datos que necesitemos a nuestro plugin?, fácil, por parámetros le pasamos un <em>objecto</em> que tenga las modificaciones que queramos hacer.<br>\nPrimero creemos un método, que será el que realmente configure e inicie nuestro slider</p>\n<pre><code>(function(){\n    $.ninjaShow = function(config){\n    \n    }\n})();\n</code></pre>\n<p>Aqui hemos añadido la función <em>ninjaShow</em> a jQuery, por lo que la podemos llamar desde cualquier sitio desde el que podamos llamar a jQuery. A esta función le pasamos por parámetro un objeto <em>config</em> que tendrá todos los cambios sobre la configuración por defecto que establezcamos.<br>\nContinuemos añadiendo lógica para nuestras imagenes, suponiendo que nos indiquen cuales son las imágenes a través del objeto <em>config</em>, podemos tener nuestras imagenes bajo la propiedad <em>images</em> dentro del objeto <em>config</em>. Hagamos una prueba para que veáis de lo que estoy hablando, nos vamos a nuestro <em>index.html</em> y añadimos lo siguiente al final (pero siempre dentro del <em>body</em>)</p>\n<pre><code>&lt;!-- añadimos nuestro js al html --&gt;\n&lt;script src=&quot;js/slider.js&quot;&gt;&lt;/script&gt;\n&lt;script&gt;\n\t//Llamamos a nuestra función pasandole un objeto con la propiedad images\n\t$.ninjaShow({\n\n        images:['img/ninja1.jpg','img/ninja2.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n\t});\n\n&lt;/script&gt;\n&lt;/body&gt;\n</code></pre>\n<p>Y luego en nuestro fichero <em>js</em>, ponemos un log para ver que estamos recibiendo.</p>\n<pre><code>(function(){\n\n    $.ninjaShow = function( config ){\n\n        console.log(config);\n    }\n\n})();\n</code></pre>\n<p>Si guardamos y miramos la consola al ejecutar nuestro <em>index.html</em>, veremos algo como lo siguiente<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/images.JPG\" alt=\"images\"></p>\n<p>Es decir, un objeto con la propiedad <em>images</em> y dentro de esta un array con la dirección donde estan nuestras imágenes.<br>\nEntonces ya tenemos nuestras imágenes, ahora creemos la lista con ellas.</p>\n<pre><code>(function(){\n\n    $.ninjaShow = function( config ){\n                //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(&quot;Necesitamos alguna imagen para mostrar&quot;);\n                return;\n            }\n\n            //Abrimos la lista\n            var imgList = &quot;&lt;ul&gt;&quot;;\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=&gt;{\n                imgList += '&lt;li&gt;&lt;img src=&quot;'+ img +'&quot;&lt;/li&gt;';\n            })\n            //Cerramos la lista\n            imgList += &quot;&lt;/ul&gt;&quot;;\n            \n            //Adjuntamos la lista al contenedor\n            $(&quot;.ninjaSlider&quot;).append(imgList);\n    }\n\n})();\n</code></pre>\n<p>Si ejecutamos nuestro <em>index.html</em> veremos algo similar a esto:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example.JPG\" alt=\"example\"></p>\n<p>Ahora mismo no vemos casi nada, ¿verdad?, vamos a modificar un poco el estilo para que veamos que realmente las cosas estan donde deben estar. Nos vamos a nuestro <em>style.css</em> y lo dejamos así</p>\n<pre><code>.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\t/* overflow: hidden; */\n\tmargin-bottom: 10px;\n}\n\n.ninjaSlider ul{\n\tpadding: 0;\n\tlist-style-type: none;\n\tmargin-left: 0px;\n\tdisplay: flex;\n}\n</code></pre>\n<p>Ahora si veríamos algo aunque solo sean las imágenes<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example2.JPG\" alt=\"example2\"></p>\n<p>Pero si miramos el código fuente de la página deberíamos ver algo como esto:<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example3.JPG\" alt=\"example3\"></p>\n<p>Ya tenemos nuestra lista de imágenes, y las vemos porque hemos cambiado la propiedad <em>overflow</em> de css, la configuración correcta sería descomentado la línea y dejandola así</p>\n<pre><code>overflow: hidden;\n</code></pre>\n<p>Pero la hemos comentado para explicar que es lo que vamos a hacer para ir cambiando de imágenes.<br>\nSi os fijáis las imágenes estan configuradas en una linea horizontal, una al lado de otra, lo que haremos será ir moviendo el interior del contenedor en esa linea horizontal, modificando el <em>margin-left</em>, es decir, supongamos que nuestro <em>margin-left</em> en nuestra primera imagen es 0 y tenemos imágenes con un ancho de 600, pues lo que haríamos para movernos entre las imágenes sería ir modificando el <em>margin-left</em> en conjuntos de 600, es decir, la siguiente imagen tendria un margen de <strong>-600</strong>, la siguiente de <strong>-1200</strong>... y el <em>-</em> es necesario porque nuestro slide se movera de izquierda a derecha y como os podréis imaginar para que funcione en este ejemplo es necesario que el ancho de las imágenes sea el mismo o muy parecido (podríamos manejar el ancho de cada <em>li</em> dentro de la lista pero prefiero dejar el código más claro).<br>\nCreo que está más o menos explicado el concepto de lo que queremos hacer, veamos como lo hacemos</p>\n<pre><code> //Variable de ayuda para gestionar la posicion\n var position = 0;\n //Numero de imagenes para controlar\n var images = config.images.length;\n\n //intervalo en el que se cambia la imagen\n var interval = setInterval(function(){\n   move();\n }, 1400);\n\n function move(){\n//Cada vez que pase por aqui aumentamos la posicion       \n   position++;\n\n//Si la posicion es igual o mayor que la cantidad de imagenes\n//ponemos position a 0\n   if (position &gt;= images ){\n        position = 0\n   }\n\n//Por ultimo movemos el margen según la posición en grupos de 600\n   $(&quot;.ninjaSlider ul&quot;).animate({\n     marginLeft: position * -600\n   },400);\n</code></pre>\n<p>Por último descomentamos el <em>overflow:hidden</em> en el fichero <em>css</em> y listo, ya lo tenemos</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/slideExample.gif\" alt=\"slideExample\"></p>\n<p>Ya tenemos nuestro slide funcionando, en este punto podríamos añadir más funcionalidad, que tuviera los puntitos típicos que te indican en que slide te encuentras y que puedes pulsar para moverte de uno a otro, o parar el slide por ejemplo. Eso lo haremos más adelante en algún post posterior ahora quería solo mostrar como podríamos hacer lo más básico de un slide, ahora lo ultimo que haremos será añadir un par de cosas al <em>js</em> para que se vaya pareciendo más a un plugin y podamos personalizarlo un poco más.</p>\n<p>Si miramos el código detenidamente y pensamos un poco que cosas podrían ser susceptibles de cambiar, podrían ser:</p>\n<ul>\n<li>El ancho básico de las imágenes para ir moviendo el slide.</li>\n<li>La clase o id del slider (podriamos tener mas de uno por ejemplo)</li>\n<li>El intervalo de transición de las imágenes.</li>\n</ul>\n<p>Estos son algunos de los cambios que se me han ocurrido con el código que tenemos actualmente podríamos tener más seguramente. Por el momento vamos a preparar esos.<br>\nPara empezar tenemos que plantearnos cuales son obligatorios y cuales podrían tener una configuración por defecto. Las imágenes deben ser obligatorias, por eso hemos puesto el control antes que nos lanzaría una alerta si no se pasa ninguna imagen, y a lo mejor el nombre del id del slide y el resto podemos tener valores por defecto si no nos lo pasan por parámetro.<br>\nPara ellos basta con usar el método <em>extend</em> de jQuery sobre el objeto que se pasa por parámetro</p>\n<pre><code>$.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: &quot;&quot;,\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n</code></pre>\n<p>Este método lo que hace es sobreescribir el objeto local, que sería el primero (el que está entre <em>{ }</em>) con el que se pasa por parámetro, pero solo las propiedades con el mismo nombre, es decir, no elimina el objeto por otro, es como si cambiaramos las propiedades que coincidan por las nuevas que se pasan por parámetro.<br>\nY ahora simplemente es cambiar los elementos que tenemos puestos a mano como <em>&quot;.ninjaslider&quot;</em> por la propiedad correspondiente y listo, ya tendríamos preparado el código como si fuera un plugin quedando así (dejo comentado el código)</p>\n<pre><code>//Función anonima\n(function(){\n\n    $.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: &quot;&quot;,\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n            //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(&quot;Necesitamos alguna imagen para mostrar&quot;);\n                return;\n            }\n            \n            //Comprobamos que nos han pasado un nombre para slider\n            if (config.slideName == &quot;&quot;){\n                alert(&quot;Falta el nombre o id donde estará el slider&quot;)\n                return\n            }\n\n            //Abrimos la lista\n            var imgList = &quot;&lt;ul&gt;&quot;;\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=&gt;{\n                imgList += '&lt;li&gt;&lt;img src=&quot;'+ img +'&quot;&lt;/li&gt;';\n            })\n            //Cerramos la lista\n            imgList += &quot;&lt;/ul&gt;&quot;;\n            \n            //Adjuntamos la lista al contenedor\n            $(config.slideName).append(imgList);\n\n            //Variable de ayuda para gestionar la posicion\n            var position = 0;\n            //Numero de imagenes para controlar\n            var images = config.images.length;\n\n            //intervalo en el que se cambia la imagen\n            var interval = setInterval(function(){\n                move();\n            }, config.timeTransition);\n\n            function move(){\n                \n                position++;\n\n                if (position &gt;= images ){\n                    position = 0\n                }\n\n                $(config.slideName + &quot; ul&quot;).animate({\n                    marginLeft: position * - config.width\n                },400);\n            }\n    }\n\n})();\n</code></pre>\n<p>Como véis ahora tenemos <em>config.algo</em> por todas partes. Y para usarlo nos vamos a nuestro <em>index.html</em> y añadimos las propiedades necesarias:</p>\n<pre><code>&lt;script&gt;\n\t\n\t$.ninjaShow({\n        slideName: &quot;.ninjaSlider&quot;,\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n&lt;/script&gt;\n</code></pre>\n<p>Y podríamos como he comentado, crear más sliders simplemente creando el elemento, dandole un nombre y crear un nuevo <em>ninjaShow</em></p>\n<pre><code>$.ninjaShow({\n        slideName: &quot;.ninjaSlider&quot;,\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n    \n$.ninjaShow({\n        slideName: &quot;.ninjaSlider2&quot;,\n        ancho: 600,\n        timeTransition: 1200,\n        images:['img/ninja4.jpg','img/ninja1.jpg','img/ninja3.jpg'],\n});\n</code></pre>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/2Sliders.JPG\" alt=\"2Sliders\"></p>\n<p>Como véis ahora es muy sencillo crear sliders básicos con este código. En algún post posterior mejoraremos este slider para que tenga más funcionalidades, esto es básicamente para que veamos un poco como podemos trabajar con jQuery para hacer todo lo que queramos con el DOM.</p>\n<p>Sin mucho más nos vemos en el siguiente, un abrazooorrrr.</p>\n<!--kg-card-end: markdown-->","url":"https://jlgarcia.fulldev.ninja/jquery-slideshow/","canonical_url":null,"uuid":"3b1de9f2-e3a4-45a7-a056-dc806e105a19","codeinjection_foot":null,"codeinjection_head":null,"codeinjection_styles":null,"comment_id":"5a8c07c98cda356bbe9bbe44","reading_time":8,"send_email_when_published":false,"email_subject":null,"childHtmlRehype":{"html":"<!--kg-card-begin: markdown--><p>Vamos con un ejemplo de creación de un <strong>Slideshow</strong> muy simple en jQuery. Lo primero de todo es generarnos la estructura del proyecto, cada uno que la haga como quiera, yo tengo algo así<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/folders.JPG\" alt=\"folders\"></p>\n<p>En mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado al index.html al igual que <strong>jQuery</strong>. También he creado mi propio fichero de estilo <strong>style.css</strong> y lo he añadido, quedando todo de esta manera:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;!DOCTYPE html>\n&#x3C;html lang=\"en\">\n&#x3C;head>\n    &#x3C;meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n    &#x3C;title>Ninja_slider&#x3C;/title>\n\n    &#x3C;script src=\"https://code.jquery.com/jquery-3.3.1.min.js\">&#x3C;/script>\n\n    &#x3C;link rel=\"stylesheet\" href=\"css/bootstrap.min.css\">\n    &#x3C;link rel=\"stylesheet\" href=\"css/style.css\">\n    \n&#x3C;/head>\n&#x3C;body>\n    \n&#x3C;/body>\n&#x3C;/html>\n</code></pre></div>\n<p>Lo siguiente es añadir donde estará el slider en el <strong>body</strong> de la página</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;body>\n\n    &#x3C;div class=\"container\" align=\"center\">\n        &#x3C;h1>Ninja-Slider&#x3C;/h1>\n        &#x3C;hr>\n\n        &#x3C;div class=\"ninjaSlider\">&#x3C;/div>\n\n    &#x3C;/div>\n    \n&#x3C;/body>\n</code></pre></div>\n<p>Nuestro slider como os podéis imaginar estará en el <em>div</em> con la clase <em>ninjaSlider</em>, y esto es todo por el momento en el html, ahora vamos a nuestro <em>css</em> para darle un poco de estilo y que se vea algo en la página. Le daremos un tamaño y un color de fondo para ir viendo algo.</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\toverflow: hidden;\n\tmargin-bottom: 10px;\n}\n</code></pre></div>\n<p>Quedando así<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/background.JPG\" alt=\"background\"></p>\n<p>Bien ahora vamos a crear un fichero <em>js</em> donde meteremos toda la lógica de funcionamiento de nuestro slider. Tener en cuenta que la idea es hacerlo estilo plugin, es decir que este encapsulado para poder usarlo en cualquiera de nuestros proyectos.<br>\nBien lo primero como hemos comentado es crearnos el fichero <em>js</em> y meterlo en la carpeta correspondiente, lo siguiente son las imágenes para que slider tenga algo que mostrar, entonces buscamos unas cuantas imágenes, yo me he descargado 4 y las metemos en la carpeta <em>img</em>.</p>\n<p>Una vez que tenemos las imagenes ya podemos empezar, con el js. Creamos una función anónima que se ejecute nada más cargar el js en el HTML:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(function(){\n    //Aqui dentro meteríamos todo el código.\n})();\n</code></pre></div>\n<p>Vamos a empezar por algo sencillo, que es recibir las imagenes desde el html que es desde donde nos las mandarían si pensamos que este es un plugin. Estas imágenes las incluiremos en una lista, es decir, dentro de un <em>ul</em> de html.<br>\nPero antes de hacer esto, pensemos...¿cómo hacemos para pasar los datos que necesitemos a nuestro plugin?, fácil, por parámetros le pasamos un <em>objecto</em> que tenga las modificaciones que queramos hacer.<br>\nPrimero creemos un método, que será el que realmente configure e inicie nuestro slider</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(function(){\n    $.ninjaShow = function(config){\n    \n    }\n})();\n</code></pre></div>\n<p>Aqui hemos añadido la función <em>ninjaShow</em> a jQuery, por lo que la podemos llamar desde cualquier sitio desde el que podamos llamar a jQuery. A esta función le pasamos por parámetro un objeto <em>config</em> que tendrá todos los cambios sobre la configuración por defecto que establezcamos.<br>\nContinuemos añadiendo lógica para nuestras imagenes, suponiendo que nos indiquen cuales son las imágenes a través del objeto <em>config</em>, podemos tener nuestras imagenes bajo la propiedad <em>images</em> dentro del objeto <em>config</em>. Hagamos una prueba para que veáis de lo que estoy hablando, nos vamos a nuestro <em>index.html</em> y añadimos lo siguiente al final (pero siempre dentro del <em>body</em>)</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;!-- añadimos nuestro js al html -->\n&#x3C;script src=\"js/slider.js\">&#x3C;/script>\n&#x3C;script>\n\t//Llamamos a nuestra función pasandole un objeto con la propiedad images\n\t$.ninjaShow({\n\n        images:['img/ninja1.jpg','img/ninja2.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n\t});\n\n&#x3C;/script>\n&#x3C;/body>\n</code></pre></div>\n<p>Y luego en nuestro fichero <em>js</em>, ponemos un log para ver que estamos recibiendo.</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(function(){\n\n    $.ninjaShow = function( config ){\n\n        console.log(config);\n    }\n\n})();\n</code></pre></div>\n<p>Si guardamos y miramos la consola al ejecutar nuestro <em>index.html</em>, veremos algo como lo siguiente<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/images.JPG\" alt=\"images\"></p>\n<p>Es decir, un objeto con la propiedad <em>images</em> y dentro de esta un array con la dirección donde estan nuestras imágenes.<br>\nEntonces ya tenemos nuestras imágenes, ahora creemos la lista con ellas.</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(function(){\n\n    $.ninjaShow = function( config ){\n                //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n\n            //Abrimos la lista\n            var imgList = \"&#x3C;ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '&#x3C;li>&#x3C;img src=\"'+ img +'\"&#x3C;/li>';\n            })\n            //Cerramos la lista\n            imgList += \"&#x3C;/ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(\".ninjaSlider\").append(imgList);\n    }\n\n})();\n</code></pre></div>\n<p>Si ejecutamos nuestro <em>index.html</em> veremos algo similar a esto:</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example.JPG\" alt=\"example\"></p>\n<p>Ahora mismo no vemos casi nada, ¿verdad?, vamos a modificar un poco el estilo para que veamos que realmente las cosas estan donde deben estar. Nos vamos a nuestro <em>style.css</em> y lo dejamos así</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">.ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\t/* overflow: hidden; */\n\tmargin-bottom: 10px;\n}\n\n.ninjaSlider ul{\n\tpadding: 0;\n\tlist-style-type: none;\n\tmargin-left: 0px;\n\tdisplay: flex;\n}\n</code></pre></div>\n<p>Ahora si veríamos algo aunque solo sean las imágenes<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example2.JPG\" alt=\"example2\"></p>\n<p>Pero si miramos el código fuente de la página deberíamos ver algo como esto:<br>\n<img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example3.JPG\" alt=\"example3\"></p>\n<p>Ya tenemos nuestra lista de imágenes, y las vemos porque hemos cambiado la propiedad <em>overflow</em> de css, la configuración correcta sería descomentado la línea y dejandola así</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">overflow: hidden;\n</code></pre></div>\n<p>Pero la hemos comentado para explicar que es lo que vamos a hacer para ir cambiando de imágenes.<br>\nSi os fijáis las imágenes estan configuradas en una linea horizontal, una al lado de otra, lo que haremos será ir moviendo el interior del contenedor en esa linea horizontal, modificando el <em>margin-left</em>, es decir, supongamos que nuestro <em>margin-left</em> en nuestra primera imagen es 0 y tenemos imágenes con un ancho de 600, pues lo que haríamos para movernos entre las imágenes sería ir modificando el <em>margin-left</em> en conjuntos de 600, es decir, la siguiente imagen tendria un margen de <strong>-600</strong>, la siguiente de <strong>-1200</strong>... y el <em>-</em> es necesario porque nuestro slide se movera de izquierda a derecha y como os podréis imaginar para que funcione en este ejemplo es necesario que el ancho de las imágenes sea el mismo o muy parecido (podríamos manejar el ancho de cada <em>li</em> dentro de la lista pero prefiero dejar el código más claro).<br>\nCreo que está más o menos explicado el concepto de lo que queremos hacer, veamos como lo hacemos</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> //Variable de ayuda para gestionar la posicion\n var position = 0;\n //Numero de imagenes para controlar\n var images = config.images.length;\n\n //intervalo en el que se cambia la imagen\n var interval = setInterval(function(){\n   move();\n }, 1400);\n\n function move(){\n//Cada vez que pase por aqui aumentamos la posicion       \n   position++;\n\n//Si la posicion es igual o mayor que la cantidad de imagenes\n//ponemos position a 0\n   if (position >= images ){\n        position = 0\n   }\n\n//Por ultimo movemos el margen según la posición en grupos de 600\n   $(\".ninjaSlider ul\").animate({\n     marginLeft: position * -600\n   },400);\n</code></pre></div>\n<p>Por último descomentamos el <em>overflow:hidden</em> en el fichero <em>css</em> y listo, ya lo tenemos</p>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/slideExample.gif\" alt=\"slideExample\"></p>\n<p>Ya tenemos nuestro slide funcionando, en este punto podríamos añadir más funcionalidad, que tuviera los puntitos típicos que te indican en que slide te encuentras y que puedes pulsar para moverte de uno a otro, o parar el slide por ejemplo. Eso lo haremos más adelante en algún post posterior ahora quería solo mostrar como podríamos hacer lo más básico de un slide, ahora lo ultimo que haremos será añadir un par de cosas al <em>js</em> para que se vaya pareciendo más a un plugin y podamos personalizarlo un poco más.</p>\n<p>Si miramos el código detenidamente y pensamos un poco que cosas podrían ser susceptibles de cambiar, podrían ser:</p>\n<ul>\n<li>El ancho básico de las imágenes para ir moviendo el slide.</li>\n<li>La clase o id del slider (podriamos tener mas de uno por ejemplo)</li>\n<li>El intervalo de transición de las imágenes.</li>\n</ul>\n<p>Estos son algunos de los cambios que se me han ocurrido con el código que tenemos actualmente podríamos tener más seguramente. Por el momento vamos a preparar esos.<br>\nPara empezar tenemos que plantearnos cuales son obligatorios y cuales podrían tener una configuración por defecto. Las imágenes deben ser obligatorias, por eso hemos puesto el control antes que nos lanzaría una alerta si no se pasa ninguna imagen, y a lo mejor el nombre del id del slide y el resto podemos tener valores por defecto si no nos lo pasan por parámetro.<br>\nPara ellos basta con usar el método <em>extend</em> de jQuery sobre el objeto que se pasa por parámetro</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n</code></pre></div>\n<p>Este método lo que hace es sobreescribir el objeto local, que sería el primero (el que está entre <em>{ }</em>) con el que se pasa por parámetro, pero solo las propiedades con el mismo nombre, es decir, no elimina el objeto por otro, es como si cambiaramos las propiedades que coincidan por las nuevas que se pasan por parámetro.<br>\nY ahora simplemente es cambiar los elementos que tenemos puestos a mano como <em>\".ninjaslider\"</em> por la propiedad correspondiente y listo, ya tendríamos preparado el código como si fuera un plugin quedando así (dejo comentado el código)</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">//Función anonima\n(function(){\n\n    $.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n            //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n            \n            //Comprobamos que nos han pasado un nombre para slider\n            if (config.slideName == \"\"){\n                alert(\"Falta el nombre o id donde estará el slider\")\n                return\n            }\n\n            //Abrimos la lista\n            var imgList = \"&#x3C;ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '&#x3C;li>&#x3C;img src=\"'+ img +'\"&#x3C;/li>';\n            })\n            //Cerramos la lista\n            imgList += \"&#x3C;/ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(config.slideName).append(imgList);\n\n            //Variable de ayuda para gestionar la posicion\n            var position = 0;\n            //Numero de imagenes para controlar\n            var images = config.images.length;\n\n            //intervalo en el que se cambia la imagen\n            var interval = setInterval(function(){\n                move();\n            }, config.timeTransition);\n\n            function move(){\n                \n                position++;\n\n                if (position >= images ){\n                    position = 0\n                }\n\n                $(config.slideName + \" ul\").animate({\n                    marginLeft: position * - config.width\n                },400);\n            }\n    }\n\n})();\n</code></pre></div>\n<p>Como véis ahora tenemos <em>config.algo</em> por todas partes. Y para usarlo nos vamos a nuestro <em>index.html</em> y añadimos las propiedades necesarias:</p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&#x3C;script>\n\t\n\t$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n&#x3C;/script>\n</code></pre></div>\n<p>Y podríamos como he comentado, crear más sliders simplemente creando el elemento, dandole un nombre y crear un nuevo <em>ninjaShow</em></p>\n<div class=\"kg-card kg-code-card gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n    \n$.ninjaShow({\n        slideName: \".ninjaSlider2\",\n        ancho: 600,\n        timeTransition: 1200,\n        images:['img/ninja4.jpg','img/ninja1.jpg','img/ninja3.jpg'],\n});\n</code></pre></div>\n<p><img src=\"https://jlgarcia.fulldev.ninja/assets/images/2018/02/2Sliders.JPG\" alt=\"2Sliders\"></p>\n<p>Como véis ahora es muy sencillo crear sliders básicos con este código. En algún post posterior mejoraremos este slider para que tenga más funcionalidades, esto es básicamente para que veamos un poco como podemos trabajar con jQuery para hacer todo lo que queramos con el DOM.</p>\n<p>Sin mucho más nos vemos en el siguiente, un abrazooorrrr.</p>\n<!--kg-card-end: markdown-->","htmlAst":{"type":"root","children":[{"type":"comment","value":"kg-card-begin: markdown"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vamos con un ejemplo de creación de un "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Slideshow"}]},{"type":"text","value":" muy simple en jQuery. Lo primero de todo es generarnos la estructura del proyecto, cada uno que la haga como quiera, yo tengo algo así"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/folders.JPG","alt":"folders"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"En mi caso voy a usar bootstrap, por comodidad, pero no es necesario, lo añado al index.html al igual que "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"jQuery"}]},{"type":"text","value":". También he creado mi propio fichero de estilo "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"style.css"}]},{"type":"text","value":" y lo he añadido, quedando todo de esta manera:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n    <title>Ninja_slider</title>\n\n    <script src=\"https://code.jquery.com/jquery-3.3.1.min.js\"></script>\n\n    <link rel=\"stylesheet\" href=\"css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n    \n</head>\n<body>\n    \n</body>\n</html>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Lo siguiente es añadir donde estará el slider en el "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"body"}]},{"type":"text","value":" de la página"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<body>\n\n    <div class=\"container\" align=\"center\">\n        <h1>Ninja-Slider</h1>\n        <hr>\n\n        <div class=\"ninjaSlider\"></div>\n\n    </div>\n    \n</body>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Nuestro slider como os podéis imaginar estará en el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"div"}]},{"type":"text","value":" con la clase "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"ninjaSlider"}]},{"type":"text","value":", y esto es todo por el momento en el html, ahora vamos a nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"css"}]},{"type":"text","value":" para darle un poco de estilo y que se vea algo en la página. Le daremos un tamaño y un color de fondo para ir viendo algo."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":".ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\toverflow: hidden;\n\tmargin-bottom: 10px;\n}\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Quedando así"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/background.JPG","alt":"background"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Bien ahora vamos a crear un fichero "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"js"}]},{"type":"text","value":" donde meteremos toda la lógica de funcionamiento de nuestro slider. Tener en cuenta que la idea es hacerlo estilo plugin, es decir que este encapsulado para poder usarlo en cualquiera de nuestros proyectos."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nBien lo primero como hemos comentado es crearnos el fichero "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"js"}]},{"type":"text","value":" y meterlo en la carpeta correspondiente, lo siguiente son las imágenes para que slider tenga algo que mostrar, entonces buscamos unas cuantas imágenes, yo me he descargado 4 y las metemos en la carpeta "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"img"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Una vez que tenemos las imagenes ya podemos empezar, con el js. Creamos una función anónima que se ejecute nada más cargar el js en el HTML:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"(function(){\n    //Aqui dentro meteríamos todo el código.\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Vamos a empezar por algo sencillo, que es recibir las imagenes desde el html que es desde donde nos las mandarían si pensamos que este es un plugin. Estas imágenes las incluiremos en una lista, es decir, dentro de un "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"ul"}]},{"type":"text","value":" de html."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPero antes de hacer esto, pensemos...¿cómo hacemos para pasar los datos que necesitemos a nuestro plugin?, fácil, por parámetros le pasamos un "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"objecto"}]},{"type":"text","value":" que tenga las modificaciones que queramos hacer."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPrimero creemos un método, que será el que realmente configure e inicie nuestro slider"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"(function(){\n    $.ninjaShow = function(config){\n    \n    }\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Aqui hemos añadido la función "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"ninjaShow"}]},{"type":"text","value":" a jQuery, por lo que la podemos llamar desde cualquier sitio desde el que podamos llamar a jQuery. A esta función le pasamos por parámetro un objeto "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"config"}]},{"type":"text","value":" que tendrá todos los cambios sobre la configuración por defecto que establezcamos."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nContinuemos añadiendo lógica para nuestras imagenes, suponiendo que nos indiquen cuales son las imágenes a través del objeto "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"config"}]},{"type":"text","value":", podemos tener nuestras imagenes bajo la propiedad "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"images"}]},{"type":"text","value":" dentro del objeto "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"config"}]},{"type":"text","value":". Hagamos una prueba para que veáis de lo que estoy hablando, nos vamos a nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"index.html"}]},{"type":"text","value":" y añadimos lo siguiente al final (pero siempre dentro del "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"body"}]},{"type":"text","value":")"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<!-- añadimos nuestro js al html -->\n<script src=\"js/slider.js\"></script>\n<script>\n\t//Llamamos a nuestra función pasandole un objeto con la propiedad images\n\t$.ninjaShow({\n\n        images:['img/ninja1.jpg','img/ninja2.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n\t});\n\n</script>\n</body>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y luego en nuestro fichero "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"js"}]},{"type":"text","value":", ponemos un log para ver que estamos recibiendo."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"(function(){\n\n    $.ninjaShow = function( config ){\n\n        console.log(config);\n    }\n\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si guardamos y miramos la consola al ejecutar nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"index.html"}]},{"type":"text","value":", veremos algo como lo siguiente"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/images.JPG","alt":"images"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Es decir, un objeto con la propiedad "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"images"}]},{"type":"text","value":" y dentro de esta un array con la dirección donde estan nuestras imágenes."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nEntonces ya tenemos nuestras imágenes, ahora creemos la lista con ellas."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"(function(){\n\n    $.ninjaShow = function( config ){\n                //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n\n            //Abrimos la lista\n            var imgList = \"<ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '<li><img src=\"'+ img +'\"</li>';\n            })\n            //Cerramos la lista\n            imgList += \"</ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(\".ninjaSlider\").append(imgList);\n    }\n\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si ejecutamos nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"index.html"}]},{"type":"text","value":" veremos algo similar a esto:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example.JPG","alt":"example"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ahora mismo no vemos casi nada, ¿verdad?, vamos a modificar un poco el estilo para que veamos que realmente las cosas estan donde deben estar. Nos vamos a nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"style.css"}]},{"type":"text","value":" y lo dejamos así"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":".ninjaSlider{\n\tbackground-color: blue;\n\twidth: 600px;\n\theight: 300px;\n\t/* overflow: hidden; */\n\tmargin-bottom: 10px;\n}\n\n.ninjaSlider ul{\n\tpadding: 0;\n\tlist-style-type: none;\n\tmargin-left: 0px;\n\tdisplay: flex;\n}\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ahora si veríamos algo aunque solo sean las imágenes"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example2.JPG","alt":"example2"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Pero si miramos el código fuente de la página deberíamos ver algo como esto:"},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/example3.JPG","alt":"example3"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ya tenemos nuestra lista de imágenes, y las vemos porque hemos cambiado la propiedad "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"overflow"}]},{"type":"text","value":" de css, la configuración correcta sería descomentado la línea y dejandola así"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"overflow: hidden;\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Pero la hemos comentado para explicar que es lo que vamos a hacer para ir cambiando de imágenes."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nSi os fijáis las imágenes estan configuradas en una linea horizontal, una al lado de otra, lo que haremos será ir moviendo el interior del contenedor en esa linea horizontal, modificando el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"margin-left"}]},{"type":"text","value":", es decir, supongamos que nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"margin-left"}]},{"type":"text","value":" en nuestra primera imagen es 0 y tenemos imágenes con un ancho de 600, pues lo que haríamos para movernos entre las imágenes sería ir modificando el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"margin-left"}]},{"type":"text","value":" en conjuntos de 600, es decir, la siguiente imagen tendria un margen de "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"-600"}]},{"type":"text","value":", la siguiente de "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"-1200"}]},{"type":"text","value":"... y el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"-"}]},{"type":"text","value":" es necesario porque nuestro slide se movera de izquierda a derecha y como os podréis imaginar para que funcione en este ejemplo es necesario que el ancho de las imágenes sea el mismo o muy parecido (podríamos manejar el ancho de cada "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"li"}]},{"type":"text","value":" dentro de la lista pero prefiero dejar el código más claro)."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nCreo que está más o menos explicado el concepto de lo que queremos hacer, veamos como lo hacemos"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":" //Variable de ayuda para gestionar la posicion\n var position = 0;\n //Numero de imagenes para controlar\n var images = config.images.length;\n\n //intervalo en el que se cambia la imagen\n var interval = setInterval(function(){\n   move();\n }, 1400);\n\n function move(){\n//Cada vez que pase por aqui aumentamos la posicion       \n   position++;\n\n//Si la posicion es igual o mayor que la cantidad de imagenes\n//ponemos position a 0\n   if (position >= images ){\n        position = 0\n   }\n\n//Por ultimo movemos el margen según la posición en grupos de 600\n   $(\".ninjaSlider ul\").animate({\n     marginLeft: position * -600\n   },400);\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Por último descomentamos el "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"overflow:hidden"}]},{"type":"text","value":" en el fichero "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"css"}]},{"type":"text","value":" y listo, ya lo tenemos"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/slideExample.gif","alt":"slideExample"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Ya tenemos nuestro slide funcionando, en este punto podríamos añadir más funcionalidad, que tuviera los puntitos típicos que te indican en que slide te encuentras y que puedes pulsar para moverte de uno a otro, o parar el slide por ejemplo. Eso lo haremos más adelante en algún post posterior ahora quería solo mostrar como podríamos hacer lo más básico de un slide, ahora lo ultimo que haremos será añadir un par de cosas al "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"js"}]},{"type":"text","value":" para que se vaya pareciendo más a un plugin y podamos personalizarlo un poco más."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Si miramos el código detenidamente y pensamos un poco que cosas podrían ser susceptibles de cambiar, podrían ser:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"El ancho básico de las imágenes para ir moviendo el slide."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"La clase o id del slider (podriamos tener mas de uno por ejemplo)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"El intervalo de transición de las imágenes."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Estos son algunos de los cambios que se me han ocurrido con el código que tenemos actualmente podríamos tener más seguramente. Por el momento vamos a preparar esos."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPara empezar tenemos que plantearnos cuales son obligatorios y cuales podrían tener una configuración por defecto. Las imágenes deben ser obligatorias, por eso hemos puesto el control antes que nos lanzaría una alerta si no se pasa ninguna imagen, y a lo mejor el nombre del id del slide y el resto podemos tener valores por defecto si no nos lo pasan por parámetro."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nPara ellos basta con usar el método "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"extend"}]},{"type":"text","value":" de jQuery sobre el objeto que se pasa por parámetro"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"$.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Este método lo que hace es sobreescribir el objeto local, que sería el primero (el que está entre "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"{ }"}]},{"type":"text","value":") con el que se pasa por parámetro, pero solo las propiedades con el mismo nombre, es decir, no elimina el objeto por otro, es como si cambiaramos las propiedades que coincidan por las nuevas que se pasan por parámetro."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nY ahora simplemente es cambiar los elementos que tenemos puestos a mano como "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\".ninjaslider\""}]},{"type":"text","value":" por la propiedad correspondiente y listo, ya tendríamos preparado el código como si fuera un plugin quedando así (dejo comentado el código)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"//Función anonima\n(function(){\n\n    $.ninjaShow = function( config ){\n            \n            config = $.extend({\n                slideName: \"\",\n                width: 600,\n                timeTransition: 1400,\n                images: []\n            }, config);\n\n\n            //Comprobamos que nos pasan alguna imagen\n            if (config.images.length == 0){\n                alert(\"Necesitamos alguna imagen para mostrar\");\n                return;\n            }\n            \n            //Comprobamos que nos han pasado un nombre para slider\n            if (config.slideName == \"\"){\n                alert(\"Falta el nombre o id donde estará el slider\")\n                return\n            }\n\n            //Abrimos la lista\n            var imgList = \"<ul>\";\n\n            //Recorremos el array y vamos añadiendo lineas con nuestra imagen como source\n            config.images.map((img)=>{\n                imgList += '<li><img src=\"'+ img +'\"</li>';\n            })\n            //Cerramos la lista\n            imgList += \"</ul>\";\n            \n            //Adjuntamos la lista al contenedor\n            $(config.slideName).append(imgList);\n\n            //Variable de ayuda para gestionar la posicion\n            var position = 0;\n            //Numero de imagenes para controlar\n            var images = config.images.length;\n\n            //intervalo en el que se cambia la imagen\n            var interval = setInterval(function(){\n                move();\n            }, config.timeTransition);\n\n            function move(){\n                \n                position++;\n\n                if (position >= images ){\n                    position = 0\n                }\n\n                $(config.slideName + \" ul\").animate({\n                    marginLeft: position * - config.width\n                },400);\n            }\n    }\n\n})();\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como véis ahora tenemos "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"config.algo"}]},{"type":"text","value":" por todas partes. Y para usarlo nos vamos a nuestro "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"index.html"}]},{"type":"text","value":" y añadimos las propiedades necesarias:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"<script>\n\t\n\t$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n</script>\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Y podríamos como he comentado, crear más sliders simplemente creando el elemento, dandole un nombre y crear un nuevo "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"ninjaShow"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["kg-card","kg-code-card","gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"$.ninjaShow({\n        slideName: \".ninjaSlider\",\n        ancho: 600,\n        timeTransition: 1400,\n        images:['img/ninja1.jpg','img/ninja3.jpg','img/ninja4.jpg'],\n    });\n    \n$.ninjaShow({\n        slideName: \".ninjaSlider2\",\n        ancho: 600,\n        timeTransition: 1200,\n        images:['img/ninja4.jpg','img/ninja1.jpg','img/ninja3.jpg'],\n});\n"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"img","properties":{"src":"https://jlgarcia.fulldev.ninja/assets/images/2018/02/2Sliders.JPG","alt":"2Sliders"},"children":[]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Como véis ahora es muy sencillo crear sliders básicos con este código. En algún post posterior mejoraremos este slider para que tenga más funcionalidades, esto es básicamente para que veamos un poco como podemos trabajar con jQuery para hacer todo lo que queramos con el DOM."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Sin mucho más nos vemos en el siguiente, un abrazooorrrr."}]},{"type":"text","value":"\n"},{"type":"comment","value":"kg-card-end: markdown"}],"data":{"quirksMode":false}},"tableOfContents":[]},"featureImageSharp":{"base":"jquery-logo-1.png","publicURL":"/static/d41803bc36890b1c71051dc26c29c3ea/jquery-logo-1.png","imageMeta":{"width":665,"height":405},"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABwklEQVQoz2MQVjYkGzFgFRVRMRJVNSZOs4oRCCkbQYTE1Iz55XW5pLWA+iGmiAGRmrEolDQCCgopGcA0A1lK+iBSGSTKIamhZGhv4ugH1M8np8Mrp8MlrckuocYjq80qpsonr8srqy0CsgyoWclASM1UwMBZSNuaX05HxdghJD5r2tzFK9Zuzi6ptXALdPCJ8I9KzStvtPMOr2npNXLwySiqDoxJ55TUYAA6mNcjDYgE3JPYZfUiErMvXr4Wn1kcnpR7+tzlgqrmJavWX7p6Y+vu/Zu276lp69tz4OiUOYuAXgC6kUFEXofHJ4cruonPO4tLwXDyjPn17f1ADRs2b+/tn7pqzYbuvsmbN2/r7J3c1jlBXtN05uyFhvbenFKaQP0MYK8aCtiFs2s7WHsEz1uySkBRX0nfWt3Oj986WNEnWdAmWNw2WM0rQdQ6UMgmWNjcR1DRAOZnSNzIaQrJaUtpmYurmwgpGQJDm0fZRMDInUfHQcDQhV/fhUfLTkDfCSgioOcoAosXWDyrGAORoKI+0CdAU0ExpGwgqqAjqqgnoqArqqgLYijqAv0IZOBMJBD3wEwExz/IXCMUNv4URiQCANQ+lfCXnaknAAAAAElFTkSuQmCC","aspectRatio":1.6355140186915889,"src":"/static/d41803bc36890b1c71051dc26c29c3ea/d5882/jquery-logo-1.png","srcSet":"/static/d41803bc36890b1c71051dc26c29c3ea/847ef/jquery-logo-1.png 175w,\n/static/d41803bc36890b1c71051dc26c29c3ea/91cba/jquery-logo-1.png 350w,\n/static/d41803bc36890b1c71051dc26c29c3ea/d5882/jquery-logo-1.png 665w","srcWebp":"/static/d41803bc36890b1c71051dc26c29c3ea/20521/jquery-logo-1.webp","srcSetWebp":"/static/d41803bc36890b1c71051dc26c29c3ea/9fca7/jquery-logo-1.webp 175w,\n/static/d41803bc36890b1c71051dc26c29c3ea/37a4e/jquery-logo-1.webp 350w,\n/static/d41803bc36890b1c71051dc26c29c3ea/20521/jquery-logo-1.webp 665w","sizes":"(max-width: 665px) 100vw, 665px"}}}}}]}},"pageContext":{"slug":"jquery-basics-i","prev":"jquery-slideshow","next":"mongodb-ninja-iv-index-ninja","tag":"jquery","limit":3,"skip":0,"primaryTagCount":2,"collectionPaths":{}}},
    "staticQueryHashes": ["1272700106","1676991999","2138873178","2546165603","2681841279","2938721187","293880488","3052966952","4156497161"]}