{"id":1619,"date":"2024-08-02T10:40:32","date_gmt":"2024-08-02T08:40:32","guid":{"rendered":"https:\/\/blog.sutilweb.eu\/?page_id=1619"},"modified":"2024-08-02T10:40:33","modified_gmt":"2024-08-02T08:40:33","slug":"003-uploader-con-ajax-3","status":"publish","type":"page","link":"https:\/\/sutilweb.eu\/index.php\/lenguajes\/javascript\/javascript-practico\/17-ejercicios-con-ajax\/003-uploader-con-ajax-3\/","title":{"rendered":"003. Uploader con Ajax (3)"},"content":{"rendered":"\n<p>En este cap\u00edtulo vamos a hacer que nuestro cargador de archivos sea <strong>DRAG AND DROP<\/strong>, para lo que vamos a tener que hacer ciertos cambios en los elementos <strong>HTML<\/strong>. Vamos a trabajar con el <strong>API DRAG AND DROP<\/strong>, donde podemos encontrar toda la informaci\u00f3n de la misma en <a href=\"https:\/\/developer.mozilla.org\/es\/docs\/Web\/API\/HTML_Drag_and_Drop_API\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>MDN<\/strong><\/a>.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Nosotros a cualquier elemento en el HTML le podemos dotar de las caracter\u00edsticas de <strong>DRAG AND DROP<\/strong>. En este cap\u00edtulo no utilizaremos la <strong>delegaci\u00f3n de eventos<\/strong> porque el \u00fanico elemento que va a ser zona de interacci\u00f3n activa va a ser la <strong>drop-zone<\/strong>, por lo que los <strong>eventos<\/strong> se los vamos a asignar directamente a la <strong>drop-zone<\/strong>.<\/p>\n\n\n\n<p>Hay varios eventos de <strong>DRAG AND DROP<\/strong>, en este cap\u00edtulo utilizaremos 3:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><em>dragover<\/em><\/strong>: el evento cuando estamos sobre el elemento. Es el evento que se va a estar ejecutando mientras tengamos un archivo sobre la zona que es <strong>DRAG AND DROP<\/strong>.<\/li>\n\n\n\n<li><strong><em>dragleave<\/em> <\/strong>(es como el <strong><em>mouseout<\/em><\/strong>): el evento cuando sales de la zona arrastrable y soltable.<\/li>\n\n\n\n<li><strong><em>drop<\/em><\/strong>: el evento cuando soltamos el archivo. Es realmente el evento que hace que los archivos suban al servidor.<\/li>\n<\/ul>\n\n\n\n<p>Unicamente vamos a modificar el archivo <em>uploader.html<\/em>, al que le vamos a llamar ahora <em>uploader-drag-and-drop.html<\/em>, cuya sintaxis es la siguiente.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&nbsp; &lt;head&gt;\n&nbsp; &nbsp; &lt;meta charset=\"UTF-8\" \/&gt;\n&nbsp; &nbsp; &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/&gt;\n&nbsp; &nbsp; &lt;title&gt;Uploader Drag and Drop con AJAX&lt;\/title&gt;\n&nbsp; &nbsp; &lt;style&gt;\n&nbsp; &nbsp; &nbsp; html {\n&nbsp; &nbsp; &nbsp; &nbsp; box-sizing: border-box;\n&nbsp; &nbsp; &nbsp; &nbsp; font-family: sans-serif;\n&nbsp; &nbsp; &nbsp; &nbsp; font-size: 16px;\n&nbsp; &nbsp; &nbsp; }\n\n&nbsp; &nbsp; &nbsp; *,\n&nbsp; &nbsp; &nbsp; *::after,\n&nbsp; &nbsp; &nbsp; *::before {\n&nbsp; &nbsp; &nbsp; &nbsp; box-sizing: inherit;\n&nbsp; &nbsp; &nbsp; }\n\n&nbsp; &nbsp; &nbsp; body {\n&nbsp; &nbsp; &nbsp; &nbsp; margin: 0;\n&nbsp; &nbsp; &nbsp; }\n\n&nbsp; &nbsp; &nbsp; main {\n&nbsp; &nbsp; &nbsp; &nbsp; display: flex;\n&nbsp; &nbsp; &nbsp; &nbsp; flex-direction: column;\n&nbsp; &nbsp; &nbsp; &nbsp; justify-content: center;\n&nbsp; &nbsp; &nbsp; &nbsp; align-items: center;\n&nbsp; &nbsp; &nbsp; &nbsp; text-align: center;\n&nbsp; &nbsp; &nbsp; &nbsp; min-height: 100vh;\n&nbsp; &nbsp; &nbsp; }\n\n&nbsp; &nbsp; &nbsp; progress {\n&nbsp; &nbsp; &nbsp; &nbsp; margin-top: 1rem;\n&nbsp; &nbsp; &nbsp; }\n\n&nbsp; &nbsp; &nbsp; .drop-zone {\n&nbsp; &nbsp; &nbsp; &nbsp; margin-left: auto;\n&nbsp; &nbsp; &nbsp; &nbsp; margin-right: auto;\n&nbsp; &nbsp; &nbsp; &nbsp; border: thin dotted #000;\n&nbsp; &nbsp; &nbsp; &nbsp; width: 80%;\n&nbsp; &nbsp; &nbsp; &nbsp; height: 40vh;\n&nbsp; &nbsp; &nbsp; &nbsp; display: flex;\n&nbsp; &nbsp; &nbsp; &nbsp; justify-content: center;\n&nbsp; &nbsp; &nbsp; &nbsp; align-items: center;\n&nbsp; &nbsp; &nbsp; &nbsp; text-align: center;\n&nbsp; &nbsp; &nbsp; }\n\n&nbsp; &nbsp; &nbsp; .drop-zone.is-active {\n&nbsp; &nbsp; &nbsp; &nbsp; border: thick dashed #000;\n&nbsp; &nbsp; &nbsp; &nbsp; background-color: rgba(0, 128, 0, 0.5);\n&nbsp; &nbsp; &nbsp; &nbsp; animation: pulse 1.5s infinite;\n&nbsp; &nbsp; &nbsp; &nbsp; animation-timing-function: linear;\n&nbsp; &nbsp; &nbsp; }\n\n&nbsp; &nbsp; &nbsp; @keyframes pulse {\n&nbsp; &nbsp; &nbsp; &nbsp; 0%,\n&nbsp; &nbsp; &nbsp; &nbsp; 100% {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; transform: scale(1);\n&nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &nbsp; &nbsp; 50% {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; transform: scale(1.1);\n&nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &lt;\/style&gt;\n&nbsp; &lt;\/head&gt;\n\n&nbsp; &lt;body&gt;\n&nbsp; &nbsp; &lt;main&gt;\n&nbsp; &nbsp; &nbsp; &lt;article class=\"drop-zone\"&gt;\n&nbsp; &nbsp; &nbsp; &nbsp; &lt;p&gt;Arrastra y suelta tus archivos...&lt;\/p&gt;\n&nbsp; &nbsp; &nbsp; &lt;\/article&gt;\n&nbsp; &nbsp; &lt;\/main&gt;\n\n&nbsp; &nbsp; &lt;script&gt;\n&nbsp; &nbsp; &nbsp; const d = document,\n&nbsp; &nbsp; &nbsp; &nbsp; $main = d.querySelector(\"main\"),\n&nbsp; &nbsp; &nbsp; &nbsp; $dropZone = d.querySelector(\".drop-zone\");\n&nbsp; &nbsp; &nbsp; \/\/ Creamos funci\u00f3n que mediante AJAX permita subir la carga de archivos\n&nbsp; &nbsp; &nbsp; \/\/ Esta funci\u00f3n se ejecutar\u00e1 por cada archivo que reciba el input\n\n&nbsp; &nbsp; &nbsp; const uploader = (file) =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; const xhr = new XMLHttpRequest(),\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; formData = new FormData();\n&nbsp; &nbsp; &nbsp; &nbsp; formData.append(\"file\", file);\n\n&nbsp; &nbsp; &nbsp; &nbsp; xhr.addEventListener(\"readystatechange\", (e) =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (xhr.readyState !== 4) return;\n\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (xhr.status &gt;= 200 &amp;&amp; xhr.status &lt; 300) {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let json = JSON.parse(xhr.responseText);\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(json);\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let message = xhr.statusText || \"Ocurri\u00f3 un error\";\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(`Error ${xhr.status}: ${message}`);\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\n&nbsp; &nbsp; &nbsp; &nbsp; });\n\n&nbsp; &nbsp; &nbsp; &nbsp; xhr.open(\"POST\", \"uploader.php\");\n&nbsp; &nbsp; &nbsp; &nbsp; xhr.setRequestHeader(\"enc-type\", \"multipart\/form-data\");\n&nbsp; &nbsp; &nbsp; &nbsp; xhr.send(formData);\n&nbsp; &nbsp; &nbsp; };\n\n&nbsp; &nbsp; &nbsp; const progressUpload = (file) =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; const $progress = d.createElement(\"progress\"),\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $span = d.createElement(\"span\");\n&nbsp; &nbsp; &nbsp; &nbsp; $progress.value = 0;\n&nbsp; &nbsp; &nbsp; &nbsp; $progress.max = 100;\n&nbsp; &nbsp; &nbsp; &nbsp; $main.insertAdjacentElement(\"beforeend\", $progress);\n&nbsp; &nbsp; &nbsp; &nbsp; $main.insertAdjacentElement(\"beforeend\", $span);\n&nbsp; &nbsp; &nbsp; &nbsp; const fileReader = new FileReader();\n&nbsp; &nbsp; &nbsp; &nbsp; fileReader.readAsDataURL(file);\n\n&nbsp; &nbsp; &nbsp; &nbsp; fileReader.addEventListener(\"progress\", (e) =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let progress = parseInt((e.loaded * 100) \/ e.total);\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $progress.value = progress;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $span.innerHTML = `&lt;b&gt;${file.name} - ${progress}%&lt;\/b&gt;`;\n&nbsp; &nbsp; &nbsp; &nbsp; });\n\n&nbsp; &nbsp; &nbsp; &nbsp; fileReader.addEventListener(\"loadend\", (e) =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uploader(file);\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setTimeout(() =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $main.removeChild($progress);\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $main.removeChild($span);\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, 3000);\n&nbsp; &nbsp; &nbsp; &nbsp; });\n&nbsp; &nbsp; &nbsp; };\n\n&nbsp; &nbsp; &nbsp; $dropZone.addEventListener(\"dragover\", (e) =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; e.preventDefault();\n&nbsp; &nbsp; &nbsp; &nbsp; e.stopPropagation();\n&nbsp; &nbsp; &nbsp; &nbsp; e.target.classList.add(\"is-active\");\n&nbsp; &nbsp; &nbsp; });\n\n&nbsp; &nbsp; &nbsp; $dropZone.addEventListener(\"dragleave\", (e) =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; e.preventDefault();\n&nbsp; &nbsp; &nbsp; &nbsp; e.stopPropagation();\n&nbsp; &nbsp; &nbsp; &nbsp; e.target.classList.remove(\"is-active\");\n&nbsp; &nbsp; &nbsp; });\n\n&nbsp; &nbsp; &nbsp; $dropZone.addEventListener(\"drop\", (e) =&gt; {\n&nbsp; &nbsp; &nbsp; &nbsp; e.preventDefault();\n&nbsp; &nbsp; &nbsp; &nbsp; e.stopPropagation();\n&nbsp; &nbsp; &nbsp; &nbsp; const files = Array.from(e.dataTransfer.files);\n&nbsp; &nbsp; &nbsp; &nbsp; files.forEach((el) =&gt; progressUpload(el));\n&nbsp; &nbsp; &nbsp; &nbsp; e.target.classList.remove(\"is-active\");\n&nbsp; &nbsp; &nbsp; });\n&nbsp; &nbsp; &lt;\/script&gt;\n&nbsp; &lt;\/body&gt;\n&lt;\/html&gt;<\/pre>\n\n\n\n<p>El ejercicio completo est\u00e1 en el siguiente ZIP:<\/p>\n\n\n\n<div class=\"wp-block-file alignleft\"><a id=\"wp-block-file--media-f0ea9857-1401-4516-b7e2-5b95f581c161\" href=\"https:\/\/blog.sutilweb.eu\/wp-content\/uploads\/2024\/08\/Drag-and-Drop.zip\">Drag-and-Drop<\/a><a href=\"https:\/\/blog.sutilweb.eu\/wp-content\/uploads\/2024\/08\/Drag-and-Drop.zip\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-f0ea9857-1401-4516-b7e2-5b95f581c161\">Descarga<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>En este cap\u00edtulo vamos a hacer que nuestro cargador de archivos sea DRAG AND DROP, para lo que vamos a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1609,"menu_order":2,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-1619","page","type-page","status-publish","hentry"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Sutil Web","author_link":"https:\/\/sutilweb.eu\/index.php\/author\/sutilweb\/"},"uagb_comment_info":0,"uagb_excerpt":"En este cap\u00edtulo vamos a hacer que nuestro cargador de archivos sea DRAG AND DROP, para lo que vamos a [&hellip;]","_links":{"self":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/1619","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/comments?post=1619"}],"version-history":[{"count":3,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/1619\/revisions"}],"predecessor-version":[{"id":1623,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/1619\/revisions\/1623"}],"up":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/1609"}],"wp:attachment":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/media?parent=1619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}