XPages: Dojo 1.8.1 & jQuery Mobile 1.3.1

As David Leedy got into trouble with Dojo 1.8.1 and jQuery Mobile 1.3.1  and after reading the follow up from Ulrich Krause with the analysis of the problem, I thought that this problem is caused from the AMD loader of Dojo. That’s why I changed the loading order (by forcing the jQuery libraries to get loaded before Dojo), and this seems to work.

I have tested it in IE 8, FF 20.0 and Chrome 26.0.

Here is my test XPage:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view
    xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:this.properties>
        <xp:parameter
            name="xsp.resources.aggregate"
            value="true" />
    </xp:this.properties>
    <xp:this.resources>
        <xp:styleSheet
            href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" />
        <xp:headTag
            tagName="script">
            <xp:this.attributes>
                <xp:parameter
                    name="type"
                    value="text/javascript" />
                <xp:parameter
                    name="src"
                    value="http://code.jquery.com/jquery-1.9.1.min.js" />
            </xp:this.attributes>
        </xp:headTag>
        <xp:headTag
            tagName="script">
            <xp:this.attributes>
                <xp:parameter
                    name="type"
                    value="text/javascript" />
                <xp:parameter
                    name="src"
                    value="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js" />
            </xp:this.attributes>
        </xp:headTag>
    </xp:this.resources>

    <div
        data-role="page"
        class="jqm-demos"
        data-quicklinks="true">

        <div
            data-role="content"
            class="jqm-content"
            id="contentRefresh">
            <h2
                id="accordion-markup">
                <script>document.write(dojo.version)</script>
            </h2>

            <div>
                <div
                    data-role="collapsible-set"
                    data-theme="c"
                    data-content-theme="d">

                    <div
                        data-role="collapsible">
                        <h3>Section</h3>
                        <p>
                            <xp:label
                                value="#{javascript:java.lang.System.currentTimeMillis()}"
                                id="labelRefresh" />
                        </p>
                    </div>
                </div>
            </div>
            <a
                href="#"
                onclick="XSP.partialRefreshGet('#{id:labelRefresh}')"
                data-role="button">Refresh Label</a>
        </div>
    </div>

</xp:view>

And this is the result:

The XSP object is loaded correctly and Partial Refreshs are executed correctly:

It is required that the resource aggregation is enabled. More details can be found here.

Veröffentlicht unter Dojo Toolkit, HTML, Java Script, ServerSide JavaScript, Web, XPages, XSP | Verschlagwortet mit , , , , , , , , , , | 2 Kommentare

Quick-n-Dirty: Dojo 1.8 & Domino 8.5.3

If you want to use Dojo 1.8 with Domino 8.5.3, you can do the following:

1. Grab the Dojo JAR file from a ND9 installation:

<PATH TO DOMINO>\osgi\shared\eclipse\plugins\com.ibm.xsp.dojo_9.0.0<VERSION>.jar

2. Create a folder “dojo-1.8.0” in your notes data directory

<PATH TO DOMINO DATA>\domino\js\dojo-1.8.0

3. Unpack the JAR file

4. Copy the content of the subfolder \resources\dojo-version of the unpacked JAR file in this folder:

5. Restart HTTP task.

6. Enjoy!

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <script>document.write(dojo.version)</script>
    <br/>
    <xp:label value="#{javascript:
        importPackage(com.ibm.xsp.core);
        Version.CurrentRuntimeVersion}" />
</xp:view>

P.S. Keep in mind that this article has been posted in the “Quick-n-Dirty” category.

Veröffentlicht unter Dojo Toolkit, Infrastruktur, Java Script, Server, XPages | Verschlagwortet mit , , , , , , , | Hinterlasse einen Kommentar

XPages: Add inline CSJS with a Theme

I needed a way to add some inline CSJS to an existing application which affects any XPage, that’s why I did this them with a theme.

Et voilà:

<theme extends="webstandard" >

    <resources mode="concat">
        <script>
            <contents>alert('THEME JS!')</contents>
            <clientSide>true</clientSide>
        </script>
    </resources>

</theme>

The javascript code is added and executed as expected:

Veröffentlicht unter Java Script, Performance, Web, XPages | Verschlagwortet mit , , , , , , , | Hinterlasse einen Kommentar

XPages: Inject CSJS code at page top

Sometimes it is required to add some CSJS code at the beginning of the XPage before the Dojo libaries are loaded and are executed. This can be easily achieved by using the resource aggregation feature and including a CSJS library with the <xp:headTag>.

First you have to create a CSJS library which contains the code you want to execute:

Then you have to add the <xp:headTag> which loads the CSJS library:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

    <xp:this.properties>
        <xp:parameter name="xsp.resources.aggregate" value="true" />
     </xp:this.properties>

     <xp:this.resources>
         <xp:headTag tagName="script">
             <xp:this.attributes>
                 <xp:parameter name="type" value="text/javascript" />
                 <xp:parameter name="src" value="Before.js" />
             </xp:this.attributes>
         </xp:headTag>
    </xp:this.resources>

</xp:view>

[The xp:parameter can ignored if resource aggregation is enabled for the whole application]

The generated HTML source code will look like this, with the CSJS library at the top of the page:

It works ONLY if resource aggregation is enabled. If it is disabled, the CSJS library is added after the Dojo libraries and style sheets:

Veröffentlicht unter Dojo Toolkit, HTML, Java Script, Web | Verschlagwortet mit , , , , , , , | 4 Kommentare

Notes 9: Some interesting xsp.properties

Some interesting new xsp.properties were introduced with Notes 9:

  • xsp.client.resources.uncompressed

When set to true, all Dojo libraries and CSS resources where delivered in the uncompressed version. The path changes f.e. to /xsp/.ibmxspres/dojoroot-1.8.1-u/dojo/dojo.js.

  • xsp.client.script.dojo.html5attr

When set to true, the Dojo HTML5 Data attribute is added to all Dojo component on the XPages. Here is an example for a Date/Time field:

<input type="text"
   id="view:_id1:inputText1"
   name="view:_id1:inputText1"
   class="xspInputFieldDateTimePicker"
   data-dojo-type="ibm.xsp.widget.layout.DateTextBox"
   iconStyleClass="xspInputFieldDatePickerIcon"
   constraints="{datePattern:&quot;dd.MM.yyyy&quot;,timePattern:&quot;HH:mm:ss&quot;,selector:&quot;date&quot;}">
  • xsp.radiobuttongroup.item.label.prefixSpace

When set to true, a blank is added before the label the label:

<xp:radioGroup id="radioGroup1">
   <xp:selectItem itemLabel="Untitled" />
</xp:radioGroup>

Resulting HTML code (There is a space before the red marked label):

<label for="view:_id1:radioGroup1:0">
   <input type="radio" id="view:_id1:radioGroup1:0" 
   name="view:_id1:radioGroup1" value="Untitled"> Untitled</label>

New properties which are described in the xsp.properties.sample file:

  • xsp.maximum.mime.tree.scanLevel
  • com.ibm.ws.webcontainer.HTTPOnlyCookies
  • xsp.client.script.xspClient.preventLayer
  • xsp.client.script.radioCheckbox.ie.onchange.trigger
  • xsp.repeat.parseSingleStringAsInt
  • xsp.client.script.dojo.loader
Veröffentlicht unter Dojo Toolkit, HTML5, Server, XPages, XSP | Verschlagwortet mit , , , , , , | 8 Kommentare

Notes 9: No Comment!

Veröffentlicht unter Allgemein | Verschlagwortet mit , | 5 Kommentare

Quick-n-Dirty: How to add HTML 5 events

One way for adding unsupported events to an XPage or a component is the trick from Keith. But this is limited to CSJS only. If you need to execute a server side event, you just need change the name of the event to a new HTML 5 event name which does not exist in the DDE.

Here is an example for the new onSearch event:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

    <xp:inputText id="inputTextSearch" type="search">
        <xp:eventHandler event="onsearch" submit="true"
            refreshMode="partial" refreshId="labelSearchFor">
            <xp:this.action>
               <![CDATA[#{javascript:print("onSearch");}]]>
            </xp:this.action>
        </xp:eventHandler>
    </xp:inputText>

    <xp:br />
    <xp:br />

    <xp:label id="labelSearchFor">
        <xp:this.value>
           <![CDATA[#{javascript:getComponent("inputTextSearch").value}]]>
        </xp:this.value>
    </xp:label>

</xp:view>

After entering a value and hitting enter…

… you can see on the server console that the event occurred:

This technique allows to add new events to the whole XPage, for example the onContextMenu event:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

        <xp:eventHandler event="oncontextmenu" submit="true"
            refreshMode="norefresh">
            <xp:this.action>
                <![CDATA[#{javascript:print("onContextMenu");}]]>
            </xp:this.action>
        </xp:eventHandler>

</xp:view>

Every time if the user opens the context menu in the browser, the event is triggered and executed on the server:

The name of the event must be lowercased. A list of HTML 5 events can be found here: http://www.tutorialspoint.com/html5/html5_events.htm. Not all browsers support every HTML 5 event in the list.

P.S. Keep in mind that this article has been posted in the “Quick-n-Dirty” category.

Veröffentlicht unter HTML, HTML5, Java Script, ServerSide JavaScript, Web, XPages | Verschlagwortet mit , , , , , , , , , , | 3 Kommentare

In Ya Facet!

Using Facets in XPages is very nice, because it gives you an easy way for a global design of your application (and much more). It can be used in all XPages and their custom controls. The xp:callback element defines a section, and this section can be filled in by the parent component with the xp:key attribute.

Take a look at this custom control:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" style="margin: 16px;">
   <xp:text escape="true" id="computedFieldTitle"
        value="#{javascript:compositeData.title}" tagName="h1" />
   <xp:callback facetName="TabAreaCallback" id="callbackTabArea"
        xp:key="TabAreaCallback" />
</xp:view>

It has a single callback area (I will never understand why it is called “Editable Area” in the DDE), and a xp:text which is filled in with the value of the property title of the custom control.

This CustomControl (ccFacet) can now be used in another custom control (ccMain) by using the xp:key attribute:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
   xmlns:xc="http://www.ibm.com/xsp/custom">

    <xc:ccFacet title="Hello World!" >
        <xp:this.facets>
            <xp:div xp:key="TabAreaCallback">
                <p>Hello World!</p>
            </xp:div>
        </xp:this.facets>        
    </xc:ccFacet>

</xp:view>

The <xp:div> element calls the facet of the embedded custom control back (with the xp:key as the phone number), and the content of the calling component will be inserted in the defined placeholder. Added to a XPage the result looks like this:

If you change now the design in the ccFacet, the design will be changed on every XPage automatically. Or you can add new buttons, footers, etc. which will be automatically used in all other XPages which are using the custom control.

OK? OK!

But  what will happen if we are using the compositeData object?

Let’s add the property “foo” to the ccMain custom control:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
   xmlns:xc="http://www.ibm.com/xsp/custom">

    <xc:ccFacet title="Hello World!" >
        <xp:this.facets>
            <xp:div xp:key="TabAreaCallback">
                <p>Hello World!</p>
                <xp:text escape="true" id="computedFieldFoo"
                                        value="#{compositeData.foo}" />
            </xp:div>
        </xp:this.facets>        
    </xc:ccFacet>

</xp:view>

The custom control definition in the XPage is changed to this…

<xc:ccMain foo="bar"></xc:ccMain>

… but in the browser you will see nothing:

If you remove the ccFacet definition from ccMain, you will see that the compositeData works as expected:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
   xmlns:xc="http://www.ibm.com/xsp/custom">

<!--    <xc:ccFacet title="Hello World!" >-->
<!--        <xp:this.facets>-->
            <xp:div xp:key="TabAreaCallback">
                <p>Hello World!</p>
                <xp:text escape="true" id="computedFieldFoo"
                                       value="#{compositeData.foo}" />
            </xp:div>
<!--        </xp:this.facets>-->        
<!--    </xc:ccFacet>-->

</xp:view>

What happened to the compositeData object? Is it broken? No, it is still working correctly and refers to the compositeData of the current custom control – but the custom control is no longer the same. It The elements added to the callback have moved to another node in the component tree, and that’s why the compositeData cannot be found anymore (see here for some details).

If you print the client id of the component and the variable in the beforePageLoad event to the console, you will see the id of the custom control:

But if you take a look in the generated source of the XPage, you will see that the client ids of the elements have been moved a node deeper in the tree:

<span id="view:_id1:_id2:_id3:callbackTabArea:computedField1" class="xspTextComputedField"></span>

If you want to use the data from the compositeData object, you have to add all the properties to the ccFacet too (and create the property in the custom control):

<xc:ccFacet title="Hello World!" foo="#{compositeData.foo}">

That’s a really annoying and reduces the usability of compositeData – but it seems to be the only usable workaround for this problem.

Veröffentlicht unter Allgemein, JSF, XPages | Verschlagwortet mit , , | 3 Kommentare

A performance bottleneck?

Paul Withers wrote an very interesting article about the difference between a passthrough UIComponents and the corresponding XPages elements. This means the use of <br> instead a <xp:br>, or a <div> instead of a <xp:div>. A while ago I have tested if this would affect the performance, and as far as I know it makes no difference.

Here is the code I used to test the performance:

<?xml version="1.0" encoding="UTF-8"?>
 <xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <h1>Name of the Element</h1>
    <xp:repeat id="repeatFull" rows="9999999">
       <xp:this.value><![CDATA[#{javascript:
          var arr:java.util.Vector = new java.util.Vector();
          for( var i=0; i<10;i++){
             arr.add( i );
          }
          var start = java.lang.System.currentTimeMillis();

          arr}]]>
       </xp:this.value>

       <xp:repeat id="repeat1" rows="9999999">
          <xp:this.value><![CDATA[#{javascript:
             var arr:java.util.Vector = new java.util.Vector();
             for( var i=0; i<100000;i++){
                arr.add( i );
             }
             var start = java.lang.System.currentTimeMillis();
             arr}]]>
          </xp:this.value>

          <!-- HERE COMES THE REPEATING ELEMENT //-->

       </xp:repeat>
       <xp:label id="labelTimer">
          <xp:this.value>
             <![CDATA[#{javascript:
                var end = java.lang.System.currentTimeMillis();
                "Total " + (end - start) + " ms."
             }]]>
          </xp:this.value>
       </xp:label>
    </xp:repeat>
    <xp:br />
    <xp:button value="Refresh" id="buttonRefresh">
       <xp:eventHandler event="onclick" submit="true"
          refreshMode="partial" refreshId="repeatFull">
       </xp:eventHandler>
   </xp:button>

</xp:view>
  • Test with a <xp:div>

  • Open the page

  • Partial Refresh

  • Test with a <div>

  • Opening the page

  • Partial Refresh

[Similar results with the other tags]

As you can see there is nothing to worry about. Yes, a UIPassthroughComponent is faster then the corresponding XPages UIComponent. But keep in mind that these test are for 100.000 elements at once. If you have an XPage with 100.000 components on it, you will have other problems (f.e. memory usage etc.).

Veröffentlicht unter Allgemein, Java, JSF, Performance, ServerSide JavaScript, XPages | Verschlagwortet mit , , , , , | Hinterlasse einen Kommentar

XPages: The Problem with DataContext Variables

There is a large problem with data context variables if they are bound dynamically.
They will be recomputed again and again, even when in Partial Execution mode and if they are not in use. Here is a small demo XPage:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

   <xp:this.dataContexts>
      <xp:dataContext var="dataContext">
         <xp:this.value>
            <![CDATA[#{javascript:
               // Sleep for 100ms
               java.lang.Thread.currentThread().sleep( 100 );
               print('-=> Recalc: ' + java.lang.System.currentTimeMillis());
               return true;
            }]]>
          </xp:this.value>
       </xp:dataContext>
    </xp:this.dataContexts>

   <xp:label id="labelRefreshMe">
      <xp:this.value>
         <![CDATA[#{javascript:
            java.lang.System.currentTimeMillis()
         }]]>
      </xp:this.value>
   </xp:label>

   <xp:button value="Refresh" id="buttonRefresh" >
      <xp:eventHandler event="onclick" submit="false"
         refreshMode="partial"
         refreshId="labelRefreshMe"
         execId="labelRefreshMe"
         execMode="partial" />
   </xp:button>

</xp:view>

If you are open the XPage, a dataContext variable will be recalculated for three times:

Clicking on the button will recalculate them up to eleven times:

Keep in mind: Partial Refresh & Partial Execution is enabled. That makes them only useable if their values are computed on page load.

Veröffentlicht unter Allgemein, Performance, XPages | Verschlagwortet mit , , , , , , | 6 Kommentare