This is an automated email from the ASF dual-hosted git repository.
benw pushed a commit to branch javax
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
The following commit(s) were added to refs/heads/javax by this push:
new ae8ff3eef TAP5-2790: Fixing grouped SelectModel for Palette
ae8ff3eef is described below
commit ae8ff3eef5af2a6b02c6c4adbe0c741cb12c65cc
Author: Ben Weidig <[email protected]>
AuthorDate: Fri Nov 15 11:21:37 2024 +0100
TAP5-2790: Fixing grouped SelectModel for Palette
---
.../META-INF/modules/t5/core/palette.coffee | 13 ++-
.../internal/util/SelectModelRenderer.java | 51 +++++++---
tapestry-core/src/test/app1/PaletteGroupedDemo.tml | 42 ++++++++
.../tapestry5/integration/app1/PaletteTests.java | 37 +++++++
.../tapestry5/integration/app1/pages/Index.java | 1 +
.../integration/app1/pages/PaletteDemo.java | 38 +++++++-
.../integration/app1/pages/PaletteGroupedDemo.java | 107 +++++++++++++++++++++
.../corelib/components/option_group_attributes.txt | 2 +-
.../tapestry5/corelib/components/option_groups.txt | 2 +-
.../option_groups_precede_ungroup_options.txt | 2 +-
10 files changed, 274 insertions(+), 21 deletions(-)
diff --git
a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee
b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee
index 0ec5dea36..52fa98404 100644
---
a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee
+++
b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee
@@ -1,4 +1,4 @@
-# Copyright 2012-2013 The Apache Software Foundation
+# Copyright 2012-2024 The Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -235,7 +235,8 @@ define ["t5/core/dom", "underscore", "t5/core/events"],
for o in movers
@insertOption toOptions, o, atEnd
- selectedOptions = if to is @selected then toOptions else fromOptions
+ isSelectedSelect = to is @selected
+ selectedOptions = if isSelectedSelect then toOptions else fromOptions
@performUpdate false, selectedOptions, =>
for i in [(from.element.length - 1)..0] by -1
@@ -249,7 +250,13 @@ define ["t5/core/dom", "underscore", "t5/core/events"],
to.element.remove i
for o in toOptions
- to.element.add o, null
+ groupIdx = o.getAttribute('data-optgroup-idx')
+ if isSelectedSelect or !groupIdx or groupIdx == ''
+ to.element.add o, null
+ else
+ group = to.element.children[parseInt(groupIdx)]
+ group.appendChild o
+
insertOption: (options, option, atEnd) ->
diff --git
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/util/SelectModelRenderer.java
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/util/SelectModelRenderer.java
index 140ac3a7d..484cd229e 100644
---
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/util/SelectModelRenderer.java
+++
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/util/SelectModelRenderer.java
@@ -1,3 +1,5 @@
+// Copyright 2008-2024 The Apache Software Foundation
+//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -24,6 +26,9 @@ public class SelectModelRenderer implements SelectModelVisitor
private final boolean raw;
+ private int optgroupIdx = -1;
+ private boolean inOptgroup = false;
+
public SelectModelRenderer(final MarkupWriter writer, ValueEncoder
encoder, boolean raw)
{
this.writer = writer;
@@ -31,56 +36,78 @@ public class SelectModelRenderer implements
SelectModelVisitor
this.raw = raw;
}
+ @Override
public void beginOptionGroup(OptionGroupModel groupModel)
{
- writer.element("optgroup", "label", groupModel.getLabel());
+ this.optgroupIdx++;
+ this.inOptgroup = true;
+ this.writer.element("optgroup", "label", groupModel.getLabel());
writeDisabled(groupModel.isDisabled());
writeAttributes(groupModel.getAttributes());
}
+ @Override
public void endOptionGroup(OptionGroupModel groupModel)
{
- writer.end(); // select
+ this.inOptgroup = false;
+ this.writer.end(); // select
}
+ @Override
@SuppressWarnings("unchecked")
public void option(OptionModel optionModel)
{
Object optionValue = optionModel.getValue();
- String clientValue = encoder.toClient(optionValue);
+ String clientValue = this.encoder.toClient(optionValue);
- writer.element("option", "value", clientValue);
+ this.writer.element("option", "value", clientValue);
- if (isOptionSelected(optionModel, clientValue))
writer.attributes("selected", "selected");
+ if (this.inOptgroup && this.optgroupIdx > -1)
+ {
+ this.writer.attributes("data-optgroup-idx", this.optgroupIdx);
+ }
+
+ if (isOptionSelected(optionModel, clientValue))
+ {
+ this.writer.attributes("selected", "selected");
+ }
writeDisabled(optionModel.isDisabled());
writeAttributes(optionModel.getAttributes());
- if (raw)
+ if (this.raw)
{
- writer.writeRaw(optionModel.getLabel());
+ this.writer.writeRaw(optionModel.getLabel());
} else
{
- writer.write(optionModel.getLabel());
+ this.writer.write(optionModel.getLabel());
}
- writer.end();
+ this.writer.end();
}
private void writeDisabled(boolean disabled)
{
- if (disabled) writer.attributes("disabled", "disabled");
+ if (disabled)
+ {
+ this.writer.attributes("disabled", "disabled");
+ }
}
private void writeAttributes(Map<String, String> attributes)
{
- if (attributes == null) return;
+ if (attributes == null)
+ {
+ return;
+ }
for (Map.Entry<String, String> e : attributes.entrySet())
- writer.attributes(e.getKey(), e.getValue());
+ {
+ this.writer.attributes(e.getKey(), e.getValue());
+ }
}
/**
diff --git a/tapestry-core/src/test/app1/PaletteGroupedDemo.tml
b/tapestry-core/src/test/app1/PaletteGroupedDemo.tml
new file mode 100644
index 000000000..de0159264
--- /dev/null
+++ b/tapestry-core/src/test/app1/PaletteGroupedDemo.tml
@@ -0,0 +1,42 @@
+<html t:type="Border"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+
+<h1>Palette Grouped Demo</h1>
+
+
+<t:form t:id="demo" class="form-horizontal">
+ <div class="checkbox">
+ <label>
+ <t:checkbox t:id="reorder"/>
+ Enable Reorder
+ </label>
+ </div>
+
+
+ <div class="form-group">
+
+ <t:label for="languages"/>
+
+ <t:palette t:id="languages" model="languageModel" reorder="reorder"
encoder="languageEncoder"
+ availableLabel="Languages Offered" validate="required">
+ <t:parameter name="selectedLabel" xml:space="default">
+ <t:if test="reorder" else="Selected">Ranked
+ </t:if>
+ Languages
+ </t:parameter>
+ </t:palette>
+ </div>
+
+ <input type="submit" class="btn btn-primary"/>
+
+</t:form>
+
+<dl class="dl-horizontal">
+ <dt>Languages:</dt>
+ <dd id="selected-languages">${languages}</dd>
+ <dt>Selected Values</dt>
+ <dd id="event-selection"/>
+ <dt>Reorder</dt>
+ <dd id="event-reorder"></dd>
+</dl>
+
+</html>
diff --git
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/PaletteTests.java
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/PaletteTests.java
index 23553e149..a725580d9 100644
---
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/PaletteTests.java
+++
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/PaletteTests.java
@@ -14,9 +14,12 @@
package org.apache.tapestry5.integration.app1;
+import java.util.List;
+
import org.apache.tapestry5.corelib.components.Palette;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
+import org.testng.Assert;
import org.testng.annotations.Test;
/**
@@ -131,4 +134,38 @@ public class PaletteTests extends App1TestCase
assertTextPresent("You must provide a value for Languages.");
}
+
+ @Test
+ public void palette_component_grouped()
+ {
+ openLinks("Palette Grouped Demo", "Reset Page State");
+
+ assertText("css=.palette-available .palette-title", "Languages
Offered");
+ assertText("css=.palette-selected .palette-title", "Selected
Languages");
+
+ addSelection(AVAILABLE_OPTIONS, "label=HASKELL");
+ addSelection(AVAILABLE_OPTIONS, "label=JAVA");
+ click(SELECT_BUTTON);
+
+ // What a listener on the events.palette.willChange event would see in
memo.selectdValues:
+ assertText("id=event-selection", "[\"HASKELL\",\"JAVA\"]");
+
+ clickAndWait(SUBMIT);
+
+ assertText("id=selected-languages", "[HASKELL, JAVA]");
+
+ addSelection(SELECTED_OPTIONS, "label=JAVA");
+
+ click(DESELECT_BUTTON);
+
+ List<WebElement> funcOptions = this.webDriver
+ .findElements(convertLocator(AVAILABLE_OPTIONS + "
optgroup[label=func] option"));
+
+ List<WebElement> ooOptions = this.webDriver
+ .findElements(convertLocator(AVAILABLE_OPTIONS + "
optgroup[label=oo] option"));
+
+ Assert.assertEquals(funcOptions.size(), 2);
+ Assert.assertEquals(ooOptions.size(), 2);
+
+ }
}
diff --git
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
index 22210bf9f..025b7eb07 100644
---
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
+++
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
@@ -396,6 +396,7 @@ public class Index
"use expansions inside attributes of ordinary
elements"),
new Item("PaletteDemo", "Palette Demo", "multiple
selection component"),
+ new Item("PaletteGroupedDemo", "Palette Grouped Demo",
"multiple selection component (grouped)"),
new Item("ReturnTypes", "Return Types", "tests various
event handler return types"),
diff --git
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
index d626c4c9a..3694f8ccc 100644
---
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
+++
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
@@ -14,7 +14,13 @@
package org.apache.tapestry5.integration.app1.pages;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.OptionGroupModel;
+import org.apache.tapestry5.OptionModel;
import org.apache.tapestry5.SelectModel;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.Import;
@@ -22,13 +28,13 @@ import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.commons.services.TypeCoercer;
import org.apache.tapestry5.integration.app1.data.ProgrammingLanguage;
+import org.apache.tapestry5.internal.OptionGroupModelImpl;
+import org.apache.tapestry5.internal.OptionModelImpl;
import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.util.AbstractSelectModel;
import org.apache.tapestry5.util.EnumSelectModel;
import org.apache.tapestry5.util.EnumValueEncoder;
-import java.util.ArrayList;
-import java.util.List;
-
@Import(module="palette-demo")
public class PaletteDemo
{
@@ -65,4 +71,30 @@ public class PaletteDemo
{
return new EnumValueEncoder(typeCoercer, ProgrammingLanguage.class);
}
+
+ public SelectModel getGroupedModel()
+ {
+ return new AbstractSelectModel()
+ {
+
+ @Override
+ public List<OptionGroupModel> getOptionGroups()
+ {
+ List<OptionGroupModel> groups = new ArrayList<>();
+ groups.add(new OptionGroupModelImpl("group1", false,
+ Arrays.asList(new OptionModelImpl("1"))));
+ groups.add(new OptionGroupModelImpl("group2", false,
+ Arrays.asList(new OptionModelImpl("1"))));
+ return null;
+ }
+
+ @Override
+ public List<OptionModel> getOptions()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ };
+ }
}
diff --git
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteGroupedDemo.java
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteGroupedDemo.java
new file mode 100644
index 000000000..0fe130ba7
--- /dev/null
+++
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteGroupedDemo.java
@@ -0,0 +1,107 @@
+// Copyright 2007-2014 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.integration.app1.pages;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.OptionGroupModel;
+import org.apache.tapestry5.OptionModel;
+import org.apache.tapestry5.SelectModel;
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.annotations.Import;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.commons.services.TypeCoercer;
+import org.apache.tapestry5.integration.app1.data.ProgrammingLanguage;
+import org.apache.tapestry5.internal.OptionGroupModelImpl;
+import org.apache.tapestry5.internal.OptionModelImpl;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.util.AbstractSelectModel;
+import org.apache.tapestry5.util.EnumValueEncoder;
+
+@Import(module="palette-demo")
+public class PaletteGroupedDemo
+{
+ @Inject
+ private ComponentResources resources;
+
+ @Persist
+ @Property
+ private List<ProgrammingLanguage> languages;
+
+ @Persist
+ @Property
+ private boolean reorder;
+
+ @Inject
+ private TypeCoercer typeCoercer;
+
+ private static final Iterable<ProgrammingLanguage> FUNC = Arrays.asList(
+ ProgrammingLanguage.ERLANG, ProgrammingLanguage.HASKELL,
ProgrammingLanguage.LISP);
+ private static final Iterable<ProgrammingLanguage> OO =
Arrays.asList(ProgrammingLanguage.JAVA,
+ ProgrammingLanguage.RUBY);
+
+ void onPrepareFromDemo()
+ {
+ if (this.languages == null)
+ {
+ this.languages = new ArrayList<>();
+ }
+ }
+
+ public SelectModel getLanguageModel()
+ {
+ return new AbstractSelectModel()
+ {
+
+ @Override
+ public List<OptionGroupModel> getOptionGroups()
+ {
+ List<OptionGroupModel> groups = new ArrayList<>();
+ groups.add(new OptionGroupModelImpl("func", false,
+ toOptionModels(FUNC)));
+ groups.add(new OptionGroupModelImpl("oo", false,
toOptionModels(OO)));
+ return groups;
+ }
+
+ @Override
+ public List<OptionModel> getOptions()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ };
+ }
+
+ private List<OptionModel> toOptionModels(Iterable<ProgrammingLanguage>
languages)
+ {
+ List<OptionModel> options = new ArrayList<>();
+ for (ProgrammingLanguage enumValue : languages)
+ {
+ options.add(new OptionModelImpl(enumValue.name(), enumValue));
+ }
+ return options;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ValueEncoder getLanguageEncoder()
+ {
+ return new EnumValueEncoder(this.typeCoercer,
ProgrammingLanguage.class);
+ }
+}
diff --git
a/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_group_attributes.txt
b/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_group_attributes.txt
index f0cff6bf5..683d4cf71 100644
---
a/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_group_attributes.txt
+++
b/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_group_attributes.txt
@@ -1,2 +1,2 @@
<?xml version="1.0"?>
-<select><optgroup class="pixie" label="Husbands"><option selected="selected"
value="Fred">Fred</option><option
value="Barney">Barney</option></optgroup></select>
\ No newline at end of file
+<select><optgroup class="pixie" label="Husbands"><option selected="selected"
data-optgroup-idx="0" value="Fred">Fred</option><option data-optgroup-idx="0"
value="Barney">Barney</option></optgroup></select>
\ No newline at end of file
diff --git
a/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_groups.txt
b/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_groups.txt
index 3035c4af9..c1d4fd14b 100644
---
a/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_groups.txt
+++
b/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_groups.txt
@@ -1,2 +1,2 @@
<?xml version="1.0"?>
-<select><optgroup label="Husbands"><option selected="selected"
value="Fred">Fred</option><option
value="Barney">Barney</option></optgroup><optgroup disabled="disabled"
label="Wives"><option value="Wilma">Wilma</option><option
value="Betty">Betty</option></optgroup></select>
\ No newline at end of file
+<select><optgroup label="Husbands"><option selected="selected"
data-optgroup-idx="0" value="Fred">Fred</option><option data-optgroup-idx="0"
value="Barney">Barney</option></optgroup><optgroup disabled="disabled"
label="Wives"><option data-optgroup-idx="1" value="Wilma">Wilma</option><option
data-optgroup-idx="1" value="Betty">Betty</option></optgroup></select>
\ No newline at end of file
diff --git
a/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_groups_precede_ungroup_options.txt
b/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_groups_precede_ungroup_options.txt
index 7d49d8e8f..da0aebcb0 100644
---
a/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_groups_precede_ungroup_options.txt
+++
b/tapestry-core/src/test/resources/org/apache/tapestry5/corelib/components/option_groups_precede_ungroup_options.txt
@@ -1,2 +1,2 @@
<?xml version="1.0"?>
-<select><optgroup label="Husbands"><option selected="selected"
value="Fred">Fred</option><option
value="Barney">Barney</option></optgroup><option
value="Wilma">Wilma</option><option value="Betty">Betty</option></select>
\ No newline at end of file
+<select><optgroup label="Husbands"><option selected="selected"
data-optgroup-idx="0" value="Fred">Fred</option><option data-optgroup-idx="0"
value="Barney">Barney</option></optgroup><option
value="Wilma">Wilma</option><option value="Betty">Betty</option></select>
\ No newline at end of file