This article is relevant if you use NetSuite and you would like to be able to copy (or cut) and paste images in HTML or rich text editors.
Background
Recently, we moved away from a third party support ticket system to help us manage all of our client NetSuite project and care requests. Instead, we built the “Prolecto Task Manager”, or PTM, on top of NetSuite’s Case system. A nice feature of the old third party ticket manager was the mechanism to copy and paste image information into our tickets. Since so much of our client work demands visual representation, the ability to easily work with images is paramount.
In our first version of the system, we recognized that NetSuite does not natively support the mechanism to copy and paste image information into its Rich Text Editor fields. The TinyMCE editor offered an image copy-and-paste feature which we valued. Thus, we took the approach to embed the TinyMCE editor into our Suitelet driven PTM application. Please see my article, Replace NetSuite’s Rich Text Editor with a Custom HTML Editor.
However, to activate the image cut-and-paste feature, the TinyMCE editor required a paid plug-in based on the number of users. I reasoned, “fine, let’s pay the monthly fee as this is valuable to our practice”. However, with the roll-out of our application in late 2018, we learned with the usage that the TinyMCE organization’s license model did not account for the way our users used our tool (in my view, they grossly over-counted the number of users) — and they demanded much greater monthly license revenue. I decided that was unacceptable and consequently needed to act. Since we are NetSuite Systems Integrators, it was not outside our reach to “roll-our-own”.
Fundamentals in Browser Based Image Copy and Paste
The good news is that with the advent of HTML 5, the clipboard events are much easier to work with. That opens up space for easier innovation. There are really two key approaches for handling Copy & Paste images in HTML documents:
- Convert to Base64 in Image Data: An image can be converted to a Base64 data stream and then wrapped with the appropriate HTML image tags to visually present the picture. Under this method, the image is not stored as a file on a web server; instead, it becomes part of the HTML data. This is how TinyMCE approached the solution. To learn more about this method, see this link.
- Post Image as a File to the Server and then Reference: Another method is to asynchronously post an image to the web server and then HTML reference it by its URL. Under this method, the image can easily be referenced multiple times and it keeps the actual HTML document trim and tidy. For the purposes of solving this challenge, I used this method. Readers may want to learn more about the pattern here.
How To Post Image as File to NetSuite Server and Reference
The mechanism to post an image to NetSuite requires two parts:
- Suitelet Application: produce a Suitelet that accepts a POST from a client web page. If the post conforms to the file data expectation, save it to the NetSuite file system. Return to the client web application the URL reference.
- Client Web Application: capture the browser paste event. If it conforms to image data, then post that data to the Suitelet application. If the post succeeds, use the URL return reference to craft an image tag and inject this into the HTML. By using an asynchronous pattern (AJAX), we can produce some instrumentation to the user about what is happening.
Cut & Paste HTML Demonstration
To see this in action, you can run this program that is hosted by one of our developer accounts. Feel free to view this page’s web source to learn the client side pattern.
Cut & Paste with Rich Text Editor in NetSuite (1:06)
After I learned how to get the basics working, I did the difficult work to connect it up to NetSuite’s Rich Text Editor. You can see a demonstration of this via the video (1:06) below. The process required that I study how NetSuite implemented the Rich Text Editor so that I could bind the Paste event, produce instrumentation, and then inject HTML into the editor. It works very fast and is quite nice as I can get control over the resulting image tag any way I want.
SuiteScript 2.0 Suitelet to Post Image Data to NetSuite
Here is the Suitelet code on the server. You can use this code template to develop your own image and file copy and paste program.
//program by Marty Zigman to learn that we can indeed post a file to NetSuite and return an anonymous hyperlink define(['N/runtime', 'N/log', 'N/file'], function (runtime, log, file) { function onRequest(context) { var objCurScript = runtime.getCurrentScript(); //make flexible by having multiple deployments const IMAGE_FOLDER = objCurScript.getParameter({ name : 'custscript_mz_filepost_learn_folder' }); const HTMLFILE = objCurScript.getParameter({ name : 'custscript_mz_filepost_learn_imghtml' }); log.debug({title: 'Server Request URL', details: context.request.url}); log.debug({title: 'Server Request Parameters', details: context.request.parameters}); //this mode is when the image is posted to the server if (context.request.method == "POST"){ var fObjs = context.request.files; var hrefs = []; //don't take a chance, we expect only one file but handle more than one for (f in fObjs) { log.debug ({title: 'f:' + f, details: fObjs[f] }) var fObj = fObjs[f] if (fObj){ //now write the file and mark it available for download var fileObj = file.create({ name: f, fileType: fObj.fileType, contents: fObj.getContents(), encoding: file.Encoding.UTF8, folder: IMAGE_FOLDER, isOnline: true }) var fileID = fileObj.save() log.debug({title: 'File fragment saved with ID', details: fileID}); var fileObj = file.load({id: fileID}) //build a JSON array of URLs hrefs.push({scr : getRootUrl(context.request.url) + fileObj.url }) } } //return the JSON to the client log.debug({title: 'hrefs', details: hrefs}); context.response.write (JSON.stringify({output: hrefs})) } //write the client web page by reading in the HTMLFILE in a GET operation if (context.request.method == "GET"){ var html = file.load({id: HTMLFILE}) context.response.write ({output: html.getContents()}) } } function getRootUrl(url) { return url.toString().replace(/^(.*\/\/[^\/?#]*).*$/,"$1"); } return { onRequest : onRequest }; /* * image/png * image/jpg, * image/jpeg * image/gif * image/svg+xml */ });
Get Image Copy & Paste in Your NetSuite Account
My hope is that this article helps you learn that your hands are really never tied up in NetSuite. The program pattern should help the NetSuite developer community implement their own image copy and paste routines. However, if you would like to enable an image cut and paste into your NetSuite account without doing the development, we can install the program in your environment to produce a better NetSuite user experience. Just reach out to me so that we can have a conversation.
Hi, thank you so much for sharing. I’m a fresher and currently on training. I want to ask: Do you know how to export excel from saved search, which have image in each cell? Sorry for my bad english.
Hello Yuu,
We are currently working on a project with a client to export crafted NetSuite saved searches that generate Excel documents. The images will likely be in reach. I recommend subscribing to this blog to get a future announcement: https://blog.prolecto.com/email-subscription/
Marty
Hi Marty,
I’m trying to get Netsuite’s backend IP address, but while getting it gives my current network IP address, is it possible to get Netsuite’s IP address? because I need to whitelist the IP address so that I want to know Netsuite IP address.
Brus, this comment is out of context from this article. But I recommend you read this article instead about the limitations to getting NetSuite’s backend IP address:
https://blog.prolecto.com/2020/08/08/netsuite-ip-restrictions-for-sftp-services/
Marty