Я разработал загрузчик файлов ajax, и он отлично работает, если один экземпляр находится на странице. Я пытаюсь преобразовать его, чтобы разрешить несколько экземпляров, и он почти работает, EXCEPT, когда я загружаю несколько файлов в одной форме, он загружает первый файл в порядке, но затем для всех последующих файлов по какой-либо причине он указывает вперед к следующему файловому считывателю из экземпляра второй формы. Если я загружу, используя последний (второй) экземпляр формы загрузки, вы сможете загрузить несколько файлов. Но если я попытаюсь загрузить первый экземпляр, он загрузит первый файл, но все последующие файлы будут отправлены на пустой входной файл из второго экземпляра. Я не понимаю, почему. Я использую уникальные имена идентификаторов в форме загрузки и ссылаюсь на этот уникальный идентификатор во всех функциях javascript. Я попытаюсь включить все необходимые биты кода ниже.Несколько экземпляров Ajax Uploader на той же странице
Формы генерируются PHP. Php var $uid
- это случайно созданный уникальный идентификатор, который я использую во всем. Во-первых, инициализация функции загрузки выводится на страницу в <script>
тэгом:
'<script> '.
'jQuery(document).ready(function($){ '.
'var myup_'.$uid.' = new MyUp({ '.
'form_id: "myup_form_'.$uid.'", '.
'uid: '.$uid.', '.
'container: "'.$name.'", '.
'table: "'.$style.'", '.
'iconcolor: "'.$iconcolor.'", '.
'maxsize: '.$maxsize.', '.
'permitted: '.$permitted.', '.
'prohibited: '.$prohibited.', '.
'fixed: '.$fixedsetting.', '.
'pathcheck: "'.$pathcheck.'", '.
'uploader: '.$uploader.', '.
'loading: "'.my_url.'/lib/img/ajax.gif" '.
}); '.
'}); '.
'</script>';
Очевидно, что все эти переменные для моих настроек определены ранее. С несколькими экземплярами на странице он правильно считывает настройки для каждого отдельного экземпляра. Они успешно отображаются с разными стилями, цветами значков, разрешениями типа файла, максимальными настройками размера файла и т. Д. Все это работает с несколькими экземплярами.
Теперь форма:
'<div class="myup_container" style="'.$inlinestyle.'">'.
'<form name="myup_form_'.$uid.'" id="myup_form_'.$uid.'" action="javascript:void(0);" enctype="multipart/form-data">'.
'<input type="hidden" id="upload-actionpath-'.$uid.'" value="'.$fixed.'" data-basename="'.$basename.'" data-start="'.$start.'" />'.
'<div class="myup_buttons_container" style="text-align:right;">'.
'<span class="myup_wrapper" style="text-align:left;">'.
'<input type="file" name="myup_files_'.$uid.'[]" id="myup_files_'.$uid.'" class="hidden_browse"'.$multiple.' />'.
'<span class="add_files">'.$addfiles.'</span>'.
'<span id="submit_upload_'.$uid.'">'.$uploadlabel.'</span>'.
'</span>'.
'</div>'.
'</form>'.
'<div id="myup_files_container_'.$uid.'" class="myup_files_container"></div>'.
'<span id="my_removedfiles_'.$uid.'" style="display:none;"></span>'.
'</div>';
Так что это урезанный вариант. Экземпляр в теге скрипта, содержащий настройки и форму html, выводится по короткому коду. Таким образом, на нескольких коротких кодах на странице будут выводиться несколько экземпляров функции MyUp.
Вот что я надеюсь, все соответствующие биты яваскрипта функций (это долго, извините, но я удалил тонну материала):
jQuery(document).ready(function($)
{
// throughout, the var fuid will refer
// to the php var $uid from the html form and instance settings
function myupRemove(id, filename, fuid)
{
// handle files the user removes from the input field
// before submitting the upload
}
function MyUp(config)
{
this.settings = config;
this.fuid = this.settings.uid;
this.file = "";
this.browsed_files = [];
var self = this;
MyUp.prototype.myupDisplay = function(value)
{
this.file = value;
if(this.file.length > 0)
{
/* this is a really long bit of code
* that i'll spare you, but basically I iterate
* through all the files in the input field
* and put them dynamically into a table
* and drop the table onto the page
* so the user can rename them, remove them before upload,
* and then watch the status bar for each file as it uploads.
* This portion of the code works fine with multiple instances.
*/
}
}
// Create Unique ID
MyUp.prototype.uid = function(name)
{
// Here I generate a unique ID for each file,
// and prepend it with the Instance's unique id (i.e., this.fuid)
return this.fuid+'_'+name.replace(/[^a-z0-9\s]/gi, '_').replace(/[_\s]/g, '_');
}
// Get File Extension
MyUp.prototype.ext = function(file, lowercase)
{
return (/[.]/.exec(file)) ? (lowercase ? /[^.]+$/.exec(file.toLowerCase()) : /[^.]+$/.exec(file)) : '';
}
// Format File Size
MyUp.prototype.nicesize = function(fileSize)
{
// a bunch of code to format the file size then...
return niceSize;
}
// Attribute FileType Icons
MyUp.prototype.icon = function(icon_ext, color)
{
// a bunch of arrays to determine
// which file type icon to display in the table
}
//File Reader
MyUp.prototype.read = function(e)
{
if(e.target.files)
{
// references the myupDisplay function
// where I add the files to a table
self.myupDisplay(e.target.files);
self.browsed_files.push(e.target.files);
}
}
function addEvent(type, el, fn)
{
if(window.addEventListener)
{
el.addEventListener(type, fn, false);
}
else if(window.attachEvent)
{
var f = function()
{
fn.call(el, window.event);
};
el.attachEvent('on' + type, f)
}
}
// Collect File IDs and Initiate Upload for Submit
MyUp.prototype.starter = function()
{
if(window.File && window.FileReader && window.FileList && window.Blob)
{
var browsed_file_id = $("#"+this.settings.form_id).find("input[type='file']").eq(0).attr("id");
document.getElementById(browsed_file_id).addEventListener('change', this.read, false);
document.getElementById('submit_upload_'+this.fuid).addEventListener('click', this.submit, true);
}
else alert(browser_cant_read_message);
}
// Begin Upload on Click
MyUp.prototype.submit = function()
{
self.begin();
}
// Initiate Upload Iterator
MyUp.prototype.begin = function()
{
if(this.browsed_files.length > 0)
{
for(var k=0; k<this.browsed_files.length; k++)
{
var file = this.browsed_files[k];
this.myupAjax(file,k);
}
this.browsed_files = [];
}
else alert(no_files_chosen_message);
}
// Ajax Upload
MyUp.prototype.myupAjax = function(file,i)
{
if(file[i]!== undefined)
{
var id = file_id = self.uid(file[i].name),
rawname = file[i].name.substr(0, file[i].name.lastIndexOf('.')) || file[i].name,
extension = self.ext(file[i].name, false),
browsed_file_id = $("#"+this.settings.form_id).find("input[type='file']").eq(0).attr("id");
path = this.settings.fixed ? this.settings.fixed : String($('input#upload-actionpath-'+this.fuid).val()),
pathcheck = String(this.settings.pathcheck),
removed_file = $("#"+id).val(),
newname = String($('input#rename_upfile_id_'+id).val()),
new_name = newname === '' || newname === 'undefined' || newname === undefined ? file[i].name : newname+'.'+extension,
removed = this.settings.removed,
loading = this.settings.loading,
fixedchars = this.settings.fixed;
// if the file is removes, skip to the next file
if(removed_file !== '' && removed_file !== undefined && removed_file == id) self.myupAjax(file,i+1);
else
{
var myupData = new FormData();
myupData.append('upload_file',file[i]);
myupData.append('upload_file_id',id);
myupData.append('max_file_size',this.settings.maxsize);
myupData.append('upload_path',path);
myupData.append('new_name',new_name);
myupData.append('extension',extension);
myupData.append('uploader',this.settings.uploader);
myupData.append('act','upload');
myupData.append('nonce',myup.nonce);
$.ajax(
{
type : 'POST',
url : myup.ajaxurl+'?action=myup-uploads',
data : myupData,
id : id,
fuid : this.fuid,
new_name : new_name,
rawname : rawname,
extension : extension,
path : path,
pathcheck : pathcheck,
removed : removed,
loading : loading,
fixedchars : fixedchars,
cache : false,
contentType : false,
processData : false,
beforeSend : function(xhr, settings)
{
// I added this alert because it shows me that when I'm using the first instance
// after the first file uploads, it starts looking to the file input field
// from the second instance
alert('path: '+settings.path+' pathcheck: '+settings.pathcheck);
// in here I do a bunch of security stuff before uploading
},
xhr: function()
{
// my progress bar function here
},
success : function(response)
{
setTimeout(function()
{
if(response.indexOf(id) != -1)
{
// do success stuff, like green checkmark, remove table row, etc.
}
else
{
// do failure stuff, like red x and error message
}
// AND HERE IS THE IMPORTANT PART
// THIS SAYS TO GO ON TO THE NEXT FILE IN THE ARRAY
// BUT WHEN USING THE FIRST INSTANCE
// IT SENDS US TO THE SECOND INSTANCE'S FILE READER
// if I'm uploading with the second form it's fine
if(i+1 < file.length) self.myupAjax(file,i+1);
},500);
}
});
}
}
}
this.starter();
}
window.MyUp = MyUp;
window.myupRemove = myupRemove;
});
Примечание комментарий блок к концу указанного выше кода фрагмент, где комментарий находится во всех шапках. Вот где он завершает загрузку ajax для файла, а затем отправляет нас назад, чтобы сделать следующий.
Так что, в основном, повторять, если у меня есть две формы на странице, когда я использую вторую форму, все работает нормально. Когда я использую первую форму, первый файл будет загружаться отлично, но затем он начинает искать следующий файл в поле ввода из второго экземпляра.
Есть ли относительно простое решение для этого?
Вы можете указать страницу с примером. – 19greg96
Вы говорите, что он работает так, как должен, когда вы загружаете второй экземпляр. Как насчет того, когда у вас есть, скажем, 3 или более экземпляра? Все последующие (от второго) работают? – melancia
Мне кажется, что когда вы объявляете 'self' здесь:' var self = this; 'он сохраняет ссылку на последний экземпляр, поэтому он будет работать нормально только с последним, независимо от того, является ли он вторым, третий и т. д., экземпляр. – melancia