Processing \Animation in NetSuite - netsuite

I have this client script which copies the line number entered in Copy line# and creates new lines from number of lines entered in Copy #Times.
This thing takes time when you increase the number of lines you require to copy. So can we give any processing animation till all the lines are set so user dont have to worry?
I have tried giving dialog.create but it didnt work. I want the animation to stay until script is executing and after that stop.
var options = {
title: 'Alert',
message: 'Processing. Please wait.',
buttons: [{
label: 'OKK...',
value: 1
},
]
};
dialog.create(options).then(success)
return (true);
success is a function I am calling.

The N/ui/dialog module is intended for showing dismissable messages, and won't really work for progress bars as you cannot hide the buttons, nor close it via code. I would recommend looking at a third party library. A very popular one is SweetAlert2, and there is some sample code on the NetSuite Professionals site for using it with NetSuite.
If you just want a quick hack, you could just used the Ext.js library that NetSuite includes by default on all pages. However I would highly recommend not doing so for any production code because NetSuite could update or remove it at any time in a future upgrade.
var messageBox = Ext.MessageBox.show({
title: 'Lines are being copied...',
msg: 'This may take a couple minutes',
wait: true,
width: 250
});
// your work here
messageBox.hide()

Related

Using webRequest API to intercept script requests, edit them and send them back

As the title says, I'm trying to intercept script requests from the user's page, make a GET request to the script url from the background, add a bit of functionality and send it back to the user.
A few caveats:
I don't want to do this with every script request
I still have to guarantee that the script tags are executed in the original order
So far I came with two solutions, none of which work properly. The basic code:
chrome.webRequest.onBeforeRequest.addListener(
function handleRequest(request) {
// First I make the get request for the script myself SYNCHRONOUSLY,
// because the webRequest API cannot handle async.
const syncRequest = new XMLHttpRequest();
syncRequest.open('GET', request.url, false);
syncRequest.send(null);
const code = syncRequest.responseText;
},
{ urls: ['<all_urls>'] },
['blocking'],
);
Now once we have the code, there are two approaches that I've tried to insert it back into the page.
I send the code through a port to a content script, that will add it to the page inside a <script></script> tag. Along with the code, I also send an index to keep sure the scripts are inserted back into the page in the correct order. This works fine for my dummy website, but it breaks on bigger apps, like youtube, where it fails to load the image of most videos. Any tips on why this happens?
I return a redirect to a data url:
if (condition) return { cancel: false }
else return { redirectUrl: 'data:application/javascript; charset=utf-8,'.concat(alteredCode) };
This second options breaks the code formatting, sometimes removing the space, sometimes cutting it short. I'm not sure on the reason behind this behavior, it might have something to do with data url spec.
I'm stuck. I've researched pretty much every related answer on this website and couldn't find anything. Any help or information is greatly appreciated!
Thanks for your time!!!

Is there any benefit to using an object instead of several variables?

I am writing an application in nodeJS - a Facebook messenger app.
My application contains a module called strings.js, which is basically used to store common strings. Any time I need to print a greeting or whatever I pull it from the strings.js file. Strings.js looks like this:
/*
* This module exports common strings.
* */
'use strict';
module.exports = {
// Quick replies for user to choose age range
ageReplies:[
{
//Option 1 CODE
},
{
//Option 2 CODE
},
{
//Option 3 CODE
}],
// Quick replies for user to choose gender
genderReplies:[
{
//Option 1 CODE
},
{
//Option 2 CODE
},
{
//Option 3 CODE
}],
// 'greetingButtons' is used to create the buttons sent to a registered
// user during the greeting
greetingButtons: [
{
//BUTTON 1 CODE
},
{
//BUTTON 2 CODE
},
{
//BUTTON 3 CODE
}],
userAgeString: "How old are you?",
userGenderString: "What's your gender?",
userInitialGreetingString: "Hello there! I don't believe we've spoken before. You'll need to create a user profile, so let's do that now.",
userNamePromptString: "What would you like me to call you?",
userPrefNamePromptString: "Ok, what would you like me to call you instead? Type it below:",
userWelcomeGreetingString: "Welcome back! I am ready and willing to serve, as always!",
};
The first two"objects" (if that's what we can call them), "ageReplies" and "GenderReplies" are used for generating quick replies in Facebook messenger when asking user for gender and age (during user profile creation).
The next is "greetingButtons", which is used for creating buttons, which are sent to a previously registered user with a "What would you like to do next?" message.
Finally I have a number of strings for greeting the user, prompting them to enter gender and age, and so on. There will be more of these as I add them.
I have been considering putting these individual strings in an object, for example as follows:
stringData: {
userAgeString: "How old are you?",
userGenderString: "What's your gender?",
userInitialGreetingString: "Hello there! I don't believe we've spoken before. You'll need to create a user profile, so let's do that now.",
userNamePromptString: "What would you like me to call you?",
userPrefNamePromptString: "Ok, what would you like me to call you instead? Type it below:",
userWelcomeGreetingString: "Welcome back! I am ready and willing to serve, as always!",
},
Is there any benefit to doing this? Is there any point?
Another question is, if I DID use an object like this, is it possible to put my buttons and quick replies into the same object, for example as below:
stringData: {
ageReplies:[ /* Age reply code */ ],
genderReplies: [ /* Gender reply code */ ],
greetingButtons: [ /* Button code */ ],
userAgeString: "How old are you?",
userGenderString: "What's your gender?",
userInitialGreetingString: "Hello there! I don't believe we've spoken before. You'll need to create a user profile, so let's do that now.",
userNamePromptString: "What would you like me to call you?",
userPrefNamePromptString: "Ok, what would you like me to call you instead? Type it below:",
userWelcomeGreetingString: "Welcome back! I am ready and willing to serve, as always!",
},
Would this work?
EDIT: Just to clarify, I'm not talking about having an object within my main code. The object I'm talking about would be within strings.js
Generally when writing a program that involves displaying text of some sort, I store all of my copy (text eventually sent to a user) in it's own file. These blocks of text have a variable name like you've made, and that allows me to refer to them around the system.
Why do I do this? Internationalisation (commonly shortened to i18n).
It's quite common practice to pull apart text displayed to uses from the rest of your application so that you can easily create multiple files for text and load from the correct one depending on the users language settings (or locale).
In that instance, you'd have a strings file per spoken language, where variable names are all the same. You then select from the specific file depending on settings / locale.
For this reason alone, I keep all my text separate from the rest of the application. This doesn't quite work when it's HTML based projects and such, but with things like nodejs server side error messages, it works perfectly.
Personally when I've built bots, the number of options (buttons) does not relate to the text I use in anyway. So my code to create varying options happens elsewhere, but will use the strings provided by my i18n module. This way text and buttons are decoupled nicely. Often button creation happens in a function that takes some sort of array of objects which represents the options for each button, I'll then pull in the text, when creating the final button markup, from my i18n files.
On a side note: I also don't label things like a "string" prefix or suffix, referring to something as i18n.welcomeGreeting or just welcomeGreeting and I find that's more than explicit enough for this stuff.
Tl;dr
It won't make a huge difference either way right now, but decoupling your text from your button creation can render useful benefits if your application is likely to grow in the future. It can also often make it easier to work with, and separates buttons from text. After all, you don't always use the two together in chat bots, so they should probably be separate concerns.

Why won't my suitescript deploy scripts fire?

I don't know when this started, but I think it happened after I did some refactoring using the IDE with renaming.
Anyway, if I attach the script through the form, they fire. However, my user event, nor client scripts fire though there is a deployment record. That deployment record uses the same script that works IF it is attached via the form custom code area.
What happened?
EDIT:
For Instance:
Trying to add a button to opportunity:
function userEventBeforeLoad(type, form, request){
var list = form.getSubList("item");
list.addButton('custpage_customconfigurebutton', 'Configure', 'clientStartConfigurator()');
}
Upload Script
Add to "Script"
Deploy:
It never fires when I "Create Opportunity"?
NONE of my user event scripts are firing
EDIT 2 (NEW SCREENS as requested
Following lines of code working for me
function userEventBeforeLoad(type, form, request) {
//nlapiLogExecution('error', 'type', type);
var list = form.getSubList("item");
list.addButton('custpage_customconfigurebutton', 'Configure',"alert('Hello World')");
}
I suspect you might have an error in your clientStartConfigurator(). To verify, you can also use the browser console on click of your button to see whether you're successfully returning from your respective function or not.
Hope this will help you.

How to modify dashlets to auto-refresh?

Is there a simple way to modify a dashlet to automatically re-load itself periodically?
I am particularly thinking of the "My Tasks" dashlet - we are using pooled review workflows, so tasks may come and go all the time as they are created and then are claimed.
It may be frustrating for users to keep clicking on tasks that turn out to have already been claimed - or having to remember to keep re-loading their Dashboard page. I'd prefer the dashlet to refresh on a timed interval so it's always reasonably up to date.
In order to do this you will need to add a new capability to the client-side class Alfresco.dashlet.MyTasks (docs, source) found in the file components/dashlets/my-tasks.get.js. First you will need to add a new method to the prototype extension specified as the second parameter in the YAHOO.lang.augmentObject() call, e.g.
...
}, // end of last OOTB function - add a comment here
// begin changes
reloadData: function MyTasks_onReady()
{
this.widgets.alfrescoDataTable.loadDataTable(
this.options.filters[this.widgets.filterMenuButton.value]
);
}
// end changes
});
})();
It's not the ideal development environment, you can modify the JS file directly in the Share webapp, although you will also need to update the corresponding -min.js file.
Once you've done this, check that it works by running the following line in your browser's JavaScript console
Alfresco.util.ComponentManager.findFirst("Alfresco.dashlet.MyTasks").reloadData();
If that works, then you can wire up your new method to a title bar action (see my DevCon presentation for more background info), in the dashlet web script. The method depends on whether you are using v4.2 or a previous version, but if it is the latter then you need to add some code to the dashlet's Freemarker file my-tasks.get.html.ftl (under WEB-INF/classes/alfresco/site-webscripts/org/alfresco/components/dashlets).
In that file you should see some JavaScript code inside a <script> tag, this sets up an instance of the client-side class and some utility classes, the contents of which you can replace with the following, to add your custom title bar action.
(function()
{
var dashlet = new Alfresco.dashlet.MyTasks("${jsid}").setOptions(
{
hiddenTaskTypes: [<#list hiddenTaskTypes as type>"${type}"<#if type_has_next>, </#if></#list>],
maxItems: ${maxItems!"50"},
filters:
{<#list filters as filter>
"${filter.type?js_string}": "${filter.parameters?js_string}"<#if filter_has_next>,</#if>
</#list>}
}).setMessages(${messages});
new Alfresco.widget.DashletResizer("${id}", "${instance.object.id}");
var refreshDashletEvent = new YAHOO.util.CustomEvent("onDashletRefresh");
refreshDashletEvent.subscribe(dashlet.reloadData, dashlet, true);
new Alfresco.widget.DashletTitleBarActions("${args.htmlid}").setOptions(
{
actions:
[
{
cssClass: "refresh",
eventOnClick: refreshDashletEvent,
tooltip: "${msg("dashlet.refresh.tooltip")?js_string}"
},
{
cssClass: "help",
bubbleOnClick:
{
message: "${msg("dashlet.help")?js_string}"
},
tooltip: "${msg("dashlet.help.tooltip")?js_string}"
}
]
});
})();
You will need to add some styles for the class name specified, in the dashlet's CSS file my-tasks.css, such as the following
.my-tasks .titleBarActions .refresh
{
display: none;
background-image: url('refresh-icon.png');
}
The icon file (here is one you could re-use) must be in the same directory as the CSS file.
Lastly you'll need to define the label dashlet.refresh.tooltop used for the title bar action's tooltip. You can do this in the dashlet web script's .properties file.
For a similar example, check out the source of my Train Times dashlet, which features a refresh title bar action.
In some ways it's actually easier to define your own dashlets than it is to extend the Alfresco-supplied ones, but if you have the option of using 4.2.x, the new method allows you to extend the existing components without duplicating any code, which obviously makes upgrades much easier.

drupal_add_js() only adds the JS when no error message (D6)

In my custom form (in a custom module) drupal_add_js() only adds the JS when there is no error message.
My code goes like this:
function ntcf_redo_order_form( &$form_state = array() ) {
global $base_path, $user;
$my_dir = drupal_get_path('module', 'ntcf_redo');
drupal_add_js("$my_dir/order.js", 'module', 'header', FALSE, TRUE, FALSE);
$form = array();
...
return $form;
}
If the validation function used _form_set_error()_ to display an error message and highlight the offending field, the message is displayed and the field highlighted, but the _drupal_add_js()_ call does nothing. Without a pending error message to display, all is well.
EDIT: this problem does not occur with drupal_set_message(), only with form_set_error().
I tried adding the 3 later parameters to the *drupal_add_js()* call to tell it to not optimize it (don't combine it with other JS files). There is no mention of the file order.js in the HTML, and it makes no difference whether I use the last 4 parameters ('header', FALSE, TRUE, FALSE) or not.
In Admin/Performance, I turned off Optimize Javascript Files, and pretty much all caching, which also made no difference.
Extra Details:
I'm not sure if this makes a difference, but it wouldn't surprise me, so here goes:
What I'm doing here is a multi-part "wizard" form that allows the user to proceed forward and go back. Also, many of the pages use AJAX, so I need to do all the "required" field validation in the _submit function instead of letting Drupal do it automatically (since that makes a mess of AJAX). So, if there's a "required" field that's missing, the _submit() function sets an error message, and the form generation function generates the same form again (with the additional decoration resulting from the error message).
Also: this is off-topic, but it might help someone using Google: when doing a multi-page form that allows going backward, you MUST assign a weight to every item on the form, or else the fields tend to "wander" when you go backwards.
Any ideas?
I had the same problem, this is a workaround I found (for Drupal 7, may work in 6) :
1. in your form setup (or hook_form_alter), do this :
$form['#post_render'][]='yourfunction';
2. define :
function yourfunction($content,$element){
$my_dir = drupal_get_path('module', 'ntcf_redo');
drupal_add_js("$my_dir/order.js", 'module', 'header', FALSE, TRUE, FALSE);
return $content;
}
I think this works (while your approach does not), because hook_form_alter (and/or hook_form)
do NOT get called again for a prepared/cached form, so the initial form load WILL load the javascript, but subsequent posts will NOT.
HTH
Mikes answer ($form['#post_render'][]='yourfunction';), will work, though its not the optimal way and will cause issues with drupal_add_js.
The best way to do this is by adding your javascript via the form api '#attached'.
Instead of using drupal_add_js or a new callback on the '#post_render':
$form['#attached']['js'] = array(
drupal_get_path('module', 'module_name') .'/file/path/filename.js',
);
You may pass in a 'css' array as well. Being an array, you can pass in as may files as you want.
*This is for Drupal 7. Other versions may be different.

Resources