Author: konstantin.mishin
Date: 2010-06-30 14:07:32 -0400 (Wed, 30 Jun 2010)
New Revision: 17686
Added:
root/ui/iteration/trunk/tables/api/src/main/java/org/richfaces/model/SelectionMode.java
Modified:
root/examples/iteration-demo/trunk/src/main/java/org/richfaces/demo/DataBean.java
root/examples/iteration-demo/trunk/src/main/webapp/extendedtable.xhtml
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/SelectionRenderer.java
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js
Log:
RF-8101
Modified:
root/examples/iteration-demo/trunk/src/main/java/org/richfaces/demo/DataBean.java
===================================================================
---
root/examples/iteration-demo/trunk/src/main/java/org/richfaces/demo/DataBean.java 2010-06-30
15:52:20 UTC (rev 17685)
+++
root/examples/iteration-demo/trunk/src/main/java/org/richfaces/demo/DataBean.java 2010-06-30
18:07:32 UTC (rev 17686)
@@ -1,5 +1,6 @@
package org.richfaces.demo;
+import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -12,6 +13,7 @@
import org.richfaces.demo.model.Employee;
import org.richfaces.demo.utils.EmployeeUtils;
import org.richfaces.event.SortingEvent;
+import org.richfaces.model.SelectionMode;
@ManagedBean(name="dataBean")
@SessionScoped
@@ -36,6 +38,10 @@
private List<Employee> employeeList;
private boolean state = true;
+ private SelectionMode selectionMode = SelectionMode.multiple;
+
+ private Collection<Object> selectedRowKeys;
+
public String getTarget() {
return target;
}
@@ -126,4 +132,24 @@
public boolean isRendered() {
return rendered;
}
+
+ public void setSelectionMode(SelectionMode selectionMode) {
+ this.selectionMode = selectionMode;
+ }
+
+ public SelectionMode getSelectionMode() {
+ return selectionMode;
+ }
+
+ public SelectionMode[] getSelectionModes() {
+ return SelectionMode.values();
+ }
+
+ public void setSelectedRowKeys(Collection<Object> selectedRowKeys) {
+ this.selectedRowKeys = selectedRowKeys;
+ }
+
+ public Collection<Object> getSelectedRowKeys() {
+ return selectedRowKeys;
+ }
}
Modified: root/examples/iteration-demo/trunk/src/main/webapp/extendedtable.xhtml
===================================================================
--- root/examples/iteration-demo/trunk/src/main/webapp/extendedtable.xhtml 2010-06-30
15:52:20 UTC (rev 17685)
+++ root/examples/iteration-demo/trunk/src/main/webapp/extendedtable.xhtml 2010-06-30
18:07:32 UTC (rev 17686)
@@ -6,7 +6,7 @@
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
-
xmlns:it="http://richfaces.org/iteration">
+
xmlns:rich="http://richfaces.org/rich">
<!--
JBoss, Home of Professional Open Source
Copyright ${year}, Red Hat, Inc. and individual contributors
@@ -34,7 +34,6 @@
<h:head>
<title>Richfaces ExtendedDataTable</title>
<style type="text/css">
- @charset "utf-8";
.extendedDataTable{
width:500px;
height: 500px;
@@ -48,13 +47,12 @@
<h:selectBooleanCheckbox value="#{dataBean.state}">
<f:ajax render="extendedDataTable" />
</h:selectBooleanCheckbox>
- <br />
- <h:outputText value="Render footer" />
+ <h:outputText value="Render footer" style="padding-left:
30px;"/>
<h:selectBooleanCheckbox value="#{dataBean.rendered}">
<f:ajax render="extendedDataTable" />
</h:selectBooleanCheckbox>
<br />
- JS API
+ <h:outputText value="JS API" />
<script type="text/javascript">
<!--
function invokeJSAPI() {
@@ -67,9 +65,21 @@
<input id="js_api_function_string_input" type="text"
value="sort('column_title')" size="60"/>
<input type="button" value="Run"
onclick="invokeJSAPI()" />
<input id="js_api_result" type="text"
readonly="readonly" size="60"/>
- <it:extendedDataTable id="extendedDataTable" clientRows="40"
rows="100" frozenColumns="2"
+ <br />
+ <h:outputText value="Selection mode" />
+ <h:selectOneMenu value="#{dataBean.selectionMode}">
+ <f:selectItems value="#{dataBean.selectionModes}"/>
+ <f:ajax render="extendedDataTable" />
+ </h:selectOneMenu>
+ <h:outputText value="Lock selection" style="padding-left:
30px;"/>
+ <input id="selectionLocker" type="checkbox"/>
+ <h:outputText value="Selected rowKeys" style="padding-left:
30px;"/>
+ <h:outputText id="selectionOutput"
value="#{dataBean.selectedRowKeys}"/>
+ <rich:extendedDataTable id="extendedDataTable" clientRows="40"
rows="100" frozenColumns="2"
value="#{dataBean.state ? dataBean.employeeList : null}"
var="record" noDataLabel="There isn't data."
- styleClass="extendedDataTable" rowKeyVar="rkv"
filterVar="fv" sortMode="multi">
+ styleClass="extendedDataTable" rowKeyVar="rkv"
filterVar="fv" sortMode="multi"
+ selectionMode="#{dataBean.selectionMode}"
selectedRowKeys="#{dataBean.selectedRowKeys}"
+ onselectionchange="document.getElementById('submit').click();"
onbeforeselectionchange="if
(document.getElementById('selectionLocker').checked) return false;">
<f:facet name="header">
<h:outputText value="Current date: #{dataBean.date}"/>
</f:facet>
@@ -79,7 +89,7 @@
<f:facet name="noData">
<h:outputText value="There isn't data." style="border: solid
black 1px;"/>
</f:facet>
- <it:column id="rkv">
+ <rich:column id="rkv">
<f:facet name="header">
<h:outputText value="Index"/>
</f:facet>
@@ -89,8 +99,8 @@
<h:outputText id="footerFacet" value="index"/>
</f:facet>
</c:if>
- </it:column>
- <it:column id="column_name"
filterExpression="#{fn:containsIgnoreCase(record.name, fv)}"
sortBy="#{record.name}">
+ </rich:column>
+ <rich:column id="column_name"
filterExpression="#{fn:containsIgnoreCase(record.name, fv)}"
sortBy="#{record.name}">
<f:facet name="header">
<h:outputText id="columnHeader1" value="Column Header
Facet"/>
</f:facet>
@@ -100,31 +110,31 @@
<h:outputText id="columnFooter1" value="Column Footer
Facet"/>
</f:facet>
</c:if>
- </it:column>
+ </rich:column>
- <it:column id="column_title" width="200px"
sortBy="#{record.title}">
+ <rich:column id="column_title" width="200px"
sortBy="#{record.title}">
<h:outputText value="#{record.title}" />
<c:if test="#{dataBean.rendered}">
<f:facet name="footer">
<h:outputText id="columnFooter2" value="Column Footer
Facet2"/>
</f:facet>
</c:if>
- </it:column>
+ </rich:column>
- <it:column id="column_email" width="300px">
+ <rich:column id="column_email" width="300px">
<h:outputText value="#{record.EMail}" />
- </it:column>
- <it:column id="column_company_name" width="300px">
+ </rich:column>
+ <rich:column id="column_company_name" width="300px">
<h:outputText value="#{record.companies[0].name}" />
- </it:column>
- <it:column id="column_company_state">
+ </rich:column>
+ <rich:column id="column_company_state">
<h:outputText value="#{record.companies[0].state}" />
- </it:column>
- <it:column id="column_company_phone">
+ </rich:column>
+ <rich:column id="column_company_phone">
<h:outputText value="#{record.companies[0].phone}" />
- </it:column>
- </it:extendedDataTable>
- <input type="submit" />
+ </rich:column>
+ </rich:extendedDataTable>
+ <input id="submit" type="submit" />
</h:form>
</h:body>
</html>
Added:
root/ui/iteration/trunk/tables/api/src/main/java/org/richfaces/model/SelectionMode.java
===================================================================
---
root/ui/iteration/trunk/tables/api/src/main/java/org/richfaces/model/SelectionMode.java
(rev 0)
+++
root/ui/iteration/trunk/tables/api/src/main/java/org/richfaces/model/SelectionMode.java 2010-06-30
18:07:32 UTC (rev 17686)
@@ -0,0 +1,30 @@
+/*
+ * 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.model;
+
+public enum SelectionMode {
+ none,
+ single,
+ multiple,
+ multipleKeyboardFree
+}
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-30
15:52:20 UTC (rev 17685)
+++
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/ExtendedDataTableRenderer.java 2010-06-30
18:07:32 UTC (rev 17686)
@@ -50,11 +50,14 @@
import org.ajax4jsf.model.DataVisitor;
import org.ajax4jsf.model.SequenceRange;
import org.ajax4jsf.renderkit.AjaxEventOptions;
+import org.ajax4jsf.renderkit.RendererUtils;
import org.ajax4jsf.renderkit.RendererUtils.HTML;
+import org.ajax4jsf.renderkit.RendererUtils.ScriptHashVariableWrapper;
import org.richfaces.component.UIDataTableBase;
import org.richfaces.component.UIExtendedDataTable;
import org.richfaces.component.util.HtmlUtil;
import org.richfaces.context.OnOffResponseWriter;
+import org.richfaces.model.SelectionMode;
/**
* @author Konstantin Mishin
@@ -292,7 +295,7 @@
writer.startElement(HTML.TBODY_ELEMENT, table);
writer.startElement(HTML.TR_ELEMENT, table);
while (columns.hasNext()) {
- if(columnFacetPresent) {
+ if (columnFacetPresent) {
encodeHeaderOrFooterCell(context, writer, columns.next(),
name);
} else {
encodeEmptyFooterCell(context, writer, columns.next());
@@ -515,6 +518,9 @@
+ "; i++ )
richTBody.appendChild(richTBody.removeChild(richRows[0]));");
writer.endEval();
}
+ writer.startUpdate(component.getClientId(context) + ":si");
+ encodeSelectionInput(writer, context, component);
+ writer.endUpdate();
writer.startEval();
writer.write("jQuery('#" +
component.getClientId(context).replace(":", "\\\\:")
+ "').triggerHandler('rich:onajaxcomplete', {first:
" + table.getClientFirst() + "});");
@@ -545,9 +551,13 @@
encodeFooter(state);
} else if (UIDataTableBase.BODY.equals(metaComponentId)) {
encodeBody(state);
+ writer.startUpdate(component.getClientId(context) +
":si");
+ encodeSelectionInput(writer, context, component);
+ writer.endUpdate();
writer.startEval();
writer.write("jQuery('#" +
component.getClientId(context).replace(":", "\\\\:")
- + "').triggerHandler('rich:onajaxcomplete',
{first: " + table.getClientFirst() + ", rowCount: " +
getRowCount(component)+ ", reinitializeBody: true});");
+ + "').triggerHandler('rich:onajaxcomplete',
{first: " + table.getClientFirst() + ", rowCount: "
+ + getRowCount(component) + ", reinitializeBody:
true});");
writer.endEval();
} else {
throw new IllegalArgumentException("Unsupported
metaComponentIdentifier: " + metaComponentId);
@@ -627,9 +637,24 @@
Map<String, Object> parameters = eventOptions.getParameters();
eventOptions.set(AjaxEventOptions.PARAMETERS, new
JSReference("parameters"));
ajaxFunction.addParameter(eventOptions);
- writer.write("new RichFaces.ExtendedDataTable('" +
component.getClientId(context) + "', "
- + getRowCount(component) + ", function(event, parameters) {" +
ajaxFunction.toScript() + ";},"
- + ScriptUtils.toScript(parameters) + ");");
+ Map<String, Object> attributes = component.getAttributes();
+ Map<String, Object> options = new HashMap<String, Object>();
+ RendererUtils utils = getUtils();
+ utils.addToScriptHash(options, "parameters", parameters);
+ utils.addToScriptHash(options, "selectionMode",
attributes.get("selectionMode"),
+ SelectionMode.multiple.toString());
+ utils.addToScriptHash(options, "onbeforeselectionchange",
attributes.get("onbeforeselectionchange"), null,
+ ScriptHashVariableWrapper.EVENT_HANDLER);
+ utils.addToScriptHash(options, "onselectionchange",
attributes.get("onselectionchange"), null,
+ ScriptHashVariableWrapper.EVENT_HANDLER);
+ StringBuilder builder = new StringBuilder("new
RichFaces.ExtendedDataTable('");
+ builder.append(component.getClientId(context)).append("',
").append(getRowCount(component))
+ .append(", function(event, parameters)
{").append(ajaxFunction.toScript()).append(";}");
+ if (!options.isEmpty()) {
+ builder.append(",").append(ScriptUtils.toScript(options));
+ }
+ builder.append(");");
+ writer.write(builder.toString());
writer.endElement(HTML.SCRIPT_ELEM);
writer.endElement(HTML.DIV_ELEM);
}
@@ -687,6 +712,12 @@
}
builder.append("rf-edt-r-a");
}
+ if (table.getRowKey().equals(table.getAttributes().get("shiftRowKey")))
{
+ if (builder.length() > 0) {
+ builder.append(' ');
+ }
+ builder.append("rf-edt-r-t");
+ }
if (builder.length() > 0) {
writer.writeAttribute(HTML.CLASS_ATTRIBUTE, builder.toString(), null);
}
Modified:
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 2010-06-30
15:52:20 UTC (rev 17685)
+++
root/ui/iteration/trunk/tables/ui/src/main/java/org/richfaces/renderkit/SelectionRenderer.java 2010-06-30
18:07:32 UTC (rev 17686)
@@ -32,8 +32,10 @@
import org.ajax4jsf.model.DataVisitResult;
import org.ajax4jsf.model.DataVisitor;
+import org.ajax4jsf.model.SequenceRange;
import org.ajax4jsf.renderkit.RendererUtils.HTML;
import org.richfaces.component.UIDataTableBase;
+import org.richfaces.component.UIExtendedDataTable;
/**
* @author Konstantin Mishin
@@ -44,7 +46,10 @@
private class ClientSelection {
public static final String FLAG_RESET = "x";
-
+ public static final String FLAG_ALL = "a";
+ public static final String FLAG_AFTER_RANGE = "d";
+ public static final String FLAG_BEFORE_RANGE = "u";
+
private int [][] ranges;
private int activeIndex;
private int shiftIndex;
@@ -64,15 +69,17 @@
} else {
ranges = new int[0][0];
}
- if (strings[1].length() > 0) {
+ if (strings[1].matches("\\d+")) {
activeIndex = Integer.parseInt(strings[1]);
} else {
activeIndex = -1;
}
- if (strings[2].length() > 0) {
+ if (strings[2].matches("\\d+")) {
shiftIndex = Integer.parseInt(strings[2]);
+ } else if (strings[2].length() > 0) {
+ shiftIndex = -1;
} else {
- shiftIndex = -1;
+ shiftIndex = -2;
}
if (strings[3].length() > 0) {
selectionFlag = strings[3];
@@ -99,6 +106,10 @@
return shiftIndex == index;
}
+ public boolean isCleanShiftIndex() {
+ return shiftIndex == -2;
+ }
+
public String getSelectionFlag() {
return selectionFlag;
}
@@ -114,6 +125,37 @@
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);
+ UIDataTableBase table = (UIDataTableBase) component;
+ StringBuilder builder = new StringBuilder("|");
+ Object key = table.getRowKey();
+ table.captureOrigValue(context);
+ SequenceRange range = (SequenceRange) table.getComponentState().getRange();
+ int first = range.getFirstRow();
+ int last = first + range.getRows() - 1;
+ Map<String, Object> attributes = component.getAttributes();
+ table.setRowKey(attributes.get("activeRowKey"));
+ int activeIndex = table.getRowIndex();
+ if (activeIndex > 0) {
+ if (activeIndex < first) {
+ builder.append(ClientSelection.FLAG_BEFORE_RANGE);
+ } else if (activeIndex > last) {
+ builder.append(ClientSelection.FLAG_AFTER_RANGE);
+ }
+ }
+ builder.append("|");
+ table.setRowKey(attributes.get("shiftRowKey"));
+ int shiftIndex = table.getRowIndex();
+ if (shiftIndex > 0) {
+ if (shiftIndex < first) {
+ builder.append(ClientSelection.FLAG_BEFORE_RANGE);
+ } else if (shiftIndex > last) {
+ builder.append(ClientSelection.FLAG_AFTER_RANGE);
+ }
+ }
+ builder.append("|");
+ table.setRowKey(context, key);
+ table.restoreOrigValue(context);
+ writer.writeAttribute(HTML.VALUE_ATTRIBUTE, builder.toString(), null);
writer.endElement(HTML.INPUT_ELEM);
}
@@ -132,15 +174,53 @@
selectedRowKeys = new HashSet<Object>();
updateAttribute(context, component, "selectedRowKeys",
selectedRowKeys);
}
- if (ClientSelection.FLAG_RESET.equals(clientSelection.getSelectionFlag())) {
+ final Collection<Object> rowKeys = selectedRowKeys;
+ if (clientSelection.getSelectionFlag() != null) {
selectedRowKeys.clear();
+ if
(!ClientSelection.FLAG_RESET.equals(clientSelection.getSelectionFlag())) {
+ Object key = table.getRowKey();
+ table.captureOrigValue(context);
+ SequenceRange range = (SequenceRange)
table.getComponentState().getRange();
+ SequenceRange newRange = null;
+ Object rowKey = attributes.get("shiftRowKey");
+ if (rowKey == null) {
+ rowKey = attributes.get("activeRowKey");
+ attributes.put("shiftRowKey", rowKey);
+ }
+ table.setRowKey(rowKey);
+ int shiftIndex = table.getRowIndex();
+ if
(ClientSelection.FLAG_ALL.equals(clientSelection.getSelectionFlag())) {
+ newRange = new SequenceRange(0, 0);
+ } else if (shiftIndex > 0) {
+ if
(ClientSelection.FLAG_BEFORE_RANGE.equals(clientSelection.getSelectionFlag())) {
+ newRange = new SequenceRange(shiftIndex, range.getFirstRow()
- shiftIndex);
+ } else {
+ int last = range.getFirstRow() + range.getRows();
+ newRange = new SequenceRange(last, shiftIndex - last + 1);
+ }
+ }
+ table.setRowKey(context, key);
+ table.restoreOrigValue(context);
+ if (newRange != null) {
+ ((UIExtendedDataTable) table).walk(context, new DataVisitor() {
//TODO Don't use cast here.
+ public DataVisitResult process(FacesContext context, Object
rowKey, Object argument) {
+ rowKeys.add(rowKey);
+ return DataVisitResult.CONTINUE;
+ }
+ }, newRange, null);
+ }
+ }
}
- final Collection<Object> rowKeys = selectedRowKeys;
+ if (clientSelection.isCleanShiftIndex()) {
+ attributes.remove("shiftRowKey");
+ }
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);
+ } else {
+ rowKeys.remove(rowKey);
}
if (clientSelection.isActiveIndex(index)) {
attributes.put("activeRowKey", rowKey);
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-30
15:52:20 UTC (rev 17685)
+++
root/ui/iteration/trunk/tables/ui/src/main/resources/META-INF/resources/extendedDataTable.js 2010-06-30
18:07:32 UTC (rev 17686)
@@ -96,28 +96,6 @@
}
},
- remove: function(index) {
- var i = 0;
- while(i < this.ranges.length && index > this.ranges[i++][1]);
- i--;
- if(this.ranges[i]) {
- if(index==(this.ranges[i][1]) ) {
- if(index==(this.ranges[i][0])){
- this.ranges.splice(i, 1);
- } else {
- this.ranges[i][1]--;
- }
- } else {
- if(index==(this.ranges[i][0])){
- this.ranges[i][0]++;
- } else {
- this.ranges.splice(i+1, 0, [index+1, this.ranges[i][1]]);
- this.ranges[i][1] = index-1;
- }
- }
- }
- },
-
clear: function() {
this.ranges = [];
},
@@ -143,10 +121,11 @@
}
};
- richfaces.ExtendedDataTable = function(id, rowCount, ajaxFunction, ajaxParameters) {
+ richfaces.ExtendedDataTable = function(id, rowCount, ajaxFunction, options) {
var WIDTH_CLASS_NAME_BASE = "rf-edt-cw-";
var MIN_WIDTH = 20;
+ options = options || {};
var ranges = new richfaces.utils.Ranges();
var element = document.getElementById(id);
var bodyElement, contentElement, spacerElement, dataTableElement, rows, rowHeight,
parts, tbodies, shiftIndex,
@@ -172,15 +151,16 @@
var timeoutId = null;
var sendAjax = function(event, map) {
- for (key in ajaxParameters) {
+ for (key in options.parameters) {
if(!map[key]) {
- map[key] = ajaxParameters[key];
+ map[key] = options.parameters[key];
}
}
ajaxFunction(event, map);
};
var updateLayout = function() {
+ normalPartStyle.width = "auto";
var offsetWidth = frozenHeaderPartElement ? frozenHeaderPartElement.offsetWidth : 0;
var width = Math.max(0, element.clientWidth - offsetWidth);
if (width) {
@@ -263,7 +243,9 @@
var initialize = function() {
bodyElement = document.getElementById(id + ":b");
- contentElement = jQuery(bodyElement).children("div:first")[0];
+ bodyElement.tabIndex = -1; //TODO don't use tabIndex.
+ var bodyJQuery = jQuery(bodyElement);
+ contentElement = bodyJQuery.children("div:first")[0];
if (contentElement) {
spacerElement = contentElement.firstChild;//TODO this.marginElement =
Richfaces.firstDescendant(this.contentElement);
dataTableElement = contentElement.lastChild;//TODO this.dataTableElement =
Richfaces.lastDescendant(this.contentElement);
@@ -273,9 +255,12 @@
if (rowCount != rows) {
contentElement.style.height = (rowCount * rowHeight) + "px";
}
- jQuery(bodyElement).bind("scroll", bodyScrollListener)
- tbodies.bind("click", selectionClickListener);
- initializeSelection();
+ bodyJQuery.bind("scroll", bodyScrollListener);
+ if (options.selectionMode != "none") {
+ tbodies.bind("click", selectionClickListener);
+ bodyJQuery.bind("keydown", selectionKeyDownListener);
+ initializeSelection();
+ }
} else {
spacerElement = null;
dataTableElement = null;
@@ -404,17 +389,15 @@
}
}
- var deselectRow = function (index, skipUpdateModel) {
- if (!skipUpdateModel) {
- ranges.remove(index);
- }
+ var deselectRow = function (index) {
+ ranges.remove(index);
for ( var i = 0; i < tbodies.length; i++) {
jQuery(tbodies[i].rows[index]).removeClass("rf-edt-r-s");
}
}
var setActiveRow = function (index) {
- if(activeIndex != null) {
+ if(typeof activeIndex == "number") {
for ( var i = 0; i < tbodies.length; i++) {
jQuery(tbodies[i].rows[activeIndex]).removeClass("rf-edt-r-a");
}
@@ -426,10 +409,31 @@
}
}
+ var resetShiftRow = function () {
+ if(typeof shiftIndex == "number") {
+ for ( var i = 0; i < tbodies.length; i++) {
+ jQuery(tbodies[i].rows[shiftIndex]).removeClass("rf-edt-r-t");
+ }
+
+ }
+ shiftIndex = null;
+ }
+
+ var setShiftRow = function (index) {
+ resetShiftRow();
+ shiftIndex = index;
+ if(typeof index == "number") {
+ for ( var i = 0; i < tbodies.length; i++) {
+ jQuery(tbodies[i].rows[shiftIndex]).addClass("rf-edt-r-t");
+ }
+ }
+ }
+
var initializeSelection = function() {
ranges.clear();
- activeIndex = null;
- shiftIndex = null;
+ var strings = selectionInput.value.split("|");
+ activeIndex = strings[1] || null;
+ shiftIndex = strings[2] || null;
selectionFlag = null;
var rows = tbodies[0].rows;
for (var i = 0; i < rows.length; i++) {
@@ -440,87 +444,153 @@
if (row.hasClass("rf-edt-r-a")) {
activeIndex = row[0].rowIndex;
}
+ if (row.hasClass("rf-edt-r-t")) {
+ shiftIndex = row[0].rowIndex;
+ }
}
- wtiteSelection();
+ writeSelection();
}
- var wtiteSelection = function() {
+ var writeSelection = function() {
selectionInput.value = [ranges, activeIndex, shiftIndex,
selectionFlag].join("|");
}
+
+ var selectRows = function(range) {
+ var changed;
+ var i = 0;
+ for (; i < range[0]; i++) {
+ if (ranges.contains(i)) {
+ deselectRow(i);
+ changed = true;
+ }
+ }
+ for (; i <= range[1]; i++) {
+ if (!ranges.contains(i)) {
+ selectRow(i);
+ changed = true;
+ }
+ }
+ for (; i < rows; i++) {
+ if (ranges.contains(i)) {
+ deselectRow(i);
+ changed = true;
+ }
+ }
+ selectionFlag = typeof shiftIndex == "string" ? shiftIndex : "x";
+ return changed;
+ }
+
+ var processSlectionWithShiftKey = function(index) {
+ if(shiftIndex == null) {
+ setShiftRow(activeIndex != null ? activeIndex : index);
+ }
+ var range;
+ if ("u" == shiftIndex) {
+ range = [0, index];
+ } else if ("d" == shiftIndex) {
+ range = [index, rows - 1];
+ } else if (index >= shiftIndex) {
+ range = [shiftIndex, index];
+ } else {
+ range = [index, shiftIndex];
+ }
+ return selectRows(range);
+ }
+
+ var onbeforeselectionchange = function (event) {
+ return !options.onbeforeselectionchange || options.onbeforeselectionchange(event) !==
false;
+ }
+
+ var onselectionchange = function (event, index, changed) {
+ if(!event.shiftKey) {
+ resetShiftRow();
+ }
+ if (activeIndex != index) {
+ setActiveRow(index);
+ }
+ if (changed) {
+ writeSelection();
+ if (options.onselectionchange) {
+ options.onselectionchange(event);
+ }
+ }
+ }
+
var selectionClickListener = function (event) {
+ if (!onbeforeselectionchange(event)) {
+ return;
+ }
+ var changed;
if (event.shiftKey || event.ctrlKey) {
- if (window.getSelection) {
- window.getSelection().removeAllRanges(); //TODO
+ if (window.getSelection) { //TODO Try to find other way.
+ window.getSelection().removeAllRanges();
} else if (document.selection) {
document.selection.empty();
}
}
-
var tr = event.target;
while (tbodies.index(tr.parentNode) == -1) {
tr = tr.parentNode;
}
var index = tr.rowIndex;
-
- if(!event.shiftKey) {
- shiftIndex = null;
- }
- if (event.shiftKey && !event.ctrlKey) {
- if(shiftIndex == null) {
- shiftIndex = activeIndex != null ? activeIndex : index;
- }
- var range;
- if (index >= shiftIndex) {
- range = [shiftIndex, index];
- } else {
- range = [index, shiftIndex];
- }
- var i = 0;
- for (; i < range[0]; i++) {
- if (ranges.contains(i)) {
- deselectRow(i);
- }
- }
- for (; i <= range[1]; i++) {
- if (!ranges.contains(i)) {
- selectRow(i);
- }
- }
- for (; i < rows; i++) {
- if (ranges.contains(i)) {
- deselectRow(i);
- }
- }
- selectionFlag = "x";
- } else if (!event.shiftKey && event.ctrlKey) {
+ if (options.selectionMode == "single" || (options.selectionMode !=
"multipleKeyboardFree"
+ && !event.shiftKey && !event.ctrlKey)) {
+ changed = selectRows([index, index]);
+ } else if (options.selectionMode == "multipleKeyboardFree" ||
(!event.shiftKey && event.ctrlKey)) {
if (ranges.contains(index)) {
deselectRow(index);
} else {
selectRow(index);
}
- } else if (!event.shiftKey && !event.ctrlKey) {
- ranges.clear();
- for (var i = 0; i < rows; i++) {
- if (i == index) {
- selectRow(i);
- } else {
- deselectRow(i, true);
+ changed = true;
+ } else {
+ changed = processSlectionWithShiftKey(index);
+ }
+ onselectionchange(event, index, changed);
+ }
+
+ var selectionKeyDownListener = function(event) {
+ if (event.ctrlKey && options.selectionMode != "single" &&
(event.keyCode == 65 || event.keyCode == 97)) { //Ctrl-A
+ if(onbeforeselectionchange(event)) {
+ selectRows([0, rows]);
+ selectionFlag = "a";
+ onselectionchange(event, activeIndex, true); //TODO Is there a way to know that
selection haven't changed?
+ }
+ return false;
+ }
+ if (typeof activeIndex == "number") {
+ var index;
+ if (event.keyCode == 38 && activeIndex) { //UP
+ index = activeIndex - 1;
+ } else if (event.keyCode == 40 && activeIndex < rows - 1) { //DOWN
+ index = activeIndex + 1;
+ }
+ if (index != null) {
+ if(onbeforeselectionchange(event)) {
+ var changed;
+ if (options.selectionMode == "single" || (!event.shiftKey &&
!event.ctrlKey)) {
+ changed = selectRows([index, index]);
+ } else if (event.shiftKey) {
+ changed = processSlectionWithShiftKey(index);
+ }
+ setActiveRow(index);
+ //showRow
+ onselectionchange(event, index, changed);
}
+ return false;
}
- selectionFlag = "x";
}
- setActiveRow(index);
- wtiteSelection();
}
var ajaxComplete = function (event, data) {
if (data.reinitializeHeader) {
bindHeaderHandlers();
} else {
+ selectionInput = document.getElementById(id + ":si");
if (data.reinitializeBody) {
rowCount = data.rowCount;
initialize();
- } else {
+ } else if (options.selectionMode != "none") {
initializeSelection();
}
if (spacerElement) {