Author: pyaschenko
Date: 2010-09-02 08:25:55 -0400 (Thu, 02 Sep 2010)
New Revision: 19094
Modified:
trunk/examples/input-demo/src/main/java/org/richfaces/demo/AutoCompleteBean.java
trunk/examples/input-demo/src/main/webapp/autocomplete.xhtml
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/Autocomplete.js
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/AutocompleteBase.js
Log:
merge changes from branch
Modified:
trunk/examples/input-demo/src/main/java/org/richfaces/demo/AutoCompleteBean.java
===================================================================
---
trunk/examples/input-demo/src/main/java/org/richfaces/demo/AutoCompleteBean.java 2010-09-02
12:22:46 UTC (rev 19093)
+++
trunk/examples/input-demo/src/main/java/org/richfaces/demo/AutoCompleteBean.java 2010-09-02
12:25:55 UTC (rev 19094)
@@ -22,6 +22,7 @@
package org.richfaces.demo;
import java.io.Serializable;
+import java.util.Arrays;
import java.util.Locale;
import javax.faces.bean.ManagedBean;
@@ -30,6 +31,8 @@
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
+import org.richfaces.component.UIAutocomplete;
+
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
@@ -60,7 +63,17 @@
return input.getName().toLowerCase(Locale.US).startsWith(countryNamePrefix);
}
}
+
+ private String mode = "lazyClient";
+ public String getMode() {
+ return mode;
+ }
+
+ public void setMode(String mode) {
+ this.mode = mode;
+ }
+
@ManagedProperty(value = "#{countriesBean}")
private CountriesBean countriesBean;
@@ -69,7 +82,13 @@
}
public Object autocomplete(FacesContext facesContext, UIComponent component, String
value) {
- return Collections2.filter(countriesBean.getCountries(), new
CountryNamePredicate(value));
+ // for tests when value does not starts with prefix
+ /*String str = value;
+ if (str.charAt(0)=='i') {
+ str = str.substring(1);
+ }*/
+ String v = mode.equals("lazyClient") || mode.equals("client")
? "" : value;
+ return Collections2.filter(countriesBean.getCountries(), new
CountryNamePredicate(v.toLowerCase()));
}
}
Modified: trunk/examples/input-demo/src/main/webapp/autocomplete.xhtml
===================================================================
--- trunk/examples/input-demo/src/main/webapp/autocomplete.xhtml 2010-09-02 12:22:46 UTC
(rev 19093)
+++ trunk/examples/input-demo/src/main/webapp/autocomplete.xhtml 2010-09-02 12:25:55 UTC
(rev 19094)
@@ -13,11 +13,17 @@
<h:body style="margin: 30px;">
<h:form id="form">
+ <h:selectOneMenu value="#{autoCompleteBean.mode}"
onchange="submit()">
+ <f:selectItem itemValue="lazyClient"/>
+ <f:selectItem itemValue="client"/>
+ <f:selectItem itemValue="cachedAjax"/>
+ <f:selectItem itemValue="ajax"/>
+ </h:selectOneMenu>
<div style="height: 300px; width: 300px; overflow: auto;">Text
block text block text block text block text block text block text
block text block
- <input:autocomplete mode="" minChars="2"
autocompleteMethod="#{autoCompleteBean.autocomplete}" var="country"
fetchValue="#{country.name}" showButton="true">
+ <input:autocomplete mode="#{autoCompleteBean.mode}" minChars="2"
autocompleteMethod="#{autoCompleteBean.autocomplete}" var="country"
fetchValue="#{country.name}" showButton="true">
#{country.name} #{country.iso} #{country.domain}
</input:autocomplete>
Modified:
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/Autocomplete.js
===================================================================
---
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/Autocomplete.js 2010-09-02
12:22:46 UTC (rev 19093)
+++
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/Autocomplete.js 2010-09-02
12:25:55 UTC (rev 19094)
@@ -1,14 +1,23 @@
(function ($, rf) {
rf.utils = rf.utils || {};
- rf.utils.Cache = function (key, items, values) {
+ rf.utils.Cache = function (key, items, values, useCache) {
this.key = key.toLowerCase();
this.cache = {}
this.cache[this.key] = items || [];
- this.values = typeof values != "function" ? values || this.cache[this.key] :
values(items);
- this.useCache = checkValuesPrefix.call(this);
+ this.originalValues = typeof values == "function" ? values(items) : values ||
this.cache[this.key];
+ this.values = processValues(this.originalValues);
+ this.useCache = useCache || checkValuesPrefix.call(this);
};
+ var processValues = function (values) {
+ var processedValues = [];
+ for (var i = 0; i<values.length; i++) {
+ processedValues.push(values[i].toLowerCase());
+ }
+ return processedValues;
+ }
+
var checkValuesPrefix = function () {
var result = true;
for (var i = 0; i<this.values.length; i++) {
@@ -33,7 +42,7 @@
} else {
var itemsCache = this.cache[this.key];
for (var i = 0; i<this.values.length; i++) {
- var value = this.values[i].toLowerCase();
+ var value = this.values[i];
var p = value.indexOf(key);
if (p == 0) {
newCache.push(itemsCache[i]);
@@ -52,7 +61,7 @@
};
var getItemValue = function (item) {
- return this.values[this.cache[this.key].index(item)];
+ return this.originalValues[this.cache[this.key].index(item)];
};
var isCached = function (key) {
@@ -107,8 +116,9 @@
minChars:1,
selectFirst:true,
ajaxMode:true,
+ lazyClientMode:false,
isCachedAjax:true,
- tokens: ",",
+ tokens: "",
attachToBody:true
};
@@ -150,9 +160,7 @@
if (element) {
if (event.type=="mouseover") {
var index = this.items.index(element);
- if (index!=this.index) {
- selectItem.call(this, index);
- }
+ selectItem.call(this, event, index);
} else {
this.__onChangeValue(event, getSelectedItemValue.call(this));
rf.Selection.setCaretTo(rf.getDomElement(this.fieldId));
@@ -164,7 +172,7 @@
var updateItemsList = function (value, fetchValues) {
this.items =
$(rf.getDomElement(this.id+ID.ITEMS)).find("."+this.options.itemClass);
if (this.items.length>0) {
- this.cache = new rf.utils.Cache(value, this.items, fetchValues || getData);
+ this.cache = new rf.utils.Cache((this.options.ajaxMode ? value : ""),
this.items, fetchValues || getData, !this.options.ajaxMode);
}
};
@@ -194,18 +202,25 @@
}
};
- var callAjax = function(event, value) {
+ var callAjax = function(event, value, callback) {
clearItems.call(this);
rf.getDomElement(this.id+ID.VALUE).value = value;
var _this = this;
+ var _event = event;
var ajaxSuccess = function (event) {
updateItemsList.call(_this, _this.value, event.componentData &&
event.componentData[_this.id]);
- if (_this.isVisible && _this.options.selectFirst) {
- selectItem.call(_this, 0);
+ if (_this.options.lazyClientMode && _this.value.length!=0) {
+ updateItemsFromCache.call(_this, _this.value);
}
+ if (_this.focused && _this.items.length!=0 && callback) {
+ callback.call(_this, _event);
+ }
+ if (!callback && _this.isVisible && _this.options.selectFirst) {
+ selectItem.call(_this, _event, 0);
+ }
}
var ajaxError = function (event) {
@@ -219,8 +234,8 @@
rf.ajax(this.id, event, {parameters: params, error: ajaxError, complete:ajaxSuccess});
};
- var selectItem = function(index, isOffset, noAutoFill) {
- if (this.items.length==0) return;
+ var selectItem = function(event, index, isOffset) {
+ if (this.items.length==0 || (!isOffset && this.index == index)) return;
if (this.index!=-1) {
this.items.eq(this.index).removeClass(this.options.selectedItemClass);
@@ -233,11 +248,11 @@
if (isOffset) {
this.index += index;
- if ( this.index<0 ) {
- this.index = this.items.length - 1;
- } else if (this.index >= this.items.length) {
- this.index = 0;
- }
+ if ( this.index<0 ) {
+ this.index = this.items.length - 1;
+ } else if (this.index >= this.items.length) {
+ this.index = 0;
+ }
} else {
if (index<0) {
index = 0;
@@ -249,14 +264,21 @@
var item = this.items.eq(this.index);
item.addClass(this.options.selectedItemClass);
scrollToSelectedItem.call(this);
- !noAutoFill && autoFill.call(this, this.value,
getSelectedItemValue.call(this));
+ if (event &&
+ event.which != rf.KEYS.BACKSPACE &&
+ event.which != rf.KEYS.DEL &&
+ event.which != rf.KEYS.LEFT &&
+ event.which != rf.KEYS.RIGHT) {
+ autoFill.call(this, this.value, getSelectedItemValue.call(this));
+ }
};
var updateItemsFromCache = function (value) {
var newItems = this.cache.getItems(value);
this.items = $(newItems);
//TODO: works only with simple markup, not with <tr>
- $(rf.getDomElement(this.id+ID.ITEMS)).empty().append(newItems);
+ $(rf.getDomElement(this.id+ID.ITEMS)).empty().append(this.items);
+ window.console && console.log &&
console.log("updateItemsFromCache");
};
var clearItems = function () {
@@ -264,31 +286,34 @@
this.items = [];
};
- var onChangeValue = function (event, value) {
- selectItem.call(this);
- this.index = -1;
+ var onChangeValue = function (event, value, callback) {
+ selectItem.call(this, event);
// value is undefined if called from AutocompleteBase onChange
var subValue = (typeof value == "undefined") ? this.__getSubValue() : value;
var oldValue = this.value;
this.value = subValue;
- if (this.cache && this.cache.isCached(subValue)) {
- updateItemsFromCache.call(this, subValue);
- if (this.options.selectFirst) {
- if (event.which == rf.KEYS.RETURN || event.type == "click") {
- this.setInputValue(subValue);
- } else {
- selectItem.call(this, 0, false, event.which == rf.KEYS.BACKSPACE || event.which ==
rf.KEYS.LEFT || event.which == rf.KEYS.RIGHT);
- }
+ if ((this.options.isCachedAjax || !this.options.ajaxMode) &&
+ this.cache && this.cache.isCached(subValue)) {
+ if (oldValue!=subValue) {
+ updateItemsFromCache.call(this, subValue);
}
+ if (this.items.length!=0 && callback) {
+ callback.call(this, event);
+ }
+ if (event.which == rf.KEYS.RETURN || event.type == "click") {
+ this.setInputValue(subValue);
+ } else if (this.options.selectFirst) {
+ selectItem.call(this, event, 0);
+ }
} else {
if (event.which == rf.KEYS.RETURN || event.type == "click") {
this.setInputValue(subValue);
}
if (subValue.length>=this.options.minChars) {
- if (this.options.ajaxMode && oldValue!=subValue) {
- this.options.ajaxMode && callAjax.call(this, event, subValue);
+ if ((this.options.ajaxMode || this.options.lazyClientMode) &&
oldValue!=subValue) {
+ callAjax.call(this, event, subValue, callback);
}
} else {
if (this.options.ajaxMode) {
@@ -365,9 +390,11 @@
*/
__updateState: function (event) {
var subValue = this.__getSubValue();
- // called from onShow method, not actually value changed
- if (this.items.length==0 && subValue.length>=this.options.minChars
&& this.isFirstAjax) {
- this.options.ajaxMode && callAjax.call(this, event, subValue);
+ // called from AutocompleteBase when not actually value changed
+ if (this.items.length==0 && this.isFirstAjax) {
+ if ((this.options.ajaxMode && subValue.length>=this.options.minChars) ||
this.options.lazyClientMode) {
+ callAjax.call(this, event, subValue);
+ }
}
return;
},
@@ -383,16 +410,16 @@
/*
* Override abstract protected methods
*/
- __onKeyUp: function () {
- selectItem.call(this, -1, true);
+ __onKeyUp: function (event) {
+ selectItem.call(this, event, -1, true);
},
- __onKeyDown: function () {
- selectItem.call(this, 1, true);
+ __onKeyDown: function (event) {
+ selectItem.call(this, event, 1, true);
},
- __onPageUp: function () {
+ __onPageUp: function (event) {
},
- __onPageDown: function () {
+ __onPageDown: function (event) {
},
__onBeforeShow: function (event) {
@@ -404,14 +431,12 @@
//rf.getDomElement(this.fieldId).focus();
},
__onShow: function (event) {
- if (event.which != rf.KEYS.BACKSPACE && this.items &&
this.items.length>0) {
- if (this.index!=0 && this.options.selectFirst) {
- selectItem.call(this, 0);
- }
+ if (this.options.selectFirst) {
+ selectItem.call(this, event, 0);
}
},
- __onHide: function () {
- selectItem.call(this);
+ __onHide: function (event) {
+ selectItem.call(this, event);
},
/*
* Destructor
Modified:
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/AutocompleteBase.js
===================================================================
---
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/AutocompleteBase.js 2010-09-02
12:22:46 UTC (rev 19093)
+++
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/AutocompleteBase.js 2010-09-02
12:25:55 UTC (rev 19094)
@@ -107,6 +107,7 @@
};
var onFocus = function (event) {
+ this.focused = true;
};
var onBlur = function (event) {
@@ -116,6 +117,7 @@
} else if (this.isVisible && !this.isMouseDown) {
var _this = this;
this.timeoutId = window.setTimeout(function(){_this.hide();}, 200);
+ this.focused=false;
}
};
@@ -128,15 +130,11 @@
//TODO: is it needed to chesk keys?
//TODO: we need to set value when autoFill used when LEFT or RIGHT was pressed
if (event.which == rf.KEYS.LEFT || event.which == rf.KEYS.RIGHT || flag) {
- if (flag || this.isVisible) {
- this.__onChangeValue(event);
- }
if (flag) {
+ this.__onChangeValue(event, undefined, (!this.isVisible ? this.show : undefined));
this.currentValue = this.getInputValue();
- /*if(value && value.length>=this.options.minChars){
- onShow.call(this, event);
- }*/ // TODO: AMarkhel: is this check needed??? for what?
- onShow.call(this, event);
+ } else if (this.isVisible) {
+ this.__onChangeValue(event);
}
}
};