/// /// // namespace namespace cf { // interface // class export class UploadFileUI extends Button { private maxFileSize: number = 100000000000; private onDomElementChangeCallback: () => void; private progressBar: HTMLElement; private loading: boolean = false; private submitTimer: number = 0; private _fileName: string = ""; private _readerResult: string = ""; private _files: FileList; public get value():string{ return ( this.referenceTag.domElement).value;//;this.readerResult || this.fileName; } public get readerResult():string{ return this._readerResult; } public get files():FileList{ return this._files; } public get fileName():string{ return this._fileName; } public get type():string{ return "UploadFileUI"; } constructor(options: IControlElementOptions){ super(options); if(Helpers.caniuse.fileReader()){ const maxFileSizeStr: string = this.referenceTag.domElement.getAttribute("cf-max-size") || this.referenceTag.domElement.getAttribute("max-size"); if(maxFileSizeStr){ const maxFileSize: number = parseInt(maxFileSizeStr, 10); this.maxFileSize = maxFileSize; } this.progressBar = this.el.getElementsByTagName("cf-upload-file-progress-bar")[0]; this.onDomElementChangeCallback = this.onDomElementChange.bind(this); this.referenceTag.domElement.addEventListener("change", this.onDomElementChangeCallback, false); }else{ throw new Error("Conversational Form Error: No FileReader available for client."); } } public getFilesAsString(): string{ // value is for the chat response --> var icon = document.createElement("span"); icon.innerHTML = Dictionary.get("icon-type-file") + this.fileName; return icon.outerHTML; } private onDomElementChange(event: any){ if(!ConversationalForm.suppressLog) console.log("...onDomElementChange"); var reader: FileReader = new FileReader(); this._files = ( this.referenceTag.domElement).files; reader.onerror = (event: any) => { if(!ConversationalForm.suppressLog) console.log("onerror", event); } reader.onprogress = (event: ProgressEvent) => { if(!ConversationalForm.suppressLog) console.log("onprogress", event); this.progressBar.style.width = ((event.loaded / event.total) * 100) + "%"; } reader.onabort = (event: any) => { if(!ConversationalForm.suppressLog) console.log("onabort", event); } reader.onloadstart = (event: any) => { // check for file size const file: File = this.files[0]; const fileSize: number = file ? file.size : this.maxFileSize + 1;// if file is undefined then abort ... if(fileSize > this.maxFileSize){ reader.abort(); const dto: FlowDTO = { errorText: Dictionary.get("input-placeholder-file-size-error") }; ConversationalForm.illustrateFlow(this, "dispatch", FlowEvents.USER_INPUT_INVALID, dto) this.eventTarget.dispatchEvent(new CustomEvent(FlowEvents.USER_INPUT_INVALID, { detail: dto })); }else{ // good to go this._fileName = file.name; this.loading = true; this.animateIn(); // set text let sizeConversion: number = Math.floor( Math.log(fileSize) / Math.log(1024) ); const sizeChart: Array = ["b", "kb", "mb", "gb"]; sizeConversion = Math.min(sizeChart.length - 1, sizeConversion); const humanSizeString: string = Number((fileSize / Math.pow(1024, sizeConversion)).toFixed(2)) * 1 + " " + sizeChart[sizeConversion]; const text: string = file.name + " ("+humanSizeString+")"; this.el.getElementsByTagName("cf-upload-file-text")[0].innerHTML = text; this.eventTarget.dispatchEvent(new CustomEvent(ControlElementEvents.PROGRESS_CHANGE, { detail: ControlElementProgressStates.BUSY })); } } reader.onload = (event: any) => { this._readerResult = event.target.result; this.progressBar.classList.add("loaded"); this.submitTimer = setTimeout(() =>{ this.el.classList.remove("animate-in"); this.onChoose(); // submit the file this.eventTarget.dispatchEvent(new CustomEvent(ControlElementEvents.PROGRESS_CHANGE, { detail: ControlElementProgressStates.READY })); }, 0); } reader.readAsDataURL(this.files[0]); } public animateIn(){ if(this.loading) super.animateIn(); } protected onClick(event: MouseEvent){ // super.onClick(event); } public triggerFileSelect(){ // trigger file prompt this.referenceTag.domElement.click(); } // override public dealloc(){ clearTimeout(this.submitTimer); this.progressBar = null; if(this.onDomElementChangeCallback){ this.referenceTag.domElement.removeEventListener("change", this.onDomElementChangeCallback, false); this.onDomElementChangeCallback = null; } super.dealloc(); } public getTemplate () : string { const isChecked: boolean = this.referenceTag.value == "1" || this.referenceTag.domElement.hasAttribute("checked"); return ` `; } } }