UNPKG

wsemi

Version:

A support package for web developer.

258 lines (210 loc) 5.92 kB
import filter from 'lodash/filter' import get from 'lodash/get' import each from 'lodash/each' import evem from './evem.mjs' import domCancelEvent from './domCancelEvent.mjs' import pmSeries from './pmSeries.mjs' import genPm from './genPm.mjs' import isIE from './isIE.mjs' async function readFilePromise(entry) { let pm = genPm() try { entry.file(pm.resolve, pm.reject) } catch (err) { pm.reject(err) } return pm } async function readEntriesPromise(directoryReader) { let pm = genPm() try { directoryReader.readEntries(pm.resolve, pm.reject) } catch (err) { pm.reject(err) } return pm } async function treeItem(item) { let r = [] //pm let pm = genPm() async function tree(item) { let file = null if (item.isFile) { file = await readFilePromise(item) } r.push({ type: item.isDirectory ? 'folder' : item.isFile ? 'file' : 'unknow', path: item.fullPath, name: item.name, entry: item, file, }) if (item.isDirectory) { let directoryReader = item.createReader() let entries = await readEntriesPromise(directoryReader) await pmSeries(entries, async (entry) => { await tree(entry) }) } } //tree await tree(item) //resolve pm.resolve(r) return pm } async function treeItems(items) { let rs = [] await pmSeries(items, async (item) => { let r = await treeItem(item) each(r, (vv) => { rs.push(vv) }) }) return rs } async function treeEntries(items) { //its let its = [] for (let i = 0; i < items.length; i++) { let item = items[i].webkitGetAsEntry() if (item) { its.push(item) } } //treeItems let r = await treeItems(its) return r } async function treeFiles(files) { let r = [] each(files, (v) => { if (v.type) { r.push({ type: 'file', name: v.name, file: v, }) } }) return r } async function treeDataTransfer(dataTransfer) { let files = [] let entries = [] try { //files, 全部瀏覽器 files = await treeFiles(get(dataTransfer, 'files', [])) //entries, 非IE11與Opera瀏覽器 if (!isIE()) { entries = await treeEntries(get(dataTransfer, 'items', [])) } } catch (err) { return Promise.reject(err) } return { files, entries, } } /** * 前端取得拖曳進指定元素的檔案陣列 * * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/domDropFiles.test.mjs Github} * @memberOf wsemi * @param {HTMLElement} ele 輸入dom元素 * @returns {Object} 回傳物件,包含emit與off事件,emit可監聽dropIn、dropOut、getFiles,通過監聽getFiles即可取得拖曳進指定元素的檔案陣列,並呼叫其內回調函數cb,方能繼續觸發dropOut事件 * @example * need test in browser * * let ele = document.querySelector('#id') * let ev = domDropFiles(ele) * ev.on('getFiles', ({ files, filesTree, entries, cb }) => { * console.log(files, filesTree, entries) * cb() * }) * ev.on('dropIn', () => { * console.log('dropIn') * }) * ev.on('dropOut', () => { * console.log('dropOut') * }) * ev.on('error', (err) => { * console.log('error', err) * }) * */ function domDropFiles(ele) { let bMouseIn = false let bMouseInTemp = false //ev let ev = evem() //addEventListener ele.addEventListener('dragenter', dgDragin, false) ele.addEventListener('dragover', dgDragin, false) ele.addEventListener('dragleave', dgDragout, false) ele.addEventListener('drop', dgDrop, false) function dgIn(e) { domCancelEvent(e) bMouseInTemp = true //所有滑鼠進入或移動都標記為滑鼠移入狀態 if (bMouseIn === false) { bMouseIn = true ev.emit('dropIn', { ev: e }) } } function dgOut(e) { domCancelEvent(e) bMouseInTemp = false //暫時視為滑鼠移出 setTimeout(function() { if (!bMouseInTemp) { //若100ms後仍為滑鼠移出狀態才emit事件 bMouseIn = false ev.emit('dropOut', { ev: e }) } }, 100) } function dgDragin(e) { dgIn(e) } function dgDragout(e) { dgOut(e) } function dgDrop(e) { //dgIn dgIn(e) //cb for dgOut function cb() { dgOut(e) } //treeDataTransfer treeDataTransfer(e.dataTransfer) .then((r) => { //filesTree let filesTree = filter(r.entries, { type: 'file' }) //emit ev.emit('getFiles', { ev: e, files: r.files, filesTree, entries: r.entries, cb }) }) .catch((err) => { ev.emit('error', err) }) } //off function off() { ele.removeEventListener('dragenter', dgDragin, false) ele.removeEventListener('dragover', dgDragin, false) ele.removeEventListener('dragleave', dgDragout, false) ele.removeEventListener('drop', dgDrop, false) } ev.off = off return ev } export default domDropFiles