Author: konstantin.mishin
Date: 2010-06-25 13:02:44 -0400 (Fri, 25 Jun 2010)
New Revision: 17673
Added:
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/SelectionRenderer.java
Modified:
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/component/UIDataTableBase.java
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/ExtendedDataTableRenderer.java
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.ecss
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js
Log:
RF-8101
Modified:
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/component/UIDataTableBase.java
===================================================================
---
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/component/UIDataTableBase.java 2010-06-25
15:23:04 UTC (rev 17672)
+++
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/component/UIDataTableBase.java 2010-06-25
17:02:44 UTC (rev 17673)
@@ -76,7 +76,7 @@
}
protected enum PropertyKeys {
- filterVar, sortPriority, sortMode, first, rows, noDataLabel
+ filterVar, sortPriority, sortMode, first, rows, noDataLabel, selectedRowKeys
}
public Iterator<UIComponent> columns() {
@@ -194,6 +194,15 @@
getStateHelper().put(PropertyKeys.filterVar, filterVar);
}
+ @SuppressWarnings("unchecked")
+ public Collection<Object> getSelectedRowKeys() {
+ return (Collection<Object>)
getStateHelper().eval(PropertyKeys.selectedRowKeys);
+ }
+
+ public void setSelectedRowKeys(Collection<Object> selectedRowKeys) {
+ getStateHelper().put(PropertyKeys.selectedRowKeys, selectedRowKeys);
+ }
+
public Collection<?> getSortPriority() {
return (Collection<?>) getStateHelper().eval(PropertyKeys.sortPriority);
}
Modified:
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/ExtendedDataTableRenderer.java
===================================================================
---
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/ExtendedDataTableRenderer.java 2010-06-25
15:23:04 UTC (rev 17672)
+++
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/ExtendedDataTableRenderer.java 2010-06-25
17:02:44 UTC (rev 17673)
@@ -27,6 +27,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -63,7 +64,7 @@
@ResourceDependency(library = "javax.faces", name = "jsf.js"),
@ResourceDependency(name = "jquery.js"),
@ResourceDependency(name = "jquery.position.js"), @ResourceDependency(name
= "richfaces.js"),
@ResourceDependency(name = "extendedDataTable.js") })
-public class ExtendedDataTableRenderer extends SortingFilteringRowsRenderer implements
MetaComponentRenderer {
+public class ExtendedDataTableRenderer extends SelectionRenderer implements
MetaComponentRenderer {
private static enum PartName {
frozen, normal
@@ -618,6 +619,7 @@
writer.writeAttribute(HTML.NAME_ATTRIBUTE, component.getClientId(context) +
":wi", null);
writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
writer.endElement(HTML.INPUT_ELEM);
+ encodeSelectionInput(writer, context, component);
writer.startElement(HTML.SCRIPT_ELEM, component);
writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
JSFunction ajaxFunction = buildAjaxFunction(context, component,
AJAX_FUNCTION_NAME);
@@ -674,6 +676,20 @@
RendererState state = (RendererState) rowHolder;
UIDataTableBase table = state.getRow();
writer.startElement(HTML.TR_ELEMENT, table);
+ StringBuilder builder = new StringBuilder();
+ Collection<Object> selectedRowKeys = table.getSelectedRowKeys();
+ if (selectedRowKeys != null &&
selectedRowKeys.contains(table.getRowKey())) {
+ builder.append("rf-edt-r-s");
+ }
+ if
(table.getRowKey().equals(table.getAttributes().get("activeRowKey"))) {
+ if (builder.length() > 0) {
+ builder.append(' ');
+ }
+ builder.append("rf-edt-r-a");
+ }
+ if (builder.length() > 0) {
+ writer.writeAttribute(HTML.CLASS_ATTRIBUTE, builder.toString(), null);
+ }
Iterator<UIComponent> columns = null;
Part part = state.getPart();
writer.writeAttribute(HTML.ID_ATTRIBUTE,
Added:
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/SelectionRenderer.java
===================================================================
---
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/SelectionRenderer.java
(rev 0)
+++
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/SelectionRenderer.java 2010-06-25
17:02:44 UTC (rev 17673)
@@ -0,0 +1,156 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.renderkit;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.ajax4jsf.model.DataVisitResult;
+import org.ajax4jsf.model.DataVisitor;
+import org.ajax4jsf.renderkit.RendererUtils.HTML;
+import org.richfaces.component.UIDataTableBase;
+
+/**
+ * @author Konstantin Mishin
+ *
+ */
+public abstract class SelectionRenderer extends SortingFilteringRowsRenderer {
+
+ private class ClientSelection {
+
+ public static final String FLAG_RESET = "x";
+
+ private int [][] ranges;
+ private int activeIndex;
+ private int shiftIndex;
+ private String selectionFlag;
+ private int index;
+
+ public ClientSelection(String selectionString) {
+ String[] strings = selectionString.split("\\|", -1);
+ String[] rangeStrings = strings[0].split(";");
+ if (strings[0].length() > 0) {
+ ranges = new int[rangeStrings.length][2];
+ for (int i = 0; i < rangeStrings.length; i++) {
+ String[] rangeString = rangeStrings[i].split(",");
+ ranges[i][0] = Integer.parseInt(rangeString[0]);
+ ranges[i][1] = Integer.parseInt(rangeString[1]);
+ }
+ } else {
+ ranges = new int[0][0];
+ }
+ if (strings[1].length() > 0) {
+ activeIndex = Integer.parseInt(strings[1]);
+ } else {
+ activeIndex = -1;
+ }
+ if (strings[2].length() > 0) {
+ shiftIndex = Integer.parseInt(strings[2]);
+ } else {
+ shiftIndex = -1;
+ }
+ if (strings[3].length() > 0) {
+ selectionFlag = strings[3];
+ }
+ index = 0;
+ }
+
+ public boolean isSelected(int index) {
+ int i = 0;
+ while (i < ranges.length && index >= ranges[i][0]) {
+ if (index >= ranges[i][0] && index <= ranges[i][1]) {
+ return true;
+ } else {
+ i++;
+ }
+ }
+ return false;
+ }
+ public boolean isActiveIndex(int index) {
+ return activeIndex == index;
+ }
+
+ public boolean isShiftIndex(int index) {
+ return shiftIndex == index;
+ }
+
+ public String getSelectionFlag() {
+ return selectionFlag;
+ }
+
+ public int nextIndex() {
+ return index++;
+ }
+ }
+
+ protected void encodeSelectionInput(ResponseWriter writer, FacesContext context,
UIComponent component)
+ throws IOException {
+ writer.startElement(HTML.INPUT_ELEM, component);
+ writer.writeAttribute(HTML.ID_ATTRIBUTE, component.getClientId(context) +
":si", null);
+ writer.writeAttribute(HTML.NAME_ATTRIBUTE, component.getClientId(context) +
":si", null);
+ writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
+ writer.endElement(HTML.INPUT_ELEM);
+ }
+
+
+ @Override
+ protected void doDecode(FacesContext context, UIComponent component) {
+ super.doDecode(context, component);
+ Map<String, String> map =
context.getExternalContext().getRequestParameterMap();
+ String selectionString = map.get(component.getClientId(context) +
":si");
+ if (selectionString != null && selectionString.length() > 0) {
+ final ClientSelection clientSelection = new
ClientSelection(selectionString);
+ final Map<String, Object> attributes = component.getAttributes();
+ UIDataTableBase table = (UIDataTableBase) component;
+ Collection<Object> selectedRowKeys = table.getSelectedRowKeys();
+ if (selectedRowKeys == null) {
+ selectedRowKeys = new HashSet<Object>();
+ updateAttribute(context, component, "selectedRowKeys",
selectedRowKeys);
+ }
+ if (ClientSelection.FLAG_RESET.equals(clientSelection.getSelectionFlag())) {
+ selectedRowKeys.clear();
+ }
+ final Collection<Object> rowKeys = selectedRowKeys;
+ table.walk(context, new DataVisitor() {
+ public DataVisitResult process(FacesContext context, Object rowKey,
Object argument) {
+ int index = clientSelection.nextIndex();
+ if (clientSelection.isSelected(index)) {
+ rowKeys.add(rowKey);
+ }
+ if (clientSelection.isActiveIndex(index)) {
+ attributes.put("activeRowKey", rowKey);
+ }
+ if (clientSelection.isShiftIndex(index)) {
+ attributes.put("shiftRowKey", rowKey);
+ }
+ return DataVisitResult.CONTINUE;
+ }
+ }, null);
+ }
+ }
+}
Modified:
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.ecss
===================================================================
---
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.ecss 2010-06-25
15:23:04 UTC (rev 17672)
+++
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.ecss 2010-06-25
17:02:44 UTC (rev 17673)
@@ -152,4 +152,8 @@
.rf-edt-r-s {
background-color: '#{richSkin.additionalBackgroundColor}'; /*TODO Probably use
other skin property.*/
+}
+
+.rf-edt-r-a {
+ font-weight: bold; /*TODO Probably use other property.*/
}
\ No newline at end of file
Modified:
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js
===================================================================
---
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js 2010-06-25
15:23:04 UTC (rev 17672)
+++
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js 2010-06-25
17:02:44 UTC (rev 17673)
@@ -122,7 +122,7 @@
this.ranges = [];
},
- isSelected: function(index) {
+ contains: function(index) {
var i = 0;
while(i < this.ranges.length && index >= this.ranges[i][0]) {
if(index >= this.ranges[i][0] && index <= this.ranges[i][1]) {
@@ -149,11 +149,13 @@
var ranges = new richfaces.utils.Ranges();
var element = document.getElementById(id);
- var bodyElement, contentElement, spacerElement, dataTableElement, rows, rowHeight,
parts, tbodies, shiftIndex, activeIndex;
+ var bodyElement, contentElement, spacerElement, dataTableElement, rows, rowHeight,
parts, tbodies, shiftIndex,
+ activeIndex, selectionFlag;
var dragElement = document.getElementById(id + ":d");
var reorderElement = document.getElementById(id + ":r");
var reorderMarkerElement = document.getElementById(id + ":rm");
var widthInput = document.getElementById(id + ":wi");
+ var selectionInput = document.getElementById(id + ":si");
var normalPartStyle = richfaces.utils.getCSSRule(".rf-edt-pw").style;
var header = jQuery(element).children(".rf-edt-h");
var resizerHolders = header.find(".rf-edt-rsh");
@@ -259,7 +261,7 @@
adjustResizers();
};
- var initializeLayout = function() {
+ var initialize = function() {
bodyElement = document.getElementById(id + ":b");
contentElement = jQuery(bodyElement).children("div:first")[0];
if (contentElement) {
@@ -273,6 +275,7 @@
}
jQuery(bodyElement).bind("scroll", bodyScrollListener)
tbodies.bind("click", selectionClickListener);
+ initializeSelection();
} else {
spacerElement = null;
dataTableElement = null;
@@ -397,7 +400,7 @@
var selectRow = function (index) {
ranges.add(index);
for ( var i = 0; i < tbodies.length; i++) {
- tbodies[i].rows[index].className = "rf-edt-r-s";
+ jQuery(tbodies[i].rows[index]).addClass("rf-edt-r-s");
}
}
@@ -406,11 +409,53 @@
ranges.remove(index);
}
for ( var i = 0; i < tbodies.length; i++) {
- tbodies[i].rows[index].className = "";
+ jQuery(tbodies[i].rows[index]).removeClass("rf-edt-r-s");
}
}
+ var setActiveRow = function (index) {
+ if(activeIndex != null) {
+ for ( var i = 0; i < tbodies.length; i++) {
+ jQuery(tbodies[i].rows[activeIndex]).removeClass("rf-edt-r-a");
+ }
+
+ }
+ activeIndex = index;
+ for ( var i = 0; i < tbodies.length; i++) {
+ jQuery(tbodies[i].rows[activeIndex]).addClass("rf-edt-r-a");
+ }
+ }
+
+ var initializeSelection = function() {
+ ranges.clear();
+ activeIndex = null;
+ shiftIndex = null;
+ selectionFlag = null;
+ var rows = tbodies[0].rows;
+ for (var i = 0; i < rows.length; i++) {
+ var row = jQuery(rows[i]);
+ if (row.hasClass("rf-edt-r-s")) {
+ ranges.add(row[0].rowIndex)
+ }
+ if (row.hasClass("rf-edt-r-a")) {
+ activeIndex = row[0].rowIndex;
+ }
+ }
+ wtiteSelection();
+ }
+
+ var wtiteSelection = function() {
+ selectionInput.value = [ranges, activeIndex, shiftIndex,
selectionFlag].join("|");
+ }
var selectionClickListener = function (event) {
+ if (event.shiftKey || event.ctrlKey) {
+ if (window.getSelection) {
+ window.getSelection().removeAllRanges(); //TODO
+ } else if (document.selection) {
+ document.selection.empty();
+ }
+ }
+
var tr = event.target;
while (tbodies.index(tr.parentNode) == -1) {
tr = tr.parentNode;
@@ -419,16 +464,10 @@
if(!event.shiftKey) {
shiftIndex = null;
- } else {
- if (window.getSelection) {
- window.getSelection().removeAllRanges(); //TODO
- } else if (document.selection) {
- document.selection.empty();
- }
}
if (event.shiftKey && !event.ctrlKey) {
- if(!shiftIndex) {//TODO
- shiftIndex = activeIndex;
+ if(shiftIndex == null) {
+ shiftIndex = activeIndex != null ? activeIndex : index;
}
var range;
if (index >= shiftIndex) {
@@ -438,22 +477,23 @@
}
var i = 0;
for (; i < range[0]; i++) {
- if (ranges.isSelected(i)) {
+ if (ranges.contains(i)) {
deselectRow(i);
}
}
for (; i <= range[1]; i++) {
- if (!ranges.isSelected(i)) {
+ if (!ranges.contains(i)) {
selectRow(i);
}
}
for (; i < rows; i++) {
- if (ranges.isSelected(i)) {
+ if (ranges.contains(i)) {
deselectRow(i);
}
}
+ selectionFlag = "x";
} else if (!event.shiftKey && event.ctrlKey) {
- if (ranges.isSelected(index)) {
+ if (ranges.contains(index)) {
deselectRow(index);
} else {
selectRow(index);
@@ -467,8 +507,10 @@
deselectRow(i, true);
}
}
+ selectionFlag = "x";
}
- activeIndex = index;
+ setActiveRow(index);
+ wtiteSelection();
}
var ajaxComplete = function (event, data) {
@@ -477,7 +519,9 @@
} else {
if (data.reinitializeBody) {
rowCount = data.rowCount;
- initializeLayout();
+ initialize();
+ } else {
+ initializeSelection();
}
if (spacerElement) {
spacerElement.style.height = (data.first * rowHeight) + "px";
@@ -485,7 +529,7 @@
}
};
- jQuery(document).ready(initializeLayout);
+ jQuery(document).ready(initialize);
jQuery(window).bind("resize", updateLayout);
jQuery(scrollElement).bind("scroll", updateScrollPosition);
var bindHeaderHandlers = function () {