1import ApplicationController from "satis/controllers/application_controller" 2 3import SignaturePad from "signature_pad" 4 5export default class SignatureComponentController extends ApplicationController { 6 static targets = ["canvas", "file"] 7 static values = { url: String } 8 9 async connect() { 10 this.signaturePad = new SignaturePad(this.canvasTarget) 11 if (this.hasUrlValue) { 12 let blob = await fetch(this.urlValue, { cache: "no-store" }) 13 .then(r => r.blob()) 14 15 let dataUrl = await new Promise(resolve => { 16 let reader = new FileReader() 17 reader.onload = () => resolve(reader.result) 18 reader.readAsDataURL(blob) 19 }) 20 const dpi = window.devicePixelRatio 21 window.devicePixelRatio = 1 22 this.signaturePad.fromDataURL(dataUrl) 23 const file = this.dataURLtoFile(dataUrl, "signature.svg") 24 window.devicePixelRatio = dpi 25 this.signaturePad.addEventListener("beginStroke", this.clear.bind(this), { once: true }) 26 this.persistFile(file) 27 } 28 this.signaturePad.addEventListener("endStroke", this.persist.bind(this)) 29 } 30 31 clear(event) { 32 this.signaturePad.clear() 33 this.fileTarget.files = new DataTransfer().files 34 } 35 36 undo(event) { 37 event.preventDefault() 38 const data = this.signaturePad.toData() 39 if (data) { 40 data.pop() 41 this.signaturePad.fromData(data) 42 } 43 } 44 45 persist(event) { 46 const dpi = window.devicePixelRatio 47 const dataUrl = this.signaturePad.toSVG() 48 window.devicePixelRatio = 1 49 const file = new File([this.signaturePad?.toSVG()], "signature.svg", { type: "image/svg+xml" }) 50 window.devicePixelRatio = dpi 51 this.persistFile(file) 52 } 53 54 persistFile(file) { 55 const dt = new DataTransfer() 56 dt.items.add(file) 57 this.fileTarget.files = dt.files 58 } 59 60 // HELPER 61 62 dataURLtoFile(dataurl, filename) { 63 var arr = dataurl.split(","), 64 mime = arr[0].match(/:(.*?);/)[1], 65 bstr = atob(arr[arr.length - 1]), 66 n = bstr.length, 67 u8arr = new Uint8Array(n); 68 while (n--) { 69 u8arr[n] = bstr.charCodeAt(n); 70 } 71 return new File([u8arr], filename, { type: mime }); 72 } 73};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.