I'm creating a plugin and i have an admin page
In the options of that page, i would like to add a button that allow me to open the Wordpress media library and select an image from it, after that, get the URL of the selected image and the alt attribute.
If it is possible, how can i do that using AJAX?
First you would need to enqueue wordpress core media scripts and a custom js script
function my_enqueue_media_lib_uploader() {
//Core media script
wp_enqueue_media();
// Your custom js file
wp_register_script( 'media-lib-uploader-js', plugins_url( 'media-lib-uploader.js' , __FILE__ ), array('jquery') );
wp_enqueue_script( 'media-lib-uploader-js' );
}
add_action('admin_enqueue_scripts', 'my_enqueue_media_lib_uploader');
Then let say you have this markup within your options page: an upload button and a text input to store the selected image url
<form method="post">
<input id="image-url" type="text" name="image" />
<input id="upload-button" type="button" class="button" value="Upload Image" />
<input type="submit" value="Submit" />
</form>
You need to add this javascript code to invoke the uploader popup
jQuery(document).ready(function($){
var mediaUploader;
$('#upload-button').click(function(e) {
e.preventDefault();
// If the uploader object has already been created, reopen the dialog
if (mediaUploader) {
mediaUploader.open();
return;
}
// Extend the wp.media object
mediaUploader = wp.media.frames.file_frame = wp.media({
title: 'Choose Image',
button: {
text: 'Choose Image'
}, multiple: false });
// When a file is selected, grab the URL and set it as the text field's value
mediaUploader.on('select', function() {
attachment = mediaUploader.state().get('selection').first().toJSON();
$('#image-url').val(attachment.url);
});
// Open the uploader dialog
mediaUploader.open();
});
});
Once the image is selected, your image-url input will now contain the url and will be saved on form submit.
The use case is: I have plugin that contain index.php as main file, I want to be able to click on a button and the media library opened and select an image from it, this image should be load into an image tag.
1- add script to your main PHP plugin
// index.php
// ...
// add script js for page
add_action('admin_enqueue_scripts', function () {
// Enqueue WordPress media scripts
if ($_GET["page"]== 'debug_area') {
wp_enqueue_media();
// Enqueue custom script that will interact with wp.media
wp_enqueue_script(
'myprefix_script',
plugins_url('/load_img.js', __FILE__),
array('jquery'),
'0.1');
}
});
// add ajax action to get the image async
add_action('wp_ajax_get_image_from_media_lib', function () {
if (isset($_GET['id'])) {
$image = wp_get_attachment_image(
filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT),
'medium',
false,
array('id' => 'image_preview')
);
$data = array(
'image' => $image,
);
wp_send_json_success($data);
} else {
wp_send_json_error();
}
});
2- add file JS that already included in enqueue
// load_img.js
jQuery(document).ready(_ => {
console.clear();
/**
* Define media_lib_frame as wp.media object
*/
const media_lib_frame = wp.media({
title: 'Select Media',
multiple: false,
library: {
type: 'image',
}
});
/**
* On close, get selections and save to the hidden input
* plus other AJAX stuff to refresh the image preview
*/
media_lib_frame.on('close', _ => {
const selection = media_lib_frame.state().get('selection');
const gallery_ids = selection.map(attachment => attachment['id']);
const ids = gallery_ids.join(",");
jQuery('input#idImage').val(ids);
loadImage(ids);
});
/**
* On open, get the id from the hidden input
* and select the appropriate images in the media manager
*/
media_lib_frame.on('open', _ => {
const selection = media_lib_frame.state().get('selection');
const ids = jQuery('input#idImage').val().split(',');
ids.forEach(id => {
const attachment = wp.media.attachment(id);
attachment.fetch();
selection.add(attachment ? [attachment] : []);
});
});
jQuery('button#btnOpenMediaLibFrame').click(e => {
e.preventDefault();
media_lib_frame.open();
});
});
// Ajax request to refresh the image preview
const loadImage = the_id => {
const data = {action: 'get_image_from_media_lib', id: the_id};
jQuery.get(ajaxurl, data, response => {
if (response.success === true) {
jQuery('#image_preview').replaceWith(response.data.image);
}
});
}
3- add this HTML into the function that responsible for render view
<img id="image_preview"/>
<input
type="hidden"
id="idImage"
class="regular-text"/>
<button
type='button'
class="button-primary"
id="btnOpenMediaLibFrame">
Select a image
</button>
Related
I´am currently work on a Wordpress Plugin and I like to set a custom upload directory for the wordpress media uploader, which I use on one subpage of my plugin. I have searched a whole week but I can´t find my mistake or a solution for my problem - so I hope anyone could help.
I add a submenu page where I call a method to load the WP Media Uploader:
add_submenu_page('w3p-listing', $pubAtt, $pubAtt, 'manage_options', 'w3p-attachments', array('w3pUploader', 'media_upload_init') );
This call the media_upload_init Method on the class w3pUploader which looks like that:
class w3pUploader {
function __construct()
{
}
public static function media_upload_init() {
// jQuery
wp_enqueue_script('jquery');
// This will enqueue the Media Uploader script
wp_enqueue_media();
?>
<div>
<label for="image_url">Image</label>
<input type="text" name="image_url" id="image_url" class="regular-text">
<input type="button" name="upload-btn" id="upload-btn" class="button-secondary" value="Upload Image">
</div>
<script type="text/javascript">
jQuery(document).ready(function($){
$('#upload-btn').click(function(e) {
e.preventDefault();
var image = wp.media({
title: 'Upload Image',
// mutiple: true if you want to upload multiple files at once
multiple: false
}).open()
.on('select', function(e){
// This will return the selected image from the Media Uploader, the result is an object
var uploaded_image = image.state().get('selection').first();
// We convert uploaded_image to a JSON object to make accessing it easier
// Output to the console uploaded_image
console.log(uploaded_image);
var image_url = uploaded_image.toJSON().url;
// Let's assign the url value to the input field
$('#image_url').val(image_url);
});
});
});
</script>
<?php
}
function awesome_wallpaper_dir( $param ){
$mydir = '/awesome';
$param['path'] = $param['path'] . $mydir;
$param['url'] = $param['url'] . $mydir;
return $param;
}
}
I found several topics about that but not one solve my issue:
https://codex.wordpress.org/Plugin_API/Filter_Reference/upload_dir
https://wordpress.stackexchange.com/questions/76895/different-upload-directory-based-on-post-type-in-a-theme/77007#77007
https://wordpress.stackexchange.com/questions/83248/post-type-specific-upload-folder-in-3-5/83254#83254
I tried to add the filter before the wp_enque_media() function, in my activation class and also in my plugin constructor but the upload dir hook was not recognized or gave me errors like: "Error on uploading media ..."
I used that line:
add_filter( 'upload_dir', array('w3pUploader', 'customize_upload_dir' ));
I hope anyone has a idea where I am wrong or how to solve that problem.
Thanks for your help :)
I solved it in a bit different way but it works:
I added those 3 lines after the enqueue_media() function in the w3pUploader class:
update_option('upload_path',WP_CONTENT_DIR.'/uploads/CUSTOM_FOLDER');
update_option('upload_url_path','../wp-content/uploads/CUSTOM_FOLDER');
update_option('uploads_use_yearmonth_folders', false);
The three update option calls set the new upload dir global when the media uploader is opened on my special page.
Then I updated the Javascript part with a close hook, so when the media uploader is closed in any way it got triggered:
on('close',function() {
var data = {
action: 'reset_upload_dir'
};
jQuery.post(ajaxurl, data, function(response) {
alert('Got this from the server: ' + response);
});
});
The reset_upload_dir is a custom ajax function with I subscribed in my plugin main file in the constructor via:
add_action( 'wp_ajax_reset_upload_dir', array('w3pUploader', 'reset_upload_dir' ));
As the last step I added the reset_upload_dir function in my w3pUploader class:
public static function reset_upload_dir() {
update_option('upload_path',null);
update_option('upload_url_path',null);
update_option('uploads_use_yearmonth_folders', true);
echo "RETURN";
wp_die();
}
This reset_upload_dir function set the options to null, which indicated wordpress to use its standards directory.
So the whole w3pUploader.php looks like that:
class w3pUploader {
function __construct()
{
}
public static function reset_upload_dir() {
update_option('upload_path',null);
update_option('upload_url_path',null);
update_option('uploads_use_yearmonth_folders', true);
echo "RETURN";
wp_die();
}
public static function media_upload_init() {
// jQuery
wp_enqueue_script('jquery');
// This will enqueue the Media Uploader script
wp_enqueue_media();
update_option('upload_path',WP_CONTENT_DIR.'/uploads/w3p_publications');
update_option('upload_url_path','../wp-content/uploads/w3p_publications');
update_option('uploads_use_yearmonth_folders', false);
?>
<div>
<label for="image_url">Image</label>
<input type="text" name="image_url" id="image_url" class="regular-text">
<input type="button" name="upload-btn" id="upload-btn" class="button-secondary" value="Upload Image">
</div>
<script type="text/javascript">
jQuery(document).ready(function($){
$('#upload-btn').click(function(e) {
e.preventDefault();
var image = wp.media({
title: 'Upload Image',
// mutiple: true if you want to upload multiple files at once
multiple: false
}).open()
.on('select', function(e){
// This will return the selected image from the Media Uploader, the result is an object
var uploaded_image = image.state().get('selection').first();
// We convert uploaded_image to a JSON object to make accessing it easier
// Output to the console uploaded_image
console.log(uploaded_image);
var image_url = uploaded_image.toJSON().url;
// Let's assign the url value to the input field
$('#image_url').val(image_url);
}).on('close',function() {
var data = {
action: 'reset_upload_dir'
};
jQuery.post(ajaxurl, data, function(response) {
alert('Got this from the server: ' + response);
});
});
});
});
</script>
<?php
}
}
When I click the Add Media button on a Post/Page, I have the option to Add Media. After selecting media, I click Insert Into Post, and the images are inserted. However, there is another option, which is on the left sidebar. I can click Create Gallery. The image selecting process is the same, but when I click Create New Gallery, it goes to a new frame which allows me to edit the order of the images.
This second window is what I am after. I am calling the frame from a metabox, and I have gotten it successfully to allow me to grab single or multiple images and save the ID's as a string, as well as insert thumbnails live into a preview box. I cannot find anything about calling the Gallery frame.
My current code is as follows:
jQuery('#fg_select').on('click', function(event){
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frame = wp.media({
title: "Select Images For Gallery",
button: {text: "Select",},
library : { type : 'image'},
multiple: true // Set to true to allow multiple files to be selected
});
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
ids = jQuery('#fg_metadata').val().split(',');
ids.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
});
file_frame.on('ready', function() {
// Here we can add a custom class to our media modal.
// .media-modal doesn't exists before the frame is
// completly initialised.
$( '.media-modal' ).addClass( 'no-sidebar' );
});
// When an image is selected, run a callback.
file_frame.on('select', function() {
var imageIDArray = [];
var imageHTML = '';
var metadataString = '';
images = file_frame.state().get('selection');
images.each(function(image) {
imageIDArray.push(image.attributes.id);
imageHTML += '<li><button></button><img id="'+image.attributes.id+'" src="'+image.attributes.url+'"></li>';
});
metadataString = imageIDArray.join(",");
if(metadataString){
jQuery("#fg_metadata").val(metadataString);
jQuery("#featuredgallerydiv ul").html(imageHTML);
jQuery('#fg_select').text('Edit Selection');
jQuery('#fg_removeall').addClass('visible');
}
});
// Finally, open the modal
file_frame.open();
});
Any ideas?
EDIT:
I've gotten it to the point where it calls the gallery directly, without any sidebars, etc. However, it now ignores the on('select') call. I guess galleries send a different call when selecting the image?
jQuery(document).ready(function($){
// Uploading files
var file_frame;
jQuery('#fg_select').on('click', function(event){
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frame = wp.media({
frame: "post",
state: "featured-gallery",
library : { type : 'image'},
button: {text: "Edit Image Order"},
multiple: true
});
file_frame.states.add([
new wp.media.controller.Library({
id: 'featured-gallery',
title: 'Select Images for Gallery',
priority: 20,
toolbar: 'main-gallery',
filterable: 'uploaded',
library: wp.media.query( file_frame.options.library ),
multiple: file_frame.options.multiple ? 'reset' : false,
editable: true,
allowLocalEdits: true,
displaySettings: true,
displayUserSettings: true
}),
]);
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
ids = jQuery('#fg_metadata').val().split(',');
if (!empty(ids)) {
ids.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
}
});
file_frame.on('ready', function() {
// Here we can add a custom class to our media modal.
// .media-modal doesn't exists before the frame is
// completly initialised.
$( '.media-modal' ).addClass( 'no-sidebar' );
});
file_frame.on('change', function() {
// Here we can add a custom class to our media modal.
// .media-modal doesn't exists before the frame is
// completly initialised.
setTimeout(function(){
$('.media-menu a:first-child').text('← Edit Selection').addClass('button').addClass('button-large').addClass('button-primary');
},0);
});
// When an image is selected, run a callback.
file_frame.on('set', function() {
alert('test');
});
// Finally, open the modal
file_frame.open();
});
EDIT 2:
Okay, so I've gotten everything to fire correctly. But I can't decipher the outputted gallery code.
// When an image is selected, run a callback.
file_frame.on('update', function() {
var imageIDArray = [];
var imageHTML = '';
var metadataString = '';
images = file_frame.state().get('selection');
images.each(function(image) {
imageIDArray.push(image.attributes.id);
imageHTML += '<li><button></button><img id="'+image.attributes.id+'" src="'+image.attributes.url+'"></li>';
});
metadataString = imageIDArray.join(",");
if (metadataString) {
jQuery("#fg_metadata").val(metadataString);
jQuery("#featuredgallerydiv ul").html(imageHTML);
jQuery('#fg_select').text('Edit Selection');
jQuery('#fg_removeall').addClass('visible');
}
});
Nothing is coming out for $imageArray, or $imageHTML. $image is something, it's an [object object].
EDIT 3: As mentioned below in comment, the main problem with the code from Edit 2 is that when using Gallery, you have to call 'library' instead of 'selection'.
// Uploading files
var file_frame;
jQuery('#fg_select').on('click', function(event){
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frame = wp.media({
frame: "post",
state: "gallery",
library : { type : 'image'},
button: {text: "Edit Image Order"},
multiple: true
});
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
var ids = jQuery('#fg_metadata').val();
if (ids) {
idsArray = ids.split(',');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
}
});
// When an image is selected, run a callback.
file_frame.on('update', function() {
var imageIDArray = [];
var imageHTML = '';
var metadataString = '';
images = file_frame.state().get('library');
images.each(function(attachment) {
imageIDArray.push(attachment.attributes.id);
imageHTML += '<li><button></button><img id="'+attachment.attributes.id+'" src="'+attachment.attributes.url+'"></li>';
});
metadataString = imageIDArray.join(",");
if (metadataString) {
jQuery("#fg_metadata").val(metadataString);
jQuery("#featuredgallerydiv ul").html(imageHTML);
jQuery('#fg_select').text('Edit Selection');
jQuery('#fg_removeall').addClass('visible');
}
});
// Finally, open the modal
file_frame.open();
});
The main thing here I'm having difficulty with now is that I can't get it to open to gallery-edit with a selection. I can get it to open there, but there are no images selected. I'm looking into that. I'm also looking into re-opening instead of creating a new view and sending a pre-selection. If I go to the selection window, then the order window, but click the X to close, I can re-open to the order window. So there should be a way.
EDIT 4
As per code from answer below, I've changed the pre-selection code to:
file_frame.on('open', function() {
var library = file_frame.state().get('library');
var ids = jQuery('#fg_perm_metadata').val();
if (ids) {
idsArray = ids.split(',');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
library.add( attachment ? [ attachment ] : [] );
});
}
});
This allows me to re-open directly to the gallery-edit state and have images pre-selected. However, when I open directly to this state, I cannot click Cancel Gallery (return to image selection state). Clicking that button/link just closes the frame. I tried pre-filling both the library and the selection, but that doesn't work either. The following is from media-views.js, and seems to be what controls that button. Instead of changing the state to a specific state, it changes it to the previous state. Since we are opening directly to gallery-edit, there is no past state. I'm wondering if it's possible to open to gallery, and then on open, change to gallery-edit. Do it instantly so that the user doesn't see, but so that it gets the past state into the system.
galleryMenu: function( view ) {
var lastState = this.lastState(),
previous = lastState && lastState.id,
frame = this;
EDIT 5:
Finally figured it all out. I couldn't get the above to work at all, I'm not sure why. So, there may be a better way to do this, involving that code. If so, I'd love to know.
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
var library = file_frame.state('gallery-edit').get('library');
var ids = jQuery('#fg_perm_metadata').val();
if (ids) {
idsArray = ids.split(',');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
file_frame.setState('gallery-edit');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
library.add( attachment ? [ attachment ] : [] );
});
}
});
FINAL EDIT
My code is now working entirely, and I appreciate the help! If you'd like to see it in action, check out http://wordpress.org/plugins/featured-galleries/
I'm relatively new to WP. In fact, I'm building my first WP theme and I'm stuck on the same question as you. Thank to your code, I can get to the Gallery page. And luckily, I've got the images saved. Here's my code:
// when click Insert Gallery, run callback
wp_media_frame.on('update', function(){
var library = wp_media_frame.state().get('library');
var images = [];
var image_ids = [];
thumb_wraper.html('');
library.map( function( image ) {
image = image.toJSON();
images.push(image.url);
image_ids.push(image.id);
thumb_wraper.append('<img src="' + image.url + '" alt="" />');
});
});
What I have found is you should get 'library' instead of get 'selection'.
Edit:
I've figured out how to go back to gallery-edit. Here is my full code:
$( '#btn_upload' ).on( 'click', function( event ) {
event.preventDefault();
var images = $( '#image_ids' ).val();
var gallery_state = images ? 'gallery-edit' : 'gallery-library';
// create new media frame
// You have to create new frame every time to control the Library state as well as selected images
var wp_media_frame = wp.media.frames.wp_media_frame = wp.media( {
title: 'My Gallery', // it has no effect but I really want to change the title
frame: "post",
toolbar: 'main-gallery',
state: gallery_state,
library: {
type: 'image'
},
multiple: true
} );
// when open media frame, add the selected image to Gallery
wp_media_frame.on( 'open', function() {
var images = $( '#image_ids' ).val();
if ( !images )
return;
var image_ids = images.split( ',' );
var library = wp_media_frame.state().get( 'library' );
image_ids.forEach( function( id ) {
attachment = wp.media.attachment( id );
attachment.fetch();
library.add( attachment ? [ attachment ] : [] );
} );
} );
// when click Insert Gallery, run callback
wp_media_frame.on( 'update', function() {
var thumb_wrapper = $( '#thumb-wrapper' );
thumb_wraper.html( '' );
var image_urls = [];
var image_ids = [];
var library = wp_media_frame.state().get( 'library' );
library.map( function( image ) {
image = image.toJSON();
image_urls.push( image.url );
image_ids.push( image.id );
thumb_wrapper.append( '<img src="' + image.url + '" alt="" />' );
} );
} );
} );
I figured that if you re-open the existed frame, it'll always keep the initial state, in your case it's 'gallery'. You'll have to create new frame every time and check if there's images to open 'gallery-edit'
Also, I prefer 'gallery-library' than 'gallery' because I want user to focus on my gallery.
I am trying to send an image name using aviary and need the image name included. I have a hidden field in my form "img" Here is the code:
<script type='text/javascript'>
var featherEditor = new Aviary.Feather({
apiKey: 'yogbsxxxxxxxx4',
apiVersion: 3,
theme: 'dark', // Check out our new 'light' and 'dark' themes!
tools: 'enhance,crop,orientation,brightness,sharpness,redeye,resize,text',
appendTo: '',
onSave: function(imageID, newURL) {
var img = document.getElementById(imageID);
img.src = newURL;
},
onError: function(errorObj) {
alert(errorObj.message);
},
postUrl: 'http://xxxxx/~gsidev/gallery/post.php',
postData : document.getElementById(img),// this is the field I need and does not work?
});
function launchEditor(id, src) {
featherEditor.launch({
image: id,
url: src
});
return false;
}
</script>
Thanks for any guidance. The support for php implementation is terrible on Aviary...
Figured it out! I added a new variable and passed it. This will send the file name in php and overwrite the existing file providing your post url file is inside the same folder as the your image you called for the editor.
function launchEditor(id, src, img) {
featherEditor.launch({
image: id,
url: src,
postData : img
});
return false;
}
</script>
Now on the save page :
$image_data = file_get_contents($_REQUEST['url']);
file_put_contents(($_REQUEST['postData']),$image_data);
?>
And change the link or button code to match
<!-- Add an edit button, passing the HTML id of the image
and the public URL to the image -->
<a href="#" onclick="return launchEditor('editableimage1',"imagename.jpg"
'http://example.com/public/images/goat.jpg');">Edit!</a>
I'm currently developing a image browser in PHP and jQuery. I've managed to create a custom button plugin that opens my image browser in a new window (not a dialog box):
CKEDITOR.plugins.add('imgbrowser',
{
init: function(editor)
{
var pluginName = 'imgbrowser';
editor.ui.addButton('Imgbrowser',
{
label: 'Image browser',
command: pluginName,
click: function (editor) { window.open('/publish/browser/index.php','Image Browser','width=900,height=600'); }
});
}
});
Is there anyone here who knows how to enable the callback function and how this will be used so that I can add the selected pictures into the editor?
Ok. Here is the answer:
In the parent window I have this function:
function InsertHTML(file_path)
{
// Get the editor instance that we want to interact with.
var oEditor = CKEDITOR.instances.page_content;
var value = file_path;
// Check the active editing mode.
if ( oEditor.mode == 'wysiwyg' )
{
// Insert the desired HTML.
oEditor.insertHtml( '<img src="' + value + '" />' );
}
else
alert( 'You must be on WYSIWYG mode!' );
}
page_content is the id of my textarea.
In the popup window I have this function:
function sendToParent(file_path) {
window.opener.InsertHTML(file_path);
}
echo "<input type='button' value='Insert image' onclick='sendToParent(\"".$img_element."\")' />"
I want to use ajax to upload image.
In this module:
On clicking browse and selecting image, it will be uploaded and displayed over file field.
After adding title and description, and clicking on the button, that image will be displayed below and upper image field will be blank
You can't upload files through AJAX. You need to work with IFRAMEs or a Flash-Based uploader.
Actualy you can upload images with the ajax function in Jquery in atleast the lates version of chrome.
HTML:
<form action="/" enctype="multipart/form-data" method="post" accept-charset="utf-8">
<input type="file" name="image"/>
<button type="submit">
</form>
JS:
$("form").submit(function(){
var formData = new FormData($(this)[0]);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
async: false,
cache: false,
contentType: false,
processData: false,
success: function (data) {
alert(data);
}
});
return false;
});
This script will send a post request with the created file data to the current page through Ajax. You can change the destination obviously through changing the url parameter.
Try to use JQuery plugin for uploading an image.
May be http://www.uploadify.com/
This will give an idea how to do it.
Assuming you have a handle on the server side.. here is a small function and example on how to implement the 'iframe hack' in javascript.
html
<form name="image-upload">
<input type="file" name="image" /></br>
<button type="submit" name="upload">Upload</button>
<div id="upload-results"></div>
</form>
javascript
var fileUpload = function(form /* HTMLElement */, action /* Form Action URL */, callback /* Callback function */) {
/* vars */
var atribs = {
"target": "upload_iframe",
"action": action,
"method": "post",
"enctype": "multipart/form-data",
"encoding": "multipart/form-data"
}, iframe;
/* iframe listener */
var ilistener = function() {
var results;
listener.remove(this, 'load', ilistener);
if( 'contentDocument' in this ) {
results = this.contentDocument.body.innerHTML;
} else if ( 'contentWindow' in this ) {
results = this.contentWindow.document.body.innerHTML;
} else if ( 'document' in this ) {
results = this.document.body.innerHTML;
} else {
throw "i'm dead jim :/";
}
callback.apply(this,[results]); // call the callback, passing the results
this.parentNode.removeChild(this); // remove the iframe
};
/* create the iframe */
form.parentNode.appendChild(FragBuilder([{"tagName": "iframe","id": "upload_iframe","name": "upload_iframe","style": {"height": "0","width": "0","border": "0"}}]));
/* collect the iframe back */
iframe = By.id('upload_iframe');
/* set the form properties */
for( var attr in atribs ) {
if( attr in form ) {
form[attr] = atribs[attr];
}
}
/* attach the event listener to the iframe */
listener.add(iframe, 'load', ilistener);
/* submitting the form */
form.submit();
};
// get the form, and the results area
var form = document.forms['image-upload'], results = By.id('upload-results');
// listen for the form submit, capture it, and run the iframe upload.
listener.add(form, 'submit', function(e) {
e.preventDefault();
results.innerHTML = 'Uploading...';
fileUpload(this, 'server.php' /* really anything */, function(data) {
console.log(data);
results.innerHTML = "Uploaded!";
});
});
Please note: for simplicity purposes I have used the following utilities.
https://github.com/rlemon/FragBuilder.js DocumentFragment builder from JSON input.
https://gist.github.com/2172100 event listener, and By utility functions.
*these are both easily removed.