Archive

Posts Tagged ‘Event’

Stolperfalle: Ids bei clientseitigen Events

Heute bin ich mal wieder über einen Fehler gestolpert, welchen ich schonmal begangen habe, und dadurch mal wieder viel Zeit verloren habe. Deshalb landets jetzt hier, in der Hoffnung dass ichs mir auch endlich mal merke =)

Ich hatte ein xp:div Element, welches eingebettet einen Text und ein Bild hatte. Mit einem onMouseover Event wollte ich die URL des zu verwendeten Bildes ändern. Leider reagierte das Element auf keinen MouseOver.

Dies kann man übrigens auf 2 Arten erreichen:

document.getElementById("#{id:zielElement}").src = "url_zum_bild.gif";

oder wenn man sich auf das aktuelle Element beziehen möchte, auf welchem das Event liegt:

try{
	if (thisEvent.originalTarget) {
		thisEvent.originalTarget.src = "btn_go_Hover.gif";
	} else {
		thisEvent.srcElement.src = "btn_go_Hover.gif";
	}
}catch(e){}

Die If-Abfrage hat den Hintergrund dass der Internet Explorer “srcElement” braucht und nicht auf originalTarget zugreifen kann.

Dass mein xp:div auf kein Event gehört hat lag einfach daran dass mein xp:div Element keine ID hatte.

MERKEN: Elemente mit einem clientseitgen Event brauchen IMMER eine ID!!

Btw: Wo wir gerade bei xp:div sind:

Mann sollte immer, wenn man nur ein einfaches div in der Seite braucht, xp:div verwenden. xp:panel hat zwar das gleiche Ergebnis, allerdings werden bei xp:panel noch ein paar Sachen im Hintergrund geladen die es ermöglichen eine Datasource anzubinden. Wenn man dies beachtet kann man noch ein paar Quäntchen Performance aus der Applikation herausholen. Besonders wenn man diese Elemente in einem xp:repeat loopt.

Notes: Ein- und Ausblenden von View-Actions

Heute mal ein kleiner Tipp für Standard-Notesclient Anwendungen.

Ich hatte die Anforderung bekommen dass in einer kategorisierten View die Actions ein- und ausgeblendet werden sollen, je nachdem ob ich eine Kategorie oder ein Dokument ausgewählt habe. Langes Suchen brachte nichts und auch ein Kollege war der Meinung es geht nicht. Ein anderer Kollege brachte dann aber doch die Lösung:

In den View-Einstellungen gibt es eine Option namens “Evaluate actions for every document change”. Das funktioniert deshalb weil auch ein Wechsel der Selektion als Change aufgefasst wird.
Schlussendlich muss man in der Hide-When Formel nur noch auf die Form abfragen. Wenn sie leer ist verstecke den Button, wenn nicht dann zeige ihn an, denn Kategorien haben keine Form.

Darüber hinaus kann man so natürlich noch sehr flexibel entsprechende Actions anzeigen, beispielsweise wenn man in der View mehrere Forms hat.

XPages: Set headers

08/11/2011 2 comments

Because today is Tuesday, there’s another advice:

You have the possiblity to set meta-headers in XPages. To do so, you have two possiblities.
1. In the properties of the XPage, you can add a ressource with the type metaData (see it on this picture)
2. Add a few lines of code to your BeforeRenderResponse event, like this:

try {
   var response = facesContext.getExternalContext().getResponse();
   response.setHeader("Expires", -1);
   response.setHeader("Cache-Control", "no-cache");
   response.setHeader("IE=EmulateIE7", "X-UA-Compatible");
} catch (e) {}

Propably, you would think it wouldnÄt matter where to do this, but remember, we are dealing with XPages…

Some headers can’t be set with the first method. I don’t know exactly at which point they are rendered, but sometimes, they are alrady there.

That means, when you want to add the header IE=EmulateIE7, which was described as a workaround in a former post by me, you should do this via the scond method in the BeforeRenderResponse. Else, you receive a browser warning, that this header will be ignored, because the doctype was already set. If you add it in the event, everything works fine and the header is rendered.

The funny thing is, there header is rendered with the first method, anyway, but he gets ignored because he seems to be set too late.

Stumbling Stone: FileUpload-Control

Today I had a tiny problem. Not even a bug, only a small booby trap.

On my page, I had three FileUpload controls and one FileDownload control. It was specified that a user can upload a maximum of three attachments. Therefore I added a rendering condition to all FileUpload controls, which chekcs the number of attachments in the document.
WARNING: The formula @Attachments doesn’t seem to work properly. It seems like @Attachment only checks the backend-document. I want to know how much attachments were uploaded right now to constrain the possibility to upload something. The function “doc.getAttachmentList(‘feldname’).size()” saved my day.

The three controls are placed below another, the first will be hidden if there are thee attachments, the second if there are two and the last one if there is at least one attachment. All this linked to a refresh, which is fired when you delete one attachment, everything works fine.

However, I faced the effect, if I add 3 attachments at once, only two were saved. The attachment from the last FileUpload control was never saved.

Get ready for the reason:

Controls seem to be processed sequential, connected with an internal refresh. That means, the first control is processed and the file is uploaded -> new there is a refresh -> second control is processed, everything is fine, so the second attachment is uploaded -> there is a refresh again -> third control wants to be processed, but there is more than one attachment in the document, so the control is not rendered anymore, therefore, the third attachment goes to hell.

The solution is quite easy, you only have to reverse the order of the number of attachments in the render condition. That means, the first control should be hidden if there is more than one attachment, the second is hidden with two attachments and the third with three attachments. Because the controls are processed in order they are in the code, everything works fine.

Another interesting fact is, that if you have some mandatory fields or have another server-side validation on your form, attachments are uploaded when you click the save button. After that the validation yells. The backend document doesn’t get bothered, but in the frontend document, there are your attachments uploaded, yet. In the context of my problem above, this could be quite confusing, but if you know that fact you can work around that.

XPages: Dojo dialogues

22/09/2011 2 comments

Again, XPages were cracking my head, this time with dialogues.

What was the scenario?

Some function in one of my application should be packed into dialogues. For instance one agent, which offers an excel-file for download which needs two different buttons to pass on some parameters to the agent. Therefore I had to call the URL of the agent, directly. Useally a simple task.
In rationally working browsers all works fine, until some genius thought it would be quite intelligent two try to click one button shortly after the other one. First button was working fine, but the second one wasn’t reacting. I fact, after that, nothing was working after that. When I reloaded the page, everything was working fine again, until someone was trying to click both buttons again.
The reason for this behavior was Dojo. One clever developer thought, to reduce the server load, he could implement a timeout for special situations. This function is hidden in the depths of theDojo source files. Who wants to check that, look here:

~NotesDatadominojsdojo-1.4.3ibmxspwidgetlayout

There are the source files of Dojo, quite useful if you want to debug your program effectively and never want stuck in some error messages like “Error in line 16, charackter 18564” again, because there are also the uncompressed sources.

There is one tiny file, called xspClientDojo.js with a tiny, nasty function:

/**
* The number of milliseconds allowed between page submissions,
* see XSP.canSubmit().
*/
// 20 sec if the latency after to re-enable the submission
// - asked by customers
this.submitLatency = 20*1000;

this._allowDirtySubmit = true;
this._dirty = false;
this._dirtyFormId = null;

this.djRequire = function x_djreq(name) {
   return dojo["require"](name);
}

“Asked by customers”, it’s sad that developers have to excuse themself for the wishes of some customers.
The bottom-line is that 20 seconds has to pass by between two submissions. Actually, that works! if you let pass 20 seconds after the first submissions, everything works fine again, even in my application.

Of course it is a little bit nasty to let customers wait 20 seconds between all submissions, tempting, but not acceptable. But Dojo has some workaround for that:

/**
* If the page is not submitted after a call to canSubmit(),
* this should be invoked to re-enable page submission.
* @return void
*/
this.allowSubmit = function x_as() {
   this.lastSubmit = 0;
}

This function resets the timestamp of the last submissions and allows some new submissions.

If we add this line of code to our program, we can avoid this problem.

XSP.allowSubmit();

You can imagine this wasn’t the end of the story. I mentioned rationally working browsers, in other browsers (Internet Explorer) it wasn’t possible to get the dialogues running.
Useally, the following meta header solves this problem:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

Unfortunately, most physical laws of the web are rather optional guidelines in XPages.

Dojo knows this problem, there is a fix for that, you can find it here: Bugs.dojotoolkit.org

Due to some timeline problems it wasn’t possible to make this fix working in short time. Therefore, the consequences are quite down-to-earth: For this application you have to use a smart browser (Firefox, for example) or rather the IE9 isn’t supported.

After this experience I will try to use dialogues only if there is no other way, that means, if the customer really wants them. I hope that in one of the next versions (maybe 8.5.3) everything gets better =)

UPDATE 2011/15/11:We could localize the problem. In fact, it is only one small CSS-Rule, called: “filter: progid:DXImageTransform.Microsoft.Aplpha(Opacity=0);”
Unfortunately we didn’t manage to remove this rule, so far. Somewhere deep in the code, it seems, it is added manually and we can’t do anything to prevent that.

UPDATE 28.03.2012: In Notes 8.5.3 and the new Dojo version it seems to work fine.

XPages: Eventparameters

Here is another advice for the horror we call XPages.

In XPages you have, theoreticaly, the possibility to pass a parameter along with an event. Sounds quite useful, doesn’t it? Unfortunately, they don’t work properly. It wasn’t possible for me to pass on some eventparameters. They simply didn’t arrive at the target.

Here is a workaround:

You can pass the parameter clientside and use them serverside after the request:

var docId = new CGIVariables().getURLParam("documentId");

Here is a link to a quite useful library which I use from time to time in my XPages:10.lotus.com

I added the following function:

this.prototype.getURLParam = function (name){
   name = name.replace(/[[]/,"\[").replace(/[]]/,"\]");
   var regexS = "[\?&]"+name+"=([^&#]*)";
   var regex = new RegExp( regexS );
   var results = regex.exec( "?" + this.request.getQueryString() );
   if( results == null ) {
      return "";
   } else  {
      return results[1];
   }
}
%d bloggers like this: