XPages - dojo IO Pipelines in combination with ExtLib xe:namepicker - dojo

I have a big problem using dojo IO Pipelines in combination with ExtLib Controls (e.g. xe:namepicker) in Domino 9.0.1 FP3.
For illustration here two scenarios....
The XPage code for the first scenario (without xe:namepicker):
<xp:this.properties>
<xp:parameter name="xsp.client.script.dojo.djConfig" value="ioPublish:true"></xp:parameter>
</xp:this.properties>
<xp:button value="Partial Refresh" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="main" execMode="partial">
<xp:this.onComplete><![CDATA[doPartialRefreshOf(['tagCloud1', 'tagCloud2']); ]]></xp:this.onComplete>
</xp:eventHandler>
</xp:button>
<xp:panel id="main" style="background-color:rgb(0,255,64);">CONTENT</xp:panel>
<xp:panel id="tagCloud1" style="background-color:rgb(255,128,0)">TAGCLOUD1</xp:panel>
<xp:panel id="tagCloud2" style="background-color:rgb(128,0,255)">TAGCLOUD2</xp:panel>
<xp:eventHandler event="onClientLoad" submit="false">
<xp:this.script><![CDATA[dojo.subscribe("/dojo/io/start", function(data){
console.log("triggered on /dojo/io/start channel");
});
dojo.subscribe("/dojo/io/stop", function(data){
console.log("triggered on /dojo/io/stop channel");
});]]></xp:this.script>
</xp:eventHandler>
Click on the button “Partial Refresh” results in the following output (on Firebug console):
triggered on /dojo/io/stop channel
POST...main
GET...tagCloud1
GET...tagCloud2
triggered on /dojo/io/stop channel
All works perfect!
The XPage code for the second scenario (with xe:namepicker):
<xp:this.properties>
<xp:parameter name="xsp.client.script.dojo.djConfig" value="ioPublish:true"></xp:parameter>
</xp:this.properties>
<xp:button value="Partial Refresh" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="main" execMode="partial">
<xp:this.onComplete><![CDATA[doPartialRefreshOf(['tagCloud1', 'tagCloud2']); ]]></xp:this.onComplete>
</xp:eventHandler>
</xp:button>
<xe:namePicker id="namePicker1" for="inputText1" pickerText="NamePicker"></xe:namePicker>
<xp:panel id="main" style="background-color:rgb(0,255,64);">CONTENT</xp:panel>
<xp:panel id="tagCloud1" style="background-color:rgb(255,128,0)">TAGCLOUD1</xp:panel>
<xp:panel id="tagCloud2" style="background-color:rgb(128,0,255)">TAGCLOUD2</xp:panel>
<xp:eventHandler event="onClientLoad" submit="false">
<xp:this.script><![CDATA[dojo.subscribe("/dojo/io/start", function(data){
console.log("triggered on /dojo/io/start channel");
});
dojo.subscribe("/dojo/io/stop", function(data){
console.log("triggered on /dojo/io/stop channel");
});]]></xp:this.script>
</xp:eventHandler>
Click on the button “Partial Refresh” results in the following output (on Firebug console):
POST...main
GET...tagCloud1
GET...tagCloud2
As you can see, there is no output (/dojo/io/...) on the firebug console (dojo/io channels will not be triggered..)!
Both scenarios are working perfect in Domino 8.5.3 FP6 + Lotus Domino Upgrade Pack.
Any hints/advices how to solve this problem?
Thanks in advance
Georg

9.0.1FP3 contains Dojo v1.9.4, and dojo/io has been deprecated since dojo 1.8. This may be part of the problem. See here: http://dojotoolkit.org/reference-guide/1.9/dojo/io.html
You could try using dojo/request instead, as suggested in that link. I'm not really familiar with the old IO or the new request packages though, so you would need to do some investgiation.

Related

Data Table stateSave refresh continues POST requests after closing dialog

I am using the Data Tables jQuery plugin on XPages to display our price list to users. The administrators of the price list search for similar items, click the item description to modify the item via a dialog box. As there are over 1000 items in the price list it is necessary to save the search and at the same time refresh the table so the user can review the changes in the list after closing before moving to the next item in their search. Due to the large number of entries refreshing the whole page is messy, so when opening the dialog I refresh only the dialog, which has always worked fine until I have introduced the stateSave on the DataTable. The problem being now when I close the dialog the page continues making POST requests to open the dialog again with a random item from the bean.
Any help would be greatly appreciated.
<xp:div style="width:30%" styleClass="mg20">
<xp:panel id="tablePanel">
<table id="keyItemsPLTable">
<thead>
<tr>
<th>Description</th>
<th>Code</th>
</tr>
</thead>
<tbody>
<xp:repeat id="repeat1" rows="10000"
var="rowData">
<xp:this.value><![CDATA[# #javascript:itemBean.getPlItems("All","Price List Sales Cat Only")}]]></xp:this.value>
<tr>
<td>
<xp:link escape="true"
text="#{rowData.description}" id="link3">
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial" refreshId="dialog1" execMode="partial"> //Problem occurs due to this partial refresh
<xp:this.action><![CDATA[#{javascript:itemBean.setPlItem(rowData);
var dialog = getComponent("dialog1");
dialog.show()}]]></xp:this.action>
</xp:eventHandler>
</xp:link>
</td>
<xp:text tagName="td" escape="true"
id="computedField1" value="#{rowData.code}">
</xp:text>
</tr>
</xp:repeat>
</tbody>
</table>
<xp:scriptBlock>
<xp:this.value><![CDATA[
$(document).ready(function() {
var table = $('#keyItemsPLTable').DataTable( {
stateSave: true, //https://datatables.net/reference/option/stateSave
stateDuration: -1//This doesn't seem to work. https://datatables.net/reference/option/stateDuration
});
});
]]></xp:this.value>
</xp:scriptBlock>
</xp:panel>
</xp:div>
<xe:dialog id="dialog1">
<xp:panel id="panelFullDialog" styleClass="mg20">
<xp:div styleClass="mg20">
<xp:inputText id="inputDesc"
value="#{itemBean.plItem.description}" styleClass="wd200">
</xp:inputText>
</xp:div>
<xp:div styleClass="mg20">
<xp:inputText value="#{itemBean.plItem.code}"
id="inputText2" styleClass="wd200">
</xp:inputText>
</xp:div>
<xe:dialogButtonBar id="dialogButtonBar1">
<xp:button value="Cancel" id="button4">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[XSP.closeDialog('#{id:dialog1}')]]></xp:this.script>
</xp:eventHandler>
</xp:button>
<xp:button id="button1">
<xp:this.value><![CDATA[Save & Close]]></xp:this.value>
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="tablePanel">
<xp:this.action><![CDATA[#{javascript:itemBean.savePLItem();
var dialog = getComponent("dialog1");
dialog.hide();
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xe:dialogButtonBar>
</xp:panel>
</xe:dialog>
On closing the Post requests continue with the dialog reappearing until the page is closed.
200
POST
instant.abc.co.uk testing.xsp?$$ajaxid=view:_id1:tablePanel xhr html 35.47 kB 426.05 kB 2165 ms
200
POST
instant.abc.co.uk testing.xsp?$$ajaxid=view:_id1:dialog1 xhr html 574 B 650 B 1969 ms
200
GET
instant.abc.co.uk testing.xsp?$$ajaxid=view:_id1:dialog1:_content&$$showdialog=true&$$created=true&$$createdialog=false&$$viewid=!6rftmmaw860jebb294nc4ay3y! xhr html 871 B 1.94 kB
6 ms
200
POST
instant.abc.co.uk testing.xsp?$$ajaxid=view:_id1:dialog1 xhr html 574 B 650 B 2057 ms
200
GET
instant.abc.co.uk testing.xsp?$$ajaxid=view:_id1:dialog1:_content&$$showdialog=true&$$created=true&$$createdialog=false&$$viewid=!6rftmmaw860jebb294nc4ay3y! xhr html 873 B 1.94 kB
4 ms
200
POST
instant.networkconnect.co.uk testing.xsp?$$ajaxid=view:_id1:dialog1 xhr html 574 B 650 B
If you're trying to refresh tablePanel after closing the dialog, don't make that the refresh ID. The hide() method takes a parameter of the area to refresh after the dialog has closed. That's because the SSJS needs to post back to the browser to make the call to close the dialog, so it will pass a client-side JavaScript call to make a GET request to refresh whatever ID was passed as a parameter of the hide() method. See https://www.intec.co.uk/xpages-dialog-control-and-partial-refreshes/.

Xpages & DataTables

I'm using the dataTables jQuery plugin with xpages and have a custom control I drop onto any page, pass in a custom property of viewName and it will display a table using REST - All based on some great examples by Oliver Busse.
Everything works perfectly if this custom control is used on a basic page, however, if it is within a tab, which is not default, when I then click on the tab containing the control, I receive an error when calling viewjson.getId()
I think the issue is because I set viewjson on beforePageLoad?
Any idea how I can get this to work in a tabbed interface?
Code below:
<xp:this.beforePageLoad><![CDATA[#{javascript:var viewjson = new org.openntf.rest.DynamicView(compositeData.viewName);}]]></xp:this.beforePageLoad>
<table
id="#{javascript:viewjson.getId()}"
class="table table-hover table-striped">
<thead>
<xp:repeat id="repeat1" rows="30" disableOutputTag="true"
var="col">
<xp:this.value><![CDATA[#{javascript:try {
viewjson.getCols()}
catch (e) {
openLogBean.addError(e,this)
}}]]></xp:this.value>
<th>
<xp:text escape="true" disableTheme="true"
value="#{col}">
</xp:text>
</th>
</xp:repeat>
</thead>
<tbody></tbody>
</table>
UPDATE
I've tried the following to try and load jQuery first
<xp:this.resources>
<xp:headTag
tagName="script">
<xp:this.attributes>
<xp:parameter
name="type"
value="text/javascript" />
<xp:parameter
name="src"
value="/xsp/.ibmxspres/.extlib/responsive/jquery/jquery.min.js" />
</xp:this.attributes>
</xp:headTag>
</xp:this.resources>
And also this in xsp properties
xsp.client.script.dojo.djConfig="dojo-amd-factory-scan": false
But I'm still getting a blank page with no dojo elements displaying
I believe the main problem is that for the XPages core controls a non active tab is not actually rendered to the browser until it becomes active. So what you called in the beforePageLoad() was looking for content that didn't exist at the time.
There's probably a CSJS thing that could re-init the data tables. Another option is to not use the tab core control but use the dojo version from the ext. library. I'm pretty sure that the dojo version renders all content and just uses CSS to hide non active tabs.
Custom control's beforePageLoad event gets executed when XPage is loaded already.
When later the tab is activated and with it the table is rendered the variable viewjson is gone.
One approach would be to put Java object into a composite data variable compositeData.viewjson in beforePageLoad and use it in table later. But, you would calculate all views for every tab before rendering page. In addition, this class is not serializable and couldn't be stored in composite data variable. You could make the class serializable though.
The better approach is to instantiate Java bean in table - without a beforePageLoad event:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<table
id="#{javascript:
var viewjson = new org.openntf.rest.DynamicView(compositeData.viewName);
return viewjson.getId();
}">
<thead>
<xp:repeat id="repeat1" rows="30" disableOutputTag="true"
var="col" value="#{javascript: viewjson.getCols()}">
<th>
<xp:text escape="true" disableTheme="true" value="#{col}">
</xp:text>
</th>
</xp:repeat>
</thead>
<tbody></tbody>
</table>
</xp:view>
I tested the custom control above (ccView with property viewName) with this XPage
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:br />
<xp:panel id="tabs">
<xe:djTabContainer id="tabContainer"
selectedTab="djTabPane1" defaultTabContent="one">
<xe:djTabPane id="djTabPaneView" title="one" closable="false"
partialRefresh="true">
tab rendered first
</xe:djTabPane>
<xe:djTabPane id="djTabPane2" title="two" closable="false"
partialRefresh="true">
<xc:ccView viewName="ByCity" />
</xe:djTabPane>
<xe:djTabPane id="djTabPane3" title="three" closable="false"
partialRefresh="true">
<xc:ccView viewName="ByName" />
</xe:djTabPane>
</xe:djTabContainer>
</xp:panel>
</xp:view>
Views in tabs "two" or "three" get loaded per REST services when user clicks the respective tab.

Is there an easy way to make the fileupload work with IE11 without updating zk

In IE11 file upload button of ZK is not working.
I got few replies, It says after updating ZK it will fix the problem.
But we can't update ZK, So in this scenario is there any way to work out this problem any how.
If you can't upgrade ZK then you can try to "downgrade" the IE using "X-UA-Compatible" either as meta-tag or as a response header
here an example using the meta tag:
<?meta http-equiv="X-UA-Compatible" content="IE=10" ?>
<zk>
<fileupload label="upload" onUpload="alert(event.getMedia().getName())"/>
</zk>
and what it looks like in the browser (in the IE dev tools F12 you can check if the meta tag had an effect, you'll see that IE falls back to version 10):
http://screencast.com/t/ftheLA9Ud8
Finally I got the Solution.
AS IE 11 having problem to attach event for listening to open File chooser.
You just manually add the listener.
<button id="browsebtn" upload="true,maxsize=-1" visible="true" sclass="text">
<attribute w:name="doMouseDown_">
function (evt) {
}
</attribute>
</button>
Its simple and weird, However what I found is make the parent component as draggable="true"
<row draggable="true">
<div style="text-align : right;">
<label value="Image File:" />
</div>
<fileupload id="fileUpload" label="Upload" tooltiptext="Click to upload image file."/>
</row>
Now suddenly you will see your fileupload button in ZK started working correctly for IE11 as well.

XPages 9 with Esri maps dojo conflict: 'defineAlreadyDefined'

With our update to XPages version 9 and the Esri ARcgis javascript api v 3.5, we're having problems with our dojo namespaces resulting in a defineAlreadyDefined error. There are a few similar problems listed here (Using Durandal dojoConfig and ESRI Maps, How can I fix this AMD path conflict?), but even with that help we are unable to get it working. I believe the issue is the dojoConfig syntax - any thoughts or help would be appreciated!
Here is a simple version of our xpage source code with js:
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.resources>
<xp:styleSheet
href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.5/js/dojo/dijit/themes/claro/claro.css">
</xp:styleSheet>
<xp:styleSheet
href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.5/js/esri/css/esri.css">
</xp:styleSheet>
<xp:script clientSide="true">
// dojo.registerModulePath("esri","http://serverapi.arcgisonline.com/jsapi/arcgis/3.5/js/esri");
dojoConfig = {
baseUrl: "http://serverapi.arcgisonline.com/jsapi/arcgis/3.5/js/esri",
packages: [
{
name: 'dojo',
location: "http://serverapi.arcgisonline.com/jsapi/arcgis/3.5/js/dojo/dojo/"
},
{
name: 'dojox',
location: "http://serverapi.arcgisonline.com/jsapi/arcgis/3.5/js/dojo/dojox"
},
{
name: 'esri',
location: "http://serverapi.arcgisonline.com/jsapi/arcgis/3.5/js/esri"
}
]};
</xp:script>
<xp:script src="http://serverapi.arcgisonline.com/jsapi/arcgis/3.5/"
clientSide="true">
</xp:script>
<xp:dojoModule name="esri.map"></xp:dojoModule>
</xp:this.resources>
<xp:eventHandler event="onClientLoad" submit="false">
<xp:this.script><![CDATA[var map;
function init(){
var map = new esri.Map("mapDiv", {
center: [-56.049, 38.485],
zoom: 3,
basemap: "streets"
});
}
dojo.ready(init);
]]></xp:this.script>
If we include the dojo.registerModulePath command, the map does load (at least in FF), but with the error. Without it, the esri dojo doesn't load - it's looking in the wrong place for the esri files.
There are few things you need to keep in mind, and probably change the code accordingly:
xPages already makes use of dojoconfig, either through xsp-config
file options or using xPages parameters.
As mentioned by Per, dojo is already used in xPages, so you don't need to load it from somewhere else (same applies to the CSS).
What you can do is following:
Option 1: Use offline copies of JS library for maps. You can add them
to your xPages app as JS resources. You will only have to specify
them in your xPage, and load dojo module as you do already;
Option 2: See below how to inject more dojoConfig options before a xPage will load
Code:
<xp:this.properties>
<xp:parameter name="xsp.client.script.dojo.djConfig" value="packages: exPackages" />
</xp:this.properties>
<xp:this.beforePageLoad>
<![CDATA[#{javascript:
var exCon = facesContext.getExternalContext();
var response = exCon.getResponse();
var writer = response.getWriter();
writer.write("<script>\n");
writer.write("var exPackages=[{name:'esri',location:'http://serverapi.arcgisonline.com/jsapi/arcgis/3.5/js/esri'}]\n");
writer.write("</script>\n");
}]]>
</xp:this.beforePageLoad>
<xp:this.resources>
<xp:dojoModule name="esri.map"></xp:dojoModule>
</xp:this.resources>
Update: Small correction of code.
Update2: After briefly checking ArcGis website, it seems they choose to provide Dojo together with their API (which is wrong in my opinion). See https://developers.arcgis.com/en/javascript/jshelp/inside_dojoversion.html (part2), although it will not help you much as they don't provide a feasible solution for Dojo 1.8.x
Seeing that their API is not free, I think the best way would be to contact them, ask for ESRI part of the API as separate download, host it on your own servers and follow either Option 1 or 2. Moreover, the version of API you try to use is based on Dojo 1.8.3, while Domino 9 has Dojo 1.8.
OK, this was a problem for me too!
I've been able to get it working by using the following code:
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.resources>
<xp:script clientSide="true">
dojo.registerModulePath("esri","http://js.arcgis.com/3.8/js/esri");
dojoConfig = { baseUrl: "http://js.arcgis.com/3.8/js/esri",
packages: [ { name: 'esri', location: "http://js.arcgis.com/3.8/js/esri" } ]};
</xp:script>
<xp:styleSheet href="http://js.arcgis.com/3.8/js/esri/css/esri.css" />
<xp:styleSheet href="http://js.arcgis.com/3.8/js/esri/dijit/css/Popup.css" />
<xp:dojoModule name="esri.map"></xp:dojoModule>
</xp:this.resources>
<xp:eventHandler event="onClientLoad" submit="false">
<xp:this.script><![CDATA[var map;
function init(){
var map = new esri.Map("mapDiv", {
center: [0,53],
zoom: 10,
basemap: "streets"
});
}
dojo.ready(init);
]]></xp:this.script>
</xp:eventHandler>
<div id="mapDiv" style="width:1000px;height:600px"></div>
</xp:view>
I think the order of scripts is important and you don't need to include the esri.map script twice.

DOJO 1.8 /dojo/request/iframe is deleting <form></form> when uploading a file

I'm seeing a really strange behavior under DOJO 1.8.0. I'm trying to asynchronously upload a file. The file is uploading just fine and I'm getting the payload as expected, but when clicking the submit button the tags and everything in between is inexplicably deleted! It just vanishes. (NOTE: I've isolated this testing to a test page, so there's nothing else at play that would account for it. You're looking at the entirety of the code.)
require(['dojox/form/Uploader',
"dojo/request/iframe",'dojo/dom','dojo/on',
'dojox/form/uploader/plugins/IFrame', 'dojo/domReady!'],
function(Uploader,iframe,dom,on){
on(dom.byId("myButton"), "click", function(){
iframe.post("UploadFile.php",{
form: dom.byId("myForm"),
handleAs: "json"
}).then(function(data){
console.log(data);
}, function(err){}
);
});
<form method="post" id="myForm" enctype="multipart/form-data" >
<input name="uploadedfile" type="file" data-dojo-type="dojox.form.Uploader"
label="Select Some Files" id="uploader" />
<input id="myButton" type="button" value="Submit" />
</form>
Any ideas from anyone with DOJO 1.8 experience? I've been using /dojo/io/iframe just fine with versions 1.6 thru 1.7. This started happening only with 1.8 using the new /dojo/request/iframe code.
See http://jsfiddle.net/seeds/XD4Dc/1/
The form element is set to have target of dojo's injected iframe. Then form gets like, 'dijitHidden' with abs position -1000 top/left. Cant see why tbh.
There's a fix in the fiddle, add to your callback:
with(dom.byId("myForm").style) {
position = "";
left = "";
top = "";
}
I took this issue to the DOJO-Interest group and it was found to be bug with DOJO 1.8.0. It'll be fixed with the upcoming 1.8.1 release.
http://bugs.dojotoolkit.org/ticket/15939
From the bug report:
The form wasn't getting "eaten", but rather the position was getting set on it and moved out of the viewport because of some faulty logic to check if the form was in the DOM. This has been fixed and should be in 1.8.1.