did you ever happen to notice this nice little “filter” field on the top right hand side of the LN designer when in a list of design elements?
really neat!
if only I could access it via keyboard, any ideas?
we needed a possibility for users to “override” the workflow, ie. interfere even though they were not “authors” at the moment. The only way was to do with an agent running with more access rights.
solution was: us “sessionAsSigner”
this would not work:
var agent = currentDatabase.getAgent(“(agnXPageWFMoveToState60)”);
agent.runWithDocumentContext(currentDocument.getDocument() );
return “xsp-reopen”;
this did work (kudos to Sven Hasselbach):
var agent = sessionAsSigner.getCurrentDatabase().getAgent(“(agnXPageWFMoveToState60)”);
agent.runWithDocumentContext(currentDocument.getDocument() );
return “xsp-reopen”;
hope this helps some people to achieve similar things
that’s how it looks:
field with type ahead waiting for input:
field with type ahead thinking
field with type ahead failure
this is the XML code of the field for the events:
<xp:eventHandler event=”onkeypress” submit=”false” id=”eventHandler2″>
<xp:this.script><![CDATA[if (event.keyCode==9 || event.keyCode==13){
removeVisual(‘view:_id1:inputText3’)
}else{
addVisual(‘view:_id1:inputText3’);
}]]></xp:this.script>
</xp:eventHandler>
<xp:eventHandler event=”onblur” submit=”false” id=”eventHandler3″>
<xp:this.script><![CDATA[removeVisual(‘view:_id1:inputText3’)]]></xp:this.script>
</xp:eventHandler>
and this is the style assigned to the field:
<xp:this.styleClass>
<![CDATA[#{javascript:if( currentDocument.isEditable()){ return ‘useTypeAhead’; }}]]>
</xp:this.styleClass>
this is needed in the CSS:
.useTypeAhead{
background: #fff url(“TypeAhead.gif”) no-repeat right;
}
.dijitValidationContainer{
width: 20px;
}
.dijitValidationContainer .dijitValidationIcon{
width: 20px;
}
this is needed in a CSJS library (cudos to Mark Roden and Sven Hasselbach)
function x$(idTag, param, jd){ //Updated 28 Feb 2012
// hardcoded
idTag=idTag.replace(/:/gi, “\:”)+(param ? param : “”);
return( jd==”d” ? “#”+idTag : $(“#”+idTag));
}
var inputField;
//addVisual function used to add a loading image to the screen and make it visible
//expected input string similar to view1_:id1_:viewPanel1
function addVisual(idTag){
var newImage=”url(‘loading.gif’)” //Change me for your server
inputField=dojo.query(x$(“widget_”+idTag, ” .dijitValidationIcon”, “d”))
inputField.style(“backgroundImage”, newImage);
inputField.style(“visibility”, “visible”);
inputField.style(“backgroundRepeat”, “no-repeat”);
inputField.style(“backgroundPosition”, “right”);
dojo.query(x$(“widget_”+idTag, ” .dijitValidationContainer”, “d”)).style(“display”, “block”)
inputField.attr(“value”,””)
}
//— hijack dojo XHR calls
//Thanks to Sven Hasselbach for this ajax intercept code
//
var typeAheadLoad;
dojo.addOnLoad( function(){
/*** hijacking xhr request ***/
if( !dojo._xhr )
dojo._xhr = dojo.xhr;
dojo.xhr = function(){
try{
var args = arguments[1];
if( args[‘content’] ){
var content = args[‘content’];
if( content[‘$$ajaxmode’] ){
if( content[‘$$ajaxmode’] == “typeahead” ){
/*** hook in load function ***/
typeAheadLoad = args[“load”];
/*** overwrite error function ***/
// args[“error”] = function(){
// alert(‘Error raised!’)
// };
/*** hijack load function ***/
args[“load”] = function(arguments){
/*** On Start ***/
// alert(“On Start!”);
/*** call original function ***/
typeAheadLoad(arguments);
/*** On Complete ***/
if (arguments.toLowerCase()==”<ul></ul>”){
var newImage=”url(‘typeAheadFailure.gif’)” //Change me for your server
inputField.style(“backgroundImage”, newImage)
}else{
inputField.style(“background”, “white”)
}
};
}
}
}
}catch(e){}
dojo._xhr( arguments[0], arguments[1], arguments[2] );
}
});
//removeVisual function used to remove the loading image from the screen and make it hidden
//expected input string similar to view1_:id1_:viewPanel1
function removeVisual(idTag){
var inputField=dojo.query(x$(“widget_”+idTag, ” .dijitValidationIcon”, “d”))
inputField.style(“backgroundImage”, “”)
inputField.style(“visibility”, “hidden”)
dojo.query(x$(“widget_”+idTag, ” .dijitValidationContainer”, “d”)).style(“display”, “none”)
}
//Checks to see if the visual icon is still running – if so then assume fail and kill it
function checkTimer(idTag){
dojo.query(x$(“widget_”+idTag, ” .dijitValidationContainer”, “d”)).style(“display”, “none”)
}
here’s the scenario:
We have what we call dynamic tables. It lets the user add as many rows as he requires. Really neat.
In some of the fields we use type ahead.
Recently I figured: it would be nice to see an indicator if the server is “thinking”… something like
I could do it easily via one specific field from which I knew it’s id …
But in those dynamic tables I have no clue on which field the event for type ahead was triggered….
until now:
Cudos to Paul Calhoun with his incredibly useful tips about CSJS (something I usually avoid as much as I can)
There I found the solution! You can call SERVER side JS from CLIENT side JS… isn’t that fantastic?
here’s how:
call the SSJS like this:
“#{javascript:<ServerSide JavaScript>}”
example to alert the id of an element via it’s event, in this case onFocus, which was triggered:
alert( “#{javascript:BackingBean.getElementId(this)}” )
For those ones interested what the getElementId does in my Java Bean:
UIInput input = (UIInput) handler.getParent();
return input.getClientId(FacesContext.getCurrentInstance());
Of course the UIInput could be changed to something more generic like UIComponent
stay tuned for my next blog which tells how I achieved proper visual indication
We had to merge two applications, so I created a background agent which copied all required documents to the “new” database. The customer tested and we set a due date for the real migration.
The night before actual migration I run an agent which deleted all “test” migration documents before the real agent to copy the documents run again!
Next morning I came to the office and thought: oh my dear. something went wrong! Only a few dozen documents had been copied, I thought!
So I rerun the agent again. First all seemed to be fine. Then a few hours later documents started disappearing. With no obvious reasons.
It took me about 3 hours to figure out that the method document.copyToDatabase would create the same UniversalId again!
So after having deleted the first round of “test” documents and recopied again at due date, the universalids of the documents had been in the deletion list of the LN db already. That’s why they started disappearing again after a while!
So I had to delete everything again to make sure, rerun the copy agent again but this time change the universalid.
Took me roughly a day to fix everything, something which normally would have taken about one hour.
You could use POI to write an Excel file, but writing to a file with APIs is usually really slow.
MYYYYYYYYYYYYYYYYYY approach is blazingly faaaaaaaaaaaaaaaaaaaaast……..
In our company we are in the lucky situation that we have single-sign-on on the web towards our Domino servers. This is important for the following solution to export documents to work properly.
Steps:
1. Create some kind of “profile” document which defines the filters for the data the user wants to export
2. Create an agent which processes those filters from the profile document and outputs XML for all documents
Example XML:
<?xml version=”1.0″ encoding=”UTF-8″?>
<data xmlns:xs=”http://www.w3.org/2001/XMLSchema-instance”>
<document>
<processeddate xs:nil=”true”></processeddate>
<wfcurrentstate><![CDATA[70]]></wfcurrentstate>
<wfcurrentstatename><![CDATA[Returned for modification]]></wfcurrentstatename>
<timecreated>2013-10-08</timecreated>
<regionname><![CDATA[SOUTH AMERICA]]></regionname>
</document>
</data>
I’m sure you also need sort of “profile documents” once in a while. Documents where a user can store some values he wants to use over and over again, in Web technology term thing of a “cookie”.
This is plain easy!
Simply open the xPage and as a Data source document id (red box) define a computed value like this:
Document ID code:
var doc:NotesDocument = database.getView(“lupUserProfiles”).getDocumentByKey(session.getEffectiveUserName(), true);
if( null != doc ){
return doc.getUniversalID();
}
that way the xPage will either be displayed empty (when no such “profile” document exists) or it will use the appropriate user profile it finds.
In the QuerySave (or somewhere else) you need to make sure to save the user name and have it in the view as sorted first column of course
QuerySave code:
try{
var doc:NotesDocument = docCurrent.getDocument();
var item:NotesItem = doc.replaceItemValue(“userName”, session.getEffectiveUserName())
item.setAuthors(true);
}catch(e){
// handle error
}
I am getting over and over mad that copy & paste is not working well at all in the LN designer especially when dealing with xPages stuff..
I add a template inheritance to a design element, select it, copy via <ctrl><c> and paste it onto another design element, either I get something pasted i copied long time ago, or nothing at all.
so I have to revert to right click copy and right click paste..
this annoys me a lot.. is it just me or anyone else facing the same issue?
use the eye dropper tool to pick up the color from the containers to assign to the individual sections, keep <shift> pressed while doing so, otherwise the whole gradient will be filled with the picked up color
fill gradient
border/stroke gradient
Developing xPages i’m sure you also have come across those nasty “Error 500” errors.
This bugs me right now. The error.log I get won’t help me at all.
Any ideas how to easier figure out the problem?
In my case the error.log simply states: “Unable to find component with ID xyz”.
Interestingly: the component IS visible.
I am a bit lost here: this happens in my xPage only when I copy the contents (some of them) to a new document which is then redirected to and opened in edit mode.
If I create the new document afresh all works as it should.
If I “copy all Items” to the new document then it also works fine.
any ideas?