ODK2 tables: cannot open submissions from map view

What is the problem? Please be detailed.

Hello, i’m trying to create an ODK tables app with a map view for the submissions (based on the geopoint example). The submissions show fine on the map display, however, clicking on them in the map view has no effect. In the adb logcat i see the following:

09-26 20:50:57.547  5422  5422 I OdkTablesWebView: reloadPage: current loadPageUrl: http://localhost:8635/default/config/tables/lxform/html/lxform_map_list.html
09-26 20:50:57.547  5422  5422 W ODKWebView: framework in process of loading -- ignoring request!

Actually, i’m seeing the same behaviour when i try to use the geopoint example …

What ODK tool and version are you using? And on what device and operating system version?

i’m using odk tables v2.1.0 on a oneplus 6.

Anybody experienced the same ?

Thanks,
Frank

Hi Frank,

This is a known issue, tracked on GitHub List of map markers no longer resorted · Issue #1383 · getodk/getodk · GitHub.

Hello Li,

The pull request #94 does not solve the issue completely for me. The problem is that i have a huge list of submissions and i display them in a chunked way (like the tea house example). For me, i’d prefer the list view not to be reloaded at all but to have it autoscroll to the selected item.

This is possible using the odkWebView , i hacked it together by changing the implementation of MapListViewFragment.setIndexOfSelectedItem to this:

@Override
public void setIndexOfSelectedItem(final int index, String rowKey) {
  this.mSelectedItemIndex = index;
  final OdkTablesWebView currentView = getWebKit();
  final String javascriptUrl = "javascript:mapSelected(" + index + ",'" + rowKey  + "')";

  // Ensure that this is run on the UI thread
  if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
      currentView.post(new Runnable() {
          public void run() {
              currentView.loadUrl(javascriptUrl);
          }
      });
  } else {
      currentView.loadUrl(javascriptUrl);
  }
  // TODO: Make map index work with async API
  //this.mTableDataReference.setSelectedMapIndex(index);
  //this.resetView();
}

Then in the map_list_view.js i do this:

 var mapSelected = function(idx,rowId) {
   console.log("feature with index " + idx + " has been selected");
   $([document.documentElement, document.body]).animate({
       scrollTop: $("#" + rowId).offset().top
    }, 400);
 }

and now it works nice and smooth even with huge tables (i also added another change to use googlemapextensions clustering to keep the googlemap fast for bigger tables).

If there is any interest, i could try to do it the proper way and make a PR but i would need some advice.

Frank

Currently in Survey and Tables, new data or changes to data come in after a reload. I would consider the selection or deselection of a marker new data. Having this behavior consistent helps keep our programs more maintainable and also keep our users’ programs more maintainable.

Could you elaborate on why you would prefer not to have a reload? Is your concern on the load time? You could try paging your list or use lazy loading in your list.

@Frank_Dekervel

Thank you for offering to contribute to ODK Tables!!! :heart:

I think your solution might be an improvement over the current method. Once we have the ODK 2 TSC formed I think this would be a great topic for discussion. ODK 2 TSC Election - 2018-09-03

If I recall correctly one of the reasons the auto scroll was not chosen in the past was people were unclear which of the items in the list had been chosen. While the item was in the current list being displayed people did not realize it. People did not want the drop down displayed unless they specifically clicked on it. Therefore the option was to color the item somehow or just put it on the top always.

Either way I think we could probably come up with a more elegant solution and look forward to your help contributing to the process of finding a user friendly answer. I do agree that a page reload does seem overkill and scrolling to the right spot might be better. However, not confusing the user is also a prime concern.

Hello Li,

Well actually i don’t think my proposal conflicts so much with what you say:

  • its not really “new data coming in”, it’s just a selection of an entry by the user. In our case, a lot of entries are displayed on the map (hence the clustering) and the user might easily mis-click (especially since there are no labels drawn on the map yet), so it would be greatly benificial to have this done quick. I’m now testing with a table of 2K entries (but the final one would have 9K or more), and the reload takes a significant amount of time.

  • actually, i think giving control to the javascript part on what to do when sth is selected gives the flexibility needed: if a reload is still appropriate, it can still be done, but if visual feedback (highlighting or something else) is desired it can be done too.

  • however, there could be a concern that in the mean time the data table changed and the indices are not correct anymore. That’s why i’d also keep the row keys in a hashmap and pass the selected row key in addition to the selected index to the javascript.

  • wrt the maintainability: couldn’t we make this configurable ? eg a reload by default unless the javascript code registers a selection callback function ? this way we don’t break anything …

greetings,

Frank

Hello,

I looked a bit at the existing code. Every JS callback (eg the ones for OdkDat when data is ready) is handled via a javascript odkTables object, and there is only one javascriptinterface published from java.

Now the question is: suppose that i want to register a “onSelectionChanged” handler from javascript, how should the API look like ? should it also be using the odkTables object ? (i would think no, since this API should only exist in map view and maybe navigate view). And how should the java-to-javascript api look like ? a new javascriptinterface ?

Frank

When you say you want to register a onSelectionChanged handler, how do you image the handler will look like? Do you want to pass a JS callback function to be called after onSelectionChanged is fired?

Yes, that would be convenient (for now i hardcoded the JS function to be called, but off course this would need to change). I think the existing onDataReady callback is done the same way.

Frank

Frank,

Thank you for your willingness to improve the map feature. Normally I would suggest your attend one of the ODK 2 developer calls that were happening twice a month. However, we have temporarily suspended the calls as a new TSC is scheduled to be appointed to shepherd ODK 2 that will probably lead to the changes in the meeting structure.

Feel free to post any specific questions you have now in this thread and hopefully we will resume developer or community calls soon.