Thanks to the innovations of HTML5, creating Drag and Drop interfaces has become much easier. Unfortunately, these innovations do not yet have extensive browser support, but I hope this will change soon (currently works in Firefox 4+, Chrome and Opera 11.10).

Markup I must say right away that the article was written more for beginners than for professionals. Therefore, some points will be described in great detail.

First, we need to create an HTML file with the following content:

To download, drag the file here.

All our work will happen with the dropZone container. Now let's add styles for our document (style.css):

Body ( font: 12px Arial, sans-serif; ) #dropZone ( color: #555; font-size: 18px; text-align: center; width: 400px; padding: 50px 0; margin: 50px auto; background: #eee ; border: 1px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px ) #dropZone.hover ( background: #ddd; border-color: #aaa; ) #dropZone.error ( background: #faa; border-color: #f00; ) #dropZone.drop ( background: #afa; border-color: #0f0; )

In styles, you can notice three states for the dropZone element: on hover, if some error occurs, and when successful.

Loading script Now we get to the fun part - writing JavaScript code. First, we need to create variables, in one of which we will place our dropZone, and in the second we will indicate maximum size file.

$(document).ready(function() ( var dropZone = $("#dropZone"), maxFileSize = 1000000; // maximum file size - 1 MB. ));

Next we need to check if the browser supports Drag and Drop, for this we will use the FileReader function. If the browser does not support Drag and Drop, then inside the dropZone element we will write “Not supported by the browser!” and add the “error” class.

If (typeof(window.FileReader) == "undefined") ( dropZone.text("Not supported by browser!"); dropZone.addClass("error"); )

The next thing we will do is animate the effect of dragging a file onto the dropZone. We will track these actions using the “ondragover” and “ondragleave” events. But, since these events cannot be tracked by the jQuery object, we need to access not just “dropZone”, but “dropZone”.

DropZone.ondragover = function() ( dropZone.addClass("hover"); return false; ); dropZone.ondragleave = function() ( dropZone.removeClass("hover"); return false; );

Now we need to write an event handler for the “ondrop” event - this is the event when the dragged file is dropped. In some browsers, when you drag files into the browser window, they automatically open, so that this does not happen, we need to cancel the standard behavior of the browser. We also need to remove the “hover” class and add the “drop” class.

DropZone.ondrop = function(event) ( event.preventDefault(); dropZone.removeClass("hover"); dropZone.addClass("drop"); );

Var file = event.dataTransfer.files; if (file.size > maxFileSize) ( dropZone.text("The file is too big!"); dropZone.addClass("error"); return false; )

Now we need to write an AJAX request that sends our file to the handler. To create AJAX request we will use the XMLHttpRequest object. Let's add two event handlers for the XMLHttpRequest object: one will show the file download progress, and the second will show the download result. We will specify the file upload.php as a handler.

Var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", uploadProgress, false); xhr.onreadystatechange = stateChange; xhr.open("POST", "/upload.php"); xhr.setRequestHeader("X-FILE-NAME", file.name); xhr.send(file);

Now let's take a look at the download progress and download result functions. There is nothing complicated about the “uploadProgress” function, just simple math.

Function uploadProgress(event) ( var percent = parseInt(event.loaded / event.total * 100); dropZone.text("Loading: " + percent + "%"); )

In the "stateChange" function, we need to check whether the loading process is completed, and if so, we need to check if any error has occurred. The successful request code is “200”; if the code differs from this, it means that an error occurred.

Function stateChange(event) ( if (event.target.readyState == 4) ( if (event.target.status == 200) ( dropZone.text("Upload completed successfully!"); ) else ( dropZone.text(" An error has occurred!"); dropZone.addClass("error"); ) ) )

The JavaScript part is completed.

Server part All that remains for us is to write a simple handler that will save the file in the location we need. I won’t go too deep into writing the handler, but will just give a small example in PHP.

That's all, I hope the article was useful to you.

You can download the source files

This markup doesn"t have anything specifically to do with drag and drop. It"s just a normal, functional, albeit with some extra HTML elements for potential states.

Choose a file or drag it here. Upload Done! Error! .

We"ll hide those states until we need them:

Box__dragndrop, .box__uploading, .box__success, .box__error ( display: none; )

A little explanation:

  • Regarding states: .box__uploading element will be visible during the Ajax process of file upload (and the others will still be hidden). Then .box__success or .box__error will be shown depending on what happens.
  • input and label are the functional parts of the form. I wrote about styling these together in my post about customizing file inputs. In that post I also described the purpose of attribute. The input and label also serve as an alternative for selecting files in the standard way (or the only way if drag and drop isn't supported).
  • .box__dragndrop will be shown if a browser supports drag and drop file upload functionality.
Feature detection

We can"t 100% rely on browsers supporting drag and drop. We should provide a fallback solution. And so: feature detection. Drag & drop file upload relies on a number of different JavaScript API"s, so we"ll need to check on all of them.

Greetings everyone! In this article I want to talk about several of my experiments with HTML5. I'll start from afar. We all periodically have to work with various web interfaces and often have the feeling that this work could be organized more efficiently.

Perhaps in some cases the service developers are to blame, but often the problem lies in the limitations imposed by browsers. Let's consider uploading files to the server. In most cases, you will be presented with a standard field with a button to select a file from your computer and/or a field in which you can specify the URL of a file located somewhere on the Web.

Downloading files from local computer Let’s not touch it for now, I plan to publish a separate post on this topic, let’s look at downloading from a remote server.

Problems start from the very first step. Even if you clearly understand where to look for a URL and are good at using tools like firebug, it will still take a few clicks to get the right address. It would be much more convenient to simply drag the desired image from one browser window to another.

I will show an example of the implementation of such an interface in this article. If you want, you can see how it works on the demo page or .

Pay attention! This example only works in Google browser Chrome. In theory, Firefox and Safari support all the necessary technologies, but I haven’t figured them out yet. As objects for “dragging”, I took mainly pictures from Wikipedia. Several problems were noticed related to non-Latin characters in the URLs of images, but in order not to overload the example with checks and transformations, I left them as is.

Operating principle

The HTML5 standard provides support for dragging and dropping page objects. By the way, I have already shown an example of the simplest implementation of D&D - Drag & Drop using HTML5. And besides, there are quite a few JavaScript libraries that implement D&D support.

But here it is important to understand that if you need to “drag” pictures from third-party resources, then you won’t be able to use libraries. Because you won't be able to add your JS code to someone else's page. And in order to download a picture, we need to get its URL, i.e. The browser must also transmit its parameters along with the dragged object (for example, the src attribute of an image or the entire img tag).

In this case, we can create a “receiver” of pictures on our page. This will be a regular div with a drop event handler assigned. If the user “drops” the image above this div, the handler will be called and in the first parameter it will receive an object containing information about the image being dragged.

Implementation

Let's start with our application page.

Images Upload


It contains two blocks: images – here we will show the downloaded images and img_target – you need to drag pictures onto this block. At the bottom of the page we connect the jQuery library and the main.js script, which will send information about the dragged images to the server.

Let's look at main.js
$(function() (
$("#img_target")
.bind("dragenter", function(event) (
$(this).addClass("drop_here");
return false;
})
.bind("dragleave", function(event) (

return false;
})
.bind("dragover", function(event) (
return false;
})
.bind("drop", function(event) (
$(this).removeClass("drop_here");
var srcRegex = /src=\"([^\s]+)\"/ig;
var data = event.originalEvent.dataTransfer.getData("text/html");
var img_data = srcRegex.exec(data);
$.post("upload.php", ("file_url":img_data), function(res) (
var response = eval("(" + res + ")");
$("#images").append($(""));
});
return true;
});
});
Here we assign handlers to the dragenter, dragleave and dragover events. All of them should simply return false and, in order to somehow inform the user that the image can be “dropped”, in the dragenter handler we set the CSS class drop_here for the receiver block. Most of the work is done in the drop event handler. When this event occurs, we read information about the “reset” object and “cut” the value of the src attribute, i.e. URL of the image. The information is transferred in the event.originalEvent.dataTransfer object.

Then we form a regular AJAX request and pass the found URL as a parameter. The server script (upload.php) will receive the URL of the image on the remote server and upload it. And in response to the AJAX request, it will send the new URL of the loaded image. In turn, the AJAX request handler will create an img tag and insert it into the images block. Thus, the downloaded pictures will appear above the download field.

Consider upload.php

The operating principle is as follows. We read the URL of the image and try to download it. If the image is uploaded, save it to the upload folder. Receiving an image from a remote server is carried out using the fread functions. The file is read in 1kB blocks. This approach allows you to interrupt the download of a file if its size exceeds a specified limit (in this case, 300kB).

After downloading the file, we form a URL for it and send it to the browser in JSON format. As you can see, implementing such a bootloader is not difficult. And it is quite convenient to use. Naturally, the main drawback is the support of HTML5 by browsers, or rather the lack thereof. However, if you are creating an interface for employees of a company, and you can specify the type of browser, then HTML5 can be used.

  • HTML

Thanks to the innovations of HTML5, creating Drag and Drop interfaces has become much easier. Unfortunately, these innovations do not yet have extensive browser support, but I hope this will change soon (currently works in Firefox 4+, Chrome and Opera 11.10).

Markup I must say right away that the article was written more for beginners than for professionals. Therefore, some points will be described in great detail.

First, we need to create an HTML file with the following content:

To download, drag the file here.

All our work will happen with the dropZone container. Now let's add styles for our document (style.css):

Body ( font: 12px Arial, sans-serif; ) #dropZone ( color: #555; font-size: 18px; text-align: center; width: 400px; padding: 50px 0; margin: 50px auto; background: #eee ; border: 1px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px ) #dropZone.hover ( background: #ddd; border-color: #aaa; ) #dropZone.error ( background: #faa; border-color: #f00; ) #dropZone.drop ( background: #afa; border-color: #0f0; )

In styles, you can notice three states for the dropZone element: on hover, if some error occurs, and when successful.

Loading script Now we get to the fun part - writing JavaScript code. First, we need to create variables, in one of which we will place our dropZone, and in the second we will indicate the maximum file size.

$(document).ready(function() ( var dropZone = $("#dropZone"), maxFileSize = 1000000; // maximum file size - 1 MB. ));

Next we need to check if the browser supports Drag and Drop, for this we will use the FileReader function. If the browser does not support Drag and Drop, then inside the dropZone element we will write “Not supported by the browser!” and add the “error” class.

If (typeof(window.FileReader) == "undefined") ( dropZone.text("Not supported by browser!"); dropZone.addClass("error"); )

The next thing we will do is animate the effect of dragging a file onto the dropZone. We will track these actions using the “ondragover” and “ondragleave” events. But, since these events cannot be tracked by the jQuery object, we need to access not just “dropZone”, but “dropZone”.

DropZone.ondragover = function() ( dropZone.addClass("hover"); return false; ); dropZone.ondragleave = function() ( dropZone.removeClass("hover"); return false; );

Now we need to write an event handler for the “ondrop” event - this is the event when the dragged file is dropped. In some browsers, when you drag files into the browser window, they automatically open, so that this does not happen, we need to cancel the standard behavior of the browser. We also need to remove the “hover” class and add the “drop” class.

DropZone.ondrop = function(event) ( event.preventDefault(); dropZone.removeClass("hover"); dropZone.addClass("drop"); );

Var file = event.dataTransfer.files; if (file.size > maxFileSize) ( dropZone.text("The file is too big!"); dropZone.addClass("error"); return false; )

Now we need to write an AJAX request that sends our file to the handler. To create an AJAX request we will use the XMLHttpRequest object. Let's add two event handlers for the XMLHttpRequest object: one will show the file download progress, and the second will show the download result. We will specify the file upload.php as a handler.

Var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", uploadProgress, false); xhr.onreadystatechange = stateChange; xhr.open("POST", "/upload.php"); xhr.setRequestHeader("X-FILE-NAME", file.name); xhr.send(file);

Now let's take a look at the download progress and download result functions. There is nothing complicated about the “uploadProgress” function, just simple math.

Function uploadProgress(event) ( var percent = parseInt(event.loaded / event.total * 100); dropZone.text("Loading: " + percent + "%"); )

In the "stateChange" function, we need to check whether the loading process is completed, and if so, we need to check if any error has occurred. The successful request code is “200”; if the code differs from this, it means that an error occurred.

Function stateChange(event) ( if (event.target.readyState == 4) ( if (event.target.status == 200) ( dropZone.text("Upload completed successfully!"); ) else ( dropZone.text(" An error has occurred!"); dropZone.addClass("error"); ) ) )

The JavaScript part is completed.

Server part All that remains for us is to write a simple handler that will save the file in the location we need. I won’t go too deep into writing the handler, but will just give a small example in PHP.

That's all, I hope the article was useful to you.

You can download the source files

And in this lesson I will show you an example of integrating the wonderful Dropzone.js plugin with your PHP website to upload files to the server in just a few lines of code.

Dropzone.JS is a wonderful open source library written in vanilla JS that provides you with a drag and drop interface for uploading files with file previews.

First, download the latest version of the library and its styles:

Then create an uploads folder and files index.php and upload.php

As a file index php may be the part of your code that contains the form for adding materials to the site. In my example, I will create a blank page with minimal markup and the included Dropzone.js library and styles:

As you probably noticed, we created a form with the upload.php action, but did not create any inputs for attaching files, and did not declare the enctype of the form. There is no error in this, everything is handled by the DropzoneJS library itself. All we need to do is give the form a dropzone class. By default, DropzoneJS finds all forms with this class and automatically draws its interface.

You can open the index.php page for execution in the browser and make sure that the library works as intended. Here's what I got:

Now let's create an upload handler for which we have already created an upload.php file. Here is an example of my simplest loading code:

Working with downloaded files

To fully interact with your files, we just need to add the ability to manipulate them. First, we need to add a piece of code to extract information about the stored files (name and size) and return it in JSON format.

To do this, update the upload.php file to this form (the else condition is inserted):

  • The PHP scandir function scans the uploads folder and returns an array of files or FALSE if the folder is empty.
  • We loop through the return value from the scandir function and save it into the $result array. Remember, we ignore "." And ".." since scandir will always return "." And ".." as valid content related to the current and previous directory.
  • We output the correct headers for JSON markup, and also convert the PHP array into a JSON string using the json_encode function.
  • Now it's time to update index.php:

    Dropzone.options.myDropzone = ( init: function() ( thisDropzone = this; $.get("upload.php", function(data) ( $.each(data, function(key,value)( var mockFile = ( name : value.name, size: value.size ); thisDropzone.options.addedfile.call(thisDropzone, mockFile); thisDropzone.options.thumbnail.call(thisDropzone, mockFile, "uploads/"+value.name )); ));

    What have we done here? Let's figure it out:

  • Alas and ah, we added Jquery library to our page. This is not really a necessity for DropzoneJs. We are only using the JQuery $.get ajax function. At your discretion, you can implement similar requests in vue.js or whatever you prefer.
  • We have added an ID element (my-dropzone) to the form. This is necessary in order to transfer configuration values ​​to Dropzone. And for this we must have a unique identifier pointing to it. This way we can configure the library by assigning values ​​to Dropzone.options.myDropzone.
  • Let's initialize the main part of editing. What we've done here is passed a function to listen for the init event to Dropzone. This event is fired when Dropzone is initialized.
  • We receive an array of files from “upload.php” using ajax.
  • Create a mockFile using the values ​​from the server. MockFile is easy JavaScript objects with name and size properties. We then explicitly call Dropbox functions and add icons to bring existing files into the Dropzone upload area and create thumbnails of them.
  • If you did everything correctly. Upload some images and reload the form page. Previously uploaded files should automatically appear in the Dropzone area.


    Close