Author: konstantin.mishin
Date: 2010-03-22 14:05:51 -0400 (Mon, 22 Mar 2010)
New Revision: 16650
Modified:
root/ui-sandbox/trunk/components/tables/ui/src/main/java/org/richfaces/component/UIExtendedDataTable.java
root/ui-sandbox/trunk/components/tables/ui/src/main/java/org/richfaces/renderkit/ExtendedDataTableRenderer.java
root/ui-sandbox/trunk/components/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.css
root/ui-sandbox/trunk/components/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js
Log:
RF-8484
Modified:
root/ui-sandbox/trunk/components/tables/ui/src/main/java/org/richfaces/component/UIExtendedDataTable.java
===================================================================
---
root/ui-sandbox/trunk/components/tables/ui/src/main/java/org/richfaces/component/UIExtendedDataTable.java 2010-03-22
12:59:20 UTC (rev 16649)
+++
root/ui-sandbox/trunk/components/tables/ui/src/main/java/org/richfaces/component/UIExtendedDataTable.java 2010-03-22
18:05:51 UTC (rev 16650)
@@ -22,35 +22,67 @@
package org.richfaces.component;
+import java.io.IOException;
+import java.util.Collection;
+
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.render.Renderer;
+
import org.ajax4jsf.model.DataComponentState;
import org.ajax4jsf.model.RepeatState;
+import org.richfaces.renderkit.PartialEncodingRenderer;
/**
* @author Anton Belevich
*
*/
-public abstract class UIExtendedDataTable extends UIDataTableBase {
+public class UIExtendedDataTable extends UIDataTableBase implements
PartiallyEncodedComponent{
+ public static final String SCROLL = "scroll";
+ public static final String SUBMITTED_CLIENT_FIRST =
"submittedClientFirst";
+
+ protected enum PropertyKeys {
+ clientFirst, clientRows
+ }
+
@Override
+ public void encodePartially(VisitContext context, VisitCallback callback,
+ Collection<String> subComponentIdentifiers)
+ throws IOException {
+ if (subComponentIdentifiers.contains(SCROLL)) {
+ Integer submittedClientFirst = (Integer)
getAttributes().remove(SUBMITTED_CLIENT_FIRST);
+ if (submittedClientFirst != null) {
+ setClientFirst(submittedClientFirst);
+ }
+ }
+ Renderer renderer = getRenderer(context.getFacesContext());
+ ((PartialEncodingRenderer) renderer).encodePartially(this, context, callback,
subComponentIdentifiers);
+ }
+
+ @Override
protected DataComponentState createComponentState() {
return new RepeatState() {
@Override
public int getFirst() {
- return UIExtendedDataTable.this.getClientFirst();
+ return UIExtendedDataTable.this.getFirst() +
UIExtendedDataTable.this.getClientFirst();
}
@Override
public int getRows() {
- return UIExtendedDataTable.this.getClientRows();
+ int rows = UIExtendedDataTable.this.getClientRows();
+ if (rows > 0) {
+ rows = Math.min(rows, UIExtendedDataTable.this.getRows());
+ } else {
+ rows = UIExtendedDataTable.this.getRows();
+ }
+
+ return rows;
}
};
}
- protected enum PropertyKeys {
- clientFirst, clientRows
- }
-
public int getClientFirst() {
return (Integer) getStateHelper().eval(PropertyKeys.clientFirst, 0);
}
@@ -62,7 +94,7 @@
@Override
public void setFirst(int first) {
super.setFirst(first);
- setClientFirst(first);
+ setClientFirst(0);
}
public int getClientRows() {
Modified:
root/ui-sandbox/trunk/components/tables/ui/src/main/java/org/richfaces/renderkit/ExtendedDataTableRenderer.java
===================================================================
---
root/ui-sandbox/trunk/components/tables/ui/src/main/java/org/richfaces/renderkit/ExtendedDataTableRenderer.java 2010-03-22
12:59:20 UTC (rev 16649)
+++
root/ui-sandbox/trunk/components/tables/ui/src/main/java/org/richfaces/renderkit/ExtendedDataTableRenderer.java 2010-03-22
18:05:51 UTC (rev 16650)
@@ -27,6 +27,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
@@ -35,7 +36,10 @@
import javax.faces.application.ResourceDependencies;
import javax.faces.application.ResourceDependency;
import javax.faces.component.UIComponent;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
import javax.faces.context.FacesContext;
+import javax.faces.context.PartialResponseWriter;
import javax.faces.context.ResponseWriter;
import org.ajax4jsf.javascript.JSFunction;
@@ -49,7 +53,7 @@
@ResourceDependency(name = "jquery.js"), @ResourceDependency(name =
"jquery.position.js"),
@ResourceDependency(name = "richfaces.js"), @ResourceDependency(name =
"extendedDataTable.js"),
@ResourceDependency(name = "extendedDataTable.css") })
-public class ExtendedDataTableRenderer extends AbstractRowsRenderer{
+public class ExtendedDataTableRenderer extends AbstractRowsRenderer implements
PartialEncodingRenderer {
private class RendererState extends RowHolderBase {
@@ -113,6 +117,41 @@
}
@Override
+ public void encodePartially(UIComponent component, VisitContext visitContext,
VisitCallback callback,
+ Collection<String> subComponentIdentifiers) throws IOException {
+ if (subComponentIdentifiers.size() == 1 &&
subComponentIdentifiers.contains(UIExtendedDataTable.SCROLL)) {
+ FacesContext context = visitContext.getFacesContext();
+ PartialResponseWriter writer =
context.getPartialViewContext().getPartialResponseWriter();
+ UIExtendedDataTable table = (UIExtendedDataTable) component;
+ Object key = table.getRowKey();
+ table.captureOrigValue(context);
+ table.setRowKey(context, null);
+ RendererState state = createRowHolder(context, table);
+ state.setFrozen(true);
+ // TODO 1. Encode fixed children 2. Load necessary rows only
+ for (int i = 0; i < 2; i++) { // TODO 1. Replace 2 with constant 2. Empty
frozen part shouldn't be rendered
+ if (i == 0) {
+ writer.startUpdate(table.getClientId(context) + ":ftb");
+ } else {
+ writer.startUpdate(table.getClientId(context) + ":ntb");
+ }
+ encodeTBody(state, i);
+ writer.endUpdate();
+ state.setFrozen(false);
+ }
+ writer.startEval();
+ writer.write("jQuery('#" +
component.getClientId(context).replace(":", "\\\\:")
+ + "').triggerHandler('rich:onscrollcomplete', " +
table.getClientFirst() + ");");
+ writer.endEval();
+ table.setRowKey(context, key);
+ table.restoreOrigValue(context);
+
+ } else {
+ throw new IllegalArgumentException("Incorect subComponentIdentifiers:
" + subComponentIdentifiers);
+ }
+ }
+
+ @Override
protected void doEncodeBegin(ResponseWriter writer, FacesContext context, UIComponent
component)
throws IOException {
writer.startElement(HTML.DIV_ELEM, component);
@@ -199,12 +238,16 @@
JSFunction ajaxFunction = buildAjaxFunction(context, component,
AJAX_FUNCTION_NAME);
AjaxEventOptions eventOptions = buildEventOptions(context, component);
eventOptions.getParameters().put("rich:columnsOrder", new
JSReference("columnsOrder"));
- if (!eventOptions.isEmpty()) {
- ajaxFunction.addParameter(eventOptions);
- }
+ ajaxFunction.addParameter(eventOptions);
+ JSFunction scrollFunction = buildAjaxFunction(context, component,
AJAX_FUNCTION_NAME);
+ AjaxEventOptions scrollOptions = buildEventOptions(context, component);
+ scrollOptions.getParameters().put("rich:clientFirst", new
JSReference("clientFirst"));
+ scrollFunction.addParameter(scrollOptions);
+
writer.write("new RichFaces.ExtendedDataTable('" +
component.getClientId(context) + "', "
- + getRowCount(component) + ", function(event, columnsOrder) {" +
ajaxFunction.toScript() + ";});");
+ + getRowCount(component) + ", function(event, columnsOrder) {" +
ajaxFunction.toScript() + ";}"
+ + ", function(event, clientFirst) {" + scrollFunction.toScript() +
";});");
writer.endElement(HTML.SCRIPT_ELEM);
writer.endElement(HTML.DIV_ELEM);
}
@@ -241,7 +284,6 @@
}
String width = getColumnWidth(column);
writer.writeText(".rich-extable-cell-width-" + id + " {",
"width"); // TODO getNormalizedId(context,
- // state.getGrid())
writer.writeText("width: " + width + ";",
"width");
writer.writeText("}", "width");
}
@@ -321,6 +363,9 @@
}
} else {
writer.startElement(HTML.DIV_ELEM, table);
+ writer.startElement(HTML.DIV_ELEM, table);
+ writer.writeAttribute(HTML.CLASS_ATTRIBUTE, "rich-extable-spacer",
null);
+ writer.endElement(HTML.DIV_ELEM);
writer.startElement(HTML.TABLE_ELEMENT, table);
writer.writeAttribute(HTML.CELLPADDING_ATTRIBUTE, "0", null);
writer.writeAttribute(HTML.CELLSPACING_ATTRIBUTE, "0", null);
@@ -337,9 +382,7 @@
writer.startElement(HTML.TABLE_ELEMENT, table);
writer.writeAttribute(HTML.CELLPADDING_ATTRIBUTE, "0", null);
writer.writeAttribute(HTML.CELLSPACING_ATTRIBUTE, "0", null);
- writer.startElement(HTML.TBOBY_ELEMENT, table);
- table.walk(context, this, state); // TODO encodeRows(context, table);
- writer.endElement(HTML.TBOBY_ELEMENT);
+ encodeTBody(state, i);
writer.endElement(HTML.TABLE_ELEMENT);
writer.endElement(HTML.DIV_ELEM);
writer.endElement(HTML.TD_ELEM);
@@ -353,6 +396,20 @@
writer.endElement(HTML.DIV_ELEM);
}
+ private void encodeTBody(RendererState state, int i) throws IOException {
+ FacesContext context = state.getContext();
+ ResponseWriter writer = context.getResponseWriter();
+ UIExtendedDataTable table = state.getRow();
+ writer.startElement(HTML.TBOBY_ELEMENT, table);
+ if (i == 0) {
+ writer.writeAttribute(HTML.ID_ATTRIBUTE, table.getClientId(context) +
":ftb", null);
+ } else {
+ writer.writeAttribute(HTML.ID_ATTRIBUTE, table.getClientId(context) +
":ntb", null);
+ }
+ table.walk(context, this, state); // TODO encodeRows(context, table);
+ writer.endElement(HTML.TBOBY_ELEMENT);
+ }
+
private void encodeHeaderOrFooterCell(FacesContext context, ResponseWriter writer,
UIComponent column,
String facetName) throws IOException {
if (column.isRendered()) {
@@ -425,6 +482,9 @@
if (map.get(component.getClientId(context)) != null) {
updateColumnsOrder(context, component,
map.get("rich:columnsOrder"));
}
+ if (map.get(component.getClientId(context)) != null) {
+ updateClientFirst(context, component,
map.get("rich:clientFirst"));
+ }
}
/**
@@ -453,6 +513,14 @@
}
}
+ private void updateClientFirst(FacesContext context, UIComponent component, String
clientFirst) {
+ if (clientFirst != null && clientFirst.length() > 0) {
+ int value = Integer.parseInt(clientFirst);
+ component.getAttributes().put(UIExtendedDataTable.SUBMITTED_CLIENT_FIRST,
value);
+
context.getPartialViewContext().getRenderIds().add(component.getClientId(context) +
"@" + UIExtendedDataTable.SCROLL);
+ }
+ }
+
private String getColumnWidth(UIComponent column) {
String width = (String) column.getAttributes().get("width");
if (width == null || width.length() == 0 || width.indexOf("%") != -1)
{
Modified:
root/ui-sandbox/trunk/components/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.css
===================================================================
---
root/ui-sandbox/trunk/components/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.css 2010-03-22
12:59:20 UTC (rev 16649)
+++
root/ui-sandbox/trunk/components/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.css 2010-03-22
18:05:51 UTC (rev 16650)
@@ -36,8 +36,14 @@
width: 100%;
}
+.rich-extable-spacer {
+ height: 0px;
+ font-size: 0px;
+ line-height: 0px;
+}
+
.rich-extable-footer {
- background-color : #CCCCCC;
+ background-color: #CCCCCC;
}
.rich-extable-footer-align{
@@ -97,6 +103,10 @@
border-right: 1px solid #C4C0C9;
}
+.rich-extable-cell-content, .rich-extable-header-cell-content,
.rich-extable-footer-cell-content{
+ padding: 2px;
+}
+
.rich-extable-reorder-marker {
position:absolute;
height: 9px;
@@ -104,8 +114,4 @@
width:9px;
background-image: url("#{resource['reorderMarker.gif']}");
display: none;
-}
-
-.rich-extable-cell-content, .rich-extable-header-cell-content,
.rich-extable-footer-cell-content{
- padding: 2px;
}
\ No newline at end of file
Modified:
root/ui-sandbox/trunk/components/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js
===================================================================
---
root/ui-sandbox/trunk/components/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js 2010-03-22
12:59:20 UTC (rev 16649)
+++
root/ui-sandbox/trunk/components/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js 2010-03-22
18:05:51 UTC (rev 16650)
@@ -34,7 +34,7 @@
return rule;
};
- richfaces.ExtendedDataTable = function(id, rowCount, ajaxFunction) {
+ richfaces.ExtendedDataTable = function(id, rowCount, ajaxFunction, scrollFunction) {
var WIDTH_CLASS_NAME_BASE = "rich-extable-cell-width-";
var MIN_WIDTH = 20;
var idSuffixs = [":header", ":footer"]; //TODO Not use idSuffixs
@@ -55,7 +55,7 @@
if (contentElement) {
idSuffixs[idSuffixs.length] = ":body";
- //TODO var marginElement = contentElement.firstChild;this.marginElement =
Richfaces.firstDescendant(this.contentElement);
+ var spacerElement = contentElement.firstChild;//TODO this.marginElement =
Richfaces.firstDescendant(this.contentElement);
var dataTableElement = contentElement.lastChild;//TODO this.dataTableElement =
Richfaces.lastDescendant(this.contentElement);
var rows = document.getElementById(id +
":body").firstChild.rows.length;//TODO Richfaces.firstDescendant;
}
@@ -65,6 +65,8 @@
var idOfReorderingColumn = "";
var newWidths = {};
+ var timeoutId = null;
+
var updateLayout = function() {
var offsetWidth = frozenHeaderPartElement ? frozenHeaderPartElement.offsetWidth : 0;
var width = Math.max(0, element.clientWidth - offsetWidth);
@@ -135,6 +137,7 @@
};
var initializeLayout = function() {
+ //TODO Use "var rowHeight" instead of "dataTableElement.offsetHeight /
rows"
contentElement.style.height = (rowCount * dataTableElement.offsetHeight / rows) +
"px";
updateLayout();
updateScrollPosition(); //TODO Restore horizontal scroll position
@@ -224,12 +227,42 @@
jQuery(element).children(".rich-extable-header").find(".rich-extable-header-cell").unbind("mouseover",
overReorder);
reorderElement.style.display = "none";
};
+
+ var loadData = function(event) {
+ var clientFirst = Math.round((bodyElement.scrollTop + bodyElement.clientHeight / 2) /
(dataTableElement.offsetHeight / rows) - rows / 2);
+ if (clientFirst <= 0) {
+ clientFirst = 0;
+ } else {
+ clientFirst = Math.min(rowCount - rows, clientFirst);
+ }
+ scrollFunction(event, clientFirst);
+ }
+ var bodyScrollListener = function(event) {
+ if(timeoutId) {
+ window.clearTimeout(timeoutId);
+ timeoutId = null;
+ }
+ if (this.scrollTop < spacerElement.offsetHeight || this.scrollTop +
this.clientHeight > spacerElement.offsetHeight + dataTableElement.offsetHeight) {
+ timeoutId = window.setTimeout(function (event) {loadData(event)}, 1000);
+ }
+ };
+
+ var scrollComplete = function (event, first) {
+ spacerElement.style.height = (first * dataTableElement.offsetHeight / rows) +
"px";
+// TODO var height = first * dataTableElement.offsetHeight / rows;
+// var style = spacerElement.style;
+// style.height = height + "px";
+// style.display = height ? "block" : "";
+ };
+
jQuery(document).ready(initializeLayout);
jQuery(window).bind("resize", updateLayout);
jQuery(scrollElement).bind("scroll", updateScrollPosition);
jQuery(element).children(".rich-extable-header").find(".rich-extable-resizer").bind("mousedown",
beginResize);
jQuery(element).children(".rich-extable-header").find(".rich-extable-header-cell").bind("mousedown",
beginReorder);
+ jQuery(bodyElement).bind("scroll", bodyScrollListener);
+ jQuery(element).bind("rich:onscrollcomplete", scrollComplete);
};
}(window.RichFaces, jQuery));