1

When you click the Add New button next to the Media Library page title...

enter image description here

It opens the Drop files to upload template...

enter image description here

I want to replicate that on my plugin settings page. Ideally using default WP resources. Can't find anything specifically about this. Any guidance will be greatly appreciated. Thanks in advance.

6
  • Seriously? Couldn't find anything? SOF Link1 SOF Link2 WPSE External Link
    – Yashar
    Feb 18, 2020 at 9:21
  • Does this answer your question? Can I use the wp media uploader for my own plugin?
    – Yashar
    Feb 18, 2020 at 9:27
  • The links from your first comment are between 4 and 8 years old. The Media Library has been rebuilt. None of those answers apply
    – Kirkland
    Feb 18, 2020 at 9:37
  • 1
    @Yashar The link in your second comment is a step in the right direction, but barely scratches the surface. I dug through source code and solved this. When I have time I'll post the answer. Long story short... WP is using Backbone.js for this now. I initiated UploaderInline and UploaderWindow and handled file uploads like normal.
    – Kirkland
    Feb 18, 2020 at 9:44
  • Does this answer your question? Use Media Uploader in Plugin
    – butlerblog
    Feb 20, 2020 at 4:46

1 Answer 1

2

WordPress is using Backbone JS for the Media Library. At this time, there doesn't seem to be much in terms of official documentation. I dug through some source code and this is how I got it working...

Disclaimer:

  1. This is my first time hacking at BackboneJS, so this could all be totally wrong.
  2. Class names matter for both WP theming and functionality. Edit with caution.
  3. Obviously this is streamlined. You'll need to add your own form validation, nonce, script enqueuing, etc.

PHP File

You need this to load all the Backbone templates for the Media Library.

wp_enqueue_media();

If it worked properly then you'll find these when you inspect...

enter image description here

This is the Add New button.

<button class="page-title-action add-new-image">
  <?php echo esc_html_x( 'Add New', 'file' ); ?>
</button>

This is where Backbone will load the templates.

<div class="media-frame mode-grid"></div>

This is the form that will handle the file uploads.

<form method="POST" enctype="multipart/form-data">

  <!--
    * the "enctype" is important
    * remove "multiple" attribute to limit to a single file
    * the brackets in the "name" attribute make it an array for multiple files
    * auto submits when the user selects a file
  -->

  <input id="uploaded_files"
         multiple="multiple"
         name="uploaded_files[]"
         onchange="form.submit()"
         type="file" >
  </input>

  ...

</form>

Do whatever you do to validate the form, then something like this to handle the file uploads...

if (empty($_FILES)) {
  echo '<div class="error"><p>No files were uploaded.</p></div>';
} else if (isset($_FILES['uploaded_files'])) {
  $files = $_FILES["uploaded_files"];

  // written for multiple files
  foreach ($files['name'] as $key => $value) {
    if ($files['name'][$key]) {
      $file = array(
        'name' => $files['name'][$key],
        'type' => $files['type'][$key],
        'tmp_name' => $files['tmp_name'][$key],
        'error' => $files['error'][$key],
        'size' => $files['size'][$key]
      );

      if ($file['error'] !== UPLOAD_ERR_OK) {
        echo '<div class="error"><p>Upload Error: ('. $file['error'] .') for <strong>'. $file['name'] .'</strong></p></div>';
        return;
      }

      $_FILES = array("uploaded_files" => $file);

      // 0 = post ID = none = unattached
      // if you want to attach it to a post then replace the 0 with the post ID
      $uploaded = media_handle_upload('uploaded_files', 0);

      if (is_wp_error($uploaded)) {
        echo '<div class="error"><p>'. $uploaded->get_error_message() . '</p></div>';
      } else {
        echo '<div class="updated"><p>File uploaded: <strong>'. $file['name'] .'</strong></p></div>';
      }
    }
  }
}

JS File

Many of the selectors you see in this JS file come from elements in WordPress templates loaded by Backbone, so don't change them. You won't find them in your files, but they are required.

// File Uploader (aka: uploaderInline)
// This loads the HTML markup for the dashed box and its contents
var uploaderInline = new wp.media.view.UploaderInline({
  controller: {
    state: function() {
      return {
        get: function(x) {
          switch (x) {
            case "suggestedHeight":
              return null;
            case "suggestedWidth":
              return null;
          }
        }
      };
    }
  },
  options: {
    browser: $(".add-new-image"),
    postId: 0 // 0 = unattached
  },
  canClose: true
}).render();

uploaderInline.ready();

$(".media-frame").append(uploaderInline.el);

$(".uploader-inline .drop-instructions").css({ display: "block" });

uploaderInline.hide();

// DropZone (aka: uploaderWindow)
// This enables the drag & drop area
var uploaderWindow = new wp.media.view.UploaderWindow({
  controller: {
    trigger: function() {},
    on: function() {}
  },
  uploader: {
    dropzone: $(".uploader-inline"),
    container: $(".uploader-inline")
  }
}).render();

uploaderWindow.ready();

$(".uploader-inline").append(uploaderWindow.el);

// This will show/hide the File Uploader
$(".add-new-image").on("click", function(e) {
  e.preventDefault();

  var isHidden = $(".uploader-inline").is(":hidden");

  if (isHidden) {
    uploaderInline.show();
  } else {
    uploaderInline.hide();
  }
});

// This triggers the file selector when the user
// clicks the "Select Files" button in the dashed box
$("button.browser").on("click", function() {
  $("#uploaded_files").click();
});

Useful Resources

File Uploader (aka: uploaderInline)

DropZone (aka: uploaderWindow)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.