1: Example
This picture represents a group of clusters(the ones that have the text in the middle) and a cluster Item, which is only one item of a specific type.
What I'm trying to achieve is that on a cluster item, I want to add some text, for example "1", which represents that is only a cluster item, therefore there is only one item in there.
I managed to get the text working on the group of clusters but not on the cluster item.
The code that does the trick in my case it's this one:
String place = item.getPlaceName();
if (place.length() > 12)
place = place.substring(0, 10) + "..";
placeAddressAndLocation.setText(place);
Now I am not aware where should I place the exact code for the cluster item.
In the example found on google dev(which is the one I'm also following), there are a couple of methods for these
protected void onBeforeClusterItemRendered
protected void onClusterItemRendered
Tried adding the code on both of the methods, but it doesn't do anything. Any suggestions? Thanks!
If you want to use onBeforeClusterItemRendered, you can try with this answer.
So in the onBeforeClusterItemRendered method, you can set the attributes of markerOptions.
You might want to try to set the title, snippet or icon of the markerOptions, you can read the documentation of the markerOptions.
Related
I am trying to create a small application where I have various file locations stored in a Vaadin grid, the grid currently only shows two columns - ID and File Name, and I would like to see as a notification the file location too whenever I click on a row.
Meaning, every time I click a row from the grid I would like it to show me the location, using Notification.show(), like that:
(Please ignore the <b></b>s, they are irrelevant.)
As my grids selection model is MULTI, per default the click listener cannot register which row it is clicked on and selecting the row via checkbox is not what I want to have the data displayed. Simply, I would like to get the item for every row I click and have the location displayed as a notification.
So far, I found a solution for a similar issue but it deals with columns and the rows in Vaadin grids are rather different from what I am used to.
public static <T> void addColumnClickListener(Grid<T> grid, Consumer<Column<T>> listener)
{
String expression = "function(){const col=element.getEventContext(event).column;return col ? col.id : '';}()";
grid.getElement().addEventListener("click", e ->
{
String colId = e.getEventData().getString(expression);
Optional<Column<T>> column = grid.getColumns().stream().filter(col -> colId.equals(col.getId().get())).findFirst();
column.ifPresent(listener);
}
).addEventData(expression);
}
And I am to call the function like that:
addColumnClickListener(grid, column -> Notification.show("fubar"));
This code snippet is from the Vaadin forums and I do not quite understand it. The string expression seems to be that it contains possible JavaScript code and the rest overrides the type of the column. (I think, I really do not understand this snippet fully)
Is there any way to do something similar to the snippet above but for rows?
You can do this with an ItemClickListener on the Grid:
grid.addItemClickListener(item -> {
Notification.show(String.format("File location: %s", item.getLocation()));
});
I made a pretty simple selenium test, where I want to open web page, clear field value, start entering text for this field, select first value from the hint drop down.
Web site is aviasales.com (I just found some site with a lot of controls, this is not an advertisement)
I did
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).clear();
and it was working perfectly, I also checked via console that this is the only one object on a page like:
document.getElementById('flights-origin-prepop-whitelabel_en')
So, in next line I'm sending value:
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).sendKeys("LAX");
but it send LAX value for both "flights-origin-prepop-whitelabel_en" and "flights-destination-prepop-whitelabel_en" for some reason, then i tried
DriverFactory.getDriver().findElement(By.id("//input[#id='flights-destination-prepop-whitelabel_en'][#placeholder='Destination']")).sendKeys(destinationAirport);
but I got the same result:
What could be a reason and how to fix this?
Thank you!
Yep... there's some weird behavior going on there. The site is copying whatever is entered into the first field into the second for reason I don't understand. I gave up trying to understand it and found a way around it.
Whenever I write code that I know I'm going to reuse, I put them into functions. Here's the script code
driver.navigate().to(url);
setOrigin("LAX");
setDestination("DFW");
...and since you are likely to use these repeatedly, the support functions.
public static void setOrigin(String origin)
{
WebElement e = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(origin);
e.sendKeys(Keys.TAB);
}
public static void setDestination(String dest)
{
WebElement e = driver.findElement(By.id("flights-destination-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(dest);
e.sendKeys(Keys.TAB);
}
You can see the functions but basically I click in the field, clear the text (because usually there's something already in there), send the text, and then press to move out of the field and choose the default (first choice).
The reason of your issue is the ORIGIN and DESTINATION inputbox binded keyboard event which used to supply an autocomplete list according to your typed characters.
The binded keyborad event breaks the normal sendKeys() functionality. I met similar case in my projects and questions on StackOverFlow.
I tried input 'GSO' into DESTINATION by sendKeys('GSO'), but I get 'GGSSOO' on page after the sendKeys() complete.
To resolve your problem, we can't use sendKeys(), we have to use executeScript() to set the value by javascript in backgroud. But executeScript() won't fire keyborad event so you won't get the autocomplete list. So we need find out a way to fire keyborady event after set value by javascript.
Below code snippet worked on chrome when i tested on aviasales.com:
private void inputAirport(WebElement targetEle, String city) {
String script = "arguments[0].value = arguments[1]";
// set value by javascript in background
((JavascriptExecutor) driver).executeScript(script, targetEle, city + "6");
// wait 1s
Thread.sleep(1000);
// press backspace key to delete the last character to fire keyborad event
targetEle.sendKeys(Keys.BACK_SPACE);
// wait 2s to wait autocomplete list pop-up
Thread.sleep(2000);
// choose the first item of autocomplete list
driver.findElement(By.cssSelector("ul.mewtwo-autocomplete-list > li:nth-child(1)")).click();
}
public void inputOrigin(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
return inputAirport(target, city);
}
public void inputDestination(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepopflights-destination-prepop-whitelabel_en"));
return inputAirport(target, city);
}
I understand that in GXT 3.0 grids are pulling their data from a store (in my case a list store). I am trying to implement a search function to help filter through some of the results in the grid dynamically. However, I am having trouble determining the best method to do this. I have considered doing this server side by modifying the source file..but ultimately I just want to toggle the displaying of a row if it doesn't contain a desired string. Any suggestions for how to best approach this?
You can try using store filter to toggle displaying row that contains the string you desired. Here is the example code:
ListStore<YourModelData> listStore = new ListStore<YourModelData>(yourPropertiesObject.key());
StoreFilter<YourModelData> sf = new StoreFilter<YourModelData>() {
#Override
public boolean select(Store<YourModelData> store, YourModelData parent,
YourModelData item) {
return item.contains("some-string");
}
};
listStore.addFilter(sf);
I am developing an Wicket application. But my question is not really Wicket related. In that app I have a horizontal menu. This menu is created by few links. On clicking the link you will be navigated to some page. Now based on the page you are currently viewing the css class attribute of the link of the menu will be changed to "selected". This is the description of the problem.
Now I am solving this problem by using a integer value. The value is saved in the session and it is updated when any one link has been clicked. Based on that saved value, which link will be "selected", will be determined at runtime.
I am implementing this in following way:
//On link click I set a number in session
public void onClick() {
session.setValue(1);// or 2 or 3
}
When the menu is created I switch between the value and modify the css class, as follows:
switch(session.getValue){
case 1: add css to home;
case 2: add css to profile;
// and so on.
}
I was wondering that is this the only right way to do it? Or there some other better techniques or design patterns exist which can help me to achieve this in better way?
Store the menu items in an array (or an ArrayList):
items[0] = home
items[1] = profile
And use the index of the array as menu identifier. When you receive the selected menu itentifier, retrieve the corresponding item with
items[selectedItem]
You could also use a Map if the identifiers are not numbers, or don't go from 0 to N.
For a start, use an enum or static constants instead of magic numbers (1, 2, 3).
The Visitor Pattern is commonly used to avoid this sort of switching. You might not want to implement the full pattern in your case, but it's worth knowning. JB Nizet's answer may be more practical in your situation.
See https://en.wikipedia.org/wiki/Visitor_pattern
These SO questions might give you some ideas, too
Java visitor pattern instead of instanceof switch
Java Enums - Switch statements vs Visitor Pattern on Enums - Performance benefits?
I have implemented it using EnumMap and an Enum type as its key. I have defined an Enum:
public enum NavigationStatus {
HOME,
PROFILE;
}
In session I set the value of the current navigation as:
private NavigationStatus activeUserNavigationStatus;
public NavigationStatus getActiveUserNavigationStatus() {
return activeUserNavigationStatus;
}
public void setActiveUserNavigationStatus(NavigationStatus activeUserNavigationStatus) {
this.activeUserNavigationStatus = activeUserNavigationStatus;
}
Primarily I set it to: setActiveUserNavigationStatus(NavigationStatus.HOME);
Now where the menu is building I created an EnumMap:
EnumMap<NavigationStatus, Component[]> menuMap = new EnumMap<NavigationStatus, Component[]>(NavigationStatus.class);
And added elements to it, as:
menuMap.put(NavigationStatus.HOME, new Component[] { homeContainer, home });
And also on click methods of the links I set the status value:
public void onClick() {
session.setActiveUserNavigationStatus(NavigationStatus.PROFILE);
}
Last of all I checked the current value from the session and set the css class accordingly:
Component[] menuComponents = menuMap.get(getSession().getActiveUserNavigationStatus());
menuComponents[0].add(new AttributeAppender("class", new Model<Serializable>(" active")));
menuComponents[1].add(new AttributeAppender("class", new Model<Serializable>(" active")));
This is without switch statement and combines the idea of JB Nizet's ArrayList index and Oli Charlesworth's Enum.
Thank you.
I was trying all of yesterday to try and integrate a SQL Database with SmartGWT for a lazy list but I just couldn't figure out how to implement it. (JavaDoc, and example of a lazy list)
What I want to do is create a list of a bunch of "sites" all over the world. The problem is there will probably be about a million of them, so I'm trying to load as few as possible at a time. Each site in my DB has an address, so I'm trying to sort them in the tree structure like (Country->State->City->Sites). Every time you go down a level there will be a query to the DB asking for all of the next level (Whether that be all the cities that have sites in the state chosen, or what ever).
Any help is greatly appreciated.
ALSO:
In the example linked the folders and leafs are the type of element, is there a way to keep folders, folders, and then leafs a separate type of object?
After a while I finally got it. I ended up creating my own RPC that would serve up an array of strings that would represent the names of all the TreeNodes for the next level.
So entry point would be:
private NodeServiceAsync nodesRpc; //The RPC that grabs more nodes
private Tree data; //The data structure to hold all of the nodes
private ColumnTree list; //The GUI element that is shown on in the browser
public void onModuleLoad() {
nodesRpc = (NodeServiceAsync) GWT.create(NodeService.class);
data = new Tree();
list = new ColumnTree;
list.setAutoFetchData(true);
list.setLoadDataOnDemand(true);
list.addNodeSelectedHandler(new NodeSelectedHandler () {
public void onNodeSelected(NodeSelectedEvent event) {
if(/*Node is folder and hasn't been opened before*/) {
//Get More Nodes
AsyncCallback<String[]> callback = new NodeGetter<String[]>();
nodesRpc.getData(event.getNode(), callback);
}
else if(/*Node is not a folder (at the end) */) {
//Do something else
}
}
});
list.setData(data); //Make the GUI Element Represent The Data Structure
RootPanel.get().add(list); //Add to screen
}
The serverlet on the server side creates the query, executes, then translates the ResultSet into an array of Strings and passes that back. All the callback has to do, back on the client side, is translate that array into an array of TreeNodes and attach them to the original Node that was clicked on. Finally after all of this the GUI element is redrawn with the new nodes.
I was surprised that there was very little down time between node loads (less then 1 sec) even when sometimes a hundred or so nodes where being queried then displayed.
Note there is also a Pro version of the product which includes SQL connectivity like this out of the box (for Java server platforms). Showcase here:
http://www.smartclient.com/smartgwtee/showcase/
The SQL connector in the Pro product includes load on demand / data paging, search, and all 4 CRUD operations, as well as DataSource Wizards that can generate a working SQL DataSource for an existing database table if you just enter JDBC settings.
Note the Pro product doesn't require SQL, that's just one of the things it can connect to.