画像ファイルをドラッグアンドドロップして文字列化(base64)する。その2?
<!DOCTYPE hrml> <head> <meta charset="utf-8"> <title></title> <body> <p> <form> <p> <img id="img" src="" alt="写真" width="200" height="100"><br> この図形領域にデスクトップから画像ファイルをドラッグ&ドロップすると画像を入力できます </p> <input type="hidden" name="hide" value=""><br> <textarea name="text" cols="180" rows="35"></textarea> </form> <script> //_____________________________________________________________________ { /*##################################################### input[type="hidden"]の要素の value値に変更があった場合 change イベントを発火させる cbFuncを指定すると、changeイベントが発火する前に呼ばれる #####################################################*/ const option = { attributes : true, attributeFilter : ['value'] } , handler = function ([mutation]) { let target = mutation.target, // => input[type="hidden"] doc = target.ownerDocument, event = doc.createEvent ('MouseEvents'); event.initEvent ('change', true, true); if (this.cbFunc) this.cbFunc.call (this.cbObj, event); target.dispatchEvent (event); } ; //_____________________________ class AddChangeEvent { constructor (element = null, cbFunc = null, cbObj = null) { if (null === element) throw new Error ('要素がありません'); let observer = new MutationObserver (handler.bind (this)); observer.observe (element, option); this.element = element; this.cbFunc = cbFunc; this.cbObj = cbObj; this.observer = observer; } } //_____________________________ this.AddChangeEvent = AddChangeEvent; } //_____________________________________________________________________ /*##################################################### ファイルを読み終わったら、コールバック関数を実行する #####################################################*/ FileLoader: { const FILE_MAX_SIZE = 65536, IMAGE_FILE_TYPE = 'image/', handler = function (event) { this.cbFunc.call (this.cbObj, event.target); } ; class FileLoader { constructor (file, cbFunc = null, cbObj = null) { this.cbFunc = cbFunc; this.cbObj = cbObj; let reader = new FileReader (); reader.addEventListener ('load', this, false); reader.readAsDataURL (file); } // file の load 後に発火 event.target = FileReader handleEvent (event) { handler.call (this, event); } } //__________________ class ImageLoader extends FileLoader { constructor (target, file, cbFunc, cbObj) { if (2 > arguments.length) throw new Error ('引数が足りません'); let { size, type } = file; if (FILE_MAX_SIZE < size) throw new Error ('ファイルサイズが制限を超えました'); if (type.indexOf (IMAGE_FILE_TYPE)) throw new Error ('イメージファイルではありません'); super (file, cbFunc, cbObj); this.target = target; } handleEvent (event) { this.target.src = event.target.result; handler.call (this, event); } } //__________________ this.FileLoader = FileLoader; this.ImageLoader = ImageLoader; } //_____________________________________________________________________ { /*##################################################### 指定された要素にドラッグアンドドロップイベントが発生した時に コールバック関数を実行する #####################################################*/ class AddDnDEventFromDeskTop { constructor (target, cbFunc, cbObj) { if (1 > arguments.length) throw new Error ('引数が不足しています'); this.target = target; this.cbFunc = cbFunc; this.cbObj = cbObj; target.addEventListener ('dragover', this, false); target.addEventListener ('drop', this, false); target.dropzone = 'copy'; } handleEvent (event) { event.stopPropagation (); event.preventDefault (); switch (event.type) { case 'drop' : this.cbFunc.call (this.cbObj, event); break; case 'dragover' : event.dataTransfer.dropEffect = 'copy'; break; } } } //___________________ this. AddDnDEventFromDeskTop = AddDnDEventFromDeskTop; } //_____________________________________________________________________ let [form, img, hide] = document.querySelectorAll ('form, img, input[type="hidden"]'); form.addEventListener ('change', function (event) { let target = event.target, {name, type, value} = target, form = target.form, text = form.elements['text'], line = [], reg = /(^data:image\/.+;base64,|.{180}|.+$)/g, tmp; while (tmp = reg.exec (value)) { line.push (tmp[0]); } text.value = line.join ('\n'); }, false); new AddChangeEvent (hide); new AddDnDEventFromDeskTop (img, DnDHandler); //_____________________________________________________________________ function DnDHandler (event) { let {dataTransfer, target} = event; if (dataTransfer) if (dataTransfer.files) new ImageLoader (target, dataTransfer.files[0], step2); } function step2 (fileReader) { let hide = document.querySelector ('input[type="hidden"]'); hide.value = fileReader.result; } </script>
img要素のsrcの値が変化するのを監視して、イベントを発火させてるとスマートな気もするが、なんだかな。