1 /**
  2  * drag file support for html5 file&dd
  3  * @author yiminghe@gmail.com
  4  * @refer: http://www.html5rocks.com/tutorials/file/filesystem/
  5  *         http://yiminghe.iteye.com/blog/848613
  6  */
  7 KISSY.add("editor/plugin/dragUpload/index", function (S, Editor) {
  8     var Node = S.Node,
  9         Event = S.Event,
 10         Utils = Editor.Utils,
 11         DOM = S.DOM;
 12 
 13     function dragUpload(config) {
 14         this.config=config||{};
 15     }
 16 
 17     S.augment(dragUpload, {
 18         renderUI:function (editor) {
 19             var cfg = this.config,
 20                 fileInput = cfg['fileInput'] || "Filedata",
 21                 sizeLimit = cfg['sizeLimit'] || Number.MAX_VALUE,
 22                 serverParams = cfg['serverParams'] || {},
 23                 serverUrl = cfg['serverUrl'] || "",
 24                 suffix = cfg['suffix'] || "png,jpg,jpeg,gif",
 25                 suffix_reg = new RegExp(suffix.split(/,/).join("|") + "$", "i"),
 26 
 27                 inserted = {}, startMonitor = false;
 28 
 29             function nodeInsert(ev) {
 30                 var oe = ev['originalEvent'],
 31                     t = oe.target;
 32                 if (DOM.nodeName(t) == "img" && t.src.match(/^file:\/\//)) {
 33                     inserted[t.src] = t;
 34                 }
 35             }
 36 
 37             editor.docReady(function () {
 38                 var document = editor.get("document")[0];
 39                 Event.on(document, "dragenter", function () {
 40                     //firefox 会插入伪数据
 41                     if (!startMonitor) {
 42                         Event.on(document, "DOMNodeInserted", nodeInsert);
 43                         startMonitor = true;
 44                     }
 45                 });
 46 
 47                 Event.on(document, "drop", function (ev) {
 48                     Event.remove(document, "DOMNodeInserted", nodeInsert);
 49                     startMonitor = false;
 50                     ev.halt();
 51                     ev = ev['originalEvent'];
 52 
 53                     var archor, ap;
 54                     /**
 55                      * firefox 会自动添加节点
 56                      */
 57                     if (!S.isEmptyObject(inserted)) {
 58                         S.each(inserted, function (el) {
 59                             if (DOM.nodeName(el) == "img") {
 60                                 archor = el.nextSibling;
 61                                 ap = el.parentNode;
 62                                 DOM.remove(el);
 63                             }
 64                         });
 65                         inserted = {};
 66                     } else {
 67                         // 空行里拖放肯定没问题,其他在文字中间可能不准确
 68                         ap = document.elementFromPoint(ev.clientX, ev.clientY);
 69                         archor = ap.lastChild;
 70                     }
 71 
 72                     var dt = ev['dataTransfer'];
 73                     dt.dropEffect = "copy";
 74                     var files = dt['files'];
 75                     if (!files) {
 76                         return;
 77                     }
 78                     for (var i = 0; i < files.length; i++) {
 79                         var file = files[i], name = file.name, size = file.size;
 80                         if (!name.match(suffix_reg)) {
 81                             continue;
 82                         }
 83                         if (size / 1000 > sizeLimit) {
 84                             continue;
 85                         }
 86                         var img = new Node("<img " + "src='" +
 87                             Utils.debugUrl("theme/tao-loading.gif")
 88                             + "'" + "/>");
 89                         var nakeImg = img[0];
 90                         ap.insertBefore(nakeImg, archor);
 91                         var np = nakeImg.parentNode, np_name = DOM.nodeName(np);
 92                         // 防止拖放导致插入到 body 以外
 93                         if (np_name == "head"
 94                             || np_name == "html") {
 95                             DOM.insertBefore(nakeImg, document.body.firstChild);
 96                         }
 97 
 98                         fileUpload(file, img);
 99                     }
100                 });
101             });
102 
103 
104             if (window['XMLHttpRequest'] && !XMLHttpRequest.prototype.sendAsBinary) {
105                 XMLHttpRequest.prototype.sendAsBinary = function (dataStr, contentType) {
106                     // chrome12 引入 WebKitBlobBuilder
107                     var bb = new (window['BlobBuilder'] || window['WebKitBlobBuilder'])();
108                     var len = dataStr.length;
109                     var data = new window['Uint8Array'](len);
110                     for (var i = 0; i < len; i++) {
111                         data[i] = dataStr['charCodeAt'](i);
112                     }
113                     bb.append(data.buffer);
114                     this.send(bb['getBlob'](contentType));
115                 }
116             }
117 
118             /**
119              *
120              * @param img loading 占位图片
121              * @param file 真实数据
122              */
123             function fileUpload(file, img) {
124 
125                 var reader = new window['FileReader']();
126                 //chrome 不支持 addEventListener("load")
127                 reader.onload = function (ev) {
128                     // Please report improvements to: marco.buratto at tiscali.it
129                     var fileName = file.name,
130                         fileData = ev.target['result'],
131                         boundary = "----kissy-editor-yiminghe",
132                         xhr = new XMLHttpRequest();
133 
134                     xhr.open("POST", serverUrl, true);
135                     xhr.onreadystatechange = function () {
136                         if (xhr.readyState == 4) {
137                             if (xhr.status == 200 || xhr.status == 304) {
138                                 if (xhr.responseText != "") {
139                                     var info = window['JSON'].parse(xhr.responseText);
140                                     img[0].src = info['imgUrl'];
141                                 }
142                             } else {
143                                 alert("服务器端出错!");
144                                 img.remove();
145                                 S.log(xhr);
146                             }
147                             xhr.onreadystatechange = null;
148                         }
149                     };
150 
151                     var body = "\r\n--" + boundary + "\r\n";
152                     body += "Content-Disposition: form-data; name=\"" +
153                         fileInput + "\"; filename=\"" + encodeURIComponent(fileName) + "\"\r\n";
154                     body += "Content-Type: " + (file.type || "application/octet-stream") + "\r\n\r\n";
155                     body += fileData + "\r\n";
156                     serverParams = Editor.Utils.normParams(serverParams);
157                     for (var p in serverParams) {
158                         if (serverParams.hasOwnProperty(p)) {
159                             body += "--" + boundary + "\r\n";
160                             body += "Content-Disposition: form-data; name=\"" +
161                                 p + "\"\r\n\r\n";
162                             body += serverParams[p] + "\r\n";
163                         }
164                     }
165                     body += "--" + boundary + "--";
166 
167                     xhr.setRequestHeader("Content-Type",
168                         "multipart/form-data, boundary=" + boundary);
169                     // simulate a file MIME POST request.
170 
171                     xhr.sendAsBinary("Content-Type: multipart/form-data; boundary=" +
172                         boundary + "\r\nContent-Length: " + body.length
173                         + "\r\n" + body + "\r\n");
174                     reader.onload = null;
175                 };
176                 reader['readAsBinaryString'](file);
177             }
178         }
179     });
180 
181     return dragUpload;
182 }, {
183     requires:['editor']
184 });