Calling WordPress Gallery Uploader/Selector From Metabox - 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.
Related
Limit wordpress gallery to post only
I've got a front-end uploader that allows users to upload images to a post. When they click the upload button that opens up the gallery they are able to see every image in the galllery, not just the ones tied to that specific post. I'd like to change that. I'd like when a user is in a post trying to upload an image, they can not see images tied to another post. I've googled all I can think of and can't find a solution. Here's my code: var image_custom_uploader_2; var $thisItem = ''; jQuery(document).on('click', '.avatar-upload-image', function(e) { e.preventDefault(); $thisItem = jQuery(this); //If the uploader object has already been created, reopen the dialog if (image_custom_uploader_2) { image_custom_uploader_2.open(); return; } //Extend the wp.media object image_custom_uploader_2 = wp.media.frames.file_frame = wp.media({ title: 'Choose Image', button: { text: 'Choose Image' }, multiple: false }); console.log(image_custom_uploader_2); //When a file is selected, grab the URL and set it as the text field's value image_custom_uploader_2.on('select', function() { attachment = image_custom_uploader_2.state().get('selection').first().toJSON(); var url = ''; url = attachment['url']; var attachId = ''; attachId = attachment['id']; $thisItem.parent().find('.listing-upload-gallery-image-data-url').val(url); $thisItem.parent().find('.listing-upload-gallery-image-data-id').val(attachId); $thisItem.parent().find(".gallery-image-holder").css("background-image", "url(" + url + ")"); $thisItem.parent().find(".avatar-upload-image").css("display", "none"); $thisItem.parent().find(".avatar-delete-image").css("display", "inline-block"); }); //Open the uploader dialog image_custom_uploader_2.open(); }); jQuery(document).on('click', '.avatar-delete-image', function(e) { jQuery(this).parent().find('.listing-upload-gallery-image-data-url').val(''); jQuery(this).parent().find('.listing-upload-gallery-image-data-id').val(''); jQuery(this).parent().find(".gallery-image-holder").css("background-image", "none"); jQuery(this).parent().find(".avatar-upload-image").css("display", "inline-block"); jQuery(this).css("display", "none"); }); I have a feeling I need to somehow incorporate one of the following: uploadedTo : post_parent : but I'm not sure how to apply a post ID to them when this would be on a brand new, unsaved post EDIT: uploadedTo : wp.media.view.settings.post.id uploadedTo : $post-id Still allow all the other media items to be seen on the post's media library
Create a jquery ajax image organizer
I want to create a button on imperavi's redactor, that will display uploaded files (only photos) in a modal, that i previously uploaded, and i will allow the user, to organize this photos, order their order and organize them in folders, and create folders. And when the user select the photo, the tag is inserted in the text field (redactor). I rely want a place to begin, or a already existing solution, my knowledge with php is big but my jquery and ajax is very small I don't want to display the computer folder, i want to display the images int the database Sorry for the bad English. Where do i begin? edit 1: I manged to add the button if (typeof RedactorPlugins === 'undefined') var RedactorPlugins = {}; RedactorPlugins.myPlugin = { init: function() { this.addBtn('myMethod', 'Add Image', function(obj) { obj.myMethod(); }); }, myMethod: function() { // callback (optional) var callback = $.proxy(function() { return 1; }, this); var modal = String() + '<div id="redactor_modal_content">' + '<div class="modal-body">' + '<p>One fine body...</p>' + '</div>' + '<div id="redactor_modal_footer">' + 'Close' + 'Save changes' + '</div>' + '</div>'; // 500 it is the width of the window in pixels // or call a modal with a code this.modalInit('<h3>Modal header</h3>', modal, 500, callback); // call a modal from element with ID #mymodal //this.modalInit('<h3>Modal header</h3>', '#mymodal', 500, callback); } }
Loading images with php and display on a gallery
I have made a javascript code that load dinamically images in a directory (php) and then display them using a jquery galery plugin. I was unable to run the galleryView after all the pictures were loaded by the client. The single way was to use a delay command. I don´t have to tell the disadvantages of this method. Does anyone knows how to "correct" the script so that the gallery plugin is called after all the images are loaded? <script type="text/javascript"> $("document").ready(function() { $('#aa').load('get_fotos.php').delay(2000).queue(function() { $('#aa').galleryView({ panel_width: 800, panel_height: 400, show_filmstrip_nav: false, enable_slideshow: false, panel_animation: 'crossfade', frame_opacity: 1, show_infobar: false, frame_width: 80, frame_height: 40, // frame_scale: 'fit', }); }); }); </script> Thanks a lot
You can check this out by this: It worked for me hope it helps. imageArray = new Array(); imageArray[0] = 'image1.jpg'; // your image path imageArray[1] = 'image2.jpg'; // your image path htmldata=''; count = 0; imgArray = new Array(); $.each(imageArray, function(i,item){ var image=new Image(); $(image).bind("load", {}, function(event) { count++; imageArray[i] = $(image).attr("src"); if(count==2){ $("#imageHolder").empty(); $.each(imageArray, function(j,item){ htmldata = '<img id="image'+j+'" src="' + imageArray[j] +'" />'; //create ur image tag u need to call $("#imageHolder").append(htmldata); }); $('#aa').galleryView({//call your bind method for plug in }); } }); image.src = imageArray[i];
multiple image uploads, display all,drag-drop from all [closed]
Closed. This question needs to be more focused. It is not currently accepting answers. Want to improve this question? Update the question so it focuses on one problem only by editing this post. Closed 1 year ago. Improve this question I am new to Jquery and ajax. I need to upload multiple images to server folder and store the details in a db table. After uploading, I need to display all images which set as 'active' in database.( I have looked into many codes which are not working for me) After that I need to drag some images to an area and also need to store dragged images information in an another table. Anyone have any idea?Please help me? Thanks
Nowadays Dropzone.js is the best js plugin to upload multiple images using drag and drop. official site. https://www.dropzonejs.com/ A complete example of the demo is here. https://learncodeweb.com/web-development/drag-drop-images-with-bootstrap-4-and-reorder-using-php-jquery-and-ajax/
For uploading multiple images you can use this script. By using single browse button you can upload multiple images $(function(){ var btnUpload=$('#photo_0'); // id of browse button new AjaxUpload(btnUpload, { action: 'url_to_upload_function', name: 'uploadfile', onSubmit: function(file, ext){ if (! (ext && /^(jpg|png|jpeg|gif|JPG|PNG|GIF|JPEG)$/.test(ext))){ $("#photo_div1").html('Only JPG,PNG,GIF files are allowed'); // return false; } var path="<?=base_url()?>images/wait.gif"; //losding image $("#photo_div1").html("<img src="+path+" width='32' height='32' style='border:#b6b6b6 solid 1px;'>"); }, onComplete: function(file, response){ response = jQuery.trim(response); if(response=="error") { $("#photo_error").css("display","block"); $("#upload_photo1").html(""); } else if(response!="error") { $("#photo_error").css("display","none"); $("#photo_div1").html(""); var path="uploads/"+response; //echo the image name from the upload function var img="<table><tr><td ><img src="+path+" style='border:#b6b6b6 solid 1px;'></td></tr></table>"; $("#img_div1").html(img);// display the image in a div it will display only one image. If you want to add more you can code according to that by using append or something like that $("#upload_photo1").val(response); $("#photo_hid1").val(response); } else { alert("error"); } } }); }); YOU HAVE TO INCLUDE THIS FILE ALSO ajaxupload.js /** * Ajax upload * Project page - http://valums.com/ajax-upload/ * Copyright (c) 2008 Andris Valums, http://valums.com * Licensed under the MIT license (http://valums.com/mit-license/) * Version 3.5 (23.06.2009) */ /** * Changes from the previous version: * 1. Added better JSON handling that allows to use 'application/javascript' as a response * 2. Added demo for usage with jQuery UI dialog * 3. Fixed IE "mixed content" issue when used with secure connections * * For the full changelog please visit: * http://valums.com/ajax-upload-changelog/ */ (function(){ var d = document, w = window; /** * Get element by id */ function get(element){ if (typeof element == "string") element = d.getElementById(element); return element; } /** * Attaches event to a dom element */ function addEvent(el, type, fn){ if (w.addEventListener){ el.addEventListener(type, fn, false); } else if (w.attachEvent){ var f = function(){ fn.call(el, w.event); }; el.attachEvent('on' + type, f) } } /** * Creates and returns element from html chunk */ var toElement = function(){ var div = d.createElement('div'); return function(html){ div.innerHTML = html; var el = div.childNodes[0]; div.removeChild(el); return el; } }(); function hasClass(ele,cls){ return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')); } function addClass(ele,cls) { if (!hasClass(ele,cls)) ele.className += " "+cls; } function removeClass(ele,cls) { var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)'); ele.className=ele.className.replace(reg,' '); } // getOffset function copied from jQuery lib (http://jquery.com/) if (document.documentElement["getBoundingClientRect"]){ // Get Offset using getBoundingClientRect // http://ejohn.org/blog/getboundingclientrect-is-awesome/ var getOffset = function(el){ var box = el.getBoundingClientRect(), doc = el.ownerDocument, body = doc.body, docElem = doc.documentElement, // for ie clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, // In Internet Explorer 7 getBoundingClientRect property is treated as physical, // while others are logical. Make all logical, like in IE8. zoom = 1; if (body.getBoundingClientRect) { var bound = body.getBoundingClientRect(); zoom = (bound.right - bound.left)/body.clientWidth; } if (zoom > 1){ clientTop = 0; clientLeft = 0; } var top = box.top/zoom + (window.pageYOffset || docElem && docElem.scrollTop/zoom || body.scrollTop/zoom) - clientTop, left = box.left/zoom + (window.pageXOffset|| docElem && docElem.scrollLeft/zoom || body.scrollLeft/zoom) - clientLeft; return { top: top, left: left }; } } else { // Get offset adding all offsets var getOffset = function(el){ if (w.jQuery){ return jQuery(el).offset(); } var top = 0, left = 0; do { top += el.offsetTop || 0; left += el.offsetLeft || 0; } while (el = el.offsetParent); return { left: left, top: top }; } } function getBox(el){ var left, right, top, bottom; var offset = getOffset(el); left = offset.left; top = offset.top; right = left + el.offsetWidth; bottom = top + el.offsetHeight; return { left: left, right: right, top: top, bottom: bottom }; } /** * Crossbrowser mouse coordinates */ function getMouseCoords(e){ // pageX/Y is not supported in IE // http://www.quirksmode.org/dom/w3c_cssom.html if (!e.pageX && e.clientX){ // In Internet Explorer 7 some properties (mouse coordinates) are treated as physical, // while others are logical (offset). var zoom = 1; var body = document.body; if (body.getBoundingClientRect) { var bound = body.getBoundingClientRect(); zoom = (bound.right - bound.left)/body.clientWidth; } return { x: e.clientX / zoom + d.body.scrollLeft + d.documentElement.scrollLeft, y: e.clientY / zoom + d.body.scrollTop + d.documentElement.scrollTop }; } return { x: e.pageX, y: e.pageY }; } /** * Function generates unique id */ var getUID = function(){ var id = 0; return function(){ return 'ValumsAjaxUpload' + id++; } }(); function fileFromPath(file){ return file.replace(/.*(\/|\\)/, ""); } function getExt(file){ return (/[.]/.exec(file)) ? /[^.]+$/.exec(file.toLowerCase()) : ''; } // Please use AjaxUpload , Ajax_upload will be removed in the next version Ajax_upload = AjaxUpload = function(button, options){ if (button.jquery){ // jquery object was passed button = button[0]; } else if (typeof button == "string" && /^#.*/.test(button)){ button = button.slice(1); } button = get(button); this._input = null; this._button = button; this._disabled = false; this._submitting = false; // Variable changes to true if the button was clicked // 3 seconds ago (requred to fix Safari on Mac error) this._justClicked = false; this._parentDialog = d.body; if (window.jQuery && jQuery.ui && jQuery.ui.dialog){ var parentDialog = jQuery(this._button).parents('.ui-dialog'); if (parentDialog.length){ this._parentDialog = parentDialog[0]; } } this._settings = { // Location of the server-side upload script action: 'upload.php', // File upload name name: 'userfile', // Additional data to send data: {}, // Submit file as soon as it's selected autoSubmit: true, // The type of data that you're expecting back from the server. // Html and xml are detected automatically. // Only useful when you are using json data as a response. // Set to "json" in that case. responseType: false, // When user selects a file, useful with autoSubmit disabled onChange: function(file, extension){}, // Callback to fire before file is uploaded // You can return false to cancel upload onSubmit: function(file, extension){}, // Fired when file upload is completed // WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE! onComplete: function(file, response) {} }; // Merge the users options with our defaults for (var i in options) { this._settings[i] = options[i]; } this._createInput(); this._rerouteClicks(); } // assigning methods to our class AjaxUpload.prototype = { setData : function(data){ this._settings.data = data; }, disable : function(){ this._disabled = true; }, enable : function(){ this._disabled = false; }, // removes ajaxupload destroy : function(){ if(this._input){ if(this._input.parentNode){ this._input.parentNode.removeChild(this._input); } this._input = null; } }, /** * Creates invisible file input above the button */ _createInput : function(){ var self = this; var input = d.createElement("input"); input.setAttribute('type', 'file'); input.setAttribute('name', this._settings.name); var styles = { 'position' : 'absolute' ,'margin': '-5px 0 0 -175px' ,'padding': 0 ,'width': '220px' ,'height': '30px' ,'fontSize': '14px' ,'opacity': 0 ,'cursor': 'pointer' ,'display' : 'none' ,'zIndex' : 2147483583 //Max zIndex supported by Opera 9.0-9.2x // Strange, I expected 2147483647 }; for (var i in styles){ input.style[i] = styles[i]; } // Make sure that element opacity exists // (IE uses filter instead) if ( ! (input.style.opacity === "0")){ input.style.filter = "alpha(opacity=0)"; } this._parentDialog.appendChild(input); addEvent(input, 'change', function(){ // get filename from input var file = fileFromPath(this.value); if(self._settings.onChange.call(self, file, getExt(file)) == false ){ return; } // Submit form when value is changed if (self._settings.autoSubmit){ self.submit(); } }); // Fixing problem with Safari // The problem is that if you leave input before the file select dialog opens // it does not upload the file. // As dialog opens slowly (it is a sheet dialog which takes some time to open) // there is some time while you can leave the button. // So we should not change display to none immediately addEvent(input, 'click', function(){ self.justClicked = true; setTimeout(function(){ // we will wait 3 seconds for dialog to open self.justClicked = false; }, 3000); }); this._input = input; }, _rerouteClicks : function (){ var self = this; // IE displays 'access denied' error when using this method // other browsers just ignore click() // addEvent(this._button, 'click', function(e){ // self._input.click(); // }); var box, dialogOffset = {top:0, left:0}, over = false; addEvent(self._button, 'mouseover', function(e){ if (!self._input || over) return; over = true; box = getBox(self._button); if (self._parentDialog != d.body){ dialogOffset = getOffset(self._parentDialog); } }); // we can't use mouseout on the button, // because invisible input is over it addEvent(document, 'mousemove', function(e){ var input = self._input; if (!input || !over) return; if (self._disabled){ removeClass(self._button, 'hover'); input.style.display = 'none'; return; } var c = getMouseCoords(e); if ((c.x >= box.left) && (c.x <= box.right) && (c.y >= box.top) && (c.y <= box.bottom)){ input.style.top = c.y - dialogOffset.top + 'px'; input.style.left = c.x - dialogOffset.left + 'px'; input.style.display = 'block'; addClass(self._button, 'hover'); } else { // mouse left the button over = false; if (!self.justClicked){ input.style.display = 'none'; } removeClass(self._button, 'hover'); } }); }, /** * Creates iframe with unique name */ _createIframe : function(){ // unique name // We cannot use getTime, because it sometimes return // same value in safari :( var id = getUID(); // Remove ie6 "This page contains both secure and nonsecure items" prompt // http://tinyurl.com/77w9wh var iframe = toElement('<iframe src="javascript:false;" name="' + id + '" />'); iframe.id = id; iframe.style.display = 'none'; d.body.appendChild(iframe); return iframe; }, /** * Upload file without refreshing the page */ submit : function(){ var self = this, settings = this._settings; if (this._input.value === ''){ // there is no file return; } // get filename from input var file = fileFromPath(this._input.value); // execute user event if (! (settings.onSubmit.call(this, file, getExt(file)) == false)) { // Create new iframe for this submission var iframe = this._createIframe(); // Do not submit if user function returns false var form = this._createForm(iframe); form.appendChild(this._input); form.submit(); d.body.removeChild(form); form = null; this._input = null; // create new input this._createInput(); var toDeleteFlag = false; addEvent(iframe, 'load', function(e){ if (// For Safari iframe.src == "javascript:'%3Chtml%3E%3C/html%3E';" || // For FF, IE iframe.src == "javascript:'<html></html>';"){ // First time around, do not delete. if( toDeleteFlag ){ // Fix busy state in FF3 setTimeout( function() { d.body.removeChild(iframe); }, 0); } return; } var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document; // fixing Opera 9.26 if (doc.readyState && doc.readyState != 'complete'){ // Opera fires load event multiple times // Even when the DOM is not ready yet // this fix should not affect other browsers return; } // fixing Opera 9.64 if (doc.body && doc.body.innerHTML == "false"){ // In Opera 9.64 event was fired second time // when body.innerHTML changed from false // to server response approx. after 1 sec return; } var response; if (doc.XMLDocument){ // response is a xml document IE property response = doc.XMLDocument; } else if (doc.body){ // response is html document or plain text response = doc.body.innerHTML; if (settings.responseType && settings.responseType.toLowerCase() == 'json'){ // If the document was sent as 'application/javascript' or // 'text/javascript', then the browser wraps the text in a <pre> // tag and performs html encoding on the contents. In this case, // we need to pull the original text content from the text node's // nodeValue property to retrieve the unmangled content. // Note that IE6 only understands text/html if (doc.body.firstChild && doc.body.firstChild.nodeName.toUpperCase() == 'PRE'){ response = doc.body.firstChild.firstChild.nodeValue; } if (response) { response = window["eval"]("(" + response + ")"); } else { response = {}; } } } else { // response is a xml document var response = doc; } settings.onComplete.call(self, file, response); // Reload blank page, so that reloading main page // does not re-submit the post. Also, remember to // delete the frame toDeleteFlag = true; // Fix IE mixed content issue iframe.src = "javascript:'<html></html>';"; }); } else { // clear input to allow user to select same file // Doesn't work in IE6 // this._input.value = ''; d.body.removeChild(this._input); this._input = null; // create new input this._createInput(); } }, /** * Creates form, that will be submitted to iframe */ _createForm : function(iframe){ var settings = this._settings; // method, enctype must be specified here // because changing this attr on the fly is not allowed in IE 6/7 var form = toElement('<form method="post" enctype="multipart/form-data"></form>'); form.style.display = 'none'; form.action = settings.action; form.target = iframe.name; d.body.appendChild(form); // Create hidden input element for each data key for (var prop in settings.data){ var el = d.createElement("input"); el.type = 'hidden'; el.name = prop; el.value = settings.data[prop]; form.appendChild(el); } return form; } }; })(); and for drag and drop you need to write another function for that you can refer this site or this
http://www.plupload.com/example_queuewidget.php Here you can find a nice plugin that will help you to upload multiple images.I have used this and works well for me.
Php/ajax files uploading: hidden iframe loads more than once
My problem occurs, when I upload images with ajax. Ajax response comes to a hidden iframe, and for debug I echo it (uploaded image name) here and then alert it. So when I upload the first image - there's one alert, as it should be. When I upload the 2nd - I see 2 alerts. The 3rd - 3 alerts. And so on. It means, that my iframe reloads as many times, as the order number of the file being just uploaded. Interesting, that the names in alerts after each file upload are always the same. For example, 2 times "mySecondImage.jpg", 3 times "myThirdImage.jpg"... What can be done to solve the problem? Thanks. // FUNCTION - AJAX FILE UPLOADER // this function creates new elements, but only in case, when user uploads files $.fn.fileUploader = function ( $inputName ) { var $body = $(this); var $form = $body.parents('form'); var $fileInput = $body.find(':file'); // after file is uploaded, we need the file input to be empty again var $fileInputEmpty = '<input type="file" name="' + $inputName + '" />'; var $iframe = $('#ajaxResult'); // user submits the form $form.submit( function() { // check the result $iframe.load( function () { var $response = $iframe.contents().find('body').html(); alert($response); // debug // add new content image $output = createUpdateImage( $response, $('[name="imageLinkURL"]').val() ); // add new element addNewElement( $output ); // success if ( $response.length ) { $fileInput.replaceWith( $fileInputEmpty ); $fileInput = $body.find(':file'); } }); }); // form submit }; $('.fileUploder').each(function () { var $inputName = $(this).find(':file').attr('name'); $(this).fileUploader( $inputName ); }); Well, the glitch is fixed! I slightly rewrote the jQuery function: ... // user submits the form $form.submit( function() { var $response = ''; $iframe.load( function () { $response = $iframe.contents().find('body').html(); }); // periodically check the result in iframe var $timer = setInterval( function() { if ( $response != '' ) { clearInterval( $timer ); // do all required actions } }, 100 ); }); // form submit ...
$form.submit( function() { $iframe.load( function () { I think the problem is here. On form submit you add an event "on load". So it called 1 time, then 2 times, etc. Maybe removing the first of these two strings can help (use only load event handler).