Implement DataSource.setFilterScript
diff --git a/bundles/org.eclipse.rap.addons.autosuggest/.settings/org.moreunit.prefs b/bundles/org.eclipse.rap.addons.autosuggest/.settings/org.moreunit.prefs
index f561a5b..42757bc 100644
--- a/bundles/org.eclipse.rap.addons.autosuggest/.settings/org.moreunit.prefs
+++ b/bundles/org.eclipse.rap.addons.autosuggest/.settings/org.moreunit.prefs
@@ -1,5 +1,5 @@
eclipse.preferences.version=1
org.moreunit.preferences.version=2
org.moreunit.testClassNameTemplate=${srcFile}_Test
-org.moreunit.unitsourcefolder=org.eclipse.rap.addons.dropdown\:src\:org.eclipse.rap.addons.dropdown.test\:src
+org.moreunit.unitsourcefolder=org.eclipse.rap.addons.autosuggest\:src\:org.eclipse.rap.addons.autosuggest.test\:src
org.moreunit.useprojectsettings=true
diff --git a/bundles/org.eclipse.rap.addons.autosuggest/src/org/eclipse/rap/addons/autosuggest/DataSource.java b/bundles/org.eclipse.rap.addons.autosuggest/src/org/eclipse/rap/addons/autosuggest/DataSource.java
index 7e3b7a2..c933b2c 100644
--- a/bundles/org.eclipse.rap.addons.autosuggest/src/org/eclipse/rap/addons/autosuggest/DataSource.java
+++ b/bundles/org.eclipse.rap.addons.autosuggest/src/org/eclipse/rap/addons/autosuggest/DataSource.java
@@ -40,6 +40,10 @@
setInitialData();
}
+ public void setFilterScript( String script ) {
+ remoteObject.set( "filterScript", script );
+ }
+
private void setInitialData() {
JsonArray array = new JsonArray();
for( Object element : dataProvider.getSuggestions() ) {
diff --git a/bundles/org.eclipse.rap.addons.autosuggest/src/org/eclipse/rap/addons/autosuggest/internal/resources/AutoSuggest.js b/bundles/org.eclipse.rap.addons.autosuggest/src/org/eclipse/rap/addons/autosuggest/internal/resources/AutoSuggest.js
index 686c94b..e3d38bc 100644
--- a/bundles/org.eclipse.rap.addons.autosuggest/src/org/eclipse/rap/addons/autosuggest/internal/resources/AutoSuggest.js
+++ b/bundles/org.eclipse.rap.addons.autosuggest/src/org/eclipse/rap/addons/autosuggest/internal/resources/AutoSuggest.js
@@ -120,8 +120,9 @@
fetchSuggestions.apply( this );
var userText = this.get( "userText" ) || "";
this.set( "replacementText", null, { "action" : "sync" } );
+ var filter = getFilter.apply( this );
var filterWrapper = function( suggestion ) {
- return defaultFilter( suggestion, userText );
+ return filter( suggestion, userText );
}
var currentSuggestions = filterArray( this.get( "suggestions" ), filterWrapper );
this.set( "currentSuggestions", currentSuggestions, { "action" : options.action } );
@@ -129,8 +130,8 @@
function fetchSuggestions() {
if( this.get( "suggestions" ) == null ) {
- if( this.get( "dataSourceId" ) != null ) {
- var dataSource = rap.getObject( this.get( "dataSourceId" ) );
+ var dataSource = getDataSource.apply( this );
+ if( dataSource != null ) {
this.set( "suggestions", dataSource.get( "data" ) );
} else {
this.set( "suggestions", [] );
@@ -138,6 +139,31 @@
}
}
+function getFilter() {
+ var filter = this.get( "filter" );
+ if( filter == null ) {
+ var dataSource = getDataSource.apply( this );
+ if( dataSource != null && dataSource.get( "filterScript" ) != null ) {
+ try {
+ filter = secureEval( "var result = " + dataSource.get( "filterScript" ) + "; result;" );
+ } catch( ex ) {
+ throw new Error( "AutoSuggest could not eval filter function: " + ex.message );
+ }
+ } else {
+ filter = defaultFilter;
+ }
+ this.set( "filter", filter );
+ }
+ return filter;
+}
+
+function getDataSource() {
+ if( this.get( "dataSourceId" ) != null ) {
+ return rap.getObject( this.get( "dataSourceId" ) );
+ }
+ return null;
+}
+
////////////////////////
// Helper - autoComplete
@@ -216,3 +242,8 @@
return result;
}
+function secureEval() {
+ // TODO : protect against global var access
+ return eval( arguments[ 0 ] );
+}
+
diff --git a/examples/org.eclipse.rap.addons.dropdown.demo/src/org/eclipse/rap/addons/dropdown/demo/AutoSuggestSnippet.java b/examples/org.eclipse.rap.addons.dropdown.demo/src/org/eclipse/rap/addons/dropdown/demo/AutoSuggestSnippet.java
index 4f7a048..d88743f 100644
--- a/examples/org.eclipse.rap.addons.dropdown.demo/src/org/eclipse/rap/addons/dropdown/demo/AutoSuggestSnippet.java
+++ b/examples/org.eclipse.rap.addons.dropdown.demo/src/org/eclipse/rap/addons/dropdown/demo/AutoSuggestSnippet.java
@@ -28,6 +28,11 @@
AutoSuggest autoSuggest = new AutoSuggest( text );
autoSuggest.setAutoComplete( true );
DataSource dataSource = new DataSource();
+ dataSource.setFilterScript(
+ "functfsdfion( suggestion, userText ) { "
+ + " return suggestion.indexOf( userText ) !== -1;"
+ + "}"
+ );
dataSource.setDataProvider( new ArrayDataProvider( "foo", "food", "foobar", "bar" ) );
autoSuggest.setDataSource( dataSource );
autoSuggest.addSelectionListener( new SuggestionSelectedListener() {
diff --git a/tests/org.eclipse.rap.addons.autosuggest.test/jasmine/jasmine/specs/AutoSuggestSpec.js b/tests/org.eclipse.rap.addons.autosuggest.test/jasmine/jasmine/specs/AutoSuggestSpec.js
index 863669a..db08e6b 100644
--- a/tests/org.eclipse.rap.addons.autosuggest.test/jasmine/jasmine/specs/AutoSuggestSpec.js
+++ b/tests/org.eclipse.rap.addons.autosuggest.test/jasmine/jasmine/specs/AutoSuggestSpec.js
@@ -31,6 +31,27 @@
return result;
};
+ describe( "secureEval", function() {
+
+ var secureEval;
+
+ beforeEach( function() {
+ if( !secureEval ) {
+ secureEval = getVarFromScript( "AutoSuggest", "secureEval" );
+ }
+ } );
+
+ it( "evals code", function() {
+ expect( secureEval( "1+2;" ) ).toBe( 3 );
+ } );
+
+ it( "can not access local variables", function() {
+ var foo = 1;
+ expect( secureEval( "typeof foo;" ) ).toBe( "undefined" );
+ } );
+
+ } );
+
describe( "commonText", function() {
var commonText;
@@ -218,6 +239,59 @@
expect( log[ 0 ][ 0 ].options.action ).toBe( "foo" );
} );
+ it( "uses custom filter from dataSource if present", function() {
+ model.addListener( "change:userText", createClientListener( "AutoSuggest" ) );
+ model.set( "suggestions", null );
+ var dataSource = rap.typeHandler[ "rwt.remote.Model" ].factory();
+ dataSource.set( "data", [ "foo", "bar" ] );
+ spyOn( rap, "getObject" ).andReturn( dataSource );
+ model.set( "dataSourceId", "fooId" );
+ dataSource.set( "filterScript",
+ "function( suggestion, userText ) { "
+ + " return suggestion.indexOf( userText ) !== -1;"
+ + "}"
+ );
+
+ model.set( "userText", "a" );
+
+ expect( model.get( "currentSuggestions" ) ).toEqual( [ "bar" ] );
+ } );
+
+ it( "caches evaluated filter function", function() {
+ model.addListener( "change:userText", createClientListener( "AutoSuggest" ) );
+ model.set( "suggestions", null );
+ var dataSource = rap.typeHandler[ "rwt.remote.Model" ].factory();
+ dataSource.set( "data", [ "foo" ] );
+ spyOn( rap, "getObject" ).andReturn( dataSource );
+ model.set( "dataSourceId", "fooId" );
+ dataSource.set( "filterScript", "function() { return false; }" );
+ model.set( "userText", "a" );
+
+ dataSource.set( "filterScript", "function() { return true; }" );
+ model.set( "userText", "b" );
+
+ expect( model.get( "currentSuggestions" ) ).toEqual( [] );
+ } );
+
+ it( "throws custom exception when filterScript not parse", function() {
+ model.addListener( "change:userText", createClientListener( "AutoSuggest" ) );
+ model.set( "suggestions", null );
+ var dataSource = rap.typeHandler[ "rwt.remote.Model" ].factory();
+ dataSource.set( "data", [ "foo", "bar" ] );
+ spyOn( rap, "getObject" ).andReturn( dataSource );
+ model.set( "dataSourceId", "fooId" );
+ dataSource.set( "filterScript", "funasdfction() { }" );
+ var error;
+
+ try {
+ model.set( "userText", "a" );
+ } catch( ex ) {
+ error = ex;
+ }
+
+ expect( error.message ).toContain( "AutoSuggest" );
+ } );
+
} );
describe( "change:suggestions", function() {
diff --git a/tests/org.eclipse.rap.addons.autosuggest.test/src/org/eclipse/rap/addons/autosuggest/DataSource_Test.java b/tests/org.eclipse.rap.addons.autosuggest.test/src/org/eclipse/rap/addons/autosuggest/DataSource_Test.java
index 9848b74..99a9437 100644
--- a/tests/org.eclipse.rap.addons.autosuggest.test/src/org/eclipse/rap/addons/autosuggest/DataSource_Test.java
+++ b/tests/org.eclipse.rap.addons.autosuggest.test/src/org/eclipse/rap/addons/autosuggest/DataSource_Test.java
@@ -79,4 +79,13 @@
verify( remoteObject ).set( eq( "data" ), eq( array ) );
}
+ @Test
+ public void testSetFilterScript_setsFilterScriptOnRemoteObject() {
+ DataSource dataSource = new DataSource();
+
+ dataSource.setFilterScript( "foobar" );
+
+ verify( remoteObject ).set( eq( "filterScript" ), eq( "foobar" ) );
+ }
+
}