UploadWizard/Geolocation

= Locator Widget =

Problem
It is difficult to geocode uploaded media on Wikimedia Commons. The existing advice is for the user to go elsewhere to figure out the latitude and longitude appropriate to their photo, then to figure out which representation of latitude and longitude to use (degrees minutes seconds, decimal degrees, or some other format) and finally to encode the latitude and longitude in appropriate wikiText, such as a Location template.

We would like to greatly lower the bar to geocode media on Commons:
 * use EXIF data contained in the media file to suggest an appropriate location
 * eliminate the need for the uploader to go outside the upload interface to search a map.
 * eliminate the need for the uploader to manually edit, or even know about, latitude and longitude.
 * eliminate the need for the uploader to create, edit, or even know about the location-related wikitext that will be entered onto the File: page for the media file.

This should also:
 * help regularize the format of the wikitext that is used on Commons to geocode media files.

Requirements
The desired solution is a JavaScript jQuery plugin which presents a map interface, which can be manipulated to select a particular location, and which can then report that location in code, preferably as wikiText containing a Location template.

The map plugin should not be dependent on any particular maps provider. It should be able to show tiles and interface from Google Maps, Yahoo Maps, and OpenStreetMaps. (This will probably reuse existing work such as the MediaWiki Maps extension.)

This plugin should be able to be integrated directly into the MediaWiki UploadWizard extension. For the most part, as long as it conforms to the Javascript API below, that should happen automatically.

This plugin should be able to show an interface centered at a pre-selected location.

The plugin will be delivered with documentation that describes the interface for creating the widget, how to manipulate the map to change a location, and how to obtain location wikiText.

The plugin should not have any effects on the HTML page or the window's DOM structure, other than within the element selected for it at creation. The plugin should not create any global variables.

The plugin should be internationalizable, at least in all messages presented to the user.

The code and other assets for this plugin will be licensed under the same terms as MediaWiki. (The code will be GPL-compatible, the images and other assets will be compatible with a Creative Commons Attribution-ShareAlike Unported 3.0 license.)

What's out of scope
We will obtaining geocoding EXIF data from the media file elsewhere. All the map widget has to do is be able to select a location based on a latitude and longitude.

Javascript API and interface specification
Feel free to abandon any aspect of this specification that does not make sense as long as it is meeting the broad goals listed above.

The names of methods and parameters are just suggestions. If they need to be changed to conform to existing conventions, please do so.

In the following examples, $ is a jQuery object.

Creation of widget
The following code would create a map widget on the page, pre-centered and pre-zoomed to a point in San Francisco, CA.

var options = { latitude: 37.775, longitude: -122.4183 };

// create widget on page, at HTML element located at #foo var locator = $('#foo').locator( options );

If the user had not passed a location in the options, then the map would display a general map of the entire world, zoomed out to the maximum extent.

If there are no parameters providing a location, or if the parameters are somehow insane, the plugin behaves as if no location had been passed in.

If a valid location is present, but 'zoom' is absent, or contains an insane value, a default zoom is chosen.

Insane parameters include:
 * null values for latitude or longitude or location
 * not an object
 * object does not contain both latitude and longitude properties
 * latitude < -90.0 or latitude > 90.0
 * longitude > 180.0 or longitude < -180.0
 * location is the empty string
 * location is not a string
 * location contains information which could not be parsed

Interacting with the map widget
Closed state shows a small map. Map may be "empty" or obviously show a location. This is not too different from what Flickr is doing.

Open state shows: map, crosshairs, address or location entry bar, buttons to accept or remove from map.

Use case: screenshot Location desired: none EXIF location: none Result: widget in closed state shows "empty map". No action needed

Use case: picture of the moon. Location desired: none EXIF location: yes Result: widget in closed state shows EXIF location. Click to open map. Press on button to "remove from map"

Use case: scanned picture of White House Location desired: yes EXIF location: no Result: widget in closed state shows "empty map". Open map. Cross hairs visible. Move map until good. Close widget by pressing "accept".

Use case: faulty GPS in my iPhone Location desired: yes EXIF location: yes, but not right Result: widget in closed state shows location in small map. I notice this is wrong, or open map to check. Cross hairs visible. Move map until correct. Close widget by pressing accept.

Use case: everything worked out better than expected Location desired: yes EXIF location: correct Result: widget shows the right thing. No action is needed. Open widget to check, then press "accept" to close.



The map widget will show a standard "slippy" map with minimal controls. It should fit comfortably in a 250px x 280px div, but also expand to fill the size of whatever element was selected in the initial jQuery call. (Some modern mapping APIs will automatically adjust the widgets to be less obtrusive at smaller sizes).

A user can pan the map around by grabbing the map and dragging it in any direction. They can zoom in or out. The programmer can choose whether to allow changing to different modes (such as between satellite or street maps). Photographic views like Google Street View or Bing's bird's eye view are left as a choice to the programmer.

A crosshair or similar location-targeting graphic will overlay the map. It will remain stationary and the same size no matter how the user pans the map.

A text field, with a simple submit button with label like "Show" appear below the map. Upon creation the field will be filled with the greyed-out help text "Enter location". If the user enters a location in that field and presses the button, the maps' geocoding API will be used to try to find the location in question.

The geocoding API will of course vary depending on the maps provider used. If there are any providers for whom this service is not available then the field and button should be hidden.

The field should accept all the formats accepted by the geocoding API in question (hopefully place names, street addresses, and decimal latitude longitude pairs).

If the location is found, the map simply updates its view to show that location. The text entered into the box remains visible.

If the location is not found, an error message is shown in red near the text field (probably below it, or perhaps right on the map itself with appropriately opaque background). The error message will be somethng like "That location could not be found." The unfindable location remains visible in the text box. If the user makes any change to the text in that box, the error message disappears. The jQuery "validator" plugin may be useful in defining this behaviour.

Obtaining wikitext
The user does not take any special action to show wikitext. Instead, this will be handled by other scripts on the page (which initialized the map widget in the first place). The widget will define a getWikiText method, such that this sample scenario works.

upload.locator = $('div.loc').locator( options );

// Sometime later, get location information var wikiText = upload.locator.getWikiText;

At minimum, the wikitext should be a simple call to a Location template. If the map was centered on 149 New Montgomery, San Francisco, CA, the Location template might show:

question: relating zoom level to "scale". Maybe best to leave it.

It would be nice if this wikiText also had an embedded map (or could show one by pressing a button), but this is not required.