Once the user clicks on the standard void button in NS, I wanna do something first before it is committed. Since there is no function triggered from client event script, I tried to use User event before submit, but I cannot see a way to identify whether the event is fired by VOID or by SAVE button. Do you have any suggestions/ideas on what work around can be done?
Usage & Explanation
Deploy as a User Event script on the Journal record
This code will find the related transaction that's being voided and before it's voided will change its memo to "This transaction has been voided!"
Note that "before it's voided" refers to when you click the "Save" button on the Voiding Journal record, not specifically when you press the "Void" button on the original transaction.
You can use this as a basis for performing other actions on the voidedRecord object.
SuiteScript 1
function beforeSubmit(type) {
if (type == 'create') {
var voidRecord = nlapiGetNewRecord();
var voidedRecordId = voidRecord.getFieldValue('createdfrom');
var voidedRecordType = voidRecord.getFieldValue('transform');
var voidedRecord = nlapiLoadRecord(voidedRecordType,voidedRecordId);
voidedRecord.setFieldValue('memo','This transaction has been voided!');
nlapiSubmitRecord(voidedRecord);
}
}
SuiteScript 2
/**
*#NApiVersion 2.x
*#NScriptType UserEventScript
*/
define(['N/record'],
function (record) {
function beforeSubmit(context) {
if (context.type == context.UserEventType.CREATE) {
var voidRecord = context.newRecord;
var voidedRecordId = voidRecord.getValue({fieldId: 'createdfrom'});
var voidedRecordType = voidRecord.getValue({fieldId: 'transform'});
var voidedRecord = record.load({
type: voidedRecordType,
id: voidedRecordId
});
voidedRecord.setValue({
fieldId: 'memo',
value: 'This transaction has been voided!'
});
voidedRecord.save();
}
}
}
);
Note this assumes that you have the option set to "Use Reversing Journals to Void Transactions". If that option is not turned-on, then there is no J/E created. The base transaction is set to posting=N, zeroed-out and saved. A voided transaction cannot be resurrected.
Related
Apologies in advance for any terminology mistakes, I'm a student and trying my hardest to be as clear as possible! and thanks in advance for any help!
I'm trying to use Azure Speech-To-Text services. I'd like the user to be able to press a start and stop button to record themselves and print out the transcription. My app will eventually be a React Frontend and Rails backend, but right now I am just trying to understand and work through the demo.
I'm confused by the documentation but was able to get things half working. However, right now it just continuously listens to the speaker and never stops.
I want to use stopContinuousRecognitionAsync() or recognizer.close() once a button is pressed, but I cannot seem to get it working. The farthest I've gotten is the result is logged only once the stop button is pressed, but it continues to listen and print out results. I've also tried using recognizer.close() -> recognizer = undefined but to no avail. I am guessing that due to the asynchronous behavior, it closes out the recognizer before logging a result.
The latest code I've tried is below. This result starts listening on start click and prints speech on stop, but continues to listen and log results.
// subscription key and region for speech services.
var subscriptionKey, serviceRegion;
var authorizationToken;
var SpeechSDK;
var recognizer;
document.addEventListener("DOMContentLoaded", function () {
startRecognizeOnceAsyncButton = document.getElementById("startRecognizeOnceAsyncButton");
subscriptionKey = document.getElementById("subscriptionKey");
serviceRegion = document.getElementById("serviceRegion");
phraseDiv = document.getElementById("phraseDiv");
startRecognizeOnceAsyncButton.addEventListener("click", function () {
startRecognizeOnceAsyncButton.disabled = true;
phraseDiv.innerHTML = "";
// if we got an authorization token, use the token. Otherwise use the provided subscription key
var speechConfig;
if (authorizationToken) {
speechConfig = SpeechSDK.SpeechConfig.fromAuthorizationToken(authorizationToken, serviceRegion.value);
} else {
speechConfig = SpeechSDK.SpeechConfig.fromSubscription(“API_KEY”, serviceRegion.value);
}
speechConfig.speechRecognitionLanguage = "en-US";
var audioConfig = SpeechSDK.AudioConfig.fromDefaultMicrophoneInput();
recognizer = new SpeechSDK.SpeechRecognizer(speechConfig, audioConfig);
recognizer.startContinuousRecognitionAsync(function () {}, function (err) {
console.trace("err - " + err);});
stopButton = document.querySelector(".stopButton")
stopButton.addEventListener("click", () =>{
console.log("clicked")
recognizer.recognized = function(s,e) {
console.log("recognized text", e.result.text)
}
})
});
Assuming the recognizer is conjured correctly outside of the code, there's a few things to change to get the result you want.
The events should be hooked to the recognizer before calling startContinuousRecognition().
In the stop button handler, call stop. I'd also hook the stop event outside of the start button click handler.
Quick typed changes, didn't compile. :-)
startRecognizeOnceAsyncButton.addEventListener("click", function () {
startRecognizeOnceAsyncButton.disabled = true;
//div where text is being shown
phraseDiv.innerHTML = "";
// The event recognized signals that a final recognition result is received.
recognizer.recognized = function(s,e) {
console.log("recognized text", e.result.text)
}
//start listening to speaker
recognizer.startContinuousRecognitionAsync(function () {}, function (err) {
console.trace("err - " + err);});
});
stopButton = document.querySelector(".stopButton")
stopButton.addEventListener("click", () =>{
console.log("clicked");
recognizer.stopContinuousRecongition();
};
I have a scenario where in Orders Form there is a Invoice Schedule Sub-grid. I need to Refresh/Reload the Main Form when the Invoice Schedule Sub-grid is reloaded on Deactivating a particular record in the Sub-grid.
P.S: This scenario is for Dynamics 365 CRM Unified Interface (UCI). I have tried all the three Sub-grid events but does not help in this scenario.
You have to attach a custom event handler to deal this. Read more
var globalFormContext;
function myFormOnload(executionContext) {
globalFormContext = executionContext.getFormContext();
addSubgridEventListener();
}
function addSubgridEventListener(){
var gridContext = globalFormContext.getControl("<your_subgrid_name>");
//ensure that the subgrid is ready…if not wait and call this function again
if (gridContext == null){
setTimeout(function () { addSubgridEventListener(); }, 500);
return;
}
//bind the event listener when the subgrid is ready
gridContext.addOnLoad(subgridEventListener);
}
function subgridEventListener(context){
globalFormContext.data.refresh(false);
}
This latest code verified and works in v9 unified interface
Reference: https://learn.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/grids/gridcontrol/addonload
Code snippet:
//On load of main form event
function OnloadOfMainForm(executionContext) {
// call onLoad of subgrid function
SubgridEventHandler(executionContext);
}
var globalFormContext;
function SubgridEventHandler(executionContext){
//make formContext as global
globalFormContext = executionContext.getFormContext();
var gridContext = globalFormContext.getControl("subgrid_name");
//Verify the subgrid is loaded, if not recursively call function again
if (gridContext != null && gridContext != undefined){
//don't try to pass formEontext some time it doesn't works
gridContext.addOnLoad(SubgridFunctionExe);
}else{
setTimeout(function () { SubgridEventHandler(); }, 200);
}
}
//It triggers onLoad of form, on load and on refresh of subgrid
//as well on add new record and on delete of record it will trigger
function SubgridFunctionExe(){
// here use globalFormContext
globalFormContext.data.refresh(false);
}
For UCI:
From ribbon button pass the parameter of PrimaryControl and use below code to Refresh.
PrimaryControl.refresh();
I'm having two pages: my-view1 and my-view2.
On my-view1 I have two buttons that add and remove data from LocalStorage.
On my-view2 I have two simple div's that READ (display) total value, and total in last 6 months value.
However, on the second page, the value will not update if the page is not refreshed. I want the values from my-view2 to be automatically updated everytime the page is loaded (viewed, even if cached).
Here is a plnkr with my-view2 so you can undestrand what I'm trying to do.
https://plnkr.co/edit/ul4T2mduxjElCN4rUUKd?p=info
How can I do this?
You can listen to the storage event to trigger and update some prop in my-view2 when you update localStorage:
<my-view-2 id="myView2"></my-view-2>
<script>
window.onstorage = function(e) {
if (e.key !== 'someKeyYouWant') return;
document.getElementById('myView2').set('someProp', {
oldValue: e.oldValue,
newValue: e.newValue
});
};
</script>
EDIT (working plunk): Because of a behavior described here the storage event will not be triggered on the window originating the change, so you have to trigger your own storage event, consider the method below:
saveToLs(e) {
e.preventDefault();
const newName = this.get('dogName');
const ls = window.localStorage;
const synthEvent = new StorageEvent('storage');
const eventConfig = [
'storage',
true,
true,
'myDog',
ls.getItem('myDog'),
newName
];
synthEvent.initStorageEvent(...eventConfig);
setTimeout((() => { // ensure async queue
ls.setItem('myDog', newName);
this.dispatchEvent(synthEvent);
}).bind(this), 0);
}
...and on the listening side:
handleStorageUpdate(e) {
if (e.key !== 'myDog' || e.newValue === this.get('dogName')) return;
this.set('dogName', e.newValue);
}
Please note the if conditional handling potential duplicate updates with the same value.
Here is a working plunk for you to play with
I am having a script as below:-
function getColorValue(aId,atitle) {
try{
var clientContext = new SP.ClientContext();
var oWebsite = clientContext.get_web();
var oList = oWebsite.get_lists().getByTitle('Item type');
var oListItem = oList.getItemById(parseInt(aId));
clientContext.load(oListItem);
clientContext.executeQueryAsync(function () {
var listItem = oListItem;
var colorname = listItem.get_item('Color_x0020_Name');
if (typeof colorname != 'undefined') {
if (colorname != null) {
$("div[title$='" + atitle + "']").css("background-color", colorname);
}
}
}, onColorQueryFail);
}
catch(e){
}
}
I need to call this script each time after a SharePoint Calendar Item is created.
Can anyone help?
The following JavaScript example demonstrates how to register event that will be triggered after Calendar item is created:
//custom handler that will be triggered after Calendar item is created
function onEventCreated(){
alert('Event has been created...');
}
function registerCalendarEventOnItemCreated(event)
{
var currentCtx = getCurrentContextInfo();
var calContainer = SP.UI.ApplicationPages.CalendarInstanceRepository.lookupInstance(currentCtx.ctxId);
for(var name in calContainer) {
if(calContainer.hasOwnProperty(name)) {
var p = calContainer[name];
if(p instanceof SP.UI.ApplicationPages.CalendarNewFormDialog) {
p.get_events().addHandler("newitemcreated",event);
}
}
}
}
//get current context info
function getCurrentContextInfo()
{
var currentListId = new SP.Guid(_spPageContextInfo.pageListId);
for(var ctxKey in g_ctxDict){
var curCtx = g_ctxDict[ctxKey];
if(curCtx.listName == currentListId.toString()){
return curCtx;
}
}
return null;
}
//register Calendar events
$('body').on('click', 'div#AsynchronousViewDefault_CalendarView', function() {
registerCalendarEventOnItemCreated(onEventCreated);
});
Has been tested against SharePoint 2013/Online
In your case the function getColorValue could be invoked from onEventCreated, for example:
function onEventCreated(){
getColorValue (id,title);
}
How to apply changes
Switch the page into Edit mode
Add Script Editor webpart into page.
Put the specified code by wrapping it using script tag code into the Script Editor, for example: <script type="text/javascript">{JavaScipt code goes here}</script>
Save the page
Results
Create an Event Receiver with List Item Events for type and Calendar for Source then check 'An item is being added' in handling the event.
Then in the code behind of your Event Receiver:
public override void ItemAdding(SPItemEventProperties properties)
{
base.ItemAdding(properties);
//Call your function through this
Page.ClientScript.RegisterStartupScript(this.GetType(), "CallMyFunction", "MyFunction()", true);
}
Hope that helps :)
I know this is an old question, but there is an issue with the solution given.
I had a requirement to implement an workaround to the missing Resource Reservation feature in Sharepoint online. It was not possible to use an approach more suitable to the Modern Experience, due its dependency of Azure (no Azure subscription available for it), so I use Sharepoint API calls to perform the the same functionality of Resource Reservation.
To use the Sharepoint API, some Ajax calls were needed. But I observed that two calls were executed for each request.
The point is when you register calendar events, it is needed to attach the click event using one, as seen below, to prevent the click event to be fired more than once.
//register Calendar events
$('body').one('click', 'div#AsynchronousViewDefault_CalendarView', function() {
registerCalendarEventOnItemCreated(onEventCreated);
});
I am developing a simple Safari extension that adds a context menu item, which when clicked will let me perform a specific task with the data on the page current. In my injected-scripts.js I have a function validForContextMenu which determines wether or not the context menu should be displayed for the clicked tab. Along with this function I am dispatching the following message to my global.html in order to let it know if the tab should display my context menu item or not.
safari.self.tab.dispatchMessage("validate", validForContextMenu());
In global.html I am doing the following to listen to message, store the data returned by injected-scripts.js, and perform the actual validation:
var contextMenuDisabled = true;
function respondToMessage(theMessageEvent) {
if (theMessageEvent.name === "validate") {
contextMenuDisabled = theMessageEvent.message;
}
}
safari.application.activeBrowserWindow.activeTab.addEventListener("message", respondToMessage, false);
function validateCommand(event) {
event.target.disabled = contextMenuDisabled;
}
safari.application.addEventListener("validate", validateCommand, false);
This all works out quite fine apart from the fact that the validation is only performed once, and only for the tab/page being frontmost at the time my extension loads. If that page is valid for context menu, then so will all other pages and vice versa. I would like the validation to be performed individually for each of Safaris tabs.
Ca this be done? Am I missing something on the way injected scripts or dispatched messages works?
The global.html is singleton and therefore your have only one variable contextMenuDisabled for all tabs. Safari has the special API for this task - safari.self.tab.setContextMenuEventUserInfo.
I use the next code in my extension. In inject.js:
document.addEventListener('contextmenu', onContextMenu, false);
function onContextMenu(ev) {
var UserInfo = {
pageId: pageId
};
var sel = document.getSelection();
if (sel && !sel.isCollapsed)
UserInfo.isSel = true;
safari.self.tab.setContextMenuEventUserInfo(ev, UserInfo);
};
In global.js:
safari.application.addEventListener('validate', onValidate, false);
function onValidate(ev) {
switch (ev.command) {
case 'DownloadSel':
if (!ev.userInfo || !ev.userInfo.isSel)
ev.target.disabled = true;
break;
};
};