This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Follow-Up for the "drag & drop file upload in SBM"

There was once a post regarding this topic here: RE: Drag & Drop file uploading in SBM 

But this post doen't seem to have any attachments any more (or i didn't found them). So I created my own drag & drop upload feature for SBM. Basic idea: Create a HTML/Javascrpt widget on a form in the SBM Composer and add the code below into the "content" of the HTML/Javascript widget. Thats it. A file drop zone will be rendered on the form. Any files put into this drop zone will be added to the current ticket.

<style>
#filedropzone \{
	width: 100%;
	line-height: 32px;   
	transition: 0.2s;
	text-align: center;
	border-style: dashed;
	border-width: 2px;
	border-color: lightgray;
	margin-bottom: 5px;
}
#filedropzone:hover \{ background-color:#ddf; }
.filedropzone \{ background-color:#ddf; }
</style>
<script>
function fileselect(e) \{
	var tableId = {_TableId};
	var recId = {_RecordId};
	var graphicFileExtentions=['.gif', '.png','.jpg', '.jpeg', '.GIF', '.PNG','.JPG', '.JPEG'];
	var preview = e.target;	/* the area where we display some info for the user, could be any other div also */
	var reader = new FileReader();
	var file;	/* will store one file, which is later used as argument for the reader: reader.readAsArrayBuffer(file); */

	e.stopPropagation();
	e.preventDefault();
	e.target.classList.remove("filedropzone");	/* just in case that this is still there... */

	if ( e.type == "change" ) file = e.target.files[0];	/* support onchange eveont of input file html element */
	else if ( e.type == "drop" ) file = e.dataTransfer.files[0]; /* support for file drag and drop */
	else return;		/* unknown event --> abort */

	preview.textContent = file.name;  /* give some feedback to the user. this is not changed back to the original text in this script, instead the refresh will revert this */

    reader.onload = function(f) \{
		var view = new Uint8Array(f.target.result);
		/* Construct base64 from the view to the Uint8Array. Looks complicated and is indeed complicated due to the required conversion from u8 array to string. */
		var b64 = btoa( 	/* array to string in blocks with size of 10000 to avoid the memory/stack error with some browsers */
				Array.from(Array(Math.ceil(view.length/10000)), (_,i)=> i*10000)
				.map(i=>String.fromCharCode.apply(null, view.slice(i, i + 10000)))
				.join('') 
				);
		/* Construct masterObj for the SBM UpdateFileAttachments REST interface */
		var fileObj = \{ 'action':'NEW-ONLY', 'title':file.name, 'filename':file.name, 'accessType':'ATTACHACCESS-UNRESTRICTED', 'showAsImage':graphicFileExtentions.some(x=>file.name.endsWith(x)), 'contentsbase64':\{'data':b64} };
		var masterObj = \{ 'deleteAll':false, 'includeFile': false, 'fileAttachFilter':[''], 'fileAttachList':[fileObj] };
		/* Post the file to the SBM REST Endpoint */ 
		var xhr = new XMLHttpRequest();
		xhr.open("POST", 'tmtrack.dll?JSONPage&command=jsonapi&JSON_Func=UpdateFileAttachments&JSON_P1='+tableId+'&JSON_P2='+recId, true);
		xhr.setRequestHeader("Content-Type", "application/json");
		xhr.onload = function(event)  \{
			if ( e.type == "change" ) e.target.value = null;		// in case of onchange event, try to clear the file input, may not work on all browsers
			console.log("Transfer to SBM server done", file.name, xhr.responseText);
			ReloadItem();  /* Optional: SBM Javascript function to reload the current item. This will also restore the original message in the dropzone. This might cause a leaving page browser alert. */
			preview.textContent = file.name + " uploaded";  /* give some feedback to the user. this is not changed back to the original text in this script, instead the refresh will revert this */
		}	
		xhr.send(JSON.stringify(masterObj));
    }
	reader.readAsArrayBuffer(file);
}
function filedragover(e) \{
    e.stopPropagation();
    e.preventDefault();
    e.dataTransfer.dropEffect = 'copy'; 
}

function filedragenter(e) \{
	if ( e.target )
		if ( e.target.classList )
			e.target.classList.add("filedropzone");
}

function filedragleave(e) \{
	if ( e.relatedTarget )
		if ( e.relatedTarget.nodeName == "#text" )
			return;		/* ignore leave event if we enter the inner text */
	if ( e.target )
		if ( e.target.classList )
			e.target.classList.remove("filedropzone");
}
</script>
<label id="filedropzone" ondragover="filedragover(event)" ondrop="fileselect(event)" ondragenter="filedragenter(event)" ondragleave="filedragleave(event)">
Upload: Drag and drop any file here (or click to open file chooser)<input style="display:none" type="file" accept="*.*" onchange="fileselect(event)"></div>

Note: The { are already escaped for the HTML/Javascript widget whereever required.

Parents Reply Children