js拖拽粘貼上傳與CodeMirror

Markdown編輯器選用https://simplemde.com
它是一款純js實現的markdown編輯器。缺點不支持圖片上傳。那咱們就得改造它。
simplemde是基於codemirror編輯器的.
先介紹基本:
codemirror文檔:http://codemirror.net/doc/man...
simplemde文檔:https://github.com/NextStepWe...
API文檔:
拖拽:
https://developer.mozilla.org...
https://developer.mozilla.org...javascript

粘貼:
https://developer.mozilla.org...
https://developer.mozilla.org...css

注意一點:目前firefox與chrome比較新的版本都實現了這些API。html

paste事件

綁定的元素不必定是input,普通的div也是能夠綁定的,若是是給document綁定了,就至關於全局了,任什麼時候候的粘貼操做都會觸發。
獲取事件對象ClipboardEvent
先寫一下事件綁定的代碼java

pasteEle.addEventListener("paste", function (e){
    if ( !(e.clipboardData && e.clipboardData.items) ) {
        return ;
    }
 
    for (var i = 0, len = e.clipboardData.items.length; i < len; i++) {
        var item = e.clipboardData.items[i];
 
        if (item.kind === "string") {
            item.getAsString(function (str) {
                // str 是獲取到的字符串
            })
        } else if (item.kind === "file") {
            var pasteFile = item.getAsFile();
            // pasteFile就是獲取到的文件
        }
    }
});

粘貼事件提供了一個clipboardData的屬性,若是該屬性有items屬性,那麼就能夠查看items中是否有圖片類型的數據了。
clipboardData介紹
介紹一下clipboardData對象,它其實是一個DataTransfer類型的對象,DataTransfer 是拖動產生的一個對象,但實際上粘貼事件也是它。
屬性介紹
dropEffect String 默認是 none
effectAllowed String 默認是 uninitialized
files FileList 在粘貼操做時爲空List
items DataTransferItemList 剪切板中的各項數據
types Array 剪切板中的數據類型。git

DataTransferItem
items是一個DataTransferItemList對象,天然裏面都是DataTransferItem類型的數據了。
DataTransferItem有兩個屬性kind和typegithub

kind 通常爲string或者file
type 具體的數據類型,例如具體是哪一種類型字符串或者哪一種類型的文件,即MIME-Type,常見的值有text/plain、text/html、Files。
方法web

getAsFile 空 若是kind是file,能夠用該方法獲取到文件
getAsString 回調函數 若是kind是string,能夠用該方法獲取到字符串,字符串須要用回調函數獲得,回調函數的第一個參數就是剪切板中的字符串
綜合chrome

// demo 程序將粘貼事件綁定到 document 上
document.addEventListener("paste", function (e) {
    var cbd = e.clipboardData;
    //var ua = window.navigator.userAgent;
 
    for(var i = 0; i < cbd.items.length; i++) {
        var item = cbd.items[i];
        if(item.kind == "file"){
            var blob = item.getAsFile();
            if (blob.size === 0) {
                return;
            }
            // blob 就是從剪切板得到的文件 能夠進行上傳或其餘操做
        }
    }
}, false);

drop事件

DragEvent
DragEvent.dataTransfersegmentfault

dropEffect String 默認是 none
effectAllowed String 默認是 uninitialized
files FileList
items DataTransferItemList 剪切板中的各項數據
types Array 剪切板中的數據類型。
DataTransferItem
items是一個DataTransferItemList對象,天然裏面都是DataTransferItem類型的數據了。數組

DataTransferItem有兩個屬性kind和type

kind 通常爲string或者file
type 具體的數據類型,例如具體是哪一種類型字符串或者哪一種類型的文件,即MIME-Type,常見的值有images/*、text/plain、text/html、Files。
方法

getAsFile 空 若是kind是file,能夠用該方法獲取到文件
getAsString 回調函數 若是kind是string,能夠用該方法獲取到字符串,字符串須要用回調函數獲得,回調函數的第一個參數就是剪切板中的字符串

dropEle.addEventListener("drop", function (e){
    var data = new FormData();
    var files = event.dataTransfer.files;
    var i = 0;
    var len = files.length;
    while (i < len){
        data.append("file" + i, files[i]);
         i++;
    }
    var xhr = new XMLHttpRequest();
    xhr.open("post", "/upload", true);
    xhr.onreadystatechange = function(){
         if (xhr.readyState == 4){
             alert(xhr.responseText);
         }
     };
     xhr.send(data);
});

阻止瀏覽器默認打開拖拽文件的行爲:參考這裏

window.addEventListener("drop",function(e){
  e = e || event;
  console.log(e);
  //e.preventDefault();
  if (e.target.tagName != "textarea") {  // check wich element is our target
    e.preventDefault();
  }  
},false);

理論知識說完了。下面開始實驗改造codemirror

codemirror支持粘貼和拖拽上傳

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>codemirror</title>
    <link rel="stylesheet" href="codemirror.css">
    <script src="codemirror.js"></script>
</head>
<body>
    <textarea name="aaa" id="aaa"></textarea>
    <script>
    var textarea=document.getElementById("aaa")
      var editor = CodeMirror.fromTextArea(textarea, {
        lineNumbers: true
      });
  editor.on("paste",function(editor,e){
      // console.log(e.clipboardData)
      if(!(e.clipboardData&&e.clipboardData.items)){
          alert("該瀏覽器不支持操做");
          return;
      }
      for (var i = 0, len = e.clipboardData.items.length; i < len; i++) {
        var item = e.clipboardData.items[i];
       // console.log(item.kind+":"+item.type);
        if (item.kind === "string") {
            item.getAsString(function (str) {
                // str 是獲取到的字符串
            })
        } else if (item.kind === "file") {
            var pasteFile = item.getAsFile();
            // pasteFile就是獲取到的文件
            console.log(pasteFile);
            fileUpload(pasteFile);
        }
    }
  });
  editor.on("drop",function(editor,e){
      // console.log(e.dataTransfer.files[0]);
      if(!(e.dataTransfer&&e.dataTransfer.files)){
          alert("該瀏覽器不支持操做");
          return;
      }
      for(var i=0;i<e.dataTransfer.files.length;i++){
          console.log(e.dataTransfer.files[i]);
          fileUpload(e.dataTransfer.files[i]);
      }
      e.preventDefault();
  });
  //文件上傳
  function fileUpload(fileObj){
      var data = new FormData();
      data.append("file",fileObj);
      var xhr = new XMLHttpRequest();
    xhr.open("post", "/upload", true);
    xhr.onreadystatechange = function(){
         if (xhr.readyState == 4){
             alert(xhr.responseText);
         }
     };
     xhr.send(data);
  }
  //阻止瀏覽器默認打開拖拽文件的行爲
  window.addEventListener("drop",function(e){
  e = e || event;
  e.preventDefault();
  if (e.target.tagName == "textarea") {  // check wich element is our target
    e.preventDefault();
  } 
},false);
</script>
</html>

附Codemirror經常使用事件與方法
參考這裏
1.onChange(instance,changeObj):codeMirror文本被修改後觸發。
instance是一個當前的codemirror對象,changeObj是一個{from,to,text,removed}對象。其中from,to分別表示起始行對象和結束行對象,行對象包括ch:改變位置距離行頭的間隔字符,line:改變的行數。text是一個字符串數組表示被修改的文本內容,即你輸入的內容。

2.onBeforeChange(instance,changObj):內容改變前被調用
3.onCursorActivity(instance):當鼠標點擊內容區、選中內容、修改內容時被觸發
4.onKeyHandled:(instance,name,event):當一個都dom元素的事件觸發時調用,name爲操做名稱。
5.onInputRead(insatance,changeObj):當一個新的input從隱藏的textara讀取出時調用
6.onBeforeSelectionChange(instance,obj):當選中的區域被改變時調用,obj對象是選擇的範圍和改變的內容(本人未測試成功)
7.onUpdate(instance):編輯器內容被改變時觸發
8.onFocus(instance):編輯器得到焦點式觸發
9.onBlur(instance):編輯器失去焦點時觸發

經常使用方法:
getValue():獲取編輯器文本內容
setValue(text):設置編輯器文本內容
getRange({line,ch},{line,ch}):獲取指定範圍內的文本內容第一個對象是起始座標,第二個是結束座標
replaceRange(replaceStr,{line,ch},{line,ch}):替換指定區域的內容
getLine(line):獲取指定行的文本內容
lineCount():統計編輯器內容行數
firstLine():獲取第一行行數,默認爲0,從開始計數
lastLine():獲取最後一行行數
getLineHandle(line):根據行號獲取行句柄
getSelection():獲取鼠標選中區域的代碼
replaceSelection(str):替換選中區域的代碼
setSelection({line:num,ch:num1},{line:num2,ch:num3}):設置一個區域被選中
somethingSelected():判斷是否被選擇
getEditor():獲取CodeMirror對像
undo():撤銷
redo():回退

simplemde支持粘貼和拖拽上傳

var simplemde = new SimpleMDE({ element: document.getElementById("MyID") });
simplemde.codemirror.on("drop", function(editor,e){
    ...
});
simplemde.codemirror.on("paste",function(editor,e){
...
});

Blob對象轉File對象

爲了使用WebUploader這個文件上傳組件,須要將粘貼獲得的Blob對象轉爲File對象。
Blob 對象是包含有隻讀原始數據的類文件對象.File 接口基於 Blob,繼承了 Blob 的功能,而且擴展支持用戶計算機上的本地文件。

var blob=new Blob();
var file = new File([blob], "image.png", {type:"image/png"});

File構造器的第一個參數必須是數組

WebUploader文件上傳

http://fex.baidu.com/webuploa...
建立Uploader對象

var uploader = WebUploader.Uploader({
    swf: 'path_of_swf/Uploader.swf',
 
    // 開起分片上傳。
    chunked: true
});

監聽fileQueued事件來實現進度UI構造:

// 當有文件被添加進隊列的時候
uploader.on( 'fileQueued', function( file ) {
    var $list=$("#list");
    $list.append( '<div id="' + file.id + '" class="item">' +
        '<h4 class="info">' + file.name + '</h4>' +
        '<p class="state">等待上傳...</p>' +
    '</div>' );
});

文件上傳進度:

// 文件上傳過程當中建立進度條實時顯示。
uploader.on( 'uploadProgress', function( file, percentage ) {
    var $li = $( '#'+file.id ),
    $percent = $li.find('.progress .progress-bar');
    // 避免重複建立
    if ( !$percent.length ) {
        $percent = $('<div class="progress progress-striped active">' +
          '<div class="progress-bar" role="progressbar" style="width: 0%">' +
          '</div>' +
        '</div>').appendTo( $li ).find('.progress-bar');
    }
 
    $li.find('p.state').text('上傳中');
    $percent.css( 'width', percentage * 100 + '%' );
});

文件成功、失敗處理:

uploader.on( 'uploadSuccess', function( file,data ) {
    $( '#'+file.id ).find('p.state').text('已上傳');
});
 
uploader.on( 'uploadError', function( file ) {
    $( '#'+file.id ).find('p.state').text('上傳出錯');
});
 
uploader.on( 'uploadComplete', function( file ) {
    $( '#'+file.id ).find('.progress').fadeOut();
});

添加文件到隊列並上傳:

uploader.addFiles( file ) 
uploader.addFiles( [file1, file2 …] )

開始上傳:

uploader.upload() 
//uploader.upload( file | fileId)

其餘參考:
js獲取剪切板內容,js控制圖片粘貼
在線代碼編輯器 CODEMIRROR 事件說明
javascript.ruanyifeng.com
https://developer.mozilla.org...

相關文章
相關標籤/搜索