Permalink
Fetching contributors…
Cannot retrieve contributors at this time
339 lines (314 sloc) 19.5 KB
<!--
Copyright (C) 2010 Orbeon, Inc.
This program is free software; you can redistribute it and/or modify it under the terms of the
GNU Lesser General Public License as published by the Free Software Foundation; either version
2.1 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
-->
<xbl:xbl xmlns:xh="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:saxon="http://saxon.sf.net/"
xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:xxbl="http://orbeon.org/oxf/xml/xbl"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:oxf="http://www.orbeon.com/oxf/processors"
xmlns:exf="http://www.exforms.org/exf/1-0" >
<xbl:binding id="fr-dialog-select1-binding" element="fr|dialog-select1">
<!-- Orbeon Form Builder Component Metadata -->
<metadata xmlns="http://orbeon.org/oxf/xml/form-builder">
<display-name lang="en">Dialog Single Selector</display-name>
<display-name lang="es">Diálogo Selección Simple</display-name>
<display-name lang="fi">Dialogin yksittäisvalitsin</display-name>
<display-name lang="fr">Dialogue liste simple</display-name>
<display-name lang="ru">Один из диалога</display-name>
<display-name lang="de">Dialog mit Einfachauswahl</display-name>
<display-name lang="it" todo="true">[Dialog Single Selector]</display-name>
<display-name lang="sv">Dialog med enkelt val</display-name>
<display-name lang="nl">Dialoog enkelvoudige selectie</display-name>
<display-name lang="pt">Diálogo Selecção Simples</display-name>
<icon>
<small-icon>/forms/orbeon/builder/images/listbox.png</small-icon>
<large-icon>/forms/orbeon/builder/images/listbox.png</large-icon>
</icon>
<editors static-itemset="true"/>
<template>
<fr:dialog-select1 separator=", ">
<xf:label ref=""/>
<xf:hint ref=""/>
<xf:help ref=""/>
<xf:alert ref=""/>
<xf:itemset ref="">
<xf:label ref="label"/>
<xf:value ref="value"/>
</xf:itemset>
</fr:dialog-select1>
</template>
</metadata>
<xbl:resources>
<xbl:style src="/xbl/orbeon/dialog-select/dialog-select.css"/>
</xbl:resources>
<xbl:implementation>
<xf:model id="model">
<xf:instance id="model-resources" src="oxf:/xbl/orbeon/dialog-select/dialog-select-resources.xml"
xxf:readonly="true" xxf:cache="true"/>
<xf:var name="resources" value="instance('model-resources')/resource[@xml:lang = 'en']" as="element()?"/>
</xf:model>
</xbl:implementation>
<xxbl:global>
<xxf:dialog id="fr-dialog-select1-double-list-dialog" level="modal" class="fr-dialog-select1-double-list-dialog" model="fr-dialog-select1-editor-double-list-model">
<xf:label ref="label"/>
<!-- Don't show the 'x' in the dialog title bar, not to "confuse" users; this way they have
clearly two choices: confirm the selection or cancel -->
<xf:model id="fr-dialog-select1-editor-double-list-model">
<xf:instance id="fr-dialog-select1-editor-double-list-instance">
<instance>
<label/>
<items/>
<available-itemset/>
<selected-itemset/>
<available/>
<selected/>
<add-trigger/>
<remove-trigger/>
<callback-id/>
</instance>
</xf:instance>
<xf:bind ref="add-trigger" readonly="xxf:is-blank(../available)"/>
<xf:bind ref="remove-trigger" readonly="xxf:is-blank(../selected)"/>
<xf:instance id="fr-dialog-select1-double-list-resources" src="oxf:/xbl/orbeon/dialog-select/dialog-select-resources.xml"
xxf:readonly="true" xxf:cache="true"/>
</xf:model>
<xf:action ev:event="fr-edit">
<!-- When dialog open, get list of available and selected items -->
<xf:setvalue ref="label" value="event('fr-label')"/>
<xf:var name="binding" value="xxf:split(event('fr-binding'))"/>
<xf:var name="items" value="event('fr-items')"/>
<xf:delete ref="items/*"/>
<xf:insert context="items" origin="$items"/>
<xf:setvalue ref="available-itemset" value="string-join($items/value/string()[not(. = $binding)], ' ')"/>
<xf:setvalue ref="selected-itemset" value="string-join($items/value/string()[. = $binding], ' ')"/>
<xf:setvalue ref="available"/>
<xf:setvalue ref="selected"/>
<xf:setvalue ref="callback-id" value="event('fr-callback-id')"/>
<xxf:show dialog="fr-dialog-select1-double-list-dialog"/>
<xf:setfocus control="fr-dialog-select1-double-list-dialog"/>
</xf:action>
<xf:var name="resources" value="instance('fr-dialog-select1-double-list-resources')/resource[@xml:lang = 'en']" as="element()?"/>
<xf:var name="available-values" value="xxf:split(available-itemset)" as="xs:string*"/>
<xf:var name="selected-values" value="xxf:split(selected-itemset)" as="xs:string*"/>
<xf:var name="items" value="items/item"/>
<xh:table>
<xh:tr>
<xh:td>
<!-- List of available items -->
<xf:select ref="available">
<xf:label value="$resources/available"/>
<xf:itemset ref="$items[value = $available-values]">
<xf:label ref="label"/>
<xf:value ref="value"/>
</xf:itemset>
</xf:select>
</xh:td>
<xh:td>
<xf:trigger ref="add-trigger" class="fr-add-button">
<xf:label>
<xh:span>
<xf:output value="$resources/add"/>
</xh:span>
</xf:label>
<xf:action ev:event="DOMActivate">
<xf:var name="selection" value="xxf:split(../available)" as="xs:string*"/>
<xf:setvalue ref="../selected-itemset"
value="string-join((xxf:split(), $selection), ' ')"/>
<xf:setvalue ref="../available-itemset"
value="string-join(xxf:split()[not(. = $selection)], ' ')"/>
<xf:setvalue ref="../available"/>
<xf:setvalue ref="../selected"/>
</xf:action>
</xf:trigger>
<xf:trigger ref="remove-trigger" class="fr-remove-button">
<xf:label>
<xh:span>
<xf:output value="$resources/remove"/>
</xh:span>
</xf:label>
<xf:action ev:event="DOMActivate">
<xf:var name="selection" value="xxf:split(../selected)" as="xs:string*"/>
<xf:setvalue ref="../available-itemset"
value="string-join((xxf:split(), $selection), ' ')"/>
<xf:setvalue ref="../selected-itemset"
value="string-join(xxf:split()[not(. = $selection)], ' ')"/>
<xf:setvalue ref="../available"/>
<xf:setvalue ref="../selected"/>
</xf:action>
</xf:trigger>
</xh:td>
<xh:td>
<!-- List of selected items -->
<xf:select1 ref="selected">
<xf:label value="$resources/selected"/>
<xf:itemset ref="$items[value = $selected-values]">
<xf:label ref="label"/>
<xf:value ref="value"/>
</xf:itemset>
</xf:select1>
</xh:td>
</xh:tr>
</xh:table>
<xh:div class="fr-dialog-buttons">
<!-- Confirm button -->
<xf:trigger>
<xf:label>
<xh:img width="11" height="16" src="/apps/fr/style/images/pixelmixer/tick_16.png" alt=""/>
<xf:output value="$resources/confirm"/>
</xf:label>
<xf:action ev:event="DOMActivate">
<!-- Store values in itemset order -->
<xf:dispatch ev:event="DOMActivate" name="fr-edit-done" targetid="{callback-id}">
<xf:property name="fr-new-values" value="for $selected-itemset in instance()/selected-itemset
return string-join($items/value/string()[. = xxf:split($selected-itemset)], ' ')"/>
</xf:dispatch>
<xxf:hide dialog="fr-dialog-select1-double-list-dialog"/>
</xf:action>
</xf:trigger>
<!-- Cancel button -->
<xf:trigger>
<xf:label>
<xh:img width="11" height="16" src="/apps/fr/style/close.gif" alt=""/>
<xf:output value="$resources/cancel"/>
</xf:label>
<xf:action ev:event="DOMActivate">
<!-- Just close -->
<xxf:hide dialog="fr-dialog-select1-double-list-dialog"/>
</xf:action>
</xf:trigger>
</xh:div>
</xxf:dialog>
<xxf:dialog id="fr-dialog-select1-single-list-dialog" appearance="minimal" close="true" level="modeless" class="fr-dialog-select1-single-list-dialog" model="fr-dialog-select1-editor-single-list-model">
<xf:label>&#160;</xf:label>
<xf:model id="fr-dialog-select1-editor-single-list-model">
<xf:instance>
<instance>
<selected/>
<items/>
<callback-id/>
</instance>
</xf:instance>
</xf:model>
<xf:action ev:event="fr-edit">
<xf:setvalue ref="selected" value="event('fr-binding')"/>
<xf:delete ref="items/*"/>
<xf:insert context="items" origin="event('fr-items')"/>
<xf:setvalue ref="callback-id" value="event('fr-callback-id')"/>
<xf:setfocus control="fr-dialog-select1-dialog"/>
<xxf:show dialog="fr-dialog-select1-single-list-dialog" neighbor="{event('fr-callback-id')}"/>
</xf:action>
<xf:action ev:event="xxforms-dialog-close" xxf:if-non-relevant="true">
<xf:dispatch name="fr-edit-done" targetid="{callback-id}">
<xf:property name="fr-new-values" value="selected"/>
</xf:dispatch>
</xf:action>
<xf:select1 ref="instance()/selected" appearance="full">
<xf:itemset ref="instance()/items/item">
<xf:label ref="label"/>
<xf:value ref="value"/>
</xf:itemset>
</xf:select1>
</xxf:dialog>
</xxbl:global>
<xbl:template xxbl:transform="oxf:unsafe-xslt">
<!-- Outer group -->
<xf:group xbl:attr="model context ref bind" xxbl:scope="outer" xsl:version="2.0">
<xbl:content includes=":root > xf|label, :root > xf|help, :root > xf|hint, :root > xf|alert"/>
<!-- Stop all events dispatched to outer group -->
<xf:action ev:event="#all" ev:propagate="stop" ev:target="#observer"/>
<!-- Inner group -->
<xf:group xxbl:scope="inner" appearance="xxf:internal">
<!-- Stop events dispatched to group and variable from propagating outside the component -->
<xf:action ev:event="#all" ev:propagate="stop" ev:target="#observer binding-var"/>
<!-- Variable pointing to external single-node binding -->
<xf:var name="binding" id="binding-var" as="node()?">
<xxf:value value="." xxbl:scope="outer"/>
</xf:var>
<!-- Variable containing the label, so we can pass it to the dialog -->
<xf:var name="label">
<xxf:value xxbl:scope="outer">
<xsl:variable name="label" select="/fr:dialog-select1/xf:label"/>
<xsl:if test="$label/@ref"><xsl:attribute name="select" select="$label/@ref"/></xsl:if>
<xsl:value-of select="$label"/>
</xxf:value>
</xf:var>
<!-- Internal selection control providing access to the itemset -->
<!-- NOTE: Events on this control will propagate out -->
<xf:select ref="$binding" appearance="xxf:internal" id="hidden-select">
<!-- Copy again label and alert for the error summary -->
<xbl:content includes=":root > xf|label, :root > xf|alert"/>
<!-- Copy itemset information -->
<xf:choices xxbl:scope="outer">
<xbl:content includes=":root > xf|itemset, :root > xf|item, :root > xf|choices"/>
</xf:choices>
<!-- Redirect focus to button -->
<xf:setfocus ev:event="xforms-focus" control="select"/>
</xf:select>
<!-- Stuff within this group doesn't contribute events to the outside -->
<xf:group appearance="xxf:internal">
<!-- Stop all elements dispatched to this group and its content -->
<xf:action ev:event="#all" ev:propagate="stop"/>
<!-- All the items in the itemset specified by the user -->
<xf:var name="items" value="xxf:itemset('hidden-select', 'xml')//item" as="element(item)*"/>
<!-- Represent selected value -->
<xf:var name="selected" value="xxf:split($binding)" as="xs:string*"/>
<!-- If a separator is specified, output a string, otherwise output ul/li -->
<xsl:variable name="separator" select="/fr:dialog-select1/@separator"/>
<xsl:choose>
<xsl:when test="exists($separator)">
<!-- Add tabindex so the element doesn't steal the focus on Firefox when styled with overflow-y: scroll.
This isn't done by default, but can be done by the application, as is the case in the test-dialog-select.xthml -->
<xf:var name="separator" xbl:attr="xbl:text=separator" as="xs:string"/>
<xf:var name="joined" value="string-join($items[value = $selected]/label, $separator)"/>
<xf:output value="$joined" tabindex="-1" id="joined" class="{{if ($joined = '') then '' else 'fr-non-empty'}}"/>
</xsl:when>
<xsl:otherwise>
<xh:ul>
<!-- Iterate over values instead of the nodes returned by xxf:itemset() so as to avoid extra
repeat nodeset recalculations -->
<xf:repeat ref="$items[value = $selected]/value/string()" id="list">
<xh:li>
<xf:output value="$items[value = context()]/label" id="item"/>
</xh:li>
</xf:repeat>
</xh:ul>
</xsl:otherwise>
</xsl:choose>
<!-- Select button -->
<xf:trigger id="select" ref="$binding">
<xf:label>
<xh:img src="/ops/yui/menu/assets/menu_down_arrow.png" alt="Select"/>
</xf:label>
<xsl:variable name="appearance" select="/fr:dialog-select1/@appearance"/>
<xf:action ev:event="DOMActivate">
<xf:dispatch name="fr-edit" xxbl:scope="outer"
targetid="fr-dialog-select1-{if ($appearance = 'double-list') then 'double-list' else 'single-list'}-dialog">
<xf:property name="fr-label" value="$label" xxbl:scope="inner"/>
<xf:property name="fr-binding" value="$binding" xxbl:scope="inner"/>
<xf:property name="fr-items" value="$items" xxbl:scope="inner"/>
<xf:property name="fr-callback-id" value="event('xxf:absolute-targetid')"/>
</xf:dispatch>
</xf:action>
<xf:setvalue ev:event="fr-edit-done" ref="$binding" value="event('fr-new-values')"/>
</xf:trigger>
</xf:group>
</xf:group>
</xf:group>
</xbl:template>
</xbl:binding>
</xbl:xbl>