2012-03-17 6 views
0

私のXHTML AJAX画像アップローダの完全版です。それはAJAXを使ってファイルをアップロードしています。私はIE9以前とOpera 11.6以前(IE10とOpera 12はそれをサポートしています)をサポートしていないので大丈夫です。しかし、私はFirefoxに問題があります。JavaScript:AJAX複数の画像アップローダの進捗状況がFirefoxで機能しない

主な問題は、IDをターゲットに動的に割り当てることです(または要素[i]と相関するiに沿って渡すこともあります)。それは、ないFirefoxの10イベントリスナーは、以下のコードでライン100上にあるものの、一部の明確化

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 
<head> 
<title>Image Preview</title> 
<script type="application/javascript"> 
//<![CDATA[ 
function images_name(s) 
{ 
var a = reverse(s); 
var b = a.split('.'); 
var c = reverse(b[1]); 
var d = c.toLowerCase(); 
var e = d.replace(/^\s+|\s+$/g,''); 
var f = e.replace(/^-+|-+$/g,''); 
var g = f.replace(/ /g,'-'); 
var h = g.replace(/[--]+/g,'-'); 
var i = h.replace(/[^a-zA-Z 0-9-]+/g,''); 
return i; 
} 


function images_preview() 
{ 
if (typeof FileReader=='function') 
{ 
    var files = document.getElementById('post_files').files; 

    for (var i = 0; i < files.length; i++) 
    { 
    var fr = new FileReader(); 
    fr.file = files[i]; 
    fr.onloadend = function(e) 
    { 
    var ip = document.getElementById('images_preview'); 
    var file = e.target.file; 

    var d1 = document.createElement('div'); 
    var dn = images_name(file.name); 
    d1.setAttribute('id',dn); 
    var t = document.createElement('img'); 
    t.setAttribute('alt','Preview'); 
    t.setAttribute('class','left'); 
    t.setAttribute('src',e.target.result); 
    d1.appendChild(t); 
    ip.appendChild(d1); 

    var d2 = document.createElement('div'); 
    var s2 = document.createElement('span'); 
    var s2t = document.createTextNode(file.name); 
    s2.appendChild(s2t); 
    d2.appendChild(s2); 
    d1.appendChild(d2); 

    var d3 = document.createElement('div'); 
    var s3 = document.createElement('span'); 
    var s3t = document.createTextNode(file.type); 
    s3.appendChild(s3t); 
    d3.appendChild(s3); 
    d1.appendChild(d3); 

    var d4 = document.createElement('div'); 
    var s4 = document.createElement('span'); 
    var s4t = document.createTextNode(Math.round(file.size/1024)+' KB'); 
    s4.appendChild(s4t); 
    d4.appendChild(s4); 
    d1.appendChild(d4); 

    var d5 = document.createElement('div'); 
    d5.setAttribute('class','progress'); 
    var d6 = document.createElement('div'); 
    d6.setAttribute('class','status'); 
    d5.appendChild(d6); 

    d1.appendChild(d5); 
    } 
    fr.readAsDataURL(files[i]); 
    } 
} 
else {alert('Notice: image preview not supported by your browser.');} 
} 


function images_upload(e) 
{ 
e.preventDefault(); 
var n = ''; 

for (var i = 0; i < document.getElementById('post_files').files.length; i++) 
{ 
    var file = document.getElementById('post_files').files[i]; 
    n = images_name(file.name); 
    //alert('n1 = '+n); 
    var xhr = new XMLHttpRequest(); 

    if (typeof xhr.upload=='object') 
    { 
    var upload = xhr.upload; 
    upload.addEventListener('progress',function(n) 
    { 
    return function(e) 
    { 
    //alert('n = '+n); 
    var loader = document.getElementById(n).getElementsByClassName('status')[0]; 
    var p = Math.round((e.loaded * 100)/e.total); 
    loader.style.width = p+'%'; 
    //alert('n = ' + n); 
    }; 

    }(n), false); 
    xhr.open('POST','upload.php'); 
    xhr.setRequestHeader('Cache-Control','no-cache'); 
    xhr.setRequestHeader('X-Requested-With','XMLHttpRequest'); 
    xhr.setRequestHeader('X-File-Name',file.name); 
    xhr.send(file); 
    } 
    else {var ns = true;} 
} 

if (ns) {alert('Error: your browser does not support AJAX file uploads.');} 
} 


function reverse(s) {return s.split('').reverse().join('');} 


window.onload = function() 
{ 
if (window.addEventListener) 
{ 
    document.getElementById('form_images').addEventListener('submit',function(e) {images_upload(e);},false); 
    document.getElementById('post_files').addEventListener('change',function() {images_preview();},false); 
} 
} 
//]]> 
</script> 
<style type="text/css"> 
.left {float: left;} 
#images_preview > div {border: #000 solid 1px; clear: both; float: right; margin: 8px; overflow: auto; width: 400px;} 
#images_preview > div > div {margin-top: 8px;} 
#images_preview div.progress, #images_preview div.status {background-color: orange; bottom: 0px; clear: both; height: 2px; position: relative;} 
#images_preview div.status {background-color: #0f0; width: 0px;} 
#images_preview img {background-color: #ccc; border: #666 solid 1px; margin: 8px; max-height: 100px; max-width: 100px; padding: 4px;} 
</style> 
</head> 

<body> 

<form action="" id="form_images" method="post" enctype="multipart/form-data"> 
<fieldset> 
<div><input id="post_files" name="post_files" multiple="multiple" size="128" type="file" /></div> 
<div><input name="post_files" type="submit" /></div> 

<div id="images_preview"></div> 
</fieldset> 
</form> 

</body> 
</html> 

... ChromeとOperaの12で正常に動作します...最初に私はFirefoxでこの仕事を持つ気にChrome、Opera 12+、IE 10+の場合、AJAX以外の単一のファイルをフォールバックする必要があります。今はただこれを仕事にすることに集中したいだけです。

これはテストしましたが、Opera 12+、IE 10、Chrome(いずれにしても)でもFirefox 14(現在の夜間ビルドバージョン)では動作しません。私は、Firefoxが例としてFirefox 4のように動作するように、合理的なバージョン番号を非常に好むだろう。

フレームワークがありません。私は、品質を試して、実際のJavaScriptコードを正しく学習するのに役立つような問題を考え出しています。

私はJavaScriptの質問を投稿する人々は明らかに残されているものを選び出します。これはAJAXファイルのアップロードなので、どうして誰かがpreventDefaultを削除する理由は私の外です。これは完全なコピーであり、誰かが小さな修正をしている場合は意図したようにほとんど動作しますので、機能分割に入る場合は少なくとも修正された関数を完全に含めてください。 2番目に重要なアイデアは、他の人々がこの質問を今後何年にもわたって見るときにも、明確な作業の答えを得ることです。

私は何らかの説明をしてもらうだけでなく、議決権を行使して有効な回答を受け入れることができます。私は

答えて

1
function images_upload(e) 
{ 
    //... 
    var n = ''; 
    //... 
    upload.addEventListener('progress',function(n) 
    { 
     return function(e) 
     { 
      //using n here 
     }; 
    }(n), false); 

- 唯一、謙虚かつ未検証 - 意見:

あなたの変数nは、最初の関数(images_upload(e)

にあなたは第二の機能(名前function(n))に渡す見えます自動的に渡されたイベントオブジェクトによってオーバーライドされていないと仮定して(これは私が疑う)、ここでも表示されます(n、以下のコードブロックのコメントを参照してください)。

function(n){...}(n) 
     1  2 
//1: the unnamed function's argument, should have been called differently to avoid confusion 
//2: the n that is declared inside images_upload() with a limited visibility (using 'var' keyword), and which is now passed to the unnamed function as its argument 

ただし、3番目の関数(名前なしのfunction(e))には渡さないでください。そこにすべてのこの制約についてWeb上で多くの記事がありますが、私は(唯一の精神で、ここで、テストする)2つの回避策を考えることができます:

upload.savemyvar=n; 
    upload.addEventListener('progress',function(e) 
    { 
     return function(e , n) 
     { 
      //using the event e and your variable n here 
     }(e , this.savemyvar); 
    }, false); 

そしてさらに簡単:

upload.savemyvar=n; 
    upload.addEventListener('progress',function(e) 
    { 
     var n=this.savemyvar; 
     //using the event e and your variable n here 
    }, false); 

か、と私は(ゆっくりが)それが動作するはずかなり確信している:

eval("upload.addEventListener('progress',function(e) 
    { 
     return function(e , n) 
     { 
      //using the event e and your variable n here 
      //don't forget to \"escape\" correctly if needed ;) 
     }(e , "+n+"); 
    }, false);"); 

そして、再び、単純:

eval("upload.addEventListener('progress',function(e) 
    { 
     var n="+n+"; 
     //using the event e and your variable n here 
     //don't forget to \"escape\" correctly if needed ;) 
    }, false);"); 

コードパーソンを終了するのにJSパーサが;を必要とするのか、それとも\nだけを必要とするのかによって、evalコードを1行にまとめる必要があります。

最初のオプションが「現状のまま」動作するかどうか、問題が解決された場合は最も重要なことを伝えてください(あなたのコードが他のブラウザで動作することが奇妙に聞こえるため)。

+0

試してみてください。返信いただきありがとうございます! – John

+0

昨夜、何が間違っていて、できるだけ多くの拠点をカバーしているかを調べるのに時間がかかりました... localhostに問題があり、127.0.0.1と192.168.x.yをテストするだけでなく、ライブドメインも違いになります。私は現在、Firefoxのバグレポートに取り組んでいます。後でチャンスがあるときに、私が投稿したコードとあなたが投稿したコードを見て、この質問を離れてぶら下げないようにします。 – John

+0

forループ内のすべてを新しいfunction(){}に囲むと、変数スコープが修正され、問題が解決されました。私は本質的に、あなたの2番目の提案の少し異なるバージョンを取った。私は非常にまれにevalを使用しています...あなたの投稿が私にしばらく時間がかかっても正しい方向に動かせるように助けてくれました。ありがとう!投票され、答えとして受け入れられる。 – John

関連する問題