How do you you add an onClick event to <xp:panel> - xpages

I'd like to make a Panel "clickable" and run SSJS code. Previously when I've done this I've added a table 1-cell 1-row to the panel since that has an onClick event. Is there a way to do it on the Panel itself?
Also - If there is a way to put onClick on a Panel, if that Panel contains a link, I assume that link would be "Above" the panel itself and be independentally clickable.... right?

Just add an onClick event to the panel. Here is some example code that redirects to "anotherpage" when the panel is clicked:
<xp:panel id="test">
Click me
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:context.redirectToPage("anotherpage.xsp")}]]></xp:this.action>
</xp:eventHandler>
</xp:panel>
If you add a link to the panel, the link is "above" the panel:
<xp:panel id="test">
Click me!
<xp:link escape="true" text="and me!" id="link1">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:context.redirectToPage("page.xsp")}]]></xp:this.action>
</xp:eventHandler>
</xp:link>
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:context.redirectToPage("window.xsp")}]]></xp:this.action>
</xp:eventHandler>
</xp:panel>

Related

Xpages onClick execution sequence

I want to create a button that executes different actions/scripts in a particular sequence.
First, I want to save the current document (server side action). After saving the document, a partial refresh is performed. Then a client side script should be carried out. When finishing this script, a new page is opened.
My current button:
<xp:button id="saveButton" value="Save">
<xp:this.rendered><![CDATA[#{javascript:if(document1.isEditable()){
return true;
}
else{
return false
}
}]]></xp:this.rendered>
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" immediate="false" save="true" refreshId="saveButton">
<xp:this.action>
<xp:actionGroup>
<xp:saveDocument var="document1"></xp:saveDocument>
<xp:openPage name="/viewer.xsp"
target="openDocument">
</xp:openPage>
</xp:actionGroup>
</xp:this.action>
<xp:this.script>
<xp:executeClientScript>
<xp:this.script><![CDATA[
someScript();
]]></xp:this.script>
</xp:executeClientScript>
</xp:this.script>
</xp:eventHandler>
</xp:button>
Currently, this button first executes all server side events and then the client script. Is there a solution to arrange the order of execution, so that I can execute server->client->server?
EDITED:
The functionality I want, splitted in three buttons:
<xp:button value="Label" id="execute1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="execute2">
<xp:this.action>
<xp:saveDocument var="document1"></xp:saveDocument>
</xp:this.action></xp:eventHandler></xp:button>
<xp:button value="Label" id="execute2"><xp:eventHandler event="onclick" submit="false">
<xp:this.script>
<xp:executeClientScript>
<xp:this.script><![CDATA[
someScript();
}});]]></xp:this.script>
</xp:executeClientScript>
</xp:this.script></xp:eventHandler></xp:button>
<xp:button value="Label" id="execute3"><xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<xp:openPage name="/viewer.xsp" target="openDocument"></xp:openPage>
</xp:this.action></xp:eventHandler></xp:button>
So I would click execute1 => execute 2 => execute 3
The order of operation is:
run client-side (JavaScript) code defined in the action on the browser
submit the page to the server
JSF lifecycle kicks in and, after processing the browser content, server-side code runs
XPage is recalculated
HTML is passed back to the browser to be rendered
Adding JavaScript into the tag of the button won't achieve what you need, because it can't.
What you're looking for is to pass JavaScript back to the page to be run after everything else has happened. This is what view.postScript(String) will do for you - it literally posts script to run after (post) the HTML has been returned to the browser. Because this runs from the view object, this is server-side code, and passes a String that will be parsed by the browser as JavaScript.
Apart from view.postScript, as Paul suggests, you can add client-side JavaScript to onComplete for the event. This will run after the event is finished. I'm not certain if there is a big difference behind the scenes in regards to view.postScript vs onComplete.
You could create a hidden button (style="display: none;") that runs the second server side code. and trigger the click event for that after the first server event is complete.

xpages button - possible to change text or item while events are running?

Is it possible to change the text on an <xp:button> element when the code under the onclick event is running (and the partial refresh is not completed)?
The XPages way is to use the onStart and onComplete properties (there's also onError):
<xp:button value="Search" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
onStart="changeText()" onComplete="unchangeText()">
<xp:this.action><![CDATA[#{javascript:serverFunction();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
You can pass the id of the button to the functions using "#{id:button1}" and use it to retrieve the button in CSJS.
We have something like that in place for our xp:button elements. We change the text and also add an FontAwesome "spinning wheel" until code is finished. At the start of our funtion we change text and icon, after code is finished - we revert to original xp:button text.
We use jQuery to modify the button element, basically you can to that with plain JavaScript (innerHTML) or dojo as well.
<xp:button value="Save" id="button-save" xp:key="submitSave">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[submitSaveFunction();]]></xp:this.script>
</xp:eventHandler>
</xp:button>
submitSaveFunction {
$("button[id$=button-save]").attr("disabled", "true").addClass("disabled").html('<i class="fa fa-spinner fa-pulse fa-fw"></i> Saving');
.....your code.....
$("button[id$=button-save]").removeAttr("disabled").removeClass("disabled").html('Save');
}

Button to save document doesn't work as expected

I would like my "save" button to make a change in the document, to save the document , to give a confirmation message, and to refresh.
When using the following code on an iPhone I have to click 2 times before getting the confirmation message and the document doesn't refresh. When using the same code in Google chrome I get the confirmation message after 1 click, but the document or page also doesn't refresh. What's wrong?
<xp:button value="Save" id="button1" style="mybutton;font-size:14pt;font-family:Arial">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:executeScript>
<xp:this.script>
<![CDATA[#{javascript:value1 = viewScope.get("client");
document1.replaceItemValue("visNrClient",value1);}]]>
</xp:this.script>
</xp:executeScript>
<xp:saveDocument var="document1"></xp:saveDocument>
<xp:confirm message="SAVED !!"></xp:confirm>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
Are you moving from the same component in both cases? If you have onblur or onchange code on the component you were in, if that triggers a partial refresh, that will run and take precedence over the button click event, which would explain the need to click twice.

Is it possible to programmatically set the partial refresh element for an event?

I have a custom control I use for view filtering and I'd like to set the viewPanel that it filters based on a property of the custom control but in order to do this I would need to partially refresh the viewPanel whatever the ID of that viewPanel is. I know I could put a facet in my custom control and put a panel around the facet and then just partially refresh that panel, but I was wondering if there is a way to do this without having to drop the viewPanel into a facet. Here is the button code:
<xp:button value="Filter" id="btnFilter">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="viewPanel1">
<xp:this.action><![CDATA[#{javascript:filterView();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
Thanks
Oops, just realized I could do this by adding a computed element ID for the partial refresh set to the compositeData value. I missed that little triangle next to "Specify Element ID".
<xp:button value="Filter" id="btnFilter"> <xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="#{javascript:compositeData.viewPanel}">
<xp:this.action><![CDATA[#{javascript:filterView();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
You could use the dynamic viewpanel of the extension library.

Why can't I use two date picker components on a dialog?

Here is an example xpage:
I am trying to put multiple date pickers on a dialog box from the extension library, i get this error...
Problem submitting area of page when I open the dialog...
Tried to register widget with id==_Container but that id is already registered
I'm not sure why it can't be done, anyone had any luck with it.
Thanks
<xp:button id="button1" value="Show Dialog">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:getComponent("dialog1").show();}]]></xp:this.action>
</xp:eventHandler></xp:button>
<xp:button id="button2" value="Hide Dialog">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:getComponent("dialog1").hide();}]]></xp:this.action>
</xp:eventHandler></xp:button>
<xe:dialog id="dialog1">
<xp:inputText value="#{doc1.field1}">
<xp:this.converter>
<xp:convertDateTime type="date"></xp:convertDateTime>
</xp:this.converter>
<xp:dateTimeHelper></xp:dateTimeHelper>
</xp:inputText>
<xp:inputText value="#{doc1.field2}">
<xp:this.converter>
<xp:convertDateTime type="date"></xp:convertDateTime>
</xp:this.converter>
<xp:dateTimeHelper></xp:dateTimeHelper>
</xp:inputText>
</xe:dialog>
Neither of your xp:inputText controls have an id attribute.
If you add this attribute to the controls then both of the date pickers will work fine both inside and outside the dialog control.
If you were to move the two date pickers outside of the dialog box you would also notice that only the first date picker would get the dojo dropdown picker control
I would use this dialog instead, its a little more upfront work but you wont have that issue and it is faster to load
http://xpagesblog.com/XPagesHome.nsf/Entry.xsp?documentId=9BB0002FE3452618852578CB0066AB75

Resources