NetSuite/Suitescript/Workflow: How do I open a URL from a field after clicking button? - url

I have a workflow that adds a button "Open Link" and a field on the record called "URL" that contains a hyperlink to an attachment in NetSuite. I want to add a workflow action script that opens this url in a different page. I have added the script and the workflow action to the workflow. My script:
function openURL() {
var url = nlapiGetFieldValue('custbody_url');
window.open(url);
}
I get this script error after clicking the button: "TypeError: Cannot find function open in object [object Object].
How can I change my script so it opens the URL in the field?
(This function works when I try it in the console)
Thanks!

Do you want it to work when the record is being viewed or edited? They have slightly different scripts. I'm going to assume you want the button to work when the record is being viewed, but I'll write it so it works even when the document is being edited as well.
The hard part about the way Netsuite has set it up is that it requires two scripts, a user event script, and a client script. The way #michoel suggests may work too... I've never inserted the script by text before personally though.
I'll try that sometime today perhaps.
Here's a user event you could use (haven't tested it myself though, so you should run it through a test before deploying it to everyone).
function userEvent_beforeLoad(type, form, request)
{
/*
Add the specified client script to the document that is being shown
It looks it up by id, so you'll want to make sure the id is correct
*/
form.setScript("customscript_my_client_script");
/*
Add a button to the page which calls the openURL() method from a client script
*/
form.addButton("custpage_open_url", "Open URL", "openURL()");
}
Use this as the Suitescript file for a User Event script. Set the Before Load function in the Script Page to userEvent_beforeLoad. Make sure to deploy it to the record you want it to run on.
Here's the client script to go with it.
function openURL()
{
/*
nlapiGetFieldValue() gets the url client side in a changeable field, which nlapiLookupField (which looks it up server side) can't do
if your url is hidden/unchanging or you only care about view mode, you can just get rid of the below and use nlapiLookupField() instead
*/
var url = nlapiGetFieldValue('custbody_url');
/*
nlapiGetFieldValue() doesn't work in view mode (it returns null), so we need to use nlapiLookupField() instead
if you only care about edit mode, you don't need to use nlapiLookupField so you can ignore this
*/
if(url == null)
{
var myType = nlapiGetRecordType();
var myId = nlapiGetRecordId();
url = nlapiLookupField(myType, myId,'custbody_url');
}
//opening up the url
window.open(url);
}
Add it as a Client Script, but don't make any deployments (the User Event Script will attach it to the form for you). Make sure this script has the id customscript_my_client_script (or whatever script id you used in the user event script in form.setScript()) or else this won't work.
Another thing to keep in mind is that each record can only have one script appended to it using form.setScript() (I think?) so you may want to title the user event script and client script something related to the form you are deploying it on. Using form.setScript is equivalent to setting the script value when you are in the Customize Form menu.
If you can get #michoel's answer working, that may end up being better because you're keeping the logic all in one script which (from my point of view) makes it easier to manage your Suitescripts.

The problem you are running into is that Workflow Action Scripts execute on the server side, so you are not able to perform client side actions like opening up a new tab. I would suggest using a User Event Script which can "inject" client code into the button onclick function.
function beforeLoad(type, form) {
var script = "window.open(nlapiGetFieldValue('custbody_url'))";
form.addButton('custpage_custom_button', 'Open URL', script);
}

Related

HTMLIFrameElement.contentWindow.print() from GoogleSheets is not opening print preview

I am using GoogleSheets to print a png/image file using HTMLService. I created a temporary Iframe element with an img tag in the modalDialog and call IFrame element's contentWindow.print() function after IFrame element and its image are loaded. (I have not set visibility:hidden attribute of IFrame element to check if image is getting loaded.)
However, I only see the printer dialog without any print preview. I am testing on Firefox. Am I missing anything?
[Updated] - I am using Googles Apps script. performPrint() is in printJsSource.html and openUrl() is in Code.gs.
Inside printJsSource.html
function performPrint(iframeElement, params) {
try {
iframeElement.focus()
// If Edge or IE, try catch with execCommand
if (Browser.isEdge() || Browser.isIE()) {
try {
iframeElement.contentWindow.document.execCommand('print', false, null)
} catch (e) {
iframeElement.contentWindow.print()
}
} else {
// Other browsers
iframeElement.contentWindow.print() // as I am using Firefox, it is coming here
}
} catch (error) {
params.onError(error)
} finally {
//cleanUp(params)
}
}
Inside Code.gs
function openUrl() {
var html = HtmlService.createHtmlOutputFromFile("printJsSource");
html.setWidth(500).setHeight(500);
var ui = SpreadsheetApp.getUi().showModalDialog(html, "Opening ..." );
}
I think there is some general confusion about the concept
First of all, function performPrint() seems to be a client-side Javascript funciton, while function openUrl() is a server-side Apps Script function.
While you did not specify either you use Google Apps Script - if you do so, function openUrl()belongs into the code.gs file and function performPrint() into printJsSource.html file
function openUrl() allows you to open a modal dialog which can show some data on the UI, e.g. your image
Do not confuse this behavior with actual printing (preview)!
It is NOT possible to trigger the opening of a Google Sheets printing preview programamticaly!
The Javascript method you are using iframeElement.contentWindow.print() might trigger the printing of the whole content of a browser window (different from the Google Sheets printing dialog, also depends on the browser), but if you try to incorporate it into the client-side coe of an Apps Script project, you will most likely run into restrictions due to the scopes of modal diloags and usage of iframes.
While from your code it is hard to say either you implemented the funcitons in the correct files of the Apps Script project, keep in mind that to work with iframes you need to specify in function openUrl()
html.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);

Override web page's javascript function using firefox addon sdk

I'm trying to override a JS function named replaceMe in the web page from my add-on's content script, but I see that the original function implementation always gets executed.
Original HTML contains the following function definition:
function replaceMe()
{
alert('original');
}
I'm trying to override it my add-on like (main.js):
tabs.activeTab.attach({
contentScriptFile: self.data.url("replacerContent.js")
});
Here's what my replacerContent.js looks like:
this.replaceMe = function()
{
alert('overridden');
}
However, when I run my addon, I always see the text original being alerted, meaning the redefinition in replacerContent.js never took effect. Can you let me know why? replaceMe not being a privileged method, I should be allowed to override, eh?
This is because there is an intentional security between web content and content scripts. If you want to communicate between web content and you have control over the web page as well, you should use postMessage.
If you don't have control over the web page, there is a hacky workaround. In your content script you can access the window object of the page directly via the global variable unsafeWindow:
var aliased = unsafeWindow.somefunction;
unsafeWindow.somefunction = function(args) {
// do stuff
aliased(args);
}
There are two main caveats to this:
this is unsafe, so you should never trust data that comes from the page.
we have never considered the unsafeWindow hack and have plans to remove it and replace it with a safer api.
Rather than relying on unsafeWindow hack, consider using the DOM.
You can create a page script from a content script:
var script = 'rwt=function()();';
document.addEventListener('DOMContentLoaded', function() {
var scriptEl = document.createElement('script');
scriptEl.textContent = script;
document.head.appendChild(scriptEl);
});
The benefit of this approach is that you can use it in environments without unsafeWindow, e. g. chrome extensions.
You can then use postMessage or DOM events to communicate between the page script and the content script.

Editing a BrowserField's History

I have a BrowserField in my app, which works great. It intercept NavigationRequests to links on my website which go to external sites, and brings up a new windows to display those in the regular Browser, which also works great.
The problem I have is that if a user clicks a link to say "www.google.com", my app opens that up in a new browser, but also logs it into the BrowserHistory. So if they click back, away from google, they arrive back at my app, but then if they hit back again, the BrowserHistory would land them on the same page they were on (Because going back from Google doesn't move back in the history) I've tried to find a way to edit the BrowserField's BrowserHistory, but this doesn't seem possible. Short of creating my own class for logging the browsing history, is there anything I can do?
If I didn't do a good job explaining the problem, don't hesitate for clarification.
Thanks
One possible solution to this problem would be to keep track of the last inner URL visited before the current NavigationRequest URL. You could then check to see whether the link clicked is an outside link, as you already do, and if it is call this method:
updateHistory(String url, boolean isRedirect)
with the last URL before the outside link. Using your example this should overwrite "www.google.com" with the last inner URL before the outside link was clicked.
Here is some half pseudocode/half Java to illustrate my solution:
BrowserFieldHistory history = browserField.getHistory():
String lastInnerURL = "";
if navigationRequest is an outside link {
history.updateHistory(lastInnerURL, true);
// Handle loading of outer website
} else {
lastInnerURL = navigationRequest;
// Visit inner navigation request as normal
}
http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/browser/field2/BrowserFieldHistory.html#updateHistory(java.lang.String, boolean)
I had a similar but a little bit different issue. Special links in html content like device:smth are used to open barcode scanner, logout etc and I wanted them not to be saved in BrowserFieldHistory. I found in WebWork source code interesting workaround for that. All that you need is throw exception at the end like below:
public void handleNavigationRequest( BrowserFieldRequest request ) throws Exception {
if scheme equals to device {
// perform logout, open barcode scanner, etc
throw new Exception(); // this exception prevent saving history
} else {
// standard behavior
}
}

cucumber , jQuery and redirects

I have a select tag on my page, I have made via jQuery on domready a listener for the change event. In this listener I redirect the user to the same page with a parameter in the url.
When I test the functionality manual, it works very well.
When I run the test, it fails, the redirect doesn't work.
How I can make it work ?
#javascript
Scenario:
When I select "2010" from "year_select"
And I wait 5 seconds
Then "2010" should be selected for "year_select"
Then I should see "time_sheet?year=2010" with html
The test fails, I see time_sheet?year=2011 (the default value) in my html source, manual I see the correct value. It is not updated via Javascript, but according to te year variable passed in the url (after the redirect)
My jQuery code:
jQuery(document).ready(function(){
var yearSelect = jQuery("#year_select");
yearSelect.change(function(){
window.location = "/time_sheet_admin?year="+yearSelect.val();
});
});
What I make wrong ?
I think u have missed out _admin in the scenario. Use time_sheet_admin instead of time_sheet in the scenario. If my suggestions is useless sorry for that.
What I usually do for testing complex JS stuff is to put them in a function and then test if that function was called:
selectChanged = function() {
window.location = "/time_sheet_admin?year="+jQuery("#year_select").val();
}
*note no need for the variable assignment because you only called it once.
then in your feature:
Then I should see "time_sheet?year=2010" in the url
step definition:
When /Then I should see "time_sheet?year=2010" in the url/ do |seconds|
page.execute_script("selectChanged()")
end

ShareThis setting properties in callback don't work

I'm using the ShareThis widget. I need to change the url property after the object has been created so I'm using the callback function option. In the callback function, I attempt to change the url property but the email that goes out still contains the old value.
Has anyone been able to solve this problem? If so, I would appreciate your help!
Here's a code sample
<script type="text/javascript">
SHARETHIS.addEntry({
title: 'ShareThis'},
{ onclick: myCustomCallback }
function myCustomCallback(SharedObject) {
SharedObject.properties.url = "http://www.myurl.com";
return true;
};
</script>
Use this:
$('span[class^="st_"]').html(''); // Empty span contents
$('span[class^="st_"]').attr('st_processed',null); // Reset ST plugin
$('span[class^="st_"]').attr('st_url',url); // Set new url
stButtons.makeButtons(); // Renew buttons
It's not possible to change the URL dynamically. If you want to do something funky, you'll need to create a new button with the new URL. This can be accomplished a few ways, the simplest being creating an element to contain the button and trigger creation of a custom button element every time something happens that should trigger the URL change.
I can show you a sample implementation that we put together for HP a few weeks ago. They actually call the "share" function from inside a Flash movie, but this prototype triggers it from a button.
You can reach me at sragan#sharethis.com

Resources