From a95f9e4ccc8d9439a1b86eebf8fb81490a89e481 Mon Sep 17 00:00:00 2001 From: "David H. DeWolf" Date: Thu, 11 Jan 2007 19:20:51 +0000 Subject: [PATCH] First draft of an inputtransfer select component; Allows text --> select; Similar to OptionTransferSelect git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@495339 13f79535-47bb-0310-9956-ffa450edef68 --- .../struts2/showcase/MoreSelectsAction.java | 115 +++++ .../src/main/resources/struts-tags-ui.xml | 11 +- .../src/main/webapp/tags/ui/index.jsp | 1 + .../tags/ui/lotsOfOptiontransferselect.jsp | 42 +- .../ui/lotsOfOptiontransferselectSubmit.jsp | 33 -- .../src/main/webapp/tags/ui/moreSelects.jsp | 61 +++ .../main/webapp/tags/ui/moreSelectsSubmit.jsp | 53 +++ .../components/InputTransferSelect.java | 319 +++++++++++++ .../tags/InputTransferSelectModel.java | 24 + .../views/freemarker/tags/StrutsModels.java | 11 + .../views/jsp/ui/InputTransferSelectTag.java | 185 ++++++++ .../InputTransferSelectDirective.java | 23 + .../main/resources/META-INF/struts-tags.tld | 316 ++++++++++++- .../struts2/static/inputtransferselect.js | 108 +++++ .../resources/template/ajax/form-close.ftl | 16 + .../css_xhtml/inputtransferselect.ftl | 4 + .../resources/template/simple/form-close.ftl | 16 + .../template/simple/inputtransferselect.ftl | 103 ++++ .../template/xhtml/inputtransferselect.ftl | 3 + .../src/site/resources/tags/doubleselect.html | 2 +- .../resources/tags/inputtransferselect.html | 442 ++++++++++++++++++ .../resources/tags/optiontransferselect.html | 2 +- .../jsp/ui/InputTransferSelectTagTest.java | 34 ++ .../views/jsp/ui/inputtransferselect-1.txt | 23 + 24 files changed, 1868 insertions(+), 79 deletions(-) create mode 100644 apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java create mode 100644 apps/showcase/src/main/webapp/tags/ui/moreSelects.jsp create mode 100644 apps/showcase/src/main/webapp/tags/ui/moreSelectsSubmit.jsp create mode 100644 core/src/main/java/org/apache/struts2/components/InputTransferSelect.java create mode 100644 core/src/main/java/org/apache/struts2/views/freemarker/tags/InputTransferSelectModel.java create mode 100644 core/src/main/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTag.java create mode 100644 core/src/main/java/org/apache/struts2/views/velocity/components/InputTransferSelectDirective.java create mode 100644 core/src/main/resources/org/apache/struts2/static/inputtransferselect.js create mode 100644 core/src/main/resources/template/css_xhtml/inputtransferselect.ftl create mode 100644 core/src/main/resources/template/simple/inputtransferselect.ftl create mode 100644 core/src/main/resources/template/xhtml/inputtransferselect.ftl create mode 100644 core/src/site/resources/tags/inputtransferselect.html create mode 100644 core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java create mode 100644 core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java new file mode 100644 index 000000000..505c8bb12 --- /dev/null +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java @@ -0,0 +1,115 @@ +package org.apache.struts2.showcase; + +import com.opensymphony.xwork2.ActionSupport; + +import java.util.List; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.ArrayList; + +/** + */ +public class MoreSelectsAction extends ActionSupport { + + + private List _prioritisedFavouriteCartoonCharacters; + private List _prioritisedFavouriteCars; + private List _prioritisedFavouriteCountries; + private List favouriteNumbers; + + + // Cartoon Characters + public Map getDefaultFavouriteCartoonCharacters() { + Map m = new LinkedHashMap(); + m.put("heMan", "He-Man"); + m.put("popeye", "Popeye"); + m.put("mockeyMouse", "Mickey Mouse"); + return m; + } + + + // Cars + public Map getDefaultFavouriteCars() { + Map m = new LinkedHashMap(); + m.put("alfaRomeo", "Alfa Romeo"); + m.put("Toyota", "Toyota"); + m.put("Mitsubitshi", "Mitsubitshi"); + return m; + } + + + + // Countries + public Map getDefaultFavouriteCountries() { + Map m = new LinkedHashMap(); + m.put("england", "England"); + m.put("america", "America"); + m.put("brazil", "Brazil"); + return m; + } + + public List getDefaultFavouriteNumbers() { + List list = new ArrayList(); + list.add("Three"); + list.add("Seven"); + return list; + } + + + + public List getPrioritisedFavouriteCartoonCharacters() { + return _prioritisedFavouriteCartoonCharacters; + } + public void setPrioritisedFavouriteCartoonCharacters(List prioritisedFavouriteCartoonCharacters) { + _prioritisedFavouriteCartoonCharacters = prioritisedFavouriteCartoonCharacters; + } + + public List getPrioritisedFavouriteCars() { + return _prioritisedFavouriteCars; + } + public void setPrioritisedFavouriteCars(List prioritisedFavouriteCars) { + _prioritisedFavouriteCars = prioritisedFavouriteCars; + } + + + public List getPrioritisedFavouriteCountries() { + return _prioritisedFavouriteCountries; + } + public void setPrioritisedFavouriteCountries(List prioritisedFavouriteCountries) { + _prioritisedFavouriteCountries = prioritisedFavouriteCountries; + } + + public List getFavouriteNumbers() { + return favouriteNumbers; + } + + public void setFavouriteNumbers(List favouriteNumbers) { + this.favouriteNumbers = favouriteNumbers; + } + + public Map getAvailableCities() { + Map map = new LinkedHashMap(); + map.put("boston", "Boston"); + map.put("new york", "New York"); + map.put("london", "London"); + map.put("rome", "Rome"); + return map; + } + + public List getDefaultFavouriteCities() { + List list = new ArrayList(); + list.add("boston"); + list.add("rome"); + return list; + } + + // actions + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + return SUCCESS; + } +} diff --git a/apps/showcase/src/main/resources/struts-tags-ui.xml b/apps/showcase/src/main/resources/struts-tags-ui.xml index 527470650..5f9568ee5 100644 --- a/apps/showcase/src/main/resources/struts-tags-ui.xml +++ b/apps/showcase/src/main/resources/struts-tags-ui.xml @@ -22,6 +22,7 @@ exampleSubmited.vm example.vm + lotsOfOptiontransferselect.jsp @@ -29,7 +30,15 @@ lotsOfOptiontransferselect.jsp lotsOfOptiontransferselectSubmit.jsp - + + + moreSelects.jsp + + + moreSelects.jsp + moreSelectsSubmit.jsp + + diff --git a/apps/showcase/src/main/webapp/tags/ui/index.jsp b/apps/showcase/src/main/webapp/tags/ui/index.jsp index 3c4e973f1..11a9fcd4f 100644 --- a/apps/showcase/src/main/webapp/tags/ui/index.jsp +++ b/apps/showcase/src/main/webapp/tags/ui/index.jsp @@ -11,6 +11,7 @@
  • UI Example
  • UI Example (Velocity)
  • Option Transfer Select UI Example
  • +
  • More Select Box UI Examples
  • Tree Example (static)
  • Tree Example (dynamic)
  • Component Tag Example diff --git a/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselect.jsp b/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselect.jsp index 4865854fe..d267ce583 100644 --- a/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselect.jsp +++ b/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselect.jsp @@ -85,48 +85,8 @@ allowSelectAll="false" />
    - - - -
    - - - -
    - - - -
    - - - + - -
    - diff --git a/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselectSubmit.jsp b/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselectSubmit.jsp index fb577566d..04d915b18 100644 --- a/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselectSubmit.jsp +++ b/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselectSubmit.jsp @@ -88,39 +88,6 @@ - - - Prioritised Favourite Cartoon Characters: - - - .  - - - - - Prioritised Favourite Cars: - - - .  - - - - - Prioritised Favourite Countries - - - .  - - - - - Favourite Cities - - - .  - - - diff --git a/apps/showcase/src/main/webapp/tags/ui/moreSelects.jsp b/apps/showcase/src/main/webapp/tags/ui/moreSelects.jsp new file mode 100644 index 000000000..6b00b3466 --- /dev/null +++ b/apps/showcase/src/main/webapp/tags/ui/moreSelects.jsp @@ -0,0 +1,61 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Show Case - Tags - UI Tags - Optiontransferselect + + + + + + + + +
    + + + +
    + + + +
    + + + + + + + +
    + +
    + + + \ No newline at end of file diff --git a/apps/showcase/src/main/webapp/tags/ui/moreSelectsSubmit.jsp b/apps/showcase/src/main/webapp/tags/ui/moreSelectsSubmit.jsp new file mode 100644 index 000000000..7b79c86c3 --- /dev/null +++ b/apps/showcase/src/main/webapp/tags/ui/moreSelectsSubmit.jsp @@ -0,0 +1,53 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - UI Tags - Select Boxes Result + + + + + + + + + + + + + + + + + + + + + + + + +
    Prioritised Favourite Cartoon Characters: + + .  + +
    Prioritised Favourite Cars: + + .  + +
    Prioritised Favourite Countries + + .  + +
    Favourite Cities + + .  + +
    Favourite Numbers + + .  + +
    + + + diff --git a/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java b/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java new file mode 100644 index 000000000..392a756c3 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java @@ -0,0 +1,319 @@ +package org.apache.struts2.components; + +import org.apache.struts.annotations.StrutsTag; +import org.apache.struts.annotations.StrutsTagAttribute; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import com.opensymphony.xwork2.util.ValueStack; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +import java.util.LinkedHashMap; + +/** + * + * + * Create a input transfer select component which is basically an text input + * and <select ...> tag with buttons in the middle of them allowing text + * to be added to the transfer select. Will auto-select all its + * elements upon its containing form submision. + * + * + * + *

    + * + * + * + * + * NOTE: The id and doubleId need not be supplied as they will generated provided + * that the inputtransferselect tag is being used in a form tag. The generated id + * and doubleId will be <form_id>_<inputtransferselect_doubleName> and + * <form_id>_<inputtransferselect_doubleName> respectively. + * + * + * + *

    + * + *

    + * 
    + *
    + * <-- minimum configuration -->
    + * <s:inputtransferselect
    + *      label="Favourite Cartoons Characters"
    + *      name="cartoons"
    + *      list="{'Popeye', 'He-Man', 'Spiderman'}"
    + *  />
    + *
    + * 
    + * 
    + * + */ +@StrutsTag(name="inputtransferselect", tldTagClass="org.apache.struts2.views.jsp.ui.InputTransferSelectTag", description="Renders an input form") +public class InputTransferSelect extends ListUIBean { + + private static final Log _log = LogFactory.getLog(InputTransferSelect.class); + + private static final String TEMPLATE = "inputtransferselect"; + + protected String size; + protected String multiple; + + protected String allowRemoveAll; + protected String allowUpDown; + + protected String leftTitle; + protected String rightTitle; + + protected String buttonCssClass; + protected String buttonCssStyle; + + protected String addLabel; + protected String removeLabel; + protected String removeAllLabel; + protected String upLabel; + protected String downLabel; + + protected String headerKey; + protected String headerValue; + + + public InputTransferSelect(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (size == null || size.trim().length() <= 0) { + addParameter("size", "5"); + } + + if (multiple == null || multiple.trim().length() <= 0) { + addParameter("multiple", Boolean.TRUE); + } + + // allowUpDown + addParameter("allowUpDown", allowUpDown != null ? findValue(allowUpDown, Boolean.class) : Boolean.TRUE); + + // allowRemoveAll + addParameter("allowRemoveAll", allowRemoveAll != null ? findValue(allowRemoveAll, Boolean.class) : Boolean.TRUE); + + + // leftTitle + if (leftTitle != null) { + addParameter("leftTitle", findValue(leftTitle, String.class)); + } + + // rightTitle + if (rightTitle != null) { + addParameter("rightTitle", findValue(rightTitle, String.class)); + } + + + // buttonCssClass + if (buttonCssClass != null && buttonCssClass.trim().length() > 0) { + addParameter("buttonCssClass", buttonCssClass); + } + + // buttonCssStyle + if (buttonCssStyle != null && buttonCssStyle.trim().length() > 0) { + addParameter("buttonCssStyle", buttonCssStyle); + } + + // addLabel + addParameter("addLabel", addLabel != null ? findValue(addLabel, String.class) : "->" ); + + // removeLabel + addParameter("removeLabel", removeLabel != null ? findValue(removeLabel, String.class) : "<-"); + + // removeAllLabel + addParameter("removeAllLabel", removeAllLabel != null ? findValue(removeAllLabel, String.class) : "<<--"); + + + // upLabel + addParameter("upLabel", upLabel != null ? findValue(upLabel, String.class) : "^"); + + + // leftDownLabel + addParameter("downLabel", downLabel != null ? findValue(downLabel, String.class) : "v"); + + if ((headerKey != null) && (headerValue != null)) { + addParameter("headerKey", findString(headerKey)); + addParameter("headerValue", findString(headerValue)); + } + + + + // inform the form component our select tag infos, so they know how to select + // its elements upon onsubmit + Form formAncestor = (Form) findAncestor(Form.class); + if (formAncestor != null) { + + // inform ancestor form that we are having a customOnsubmit (see form-close.ftl [simple theme]) + enableAncestorFormCustomOnsubmit(); + + + // key -> select tag id, value -> headerKey (if exists) + Map formInputtransferselectIds = (Map) formAncestor.getParameters().get("inputtransferselectIds"); + + // init lists + if (formInputtransferselectIds == null) { + formInputtransferselectIds = new LinkedHashMap(); + } + + // id + String tmpId = (String) getParameters().get("id"); + String tmpHeaderKey = (String) getParameters().get("headerKey"); + if (tmpId != null && (! formInputtransferselectIds.containsKey(tmpId))) { + formInputtransferselectIds.put(tmpId, tmpHeaderKey); + } + + formAncestor.getParameters().put("inputtransferselectIds", formInputtransferselectIds); + + } + else { + _log.warn("form enclosing inputtransferselect "+this+" not found, auto select upon form submit of inputtransferselect will not work"); + } + } + + public String getSize() { + return size; + } + + @StrutsTagAttribute(description="the size of the select box") + public void setSize(String size) { + this.size = size; + } + + public String getMultiple() { + return multiple; + } + + @StrutsTagAttribute(description="Determine whether or not multiple entries are shown") + public void setMultiple(String multiple) { + this.multiple = multiple; + } + + public String getAllowRemoveAll() { + return allowRemoveAll; + } + + @StrutsTagAttribute(description="Determine whether the remove all button will display") + public void setAllowRemoveAll(String allowRemoveAll) { + this.allowRemoveAll = allowRemoveAll; + } + + public String getAllowUpDown() { + return allowUpDown; + } + + @StrutsTagAttribute(description="Determine whether items in the list can be reordered") + public void setAllowUpDown(String allowUpDown) { + this.allowUpDown = allowUpDown; + } + + public String getLeftTitle() { + return leftTitle; + } + + @StrutsTagAttribute(description="the left hand title") + public void setLeftTitle(String leftTitle) { + this.leftTitle = leftTitle; + } + + public String getRightTitle() { + return rightTitle; + } + + @StrutsTagAttribute(description="the right hand title") + public void setRightTitle(String rightTitle) { + this.rightTitle = rightTitle; + } + + public String getButtonCssClass() { + return buttonCssClass; + } + + @StrutsTagAttribute(description="the css class used for rendering buttons") + public void setButtonCssClass(String buttonCssClass) { + this.buttonCssClass = buttonCssClass; + } + + public String getButtonCssStyle() { + return buttonCssStyle; + } + + @StrutsTagAttribute(description="the css style used for rendering buttons") + public void setButtonCssStyle(String buttonCssStyle) { + this.buttonCssStyle = buttonCssStyle; + } + + public String getAddLabel() { + return addLabel; + } + + @StrutsTagAttribute(description="the label used for the add button") + public void setAddLabel(String addLabel) { + this.addLabel = addLabel; + } + + public String getRemoveLabel() { + return removeLabel; + } + + @StrutsTagAttribute(description="the label used for the remove button") + public void setRemoveLabel(String removeLabel) { + this.removeLabel = removeLabel; + } + + public String getRemoveAllLabel() { + return removeAllLabel; + } + + @StrutsTagAttribute(description="the label used for the remove all button") + public void setRemoveAllLabel(String removeAllLabel) { + this.removeAllLabel = removeAllLabel; + } + + public String getUpLabel() { + return upLabel; + } + + @StrutsTagAttribute(description="the label used for the up button") + public void setUpLabel(String upLabel) { + this.upLabel = upLabel; + } + + public String getDownLabel() { + return downLabel; + } + + @StrutsTagAttribute(description="the label used for the down button") + public void setDownLabel(String downLabel) { + this.downLabel = downLabel; + } + + public String getHeaderKey() { + return headerKey; + } + + @StrutsTagAttribute(description="the header key of the select box") + public void setHeaderKey(String headerKey) { + this.headerKey = headerKey; + } + + public String getHeaderValue() { + return headerValue; + } + + @StrutsTagAttribute(description="the header value of the select box") + public void setHeaderValue(String headerValue) { + this.headerValue = headerValue; + } +} diff --git a/core/src/main/java/org/apache/struts2/views/freemarker/tags/InputTransferSelectModel.java b/core/src/main/java/org/apache/struts2/views/freemarker/tags/InputTransferSelectModel.java new file mode 100644 index 000000000..fb73c9e82 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/views/freemarker/tags/InputTransferSelectModel.java @@ -0,0 +1,24 @@ +package org.apache.struts2.views.freemarker.tags; + +import com.opensymphony.xwork2.util.ValueStack; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.components.Component; +import org.apache.struts2.components.InputTransferSelect; + +/** + * @see org.apache.struts2.components.InputTransferSelect + */ +public class InputTransferSelectModel extends TagModel { + + public InputTransferSelectModel(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { + super(stack, req, res); + } + + protected Component getBean() { + return new InputTransferSelect(stack, req, res); + } + +} diff --git a/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java b/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java index 7a11568ee..a351ac1b9 100644 --- a/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java +++ b/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java @@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.components.InputTransferSelect; /** * Provides @s.tag access for various tags. @@ -81,6 +82,7 @@ public class StrutsModels { protected ElseModel elseModel; protected ElseIfModel elseIfModel; protected AutocompleterModel autocompleterModel; + protected InputTransferSelectModel inputtransferselect; public StrutsModels(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { @@ -463,4 +465,13 @@ public class StrutsModels { } return elseIfModel; } + + + public InputTransferSelectModel getInputtransferselect() { + if (inputtransferselect == null) { + inputtransferselect = new InputTransferSelectModel(stack, req, res); + } + return inputtransferselect; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTag.java new file mode 100644 index 000000000..005a7d750 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTag.java @@ -0,0 +1,185 @@ +package org.apache.struts2.views.jsp.ui; + +import org.apache.struts2.components.Component; +import org.apache.struts2.components.InputTransferSelect; +import com.opensymphony.xwork2.util.ValueStack; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * InputTransferSelect jsp tag. + */ +public class InputTransferSelectTag extends AbstractListTag { + + private static final long serialVersionUID = 250474334495763536L; + + protected String size; + protected String multiple; + + protected String allowRemoveAll; + protected String allowUpDown; + + protected String leftTitle; + protected String rightTitle; + + protected String buttonCssClass; + protected String buttonCssStyle; + + protected String addLabel; + protected String removeLabel; + protected String removeAllLabel; + protected String upLabel; + protected String downLabel; + + protected String headerKey; + protected String headerValue; + + public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { + return new InputTransferSelect(stack, req, res); + } + + protected void populateParams() { + super.populateParams(); + + InputTransferSelect inputTransferSelect = (InputTransferSelect) component; + inputTransferSelect.setSize(size); + inputTransferSelect.setMultiple(multiple); + inputTransferSelect.setAllowRemoveAll(allowRemoveAll); + inputTransferSelect.setAllowUpDown(allowUpDown); + inputTransferSelect.setLeftTitle(leftTitle); + inputTransferSelect.setRightTitle(rightTitle); + + inputTransferSelect.setButtonCssClass(buttonCssClass); + inputTransferSelect.setButtonCssStyle(buttonCssStyle); + + inputTransferSelect.setAddLabel(addLabel); + inputTransferSelect.setRemoveLabel(removeLabel); + inputTransferSelect.setRemoveAllLabel(removeAllLabel); + inputTransferSelect.setUpLabel(upLabel); + inputTransferSelect.setDownLabel(downLabel); + inputTransferSelect.setHeaderKey(headerKey); + inputTransferSelect.setHeaderValue(headerValue); + } + + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + public String getMultiple() { + return multiple; + } + + public void setMultiple(String multiple) { + this.multiple = multiple; + } + + public String getAllowRemoveAll() { + return allowRemoveAll; + } + + public void setAllowRemoveAll(String allowRemoveAll) { + this.allowRemoveAll = allowRemoveAll; + } + + public String getAllowUpDown() { + return allowUpDown; + } + + public void setAllowUpDown(String allowUpDown) { + this.allowUpDown = allowUpDown; + } + + public String getLeftTitle() { + return leftTitle; + } + + public void setLeftTitle(String leftTitle) { + this.leftTitle = leftTitle; + } + + public String getRightTitle() { + return rightTitle; + } + + public void setRightTitle(String rightTitle) { + this.rightTitle = rightTitle; + } + + public String getButtonCssClass() { + return buttonCssClass; + } + + public void setButtonCssClass(String buttonCssClass) { + this.buttonCssClass = buttonCssClass; + } + + public String getButtonCssStyle() { + return buttonCssStyle; + } + + public void setButtonCssStyle(String buttonCssStyle) { + this.buttonCssStyle = buttonCssStyle; + } + + public String getAddLabel() { + return addLabel; + } + + public void setAddLabel(String addLabel) { + this.addLabel = addLabel; + } + + public String getRemoveLabel() { + return removeLabel; + } + + public void setRemoveLabel(String removeLabel) { + this.removeLabel = removeLabel; + } + + public String getRemoveAllLabel() { + return removeAllLabel; + } + + public void setRemoveAllLabel(String removeAllLabel) { + this.removeAllLabel = removeAllLabel; + } + + public String getUpLabel() { + return upLabel; + } + + public void setUpLabel(String upLabel) { + this.upLabel = upLabel; + } + + public String getDownLabel() { + return downLabel; + } + + public void setDownLabel(String downLabel) { + this.downLabel = downLabel; + } + + public String getHeaderKey() { + return headerKey; + } + + public void setHeaderKey(String headerKey) { + this.headerKey = headerKey; + } + + public String getHeaderValue() { + return headerValue; + } + + public void setHeaderValue(String headerValue) { + this.headerValue = headerValue; + } +} diff --git a/core/src/main/java/org/apache/struts2/views/velocity/components/InputTransferSelectDirective.java b/core/src/main/java/org/apache/struts2/views/velocity/components/InputTransferSelectDirective.java new file mode 100644 index 000000000..3eab677b0 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/views/velocity/components/InputTransferSelectDirective.java @@ -0,0 +1,23 @@ +package org.apache.struts2.views.velocity.components; + +import org.apache.struts2.components.Component; +import org.apache.struts2.components.InputTransferSelect; +import com.opensymphony.xwork2.util.ValueStack; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @see org.apache.struts2.components.InputTransferSelect + */ +public class InputTransferSelectDirective extends AbstractDirective { + + public String getBeanName() { + return "inputtransferselect"; + } + + protected Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { + return new InputTransferSelect(stack, req, res); + } + +} diff --git a/core/src/main/resources/META-INF/struts-tags.tld b/core/src/main/resources/META-INF/struts-tags.tld index c87d219c4..a3046b735 100644 --- a/core/src/main/resources/META-INF/struts-tags.tld +++ b/core/src/main/resources/META-INF/struts-tags.tld @@ -2762,7 +2762,7 @@ doubleListKey false true - + doubleListValue @@ -4505,6 +4505,318 @@ + + inputtransferselect + org.apache.struts2.views.jsp.ui.InputTransferSelectTag + JSP + + + accesskey + false + true + + + + addLabel + false + true + + + + allowRemoveAll + false + true + + + + allowUpDown + false + true + + + + buttonCssClass + false + true + + + + buttonCssStyle + false + true + + + + cssClass + false + true + + + + cssStyle + false + true + + + + disabled + false + true + + + + downLabel + false + true + + + + headerKey + false + true + + + + headerValue + false + true + + + + id + false + true + + + + key + false + true + + + + label + false + true + + + + labelposition + false + true + + + + leftTitle + false + true + + + + list + true + true + + + + listKey + false + true + + + + listValue + false + true + + + + multiple + false + true + + + + name + false + true + + + + onblur + false + true + + + + onchange + false + true + + + + onclick + false + true + + + + ondblclick + false + true + + + + onfocus + false + true + + + + onkeydown + false + true + + + + onkeypress + false + true + + + + onkeyup + false + true + + + + onmousedown + false + true + + + + onmousemove + false + true + + + + onmouseout + false + true + + + + onmouseover + false + true + + + + onmouseup + false + true + + + + onselect + false + true + + + + removeAllLabel + false + true + + + + removeLabel + false + true + + + + required + false + true + + + + requiredposition + false + true + + + + rightTitle + false + true + + + + size + false + true + + + + tabindex + false + true + + + + template + false + true + + + + templateDir + false + true + + + + theme + false + true + + + + title + false + true + + + + tooltip + false + true + + + + tooltipConfig + false + true + + + + upLabel + false + true + + + + value + false + true + + + iterator org.apache.struts2.views.jsp.IteratorTag @@ -4958,7 +5270,7 @@ doubleListKey false true - + doubleListValue diff --git a/core/src/main/resources/org/apache/struts2/static/inputtransferselect.js b/core/src/main/resources/org/apache/struts2/static/inputtransferselect.js new file mode 100644 index 000000000..df4589538 --- /dev/null +++ b/core/src/main/resources/org/apache/struts2/static/inputtransferselect.js @@ -0,0 +1,108 @@ +function addOption(objTextBox, objTargetElement) { + var value = objTextBox.value; + if(value != null && value != '') { + objTargetElement.options[objTargetElement.options.length] = new Option(value, value); + objTextBox.value = ''; + } +} + +function removeOptions(objTargetElement) { + for(var i=0;i= 0; i--) { + if (objTargetElement[i].selected) { + var v; + if ((i != (objTargetElement.length-1)) && !objTargetElement[i+1].selected) { + if (type == 'key') { + v = objTargetElement[i].value + } + else { + v = objTargetElement[i].text; + } + if (!test(v)) { + swapOptions(objTargetElement,i,i+1); + } + } + } + } +} + +function swapOptions(objTargetElement, first, second) { + var opt = objTargetElement.options; + var temp = new Option(opt[first].text, opt[first].value, opt[first].defaultSelected, opt[first].selected); + var temp2= new Option(opt[second].text, opt[second].value, opt[second].defaultSelected, opt[second].selected); + opt[first] = temp2; + opt[second] = temp; +} diff --git a/core/src/main/resources/template/ajax/form-close.ftl b/core/src/main/resources/template/ajax/form-close.ftl index 99e553dbf..d83c75eaf 100644 --- a/core/src/main/resources/template/ajax/form-close.ftl +++ b/core/src/main/resources/template/ajax/form-close.ftl @@ -22,6 +22,22 @@ dojo.require("dojo.event.connect"); }); +<#if (parameters.inputtransferselectIds?if_exists?size > 0)> + var containingForm = document.getElementById("${parameters.id}"); + <#assign selectObjIds = parameters.inputtransferselectIds.keySet() /> + <#list selectObjIds as selectObjectId> + dojo.event.connect(containingForm, "onsubmit", + function(evt) { + var selectObj = document.getElementById("${selectObjectId}"); + <#if parameters.inputtransferselectIds.get(selectObjectId)?exists> + <#assign selectTagHeaderKey = parameters.inputtransferselectIds.get(selectObjectId)/> + selectAllOptionsExceptSome(selectObj, "key", "${selectTagHeaderKey}"); + <#else> + selectAllOptionsExceptSome(selectObj, "key", ""); + + }); + + <#if (parameters.optiontransferselectDoubleIds?if_exists?size > 0)> var containingForm = document.getElementById("${parameters.id}"); <#assign selectDoubleObjIds = parameters.optiontransferselectDoubleIds.keySet() /> diff --git a/core/src/main/resources/template/css_xhtml/inputtransferselect.ftl b/core/src/main/resources/template/css_xhtml/inputtransferselect.ftl new file mode 100644 index 000000000..53b08e7d4 --- /dev/null +++ b/core/src/main/resources/template/css_xhtml/inputtransferselect.ftl @@ -0,0 +1,4 @@ +<#--include "/${parameters.templateDir}/css_xhtml/controlheader.ftl" /--> +<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" /> +<#include "/${parameters.templateDir}/simple/inputtransferselect.ftl" /> +<#include "/${parameters.templateDir}/css_xhtml/controlfooter.ftl" /> diff --git a/core/src/main/resources/template/simple/form-close.ftl b/core/src/main/resources/template/simple/form-close.ftl index 014bddd9a..593c04b7d 100644 --- a/core/src/main/resources/template/simple/form-close.ftl +++ b/core/src/main/resources/template/simple/form-close.ftl @@ -23,6 +23,22 @@ dojo.require("dojo.event.*"); }); +<#if (parameters.inputtransferselectIds?if_exists?size > 0)> + var containingForm = document.getElementById("${parameters.id}"); + <#assign selectObjIds = parameters.inputtransferselectIds.keySet() /> + <#list selectObjIds as selectObjectId> + dojo.event.connect(containingForm, "onsubmit", + function(evt) { + var selectObj = document.getElementById("${selectObjectId}"); + <#if parameters.inputtransferselectIds.get(selectObjectId)?exists> + <#assign selectTagHeaderKey = parameters.inputtransferselectIds.get(selectObjectId)/> + selectAllOptionsExceptSome(selectObj, "key", "${selectTagHeaderKey}"); + <#else> + selectAllOptionsExceptSome(selectObj, "key", ""); + + }); + + <#if (parameters.optiontransferselectDoubleIds?if_exists?size > 0)> var containingForm = document.getElementById("${parameters.id}"); <#assign selectDoubleObjIds = parameters.optiontransferselectDoubleIds.keySet() /> diff --git a/core/src/main/resources/template/simple/inputtransferselect.ftl b/core/src/main/resources/template/simple/inputtransferselect.ftl new file mode 100644 index 000000000..497b388b5 --- /dev/null +++ b/core/src/main/resources/template/simple/inputtransferselect.ftl @@ -0,0 +1,103 @@ +<#if !stack.findValue("#inputtransferselect_js_included")?exists><#t/> + + <#assign temporaryVariable = stack.setValue("#inputtransferselect_js_included", "true") /><#t/> +<#t/> + + + + + + +
    +<#if parameters.leftTitle?exists><#t/> +
    +<#t/> + + + + name="${parameters.name?default("")?html}_input"<#rt/> +<#if parameters.disabled?default(false)> + disabled="disabled"<#rt/> + +<#if parameters.readonly?default(false)> + readonly="readonly"<#rt/> + +<#if parameters.tabindex?exists> + tabindex="${parameters.tabindex?html}"<#rt/> + +<#if parameters.id?exists> + id="${parameters.id?html}_input"<#rt/> + +<#if parameters.cssClass?exists> + class="${parameters.cssClass?html}"<#rt/> + +<#if parameters.cssStyle?exists> + style="${parameters.cssStyle?html}"<#rt/> + +<#if parameters.title?exists> + title="${parameters.title?html}"<#rt/> + +<#include "/${parameters.templateDir}/simple/scripting-events.ftl" /> +<#include "/${parameters.templateDir}/simple/common-attributes.ftl" /> +/> + + +
    + <#assign addLabel=parameters.addLabel?default("->")?html /><#t/> + <#t/> + class="${parameters.buttonCssClass?html}" + <#t/> + <#if parameters.buttonCssStyle?exists> + style="${parameters.buttonCssStyle?html}" + <#t/> + value="${addLabel}" onclick="addOption(document.getElementById('${parameters.id?html}_input'), document.getElementById('${parameters.id?html}'))" />

    + <#t/> + <#assign removeLabel=parameters.removeLabel?default("<-")?html /><#t/> + <#t/> + class="${parameters.buttonCssClass?html}" + <#t/> + <#if parameters.buttonCssStyle?exists> + style="${parameters.buttonCssStyle?html}" + <#t/> + value="${removeLabel}" onclick="removeOptions(document.getElementById('${parameters.id?html}'))" />

    + <#t/> + <#assign removeAllLabel=parameters.removeAllLabel?default("<<--")?html /><#t/> + <#t/> + class="${parameters.buttonCssClass?html}" + <#t/> + <#if parameters.buttonCssStyle?exists> + style="${parameters.buttonCssStyle?html}" + <#t/> + value="${removeAllLabel}" onclick="removeAllOptions(document.getElementById('${parameters.id?html}'))" />

    +
    +<#if parameters.rightTitle?exists><#t/> +
    +<#t/> +<#include "/${parameters.templateDir}/simple/select.ftl" /> +<#if parameters.allowUpDown?default(true)> + + onclick="moveOptionDown(document.getElementById('${parameters.id}'), 'key', '${parameters.headerKey}');" +<#else> + onclick="moveOptionDown(document.getElementById('${parameters.id}'), 'key', '');" + +<#if parameters.downLabel?exists> + value="${parameters.downLabel?html}" + +/> + + onclick="moveOptionUp(document.getElementById('${parameters.id}'), 'key', '${parameters.headerKey}');" +<#else> + onclick="moveOptionUp(document.getElementById('${parameters.id}'), 'key', '');" + +<#if parameters.upLabel?exists> + value="${parameters.upLabel?html}" + +/> + +
    + diff --git a/core/src/main/resources/template/xhtml/inputtransferselect.ftl b/core/src/main/resources/template/xhtml/inputtransferselect.ftl new file mode 100644 index 000000000..51f1d7224 --- /dev/null +++ b/core/src/main/resources/template/xhtml/inputtransferselect.ftl @@ -0,0 +1,3 @@ +<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" /> +<#include "/${parameters.templateDir}/simple/inputtransferselect.ftl" /> +<#include "/${parameters.templateDir}/xhtml/controlfooter.ftl" /><#nt/> diff --git a/core/src/site/resources/tags/doubleselect.html b/core/src/site/resources/tags/doubleselect.html index 807e6bf59..3c156d9e7 100644 --- a/core/src/site/resources/tags/doubleselect.html +++ b/core/src/site/resources/tags/doubleselect.html @@ -137,7 +137,7 @@ Please do not edit it directly. true String - Set the list key of the second attribute + The key expression to use for second list doubleListValue diff --git a/core/src/site/resources/tags/inputtransferselect.html b/core/src/site/resources/tags/inputtransferselect.html new file mode 100644 index 000000000..3521df28a --- /dev/null +++ b/core/src/site/resources/tags/inputtransferselect.html @@ -0,0 +1,442 @@ + + + + inputtransferselect + + + +

    Tag Name: inputtransferselect

    +

    Description

    +

    + + Renders an input form + +

    + +

    Attributes

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Name

    Required

    Default

    Evaluated

    Type

    Description

    accesskeyfalsetrueStringSet the html accesskey attribute on rendered html element
    addLabelfalsetrueStringthe label used for the add button
    allowRemoveAllfalsetrueStringDetermine whether the remove all button will display
    allowUpDownfalsetrueStringDetermine whether items in the list can be reordered
    buttonCssClassfalsetrueStringthe css class used for rendering buttons
    buttonCssStylefalsetrueStringthe css style used for rendering buttons
    cssClassfalsetrueStringThe css class to use for element
    cssStylefalsetrueStringThe css style definitions for element ro use
    disabledfalsetrueStringSet the html disabled attribute on rendered html element
    downLabelfalsetrueStringthe label used for the down button
    headerKeyfalsetrueStringthe header key of the select box
    headerValuefalsetrueStringthe header value of the select box
    idfalsetrueStringid for referencing element. For UI and form tags it will be used as HTML id attribute
    keyfalsetrueStringSet the key (name, value, label) for this particular component
    labelfalsetrueStringLabel expression used for rendering a element specific label
    labelpositionfalsetrueStringDefine label position of form element (top/left)
    leftTitlefalsetrueStringthe left hand title
    listtruetrueStringIterable source to populate from. If the list is a Map (key, value), the Map key will become the option 'value' parameter and the Map value will become the option body.
    listKeyfalsetrueString Property of list objects to get field value from
    listValuefalsetrueStringProperty of list objects to get field content from
    multiplefalsetrueStringDetermine whether or not multiple entries are shown
    namefalsetrueStringThe name to set for element
    onblurfalsetrueString Set the html onblur attribute on rendered html element
    onchangefalsetrueStringSet the html onchange attribute on rendered html element
    onclickfalsetrueStringSet the html onclick attribute on rendered html element
    ondblclickfalsetrueStringSet the html ondblclick attribute on rendered html element
    onfocusfalsetrueStringSet the html onfocus attribute on rendered html element
    onkeydownfalsetrueStringSet the html onkeydown attribute on rendered html element
    onkeypressfalsetrueStringSet the html onkeypress attribute on rendered html element
    onkeyupfalsetrueStringSet the html onkeyup attribute on rendered html element
    onmousedownfalsetrueStringSet the html onmousedown attribute on rendered html element
    onmousemovefalsetrueStringSet the html onmousemove attribute on rendered html element
    onmouseoutfalsetrueStringSet the html onmouseout attribute on rendered html element
    onmouseoverfalsetrueStringSet the html onmouseover attribute on rendered html element
    onmouseupfalsetrueStringSet the html onmouseup attribute on rendered html element
    onselectfalsetrueStringSet the html onselect attribute on rendered html element
    removeAllLabelfalsetrueStringthe label used for the remove all button
    removeLabelfalsetrueStringthe label used for the remove button
    requiredfalsefalsetrueBooleanIf set to true, the rendered element will indicate that input is required
    requiredpositionfalsetrueStringDefine required position of required form element (left|right)
    rightTitlefalsetrueStringthe right hand title
    sizefalsetrueStringthe size of the select box
    tabindexfalsetrueStringSet the html tabindex attribute on rendered html element
    templatefalsetrueStringThe template (other than default) to use for rendering the element
    templateDirfalsetrueStringThe template directory.
    themefalsetrueStringThe theme (other than default) to use for rendering the element
    titlefalsetrueStringSet the html title attribute on rendered html element
    tooltipfalsetrueStringSet the tooltip of this particular component
    tooltipConfigfalsetrueStringSet the tooltip configuration
    upLabelfalsetrueStringthe label used for the up button
    valuefalsetrueStringPreset the value of input element.
    + + + + diff --git a/core/src/site/resources/tags/optiontransferselect.html b/core/src/site/resources/tags/optiontransferselect.html index 5dfa2ea31..c9a9221b9 100644 --- a/core/src/site/resources/tags/optiontransferselect.html +++ b/core/src/site/resources/tags/optiontransferselect.html @@ -241,7 +241,7 @@ Please do not edit it directly. true String - Set the list key of the second attribute + The key expression to use for second list doubleListValue diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java new file mode 100644 index 000000000..6cf989fa7 --- /dev/null +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java @@ -0,0 +1,34 @@ +package org.apache.struts2.views.jsp.ui; + +import org.apache.struts2.views.jsp.AbstractUITagTest; +import org.apache.struts2.TestAction; + +import java.util.List; +import java.util.ArrayList; + +/** + * + */ +public class InputTransferSelectTagTest extends AbstractUITagTest { + + public void testWithRequired() throws Exception { + List list = new ArrayList(); + list.add("Item One"); + list.add("Item Two"); + + TestAction testaction = (TestAction) action; + testaction.setCollection(list); + + InputTransferSelectTag tag = new InputTransferSelectTag(); + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setList("collection"); + + tag.doStartTag(); + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(InputTransferSelectTagTest.class.getResource("inputtransferselect-1.txt")); + } +} diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt new file mode 100644 index 000000000..6f6a812d4 --- /dev/null +++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt @@ -0,0 +1,23 @@ + + + + + + + +

    + +

    + +
    +
    + + + + ItemOne + ItemTwo + + + + + \ No newline at end of file