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
綁定的元素不必定是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);
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
<!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():回退
var simplemde = new SimpleMDE({ element: document.getElementById("MyID") }); simplemde.codemirror.on("drop", function(editor,e){ ... }); simplemde.codemirror.on("paste",function(editor,e){ ... });
爲了使用WebUploader這個文件上傳組件,須要將粘貼獲得的Blob對象轉爲File對象。
Blob 對象是包含有隻讀原始數據的類文件對象.File 接口基於 Blob,繼承了 Blob 的功能,而且擴展支持用戶計算機上的本地文件。
var blob=new Blob(); var file = new File([blob], "image.png", {type:"image/png"});
File構造器的第一個參數必須是數組
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...