How to obtain information of a field or variable on the Client side - acumatica

I am using the Receipts page (IN301000) for reference purposes:
I would like to be able to obtain a field's information on the client side with the GetElementByID() method.
When I inspect the field, and identify the rendered ID, I obtain data:
However, if I refresh the page and invoke the method again, I obtain NULL:
Does anyone know how to make that information always available?
The final goal here is being able to pass data to the client side. I can - for instance -populate an unbounded field with the FieldSelecting event, and would like to ideally read data out of it.
If there are client variables that could be set from the graph, it would work as well.
Thanks!

You likely get null because the script is executed in the top iFrame instead of the main iFrame which contains the control.
The JavaScript global variable px_alls contains the editor controls and can be indexed by editor control ID.
px_alls["edTransferNbr"].getValue();
document.getElementById("ctl00_phF_form_t0_edTransferNbr_text").value;
Script executed in main iFrame context:
When the script is executed in the context of the top iFrame you would have to select the main iFrame.
var mainframe = document.querySelector('[name=main]').contentDocument;
mainFrame.getElementById('ctl00_phF_form_t0_edTransferNbr_text').value;
Script executed in top iFrame context:

Related

XAgent breaks previous navigation

If I use
context.redirectToPrevious()
It works great, but If I call an xagent with or without state between opening the document and doing a close of the document. I end up navigating to the xagent.
And If I go directly to the view behind I loose opened categories in the view.
Is there a way to block an xpage to end up in the navigation/history tree?
There are two approaches that would work.
The first is to use client-side JavaScript to open the XAgent. How you handle that will depend on whether there are values set in the browser that you are passing to sessionScope for the XAgent to use. If not, you can just use client-side JavaScript to open the relevant XAgent page. If you do need values, there are two options:
Pass them as query string parameters to the XAgent instead of storing them as sessionScope variables.
Perform a partial refresh to store the values in sessionScope and open the XAgent page via client-side JavaScript either in the onComplete() event (will trigger every time) or using view.postScript(), passing the relevant CSJS as a string (will only trigger if validation is successful).
The second is to set the previous page in the beforePageLoad event and then use that value in context.redirectToPage().

How to dynamically initialize content script in Firefox/Chrome web extension?

We have a Firefox/Chrome web extension which contains both background and content scripts. The background script maintains a cache of shared key/value pairs which are needed by the content scripts. It is not difficult to access them via the browser.runtime.SendMessage functionality.
However, we need access to these key/value pairs as quickly as possible on page load, before any scripts run on the original page. This is generally not possible because the async nature of SendMessage means that the background script will not respond to requests made by the content scripts fast enough.
We've been looking for solutions along the following lines:
1. Sync/blocking lookup
It doesn't appear that there are any mechanisms for this.
2. Initializing the content script
We can register content scripts using browser.contentScripts.register and potentially pass a copy of the entire cache in via javascript. However, this is called only once and all subsequent tabs/pages will load whatever was specified in it. We might be able - with great difficulty - create a listener for global cache changes and re-register a new content script each time.
Are there any better approaches than this?
Update: By adding a listener to browser.webNavigation.onBeforeNavigate, I am now able to inject a global variable which displays in the console output:
In background.js:
browser.webNavigation.onBeforeNavigate.addListener(function(details) {
browser.tabs.executeScript(
details.tabId,
{
code: `window.scope.somevariable=true;
console.log("I executed in content script:", "somevariable", window.scope.somevariable);`
}
);
});
In my library which was injected by register, I am also able to print window.scope out to the console and I see the variable there.
However... when I try to access the variable programmatically, it returns "undefined".
In content script:
// this displays "somevariable" among the window scope properties:
console.log("window.scope", window.scope);
// this displays "undefined":
console.log("somevariable", window.scope.somevariable);
Why can the registered js library output the variable to the console window but can't actually read it?

Xpages equivalent to Database Script initialize

I am running Xpages in XPiNC.
My usual pattern for an Xpages app is to have a xpHome.xsp page that is set to be the first page that is opened. In this I page I set any scope variables that are at the application level, then head to the "real" first page.
Now I have run into a problem. My current database will send out emails when a status changes, and this will include a doc link to the document, which points to the correct Xpage to open. However, because the user is not going through the home page, then my applicationScope vars are being set.
I thought I could fix this by setting a semaphore in the initApp function - the last thing it would do is to place a "Y" in an applicationScope.semaphore field. So when I open my Xpage the first thing it does is check for that, and if it is null, then I call the initApp function.
For some reason this is not working. But even so I would like to find the equivalent of the old database script "Initialize" event. Something I can call whenever the db is opened for the first time.
How do others handle this problem?
Create a managed Java bean "app" which
works on application scope
sets all application parameters
offers all application parameters
Access the bean with app.xxx in EL or Javascript or call methods directly like app.getXxx() or app.doWhatEverYouWant() in JavaScript.
The bean "app" gets initalized automatically when one of the methods gets called first time.
You can find an example here for start or google for "XPages managed beans" for more Information.
Yes, you have to switch your current code partly to Java but it should be worth it in the long run.
If you want to or have to stay with JavaScript then initialize your application scope variables in a custom control which is included in every XPage like layout.xsp in beforePageLoad event.
Use an additional variable applicationScope.initialized. Check if applicationScope variables aren't initialized yet in JavaScript with
if (!applicationScope.initialized) {
... initialize your applicationScope variables ...
applicationScope.initialized = "yes";
}

XPages Mobile Controls - sessionScope variable being lost

I am building a mobile app for iPhone using the mobile controls in the XPages Extension Library.
The first page displays a list of categories (happens to be a list of user names). When a category is selected the second page is displayed listing all documents belonging to the selected user.
The URL to open the second page includes a parameter with the user's name. The second page has a page heading control and on the "label" property I have added the following code:-
if (param.get("User") != null) {
sessionScope.put("UserName", param.get("User"));
}
return sessionScope.UserName;
I'm doing this so that I have access to the user name on subsequent pages, e.g. the third page is displayed when the user opens a document from the list on the second page.
When I test this in Chrome everything is fine. When I test in Safari I can see that the sessionScope variable is set when the second page is opened. However, when I select a document and the third page is opened the sessionScope variable is disappearing. I can't see any code that would explain this and when tested in Chrome the sessionScope variable is still there on page 3. Unsurprisingly I get the same issue when I test on an iPhone.
The problem this gives me is that, when navigating back from a document (p.3) to the list of documents for the selected user (p.2) I don't know which user was selected originally.
Anyone seen this before or have any explanation as to what might be going on?
Thanks for any suggestions.
you might want to refrain from the parameter approach unless you are sanetizing your input first, so instead of the URL write the userName directly into the scope - or even easier - bind the first field with the categories to the sessionScope. Did u try to modify your code to use a different variable name?

Getting to scope variables in client side javascript (CSJS) on XPages

I am setting a viewScope variable in a server side javascript (SSJS) button.
viewScope.put("branchName",doc.getItemValueString("BranchName"))
How can I access that variable on the client side?
If you need to access the viewScope variable from a client side script you can use the xp:scriptBlock tag to setup a number of global javascript variables.
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[var myVar = #{javascript:viewScope.get("scopeVar")}]]></xp:this.value>
</xp:scriptBlock>
The main problem with this method is that the inner server side javascript is only computed when that element is initially rendered or when a partial refresh is performed on the element so there is no guarantee that the client side JS variable is set to the correct value.
You can't access viewScope Variables directly, but you could bind it to a hidden field
then access that value via csjs
XSP.getElementById("#{id:inputHidden1}").value
There are other ways to access it also, using something like rpc or an ajax request.
use the below code:
var value = "#{javascript:viewScope.variablename}"
I would take a look at the JSON RPC included with the extension library. This component will allow you to define a SSJS function that may/may not accept arguments. Let's say you add the RPC with an ID of myRPC and a method called getViewScopeVar that accepts a single String argument and returns the value of the viewScope variable with the name that you include as the argument. You can then call that method like:
myRPC.getViewScopeVar("branchName")
This is the easiest most effective way to interact with server side elements from client side javascript. Plus it gives you the option of all the required methods being in one place as long as you place that RPC on a strategic custom control (i.e. like a layout custom control that every xpage is based off of).
If you need frequent updates you can use the Ajax service from the extension library.

Resources