2014-03-12 39 views
12

是否可以使用JavaScript模擬/僞造放置事件?如何測試這種類型的事件?模擬放置文件事件

舉例來說,這個dnd上傳示例page,是否可以通過文件觸發「drop」事件而不實際丟棄文件?假設點擊一個按鈕?

我已經開始編寫一個Sukuli腳本,它可以控制鼠標並完成技巧,但我一直在尋找更好的解決方案。

編輯

@kol答案是擺脫拖放事件的好辦法,但我還是要手動選擇從我的計算機中的文件。這是我對模擬感興趣的一點。有沒有辦法以編程方式創建文件變量?

var fileInput = document.getElementById('fileInput'), 
file = fileInput.files[0];  

回答

16

1.由用戶選擇刪除圖像

我已經作出了jsfiddle。這是你提到的html5demos.com page的精簡版,但:

  • 我增加了一個<input type="file">標籤可以用來選擇從本地電腦中的圖片文件,並
  • 我還添加了一個<input type="button">標記onclick處理程序,它通過直接調用DND目標div標記的ondrop事件處理程序來模擬「丟棄文件」事件。

ondrop處理程序是這樣的:

holder.ondrop = function (e) { 
    this.className = ''; 
    e.preventDefault(); 
    readfiles(e.dataTransfer.files); 
} 

也就是說,我們有一個參數傳遞給ondrop,這

  • 有一個files陣列子字段,dataTransfer字段,包含所選的File
  • 有一個preventDefault方法(一個沒有body的函數)。

所以 「模擬降」 按鈕onclick處理程序如下:

function simulateDrop() { 
    var fileInput = document.getElementById('fileInput'), 
     file = fileInput.files[0];   
    holder.ondrop({ 
     dataTransfer: { files: [ file ] }, 
     preventDefault: function() {} 
    }); 
} 

測試

  1. 選擇一個圖像文件(PNG,JPEG或GIF)
  2. 點擊「模擬降」按鈕

結果

Result

2.刪除自動生成的測試文件,而無需用戶交互(GOOGLE CHROME ONLY!!!

我已完成另一jsfiddle。當加載頁面時,一個函數被調用,其中:

  • 創建一個文本文件到臨時文件系統,並
  • 負載和降低該文本文件到目標<div>;然後
  • 將圖像文件創建到臨時文件系統中,並且
  • 將該圖像文件加載並放入目標<div>

這個下拉式模擬器函數調用的代碼如下:

(function() { 
    var fileErrorHandler = function (e) { 
      var msg = ""; 
      switch (e.code) { 
       case FileError.QUOTA_EXCEEDED_ERR: 
        msg = "QUOTA_EXCEEDED_ERR"; 
        break; 
       case FileError.NOT_FOUND_ERR: 
        msg = "NOT_FOUND_ERR"; 
        break; 
       case FileError.SECURITY_ERR: 
        msg = "SECURITY_ERR"; 
        break; 
       case FileError.INVALID_MODIFICATION_ERR: 
        msg = "INVALID_MODIFICATION_ERR"; 
        break; 
       case FileError.INVALID_STATE_ERR: 
        msg = "INVALID_STATE_ERR"; 
        break; 
       default: 
        msg = "Unknown Error"; 
        break; 
      }; 
      console.log("Error: " + msg); 
     }, 
     requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem, 
     dropFile = function (file) { 
      holder.ondrop({ 
       dataTransfer: { files: [ file ] }, 
       preventDefault: function() {} 
      }); 
     }; 

    if (!requestFileSystem) { 
     console.log("FileSystem API is not supported"); 
     return; 
    } 
    requestFileSystem(
     window.TEMPORARY, 
     1024 * 1024, 
     function (fileSystem) { 
      var textFile = { 
        name: "test.txt", 
        content: "hello, world", 
        contentType: "text/plain" 
       }, 
       imageFile = { 
        name: "test.png", 
        content: "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==", 
        contentType: "image/png", 
        contentBytes: function() { 
         var byteCharacters = atob(this.content), 
          byteArrays = [], offset, sliceSize = 512, slice, byteNumbers, i, byteArray; 

         for (offset = 0; offset < byteCharacters.length; offset += sliceSize) { 
          slice = byteCharacters.slice(offset, offset + sliceSize); 
          byteNumbers = new Array(slice.length); 
          for (i = 0; i < slice.length; i++) { 
           byteNumbers[i] = slice.charCodeAt(i); 
          } 
          byteArray = new Uint8Array(byteNumbers); 
          byteArrays.push(byteArray); 
         } 
         return byteArrays; 
        } 
       }; 

      // Create and drop text file 
      fileSystem.root.getFile(
       textFile.name, 
       { create: true }, 
       function (fileEntry) { 
        fileEntry.createWriter(
         function (fileWriter) { 
          fileWriter.onwriteend = function(e) { 
           console.log("Write completed (" + textFile.name + ")"); 
           fileSystem.root.getFile(
            textFile.name, 
            {}, 
            function (fileEntry) { 
             fileEntry.file(
              function (file) { 
               dropFile(file); 
              }, 
              fileErrorHandler 
             ); 
            }, 
            fileErrorHandler 
           );  

          }; 
          fileWriter.onerror = function(e) { 
           console.log("Write failed (" + textFile.name + "): " + e.toString()); 
          }; 
          fileWriter.write(new Blob([ textFile.content ], { type: textFile.contentType })); 
         }, 
         fileErrorHandler 
        ); 
       }, 
       fileErrorHandler 
      ); 

      // Create and drop image file 
      fileSystem.root.getFile(
       imageFile.name, 
       { create: true }, 
       function (fileEntry) { 
        fileEntry.createWriter(
         function (fileWriter) { 
          fileWriter.onwriteend = function(e) { 
           console.log("Write completed (" + imageFile.name + ")"); 
           fileSystem.root.getFile(
            imageFile.name, 
            {}, 
            function (fileEntry) { 
             fileEntry.file(
              function (file) { 
               dropFile(file); 
              }, 
              fileErrorHandler 
             ); 
            }, 
            fileErrorHandler 
           );  

          }; 
          fileWriter.onerror = function(e) { 
           console.log("Write failed (" + imageFile.name + "): " + e.toString()); 
          }; 
          fileWriter.write(new Blob(imageFile.contentBytes(), { type: imageFile.contentType })); 
         }, 
         fileErrorHandler 
        ); 
       }, 
       fileErrorHandler 
      ); 
     }, 
     fileErrorHandler 
    );  
})(); 

的自動生成的文本文件的內容被指定爲一個字符串,並且將圖像文件的內容被給定作爲base64編碼的字符串。這些很容易改變。例如,測試文本文件不僅可以包含純文本,還可以包含HTML。在這種情況下,不要忘記將textFile.contentType場改變從text/plaintext/html,並將該內容類型添加到acceptedTypes陣列上以及previewfile功能。測試圖像也可以很容易地更改,你只需要一個image-to-base64 converter

我不得不延長滴處理代碼來處理,除了圖像的文本文件:

acceptedTypes = { 
    'text/plain': true, // <-- I added this 
    'image/png': true, 
    'image/jpeg': true, 
    'image/gif': true 
}, 

... 

function previewfile(file) { 
    if (tests.filereader === true && acceptedTypes[file.type] === true) { 
     var reader = new FileReader(); 
     if (file.type === 'text/plain') { // <-- I added this branch 
      reader.onload = function (event) { 
       var p = document.createElement("p"); 
       p.innerText = event.target.result; 
       holder.appendChild(p); 
      } 
      reader.readAsText(file); 
     } else { 
      reader.onload = function (event) { 
       var image = new Image(); 
       image.src = event.target.result; 
       image.width = 250; // a fake resize 
       holder.appendChild(image); 
      }; 
      reader.readAsDataURL(file); 
     } 
    } else { 
     holder.innerHTML += '<p>Uploaded ' + file.name + ', ' + file.size + ' B, ' + file.type; 
     console.log(file); 
    } 
} 

注意,裝載jsfiddle後,自動生成的文件可上市調試目的:

Temporary file system

結果

Result

的屏幕截圖顯示,模擬降插入自動生成的文本文件的自動生成的圖像之前的內容。免打擾目標<div>的HTML代碼如下所示:

<div id="holder" class=""> 
    <p>hello, world</p> 
    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggkFBTzlUWEwwWTRPSHdBQUFBQkpSVTVFcmtKZ2dnPT0=" width="250"> 
</div> 
+0

感謝您的回答,我不知道我們能做到這一點。這不是我所需要的,但應該是我的問題的一部分。如果我們沒有得到另一個編輯答案,我會給你賞金! – caiocpricci2

+0

「這不完全是我需要的」 - 你需要什麼*完全*?這不是唯一可能的解決方案。例如,(1)如果刪除動態生成的圖像或已經是頁面一部分的圖像,或者(2)「模擬放置」按鈕可以是瀏覽器擴展的一部分,則可以省略文件選擇器。 – kol

+0

我需要刪除用戶交互。生成一個「文件」變量,它接受來自我係統的另一個文件,並可以像樣例小提琴中那樣「拖放」到元素中。不一定只是一個圖像,但如果我們只能做圖像,它已經足夠了。 – caiocpricci2

3

@kol答案是擺脫拖放事件的好辦法,但我仍然 必須手動選擇從文件我電腦。這是我對模擬感興趣的位 。有沒有辦法以編程方式創建文件 變量? -caiocpricci2

試試這個

function createFile() { 
    var create = ["<!doctype html><div>file</div>"]; 
    var blob = new Blob([create], {"type" : "text/html"}); 
    return (blob.size > 0 ? blob : "file creation error") 
}; 
createFile() 
+1

你的代碼的FileReader('processFile')部分是沒有必要的。 'createFile'是你所需要的。 –