I have a computed field on an xpage the result of which is HTML. In that HTML I want to compute a link that will trigger some server side js function followed by a partial refresh.
My current code looks like this:
Click Here
This will work if my js function is a client-side function but I want to use this function to set the value of a field on the document so I need SSJS.
Static links that are created from the controls pallet in an xpage allow the link to call SSJS with partial refreshes. How can I do this with a computed HTML link?
Another option could be creating your own event handler and executing that via client side JavaScript code described in this article. So suppose you create an event handler something like this:
<xp:eventHandler event="name" id="eventhandler1a">
<xp:this.action>
<xp:saveDocument />
</xp:this.action>
</xp:eventHandler>
You can then create a function to call this event handler via JavaScript code:
XSP.executeOnServer = function () {
// the event handler id to be executed is the first argument, and is required
if (!arguments[0])
return false;
var functionName = arguments[0];
// OPTIONAL - The Client Side ID that is partially refreshed after executing the event handler
var refreshId = (arguments[1]) ? arguments[1] : "#none";
var form = (arguments[1]) ? this.findForm(arguments[1]) : dojo.query('form')[0];
// catch all in case dojo element has moved object outside of form...
if (!form)
form = dojo.query('form')[0];
// OPTIONAL - Options object containing onStart, onComplete and onError functions for the call to the
// handler and subsequent partial refresh
var options = (arguments[2]) ? arguments[2] : {};
// OPTIONAL - Value to submit in $$xspsubmitvalue. can be retrieved using context.getSubmittedValue()
var submitValue = (arguments[3]) ? arguments[3] : '';
// Set the ID in $$xspsubmitid of the event handler to execute
dojo.query('[name="$$xspsubmitid"]')[0].value = functionName;
dojo.query('[name="$$xspsubmitvalue"]')[0].value = submitValue;
this._partialRefresh("post", form, refreshId, options);
}
You can then call the event handler via this client side JavaScript code:
XSP.executeOnServer('#{id:eventhandler1a}', '#{id:panel1}')
Here panel1 refers to control which would be partially refreshed.
You can stick with your code if you use the XSP Object in the myFunction() client side function. This allows you to call a partial refresh. The other option is to call a Extlib JSON control and have your logic there. Depends a little on your coding style
The link control is not static. You can compute whatever you want, for example:
<xp:link escape="true" id="lnk">
<xp:this.value><![CDATA[#{javascript:"#"}]]></xp:this.value>
<xp:this.text><![CDATA[#{javascript:"Label here"}]]></xp:this.text>
</xp:link>
Related
I have a simple XPage which contains links to .pdf files stored within the application. In the onClick event of each link I have code that updates a document in another application. My problem is that when I open the page containing the links, the onClick event for each link also executes. How do I prevent the onClick events from executing when the page opens?
Here's the code from the onClick event of one of the links on the page:
<xp:link escape="true" text="Complex Passwords" id="link1"
value="/ComplexPasswords.pdf">
<xp:this.onclick><![CDATA[#{javascript:var dbc: NotesDatabase =
session.getCurrentDatabase();
if (dbc != null) {
var dbnam1 = dbc.getFileName();
} else {
print("No current db found");
return("");
}
var server = session.getServerName();
var db:NotesDatabase = session.getDatabase(server, "PageHitC", false);
if (db == null) {
print("No page hit db found");
return("");
}
var myView:NotesView = db.getView("ByAppName");
if (myView == null){
print("No page hit db found");
return("");
}
var nkey = "Complex Passwords"; //'build the key to see if there is
already a document for this page in the page hit db
var query = new java.util.Vector();
query.add(dbnam1);
query.add(nkey);
var myDoc:NotesDocument = myView.getDocumentByKey(query,true);
if (myDoc == null) {
//'if there's no document found, create a new one
var newdoc:NotesDocument = db.createDocument();
newdoc.replaceItemValue("Form","HitCnt");
newdoc.replaceItemValue("AppName", dbnam1);
newdoc.replaceItemValue("SName", server);
newdoc.replaceItemValue("HitPages", "Complex Passwords");
newdoc.replaceItemValue("HitSummary",1);
var dt:NotesDateTime = session.createDateTime("Today 12");
dt.setNow();
newdoc.replaceItemValue("CntStart", dt);
newdoc.replaceItemValue("LastUpd", dt);
newdoc.save();
}else
{ //'otherwise update the existing document
var tmp = myDoc.getItemValueInteger("HitSummary");
tmp++;
myDoc.replaceItemValue("HitSummary",tmp);
myDoc.save();
}}]]></xp:this.onclick>
</xp:link>
Chances are you've added SSJS to the standard browser-side onClick event. Bear in mind the onClick event is to run on the browser, so is intended to contain CSJS. Use of SSJS there is to be processed on the server to return a String which the browser can parse as (normal Client-Side) JavaScript and run when the button or link is clicked.
It's normal processing for all SSJS in an onClick event of links to be processed server-side and so run before your page run.
What you probably need to do instead is trigger a partial refresh and, in its eventHandler onClick, run your SSJS.
My app uses KendoUI Grids for user views, but Xpages with custom controls for form pages (at least for now).
The Xpage looks for a sessionScope variable to determine if it is a new doc (nothing in the scope Var) or and update (unid is in the var).
<xp:this.data>
<xe:objectData
saveObject="#{javascript:PCModel.save()}"
var="PCModel">
<xe:this.createObject><![CDATA[#{javascript:var pc = new com.scoular.model.PC();
var unid = sessionScope.get("key");
if (unid != null) {
pc.loadByUnid(unid);
sessionScope.put("key","");
viewScope.put("readOnly","Yes");
} else {
pc.create();
viewScope.put("readOnly","No");
}
viewScope.status = pc.status;
return pc;}]]></xe:this.createObject>
</xe:objectData>
</xp:this.data>
This worked for a completely Xpage app. I just put a value in the sessionScope key and called the Xpage.
In the Kendo UI code I am using client-side javascript and I don't see a way to set the sessionScope.
I can control the URL, so I could switch gears and use that, however the data for my app is in a different DB than my code.
Any help would be greatly appreciated.
The easiest way is indeed using the URL:
call the XPage with a parameter ?key=... and change your CSJS code line to
var unid = param.key;
In case you really need to set a sessionScope variable from client side
then add this empty computed text field
<xp:text
escape="true"
id="setSessionScope"
value="#{javascript: if (param.key) {sessionScope.key = param.key} ''}" />
to your XPage and set the sessionScope variable in CSJS code with
XSP.partialRefreshGet("#{id:setSessionScope}", {params: {'key': 'your key'}})
I'm trying and trying for some time to resolve a viewPanel functionality - var property set to rowData.
Depending on the form name, I want to open the docs. ( which are listed in my viewPanel ) in a normal way and into a <xe:dialog> control. I did found this question Xpages Dynamic dojo dialog control and I'm trying to make it works in my case. the docs which I want to be open in the <xe:dialog>, are also created inside the dialog. By this viewpanel, I want to show/open them using this viewPanel control.
Here is the code from the onClick column event:
var formName = rowData.getDocument().getItemValueString("Form");
var docUNID = rowData.getDocument().getUniversalID();
var href = facesContext.getExternalContext().getRequest().getContextPath();
var pe:NotesViewEntry = rowData
if ( formName == "fmCompanie") // in this case, it works OK.
{ href + "/doc.xsp?documentId=" + docUNID + "&action=openDocument"; }
else if ( formName == "fmPersContact" ) // hmm... Still trying...
{ viewScope.put("dlgDocUnid", pe.getUniversalID())
getComponent("exampleDialog").show(); }
So, by this event I'm trying to set a viewScope variable which uses the UNID for the datasource in my exampleDialog control.
Also: the dialog control ( which lays on the same custom control as the viewPanel) has the documentId:
<xp:this.data>
<xp:dominoDocument var="Pdoc" formName="fmPersContact"
ignoreRequestParams="true" scope="request">
<xp:this.documentId><![CDATA[#{javascript:viewScope.get("dlgDocUnid");}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
Still, when I'm trying to open a doc. ( using form == "fmPersContact") the dialog has all fields empty, even if the doc. is already fill with some field values.
I appreciate your help. Thanks for your time.
The data source in the dialog does not contain action attribute. Therefore it does not respect the documentId parameter and creating a new document within the dialog.
Add action="editDocument" attribute and it will work.
Also, check what you are refreshing with the onclick event. You should partially refresh an area that contains your data (e.g. dialog or the panel in your dialog, etc.)
I want to assign value to the element and auto submit after page completely load.I encounter some question.
1.How to get the element in the tab?
2.How to fire submit event when assigned value?
I want to fire as the follow code:
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
var url = tab.url;
var config = null;
if (tab.status !== "complete") {
return;
}
else {
// assign value and fire submit event
}
});
Help!!
I wouldn't do it this way. Why not use jQuery in a content script and trigger your action on ($document).ready()? That way you'll have the document and can use jQuery selectors to get the elements that interest you. To submit, just get button using a selector and call click().
This seems like it should be pretty straightforward but I'm not feeling it.
I have a JSF CommandButton that executes a long running serverside task (10-15 seconds). I've seen forms where the button context changes after it's been clicked (The label on the button changes and the button becomes disabled until the processing is complete).
I'm using ICEFaces and have the disabled property set to a boolean on the underlying page code.
The action listener bound to the button changes that boolean to disable it but alas, no changes on the JSP.
Anyone?
What you can do is to change the status of the button using Javascript:
<h:commandButton ... onclick="this.disabled=true"/>
Edit regarding the comment:
If the previous code does not submit the form, then you have to disable the button a little time after the click, not "during" the click itself. You can do that using the following code:
<h:commandButton ... onclick="setTimeout('this.disabled=true', 100);"/>
I'm not sure if the fact to use the this keyword directly in the setTimeout method will work correctly. If not, you can use another way to do that:
<h:commandButton ... onclick="disableButton(this.id);"/>
with the following Javascript function:
function disableButton(buttonId) {
setTimeout("subDisableButton(" + buttonId + ")", 100);
}
function subDisableButton(buttonId) {
var obj = document.getElementById(buttonId);
if (obj) {
obj.disabled = true;
}
}
(I'm sure this code can be enhanced, thus)
You should use an ice:commandButton instead of h:commandButton, since it has the partialSubmit property, which will perform the action as an AJAX call. This should refresh your button's state, so if the property on the server has been set to false, your button should be disabled.
do a javascript submit(); first and then disable the button
Similar to the solution from romaintaz
For a Firefox specific solution, the following works (it does not work in IE):
<h:commandButton ... onclick="disableButton(this.id);" />
Using Javascript function:
function disableButton(buttonId) {
var obj = document.getElementById(buttonId);
if (obj) {
setTimeout(function(thisObj) { thisObj.disabled=true; }, 50, obj);
}
}
do it after icefaces has updated the DOM. you can use ice.onAfterUpdate(callback):
Here with jQuery
ice.onAfterUpdate(function(){
updateButtons();
});
function updateButtons(){
if(!isButtonEnabled()){
jQuery(".myButton").attr('disabled', true);
jQuery(".myButton").removeClass("iceCmdBtn").addClass("iceCmdBtn-dis");
}else{
jQuery(".myButton").removeAttr('disabled');
jQuery(".myButton").removeClass("iceCmdBtn-dis").addClass("iceCmdBtn");
}
}