Author: kake Date: 2012-04-14 11:56:32 +0100 (Sat, 14 Apr 2012) New Revision: 1336
Added: trunk/static/map-leaflet.js trunk/t/94_leaflet.t trunk/templates/map_index_leaflet.tt Modified: trunk/Build.PL trunk/INSTALL trunk/MANIFEST trunk/README.GMAPS trunk/lib/OpenGuides.pm trunk/lib/OpenGuides/Config.pm trunk/t/13_cookies.t trunk/t/46_map_in_node_display.t trunk/t/53_show_index.t trunk/t/59_preferences.t trunk/templates/header.tt trunk/templates/node.tt trunk/templates/preferences.tt Log: Added support for using Leaflet instead of the Google Maps API.
Modified: trunk/Build.PL =================================================================== --- trunk/Build.PL 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/Build.PL 2012-04-14 10:56:32 UTC (rev 1336) @@ -46,7 +46,7 @@ my %yn_vars = map { $_ => 1 } qw(use_plucene enable_page_deletion navbar_on_home_page backlinks_in_title moderation_requires_password enable_node_image enable_common_categories - enable_common_locales recent_changes_on_home_page + enable_common_locales recent_changes_on_home_page use_leaflet random_page_omits_locales random_page_omits_categories content_above_navbar_in_html show_gmap_in_node_display force_wgs84 send_moderation_notifications read_only); @@ -97,6 +97,9 @@
my $install_directory; # used to suggest template paths my $use_plucene = 1; # keep track of this so we know what to put in prereqs +my $use_leaflet; # if true, we skip the GMaps questions +my %gmaps_vars = map { $_ => 1 } qw( gmaps_api_key centre_long centre_lat + default_gmaps_zoom default_gmaps_search_zoom ); my $centre_lat = ''; # contains centre lat derived from Google Maps URL foreach my $var ( qw( dbname dbuser dbpass dbhost dbport script_name @@ -106,8 +109,8 @@ recent_changes_on_home_page random_page_omits_locales random_page_omits_categories content_above_navbar_in_html home_name site_desc default_city default_country contact_email default_language - formatting_rules_node backlinks_in_title gmaps_api_key centre_long - centre_lat show_gmap_in_node_display default_gmaps_zoom + formatting_rules_node backlinks_in_title use_leaflet gmaps_api_key + centre_long centre_lat show_gmap_in_node_display default_gmaps_zoom default_gmaps_search_zoom force_wgs84 google_analytics_key licence_name licence_url licence_info_url moderation_requires_password enable_node_image enable_common_categories enable_common_locales @@ -148,6 +151,15 @@ next; }
+ # If we're using Leaflet, we can skip the GMaps stuff. Don't erase any + # previous answers from their config file though. + if ( $use_leaflet && $gmaps_vars{$var} ) { + push @answers, { question => $qu, + variable => $var, + value => $val }; + next; + } + # Make sensible suggestions for template paths if we don't already # have them stored. Not really a default, but a useful hint/shortcut. if ( $var eq "template_path" && !defined $existing_config->$var ) { @@ -197,6 +209,10 @@ # From Module::Build docs: ->y_n returns a Perl boolean true or false. $use_plucene = 1 if $var eq "use_plucene" and $val;
+ # If they've just chosen to use Leaflet, we won't need to ask any of the + # GMaps questions. + $use_leaflet = 1 if $var eq "use_leaflet" and $val; + # Make sure that script_url ends in a / if ( $var eq "script_url" and $val !~ //$/ ) { $val .= "/"; @@ -366,6 +382,7 @@ "header.tt", "home_node.tt", "map_index.tt", + "map_index_leaflet.tt", "missing_metadata.tt", "moderate_confirm.tt", "moderate_password_wrong.tt", @@ -402,7 +419,7 @@ ] );
$build->config_data( __static_files => [ - # XXX to be supplied when we have some + "map-leaflet.js", ] );
# Finally write the build script.
Modified: trunk/INSTALL =================================================================== --- trunk/INSTALL 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/INSTALL 2012-04-14 10:56:32 UTC (rev 1336) @@ -223,17 +223,37 @@ pages. This was the convention with older wikis ("C2" refers to the original wiki at http://c2.com/cgi/wiki), but is not intuitive.
+ "Do you want to use the Leaflet mapping library?" + +Answer "y" or "n", but "y" is recommended. In version 0.67 of OpenGuides, +we switched from using the Google Maps API to the open source Leaflet mapping +library. For now, Google Maps support is retained for legacy reasons, but is +deprecated and will be removed in the future. We therefore recommend that +you answer "y" to this question. + + "Would you like to display a map on every node that has geodata?" + +Answer "y" or "n". Note that an answer of "y" will only take effect if you've +either chosen to use the Leaflet mapping library, or you've supplied a Google +Maps API key. Note further that users can choose to turn this off in their +preferences. + "Do you have a Google Maps API key to use with this guide?"
-If you want Google Maps integration, you need to register with Google to get -an API key. Visit http://www.google.com/apis/maps/signup.html and follow the +As of version 0.67 of OpenGuides, we recommend using the Leaflet mapping +library instead of Google Maps - our Google Maps support is out of date and +no longer maintained. However, if you do want to use Google Maps, you need +to register with Google to get an API key. Visit +http://www.google.com/apis/maps/signup.html and follow the instructions. Paste the great long string into the console window where you are installing. See README.GMAPS for more information.
"What is the longitude of the centre point of a map to draw for your guide?" "What is the latitude of the centre point of a map to draw for your guide?"
-It's probably a good idea to pick some notionally central point for your +This is only necessary if you're using Google Maps - our Leaflet code will +figure this out for you. If you do choose to use Google Maps, it's probably +a good idea to pick some notionally central point for your guide. For example, Carfax for Oxford, Charing Cross for London. As a convenience, you may paste in a Google Maps URL for the centre longitude question and the (long,lat) will be parsed out from the URL. @@ -243,12 +263,6 @@
The defaults are probably appropriate in most cases.
- "Would you like to display a Google Map on every node that has geodata?" - -Answer "y" or "n". Note that an answer of "y" will only take effect if you've -supplied a Google Maps API key above. Note further that users can choose to -turn this off in their preferences. - "Forcibly treat stored lat/long data as if they used the WGS84 ellipsoid?"
Default this answer if you don't know what it means. @@ -336,7 +350,7 @@ Grid, and Geo::Coordinates::UTM to use a UTM ellipsoid.
If you want to use a UTM ellipsoid, WGS-84 is the best choice, as it -will allow you to use the Google Maps support with the minimum of fuss. +will allow you to use the mapping support with the minimum of fuss.
* Dependency errors
Modified: trunk/MANIFEST =================================================================== --- trunk/MANIFEST 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/MANIFEST 2012-04-14 10:56:32 UTC (rev 1336) @@ -27,6 +27,7 @@ newpage.cgi preferences.cgi search.cgi +static/map-leaflet.js templates/admin_home.tt templates/admin_revert_user.tt templates/autocreate_content.tt @@ -45,6 +46,7 @@ templates/header.tt templates/home_node.tt templates/map_index.tt +templates/map_index_leaflet.tt templates/missing_metadata.tt templates/metadata.tt templates/moderate_confirm.tt @@ -159,6 +161,7 @@ t/91_username_in_templates.t t/92_node_name_from_cgi_obj.t t/93_redirect_without_spaces.t +t/94_leaflet.t t/templates/15_test.tt wiki.cgi META.json
Modified: trunk/README.GMAPS =================================================================== --- trunk/README.GMAPS 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/README.GMAPS 2012-04-14 10:56:32 UTC (rev 1336) @@ -1,3 +1,16 @@ +NOTE: as of version 0.67, OpenGuides has switched from the Google Maps API +to the open source Leaflet mapping library. Our Google Maps support is +out of date and no longer maintained. To ensure you're using the latest +mapping code, set + + use_leaflet = 1 + +in your wiki.conf. + +The instructions below are retained for the benefit of legacy users. + +---------------------------------------------------------------------- + As of 0.52, OpenGuides supports Google Maps using the API. The support has a few rough edges that still need ironing out, mostly relating to ellipsoids, and for that reason they aren't exposed by default.
Modified: trunk/lib/OpenGuides/Config.pm =================================================================== --- trunk/lib/OpenGuides/Config.pm 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/lib/OpenGuides/Config.pm 2012-04-14 10:56:32 UTC (rev 1336) @@ -20,7 +20,7 @@ default_language http_charset ping_services formatting_rules_node formatting_rules_link backlinks_in_title template_path custom_template_path geo_handler ellipsoid gmaps_api_key centre_long - show_gmap_in_node_display google_analytics_key + show_gmap_in_node_display google_analytics_key use_leaflet centre_lat default_gmaps_zoom default_gmaps_search_zoom force_wgs84 licence_name licence_url licence_info_url moderation_requires_password moderate_whitelist @@ -104,6 +104,7 @@ backlinks_in_title => 0, geo_handler => 1, ellipsoid => "WGS-84", + use_leaflet => 0, show_gmap_in_node_display => 1, centre_long => 0, centre_lat => 0, @@ -188,12 +189,13 @@ formatting_rules_link => "What URL do you want to use for the text formatting rules (leave blank to use a wiki node instead)?", backlinks_in_title => "Make node titles link to node backlinks (C2 style)?", ellipsoid => "Which ellipsoid do you want to use? (eg 'Airy', 'WGS-84')", - gmaps_api_key => "Do you have a Google Maps API key to use with this guide? If you enter it here the Google Maps functionality will be automatically enabled.", - centre_long => "What is the longitude of the centre point of a map to draw for your guide? (This question can be ignored if you aren't using Google Maps). You may paste in a Google Maps URL here (hint: copy URL from 'Link to this page')", - centre_lat => "What is the latitude of the centre point of a map to draw for your guide? (This question can be ignored if you aren't using Google Maps)", + use_leaflet => "Do you want to use the Leaflet mapping library? (this is recommended)", + gmaps_api_key => "Do you have a Google Maps API key to use with this guide? If so, enter it here. (Note: our Google Maps support is deprecated, and we recommend you choose to use Leaflet instead.)", + centre_long => "What is the longitude of the centre point of a map to draw for your guide? (This question can be ignored if you aren't using Google Maps - we recommend you use Leaflet instead, as our Leaflet code will figure this out for you.) You may paste in a Google Maps URL here (hint: copy URL from 'Link to this page')", + centre_lat => "What is the latitude of the centre point of a map to draw for your guide? (This question can be ignored if you aren't using Google Maps - we recommend you use Leaflet instead, as our Leaflet code will figure this out for you.)", default_gmaps_zoom => "What default zoom level shall we use for Google Maps? (This question can be ignored if you aren't using Google Maps)", default_gmaps_search_zoom => "What default zoom level shall we use for Google Maps in the search results? (This question can be ignored if you aren't using Google Maps)", - show_gmap_in_node_display => "Would you like to display a Google Map on every node that has geodata? (This question can be ignored if you aren't using Google Maps)", + show_gmap_in_node_display => "Would you like to display a map on every node that has geodata?", force_wgs84 => "Forcibly treat stored lat/long data as if they used the WGS84 ellipsoid?", google_analytics_key => "Do you have a Google Analytics key to use with this guide? If you enter it here, then Google Analytics functionality will be automatically enabled.", licence_name => "What licence will you use for the guide?", @@ -309,6 +311,8 @@
=item * ellipsoid (default: C<WGS-84>)
+=item * use_leaflet + =item * gmaps_api_key
=item * centre_long @@ -337,8 +341,18 @@
=item * static_path
-=item * static_url +=item * static_url (this is constrained to always end in C</>)
+=cut + +sub static_url { + my $self = shift; + # See perldoc Class::Accessor - can't just use SUPER. + my $url = $self->_static_url_accessor( @_ ); + $url .= "/" unless (defined $url && $url =~ //$/); + return $url; +} + =item * send_moderation_notifications
=item * moderate_whitelist @@ -355,7 +369,7 @@
=head1 COPYRIGHT
- Copyright (C) 2004-2010 The OpenGuides Project. All Rights Reserved. + Copyright (C) 2004-2012 The OpenGuides Project. All Rights Reserved.
The OpenGuides distribution is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Modified: trunk/lib/OpenGuides.pm =================================================================== --- trunk/lib/OpenGuides.pm 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/lib/OpenGuides.pm 2012-04-14 10:56:32 UTC (rev 1336) @@ -14,7 +14,7 @@
use vars qw( $VERSION );
-$VERSION = '0.66'; +$VERSION = '0.67';
=head1 NAME
@@ -872,6 +872,14 @@ return_output => 1, );
+ # Or return the template variables (again, useful for writing tests). + $guide->show_index( + type => "category", + value => "pubs", + format => "map" + return_tt_vars => 1, + ); + If either the C<type> or the C<value> parameter is omitted, then all pages will be returned.
@@ -881,6 +889,7 @@ my ($self, %args) = @_; my $wiki = $self->wiki; my $formatter = $wiki->formatter; + my $use_leaflet = $self->config->use_leaflet; my %tt_vars; my @selnodes;
@@ -927,7 +936,9 @@ param => $formatter->node_name_to_node_param($_) } } sort @selnodes;
- # Convert the lat+long to WGS84 as required + # Convert the lat+long to WGS84 as required. If displaying a map + # using Leaflet, also grab the min and max lat and long. + my ( $min_lat, $max_lat, $min_long, $max_long ); for(my $i=0; $i<scalar @nodes;$i++) { my $node = $nodes[$i]; if($node) { @@ -943,6 +954,28 @@
push @{$nodes[$i]->{node_data}->{metadata}->{wgs84_long}}, $wgs84_long; push @{$nodes[$i]->{node_data}->{metadata}->{wgs84_lat}}, $wgs84_lat; + if ( $use_leaflet ) { + if ( defined $wgs84_lat && $wgs84_lat =~ /^[-.\d]+$/ + && defined $wgs84_long && $wgs84_long =~ /^[-.\d]+$/ ) { + $node->{has_geodata} = 1; + $node->{wgs84_lat} = $wgs84_lat; + $node->{wgs84_long} = $wgs84_long; + if ( !defined $min_lat ) { + $min_lat = $max_lat = $wgs84_lat; + } elsif ( $wgs84_lat < $min_lat ) { + $min_lat = $wgs84_lat; + } elsif ( $wgs84_lat > $max_lat ) { + $max_lat = $wgs84_lat; + } + if ( !defined $min_long ) { + $min_long = $max_long = $wgs84_long; + } elsif ( $wgs84_long < $min_long ) { + $min_long = $wgs84_long; + } elsif ( $wgs84_long > $max_long ) { + $max_long = $wgs84_long; + } + } + } } }
@@ -961,18 +994,32 @@ $template = "plain_index.tt"; $conf{content_type} = "text/plain"; } elsif ( $args{format} eq "map" ) { - my $q = CGI->new; - $tt_vars{zoom} = $q->param('zoom') || ''; - $tt_vars{lat} = $q->param('lat') || ''; - $tt_vars{long} = $q->param('long') || ''; - $tt_vars{map_type} = $q->param('map_type') || ''; - $tt_vars{centre_long} = $self->config->centre_long; - $tt_vars{centre_lat} = $self->config->centre_lat; - $tt_vars{default_gmaps_zoom} = $self->config->default_gmaps_zoom; - $tt_vars{enable_gmaps} = 1; $tt_vars{display_google_maps} = 1; # override for this page - $template = "map_index.tt"; - + if ( $use_leaflet ) { + if ( defined $min_lat ) { + %tt_vars = ( %tt_vars, + min_lat => $min_lat, + max_lat => $max_lat, + min_long => $min_long, + max_long => $max_long, + centre_lat => ( ( $max_lat + $min_lat ) / 2 ), + centre_long => ( ( $max_long + $min_long ) / 2 ), + ); + } + $template = "map_index_leaflet.tt"; + } else { + my $q = CGI->new; + $tt_vars{zoom} = $q->param('zoom') || ''; + $tt_vars{lat} = $q->param('lat') || ''; + $tt_vars{long} = $q->param('long') || ''; + $tt_vars{map_type} = $q->param('map_type') || ''; + $tt_vars{centre_long} = $self->config->centre_long; + $tt_vars{centre_lat} = $self->config->centre_lat; + $tt_vars{default_gmaps_zoom} + = $self->config->default_gmaps_zoom; + $tt_vars{enable_gmaps} = 1; + $template = "map_index.tt"; + } } elsif( $args{format} eq "rss" || $args{format} eq "atom") { # They really wanted a recent changes style rss/atom feed my $feed_type = $args{format}; @@ -1000,6 +1047,8 @@ $template = "site_index.tt"; }
+ return %tt_vars if $args{return_tt_vars}; + %conf = ( %conf, template => $template,
Added: trunk/static/map-leaflet.js =================================================================== --- trunk/static/map-leaflet.js (rev 0) +++ trunk/static/map-leaflet.js 2012-04-14 10:56:32 UTC (rev 1336) @@ -0,0 +1,55 @@ +var centre_lat, centre_long, map, map_div_id; +var positions = [], markers = []; + +var gicon = L.Icon.extend( { + iconUrl: 'http://maps.google.com/mapfiles/ms/micons/red-dot.png', + shadowUrl: null, + iconSize: new L.Point( 32, 32 ), + iconAnchor: new L.Point( 15, 32 ), + popupAnchor: new L.Point( 0, -40 ) +} ); + +$( + function() { + if ( map_div_id && centre_lat && centre_long ) { + map = new L.Map( map_div_id ); + var map_centre = new L.LatLng( centre_lat, centre_long ); + + var mq_url = 'http://%7Bs%7D.mqcdn.com/tiles/1.0.0/osm/%7Bz%7D/%7Bx%7D/%7By%7D.png'; + var subdomains = [ 'otile1', 'otile2', 'otile3', 'otile4' ]; + var attrib = 'Data, imagery and map information provided by <a href="http://open.mapquest.co.uk" target="_blank">MapQuest</a>, <a href="http://www.openstreetmap.org/" target="_blank">OpenStreetMap</a> and contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a>'; + + var tile_layer = new L.TileLayer( mq_url, { maxZoom: 18, attribution: attrib, subdomains: subdomains } ); + + map.setView( map_centre, 13 ).addLayer( tile_layer ); + + add_markers(); + } + } +); + +function add_marker( i, node ) { + var content, marker, position; + + // This should have already been checked, but no harm in checking again. + if ( !node.lat || !node.long ) { + return; + } + + position = new L.LatLng( node.lat, node.long ); + + marker = new L.Marker( position, { icon: new gicon() } ); + map.addLayer( marker ); + + content = node.name; + marker.bindPopup( content ); + + markers[ i ] = marker; + positions[ i ] = position; +} + +function show_marker( i ) { + markers[ i ].openPopup(); + map.panTo( positions[ i ] ); + return false; +}
Modified: trunk/t/13_cookies.t =================================================================== --- trunk/t/13_cookies.t 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/t/13_cookies.t 2012-04-14 10:56:32 UTC (rev 1336) @@ -68,7 +68,7 @@ is( $prefs{track_recent_changes_views}, "rc_pref", "...and recent changes tracking" ); is( $prefs{display_google_maps}, "gm_pref", - "...and Google Maps display preference" ); + "...and map display preference" ); is( $prefs{is_admin}, "admin_pref", "...and admin preference" ); # Now make sure that true/false preferences are taken account of when
Modified: trunk/t/46_map_in_node_display.t =================================================================== --- trunk/t/46_map_in_node_display.t 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/t/46_map_in_node_display.t 2012-04-14 10:56:32 UTC (rev 1336) @@ -16,7 +16,7 @@ exit 0; }
-plan tests => 4; +plan tests => 10;
my ( $config, $guide, $wiki, $cookie, $output );
@@ -36,8 +36,9 @@ os_y => 180000, );
-# Maps shouldn't show up if there's no API key. +# Maps shouldn't show up if there's no API key and we're not using Leaflet. $config->show_gmap_in_node_display( 1 ); +$config->use_leaflet( 0 ); $cookie = OpenGuides::CGI->make_prefs_cookie( config => $config, display_google_maps => 1, @@ -50,9 +51,9 @@ ); $output =~ s/^Content-Type.*[\r\n]+//m; Test::HTML::Content::no_tag( $output, "div", { id => "map" }, - "Google map omitted from node if no API key" ); + "Map omitted from node if no API key and not using Leaflet" );
-# And they should if there is. +# And they should if there is a Google API key. $config->gmaps_api_key( "This is not a real API key." ); $output = $guide->display_node( id => "Red Lion", @@ -60,7 +61,7 @@ ); $output =~ s/^Content-Type.*[\r\n]+//m; Test::HTML::Content::tag_ok( $output, "div", { id => "map" }, - "Google map shown on node if we have an API key"); + "Map shown on node if we have a Google API key");
# But not if the user doesn't want them. $cookie = OpenGuides::CGI->make_prefs_cookie( @@ -90,3 +91,60 @@ $output =~ s/^Content-Type.*[\r\n]+//m; Test::HTML::Content::no_tag( $output, "div", { id => "map" }, "...and not if the admin turned it off" ); + +# Now test with Leaflet. +$cookie = OpenGuides::CGI->make_prefs_cookie( + config => $config, display_google_maps => 1 ); +$ENV{HTTP_COOKIE} = $cookie; +$config->gmaps_api_key( "I still have a key but don't expect to use it" ); +$config->show_gmap_in_node_display( 1 ); +$config->use_leaflet( 1 ); + +# Shouldn't get any of the GMap stuff. +$output = $guide->display_node( + id => "Red Lion", + return_output => 1, + ); +unlike( $output, qr|new GMap|, + "No invocation of GMap constructor when using Leaflet" ); +unlike ( $output, qr|new GPoint|, "...nor GPoint" ); +unlike ( $output, qr|new GIcon|, "...nor GIcon" ); + +# Map should show in node if we're using Leaflet and have no GMap API key. +$config->gmaps_api_key( "" ); +$output = $guide->display_node( + id => "Red Lion", + return_output => 1, + ); +$output =~ s/^Content-Type.*[\r\n]+//m; +Test::HTML::Content::tag_ok( $output, "div", { id => "node_map_canvas" }, + "Map shown on node if using Leaflet"); + +# But not if the user doesn't want them. +$cookie = OpenGuides::CGI->make_prefs_cookie( + config => $config, + display_google_maps => 0, + ); +$ENV{HTTP_COOKIE} = $cookie; +$output = $guide->display_node( + id => "Red Lion", + return_output => 1, + ); +$output =~ s/^Content-Type.*[\r\n]+//m; +Test::HTML::Content::no_tag( $output, "div", { id => "map" }, + "...but not if the user turned it off" ); + +# And not if the admin doesn't want them. +$config->show_gmap_in_node_display( 0 ); +$cookie = OpenGuides::CGI->make_prefs_cookie( + config => $config, + display_google_maps => 1, + ); +$ENV{HTTP_COOKIE} = $cookie; +$output = $guide->display_node( + id => "Red Lion", + return_output => 1, + ); +$output =~ s/^Content-Type.*[\r\n]+//m; +Test::HTML::Content::no_tag( $output, "div", { id => "map" }, + "...and not if the admin turned it off" );
Modified: trunk/t/53_show_index.t =================================================================== --- trunk/t/53_show_index.t 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/t/53_show_index.t 2012-04-14 10:56:32 UTC (rev 1336) @@ -11,10 +11,10 @@ plan skip_all => "DBD::SQLite could not be used - no database to test with ($error)"; }
-plan tests => 23; # 25 when all enabled +plan tests => 27; # 29 when all enabled
# Clear out the database from any previous runs. - OpenGuides::Test::refresh_db(); +OpenGuides::Test::refresh_db();
my $config = OpenGuides::Test->make_basic_config; $config->script_name( "wiki.cgi" ); @@ -107,23 +107,42 @@ };
SKIP: { - skip "No Helmert Transform provider installed, can't test geo stuff", 6 + skip "No Helmert Transform provider installed, can't test geo stuff", 10 unless $has_helmert;
+ # This is testing the legacy stuff. + $config->use_leaflet( 0 ); + $output = eval { $guide->show_index( return_output => 1, format => "map", ); }; - is( $@, "", "->show_index doesn't die when asked for map" ); + is( $@, "", "Using GMaps: ->show_index doesn't die when asked for map" ); like( $output, qr|Content-Type: text/html|, - "Map output gets content-type of text/html" ); - like( $output, qr|new GMap|, "Really is google map" ); + "...map output gets content-type of text/html" ); + like( $output, qr|new GMap|, "...really is google map" ); my @points = ($output =~ /point\d+ = (new GPoint(.*?, .*?))/g); - is( 1, scalar @points, "Right number of nodes included on map" ); + is( 1, scalar @points, "...right number of nodes included on map" );
# -1.259687,51.754813 - like( $points[0], qr|51.75481|, "Has latitude"); - like( $points[0], qr|-1.25968|, "Has longitude"); + like( $points[0], qr|51.75481|, "...has latitude"); + like( $points[0], qr|-1.25968|, "...has longitude"); + + # But we don't want the GMaps stuff if we're using Leaflet. + $config->use_leaflet( 1 ); + + $output = eval { + $guide->show_index( + return_output => 1, + format => "map", + ); + }; + + is( $@, "", "Using Leaflet: ->show_index doesn't die when asked for map" ); + like( $output, qr|Content-Type: text/html|, + "...map output gets content-type of text/html" ); + unlike( $output, qr|new GMap|, "...no invocation of GMap constructor" ); + unlike ( $output, qr|new GPoint|, "...nor GPoint" ); }
Modified: trunk/t/59_preferences.t =================================================================== --- trunk/t/59_preferences.t 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/t/59_preferences.t 2012-04-14 10:56:32 UTC (rev 1336) @@ -23,7 +23,7 @@ exit 0; }
-plan tests => 2; +plan tests => 4;
OpenGuides::Test::refresh_db();
@@ -31,6 +31,8 @@ my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki;
+# If we have a google API key and node maps are enabled, we should see the +# checkbox for this pref. $config->gmaps_api_key( "This is not a real API key." ); $config->show_gmap_in_node_display( 1 );
@@ -39,20 +41,35 @@ display_google_maps => 1, ); $ENV{HTTP_COOKIE} = $cookie; +Test::HTML::Content::tag_ok( get_output($wiki, $config), + "input", { type => "checkbox", name => "display_google_maps" }, + "Node map preference checkbox shown when we have a GMaps API key." );
-# If the google API is present and node maps are enabled, we should have the pref -Test::HTML::Content::tag_ok( get_output($wiki, $config), 'input', - { type => 'checkbox', name => 'display_google_maps' }, - 'Google maps pref shown' - ); - # But not if the node map is globally disabled $config->show_gmap_in_node_display( 0 ); -Test::HTML::Content::no_tag( get_output($wiki, $config), 'input', - { type => 'checkbox', name => 'display_google_maps' }, - 'No google maps prefs if node maps disabled' - ); +Test::HTML::Content::no_tag( get_output($wiki, $config), + "input", { type => "checkbox", name => "display_google_maps" }, + "...but not when node maps are globally disabled." );
+# Now test with Leaflet enabled and no Google API key. +$config->gmaps_api_key( "" ); +$config->show_gmap_in_node_display( 1 ); +$config->use_leaflet( 1 ); + +my $cookie = OpenGuides::CGI->make_prefs_cookie( + config => $config, + display_google_maps => 1, + ); +$ENV{HTTP_COOKIE} = $cookie; +Test::HTML::Content::tag_ok( get_output($wiki, $config), + "input", { type => "checkbox", name => "display_google_maps" }, + "Node map preference checkbox shown when we're using Leaflet." ); + +$config->show_gmap_in_node_display( 0 ); +Test::HTML::Content::no_tag( get_output($wiki, $config), + "input", { type => "checkbox", name => "display_google_maps" }, + "...but not when node maps are globally disabled." ); + sub get_output { my ($wiki, $config) = @_;
Added: trunk/t/94_leaflet.t =================================================================== --- trunk/t/94_leaflet.t (rev 0) +++ trunk/t/94_leaflet.t 2012-04-14 10:56:32 UTC (rev 1336) @@ -0,0 +1,151 @@ +use strict; +use OpenGuides; +use OpenGuides::CGI; +use OpenGuides::Test; +use Test::More; + +eval { require DBD::SQLite; }; +if ( $@ ) { + my ($error) = $@ =~ /^(.*?)\n/; + plan skip_all => + "DBD::SQLite could not be used - no database to test with. ($error)"; +} + +plan tests => 18; + +my $config = OpenGuides::Test->make_basic_config; +$config->static_url( "http://example.com/static" ); +my $guide = OpenGuides->new( config => $config ); +my $wiki = $guide->wiki; + +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + +# Write a couple of nodes, two with legitimate geodata, another with +# broken geodata, another with no geodata. +OpenGuides::Test->write_data( + guide => $guide, + node => "Red Lion", + address => "High Street", + latitude => 51.4, + longitude => -0.2, + locales => "Croydon\r\nWaddon", + return_output => 1, + ); + +OpenGuides::Test->write_data( + guide => $guide, + node => "Blue Lion", + latitude => 51.6, + longitude => 0.6, + locales => "Croydon", + return_output => 1, + ); + +# We have to write this one using Wiki::Toolkit, since OpenGuides now has +# checks for bad geodata - but we still want to test it, since someone might +# have old data in their database. +$wiki->write_node( "Broken Lion", "Here is some content.", undef, { + latitude => "51d 32m 31.94s", + longitude => "0d 0m 8.23s", + locale => "Croydon" + } ) + or die "Can't write node."; + +OpenGuides::Test->write_data( + guide => $guide, + node => "Lost Lion", + locales => "Croydon\r\nAddiscombe", + return_output => 1, + ); + +# Make sure we include the GMaps JavaScript if we're not using Leaflet and +# we've included an API key. +$config->use_leaflet( 0 ); +$config->gmaps_api_key( "I like using deprecated code" ); + +my $output = $guide->display_node( id => "Red Lion", return_output => 1 ); +like( $output, qr/<script.*I like using deprecated code/, + "GMaps JavaScript included when Leaflet switched off and GMaps API key " + . "supplied." ); + +# Conversely, if we are using Leaflet then we need its JS but not GMaps', and +# we also need our own. +$config->use_leaflet( 1 ); +$output = $guide->display_node( id => "Red Lion", return_output => 1 ); +unlike( $output, qr/<script.*I like using deprecated code/, + "...but not when Leaflet switched on." ); +like( $output, qr|http://code.leafletjs.com/.*leaflet.js%7C, + "Leaflet JavaScript is included when Leaflet switched on." ); +like( $output, qr|http://example.com/static/map-leaflet.js%7C, + "...as is our own Leaflet map JavaScript." ); + +# Make sure the map doesn't try to show nodes with missing or broken geodata. +my %tt_vars = $guide->show_index( type => "locale", value => "Croydon", + format => "map", return_tt_vars => 1 ); +my @nodes = @{$tt_vars{nodes}}; +is( scalar @nodes, 4, "Right number of nodes in TT variables." ); +my %node_hash = map { $_->{name} => $_ } @nodes; +ok( !$node_hash{"Broken Lion"}{has_geodata}, + "Nodes with broken geodata don't have has_geodata set." ); +ok( !$node_hash{"Lost Lion"}{has_geodata}, + "Nodes with no geodata don't have has_geodata set." ); + +# And check again in the HTML, in case of template bugs. +$output = $guide->show_index( type => "locale", value => "Croydon", + format => "map", return_output => 1 ); +unlike( $output, qr|name:\s*Lost\s+Lion|, + "Nodes with no geodata are not passed to JavaScript object." ); + +# Check geodata variables for nodes that do have such data. +ok( $node_hash{"Red Lion"}{has_geodata}, + "Nodes with geodata have has_geodata set" ); +ok( $node_hash{"Red Lion"}{wgs84_lat}, + "Nodes with geodata have wgs84_lat set" ); +ok( $node_hash{"Red Lion"}{wgs84_long}, + "Nodes with geodata have wgs84_long set" ); + +# Make sure the centre of the map is set properly. +is( $tt_vars{centre_lat}, 51.5, "centre_lat set correctly" ); +is( $tt_vars{centre_long}, 0.2, "centre_long set correctly" ); + +# Make sure name and address are passed through to the JavaScript for adding +# markers to the map. +$output = $guide->show_index( type => "locale", value => "Waddon", + format => "map", return_output => 1 ); +like( $output, qr/name:\s*'Red\s+Lion'/, "Name added to JavaScript object." ); +like( $output, qr/address:\s*'High\s+Street'/, + "Address added to JavaScript object." ); + +# Make sure nodes with no geodata get linked to despite not being on the map. +$output = $guide->show_index( type => "locale", value => "Addiscombe", + format => "map", return_output => 1 ); +like( $output, qr|Lost_Lion|, "Nodes with no geodata still get linked." ); + +# Make sure nodes with zero lat or long still have has_geodata set. +OpenGuides::Test->write_data( + guide => $guide, + node => "Zero Lat", + latitude => 0, + longitude => -0.2, + locales => "Zero Land", + return_output => 1, + ); + +OpenGuides::Test->write_data( + guide => $guide, + node => "Zero Long", + latitude => 51.6, + longitude => 0, + locales => "Zero Land", + return_output => 1, + ); + +%tt_vars = $guide->show_index( type => "locale", value => "Zero Land", + format => "map", return_tt_vars => 1 ); +@nodes = @{$tt_vars{nodes}}; +%node_hash = map { $_->{name} => $_ } @nodes; +ok( $node_hash{"Zero Lat"}{has_geodata}, + "Nodes with zero latitude have has_geodata set." ); +ok( $node_hash{"Zero Long"}{has_geodata}, + "Nodes with zero longitude have has_geodata set." );
Modified: trunk/templates/header.tt =================================================================== --- trunk/templates/header.tt 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/templates/header.tt 2012-04-14 10:56:32 UTC (rev 1336) @@ -26,9 +26,17 @@ locales.size > 0 %][% FOREACH locale = locales %][% locale.name %][%- ", " UNLESS loop.last %][% END %][% END %]" /> [% END %] + [% IF stylesheet %] <link rel="stylesheet" href="[% stylesheet %]" type="text/css" title="Stylesheet for [% site_name %]" /> [% END %] + [% IF config.use_leaflet %] + <link rel="stylesheet" href="http://code.leafletjs.com/leaflet-0.3.1/leaflet.css" /> + <!--[if lte IE 8]> + <link rel="stylesheet" href="http://code.leafletjs.com/leaflet-0.3.1/leaflet.ie.css" /> + <![endif]--> + [% END %] + [% IF feed_base %] <link rel="alternate" type="application/rss+xml" title="Page as RSS" href="[% feed_base %];format=rss" /> <link rel="alternate" type="application/atom+xml" title="Page as Atom" href="[% feed_base %];format=atom" /> @@ -59,8 +67,19 @@ <link rel="alternate" type="application/wiki" title="Edit this page!" href="[% source_site or full_cgi_url %]?id=[% node_param %];action=edit"> [% END %] - [% IF enable_gmaps AND display_google_maps AND gmaps_api_key %] - <script src="http://maps.google.com/maps?file=api&v=2&key=[% gmaps_api_key %]" type="text/javascript"></script> + + [% IF display_google_maps %] + [% IF config.use_leaflet %] + <script + src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" + type="text/javascript"></script> + <script src="http://code.leafletjs.com/leaflet-0.3.1/leaflet.js" + type="text/javascript"></script> + <script src="[% config.static_url %]map-leaflet.js" + type="text/javascript"></script> + [% ELSIF enable_gmaps AND gmaps_api_key %] + <script src="http://maps.google.com/maps?file=api&v=2&key=[% gmaps_api_key %]" type="text/javascript"></script> + [% END %] [% END %]
[% TRY %] @@ -71,7 +90,8 @@ </head> <body> <div id="body_wrapper"> - [% IF enable_gmaps AND display_google_maps AND gmaps_api_key %] + [% IF !config.use_leaflet AND enable_gmaps AND display_google_maps + AND gmaps_api_key %] <script defer="defer" type="text/javascript"> //<![CDATA[ var baseIcon = new GIcon();
Added: trunk/templates/map_index_leaflet.tt =================================================================== --- trunk/templates/map_index_leaflet.tt (rev 0) +++ trunk/templates/map_index_leaflet.tt 2012-04-14 10:56:32 UTC (rev 1336) @@ -0,0 +1,57 @@ +[% INCLUDE header.tt page_title = criterion.name || "Map of all nodes" %] +[% INCLUDE banner.tt %] +<div id="content"> + + <div id="maincontent"> + + <div id="map_index_node_list" style="height:400px; overflow:auto;float:right; width:30%"> + <ul> + [% i = 0 %] + [% FOREACH node = nodes %] + [% i = i + 1 %] + <li> + [% IF node.has_geodata %] + <a href="#" onclick="return show_marker( [% i %] )">[% node.name | html %]</a> + [% ELSE %] + [% node.name | html %] (not on map — + <a href="?[% node.param %]">view info</a>) + [% END %] + </li> + [% END %] + </ul> + </div> + + <div id="map_index_canvas" style="width:60%; height:450px"></div> + + <script type="text/javascript"> + + map_div_id = 'map_index_canvas'; + centre_lat = [% centre_lat %]; + centre_long = [% centre_long %]; + + function add_markers() { + var node; + [% i = 0 %] + [% FOREACH node = nodes %] + [% i = i + 1 %] + [% IF node.has_geodata %] + node = { + name: '[% node.name | html %]', + param: '[% node.param %]', + [% address = node.node_data.metadata.address.list.first %] + [% IF address %] + address: '[% address | html %]', + [% END %] + lat: [% node.wgs84_lat %], + long: [% node.wgs84_long %], + }; + add_marker( [% i %], node ); + [% END %] + [% END %] + } + </script> + + </div> +</div> + +[% INCLUDE footer.tt %]
Modified: trunk/templates/node.tt =================================================================== --- trunk/templates/node.tt 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/templates/node.tt 2012-04-14 10:56:32 UTC (rev 1336) @@ -16,21 +16,36 @@ <div id="redirect_message">(redirected from <a href="[% full_cgi_url %]?id=[% oldid %];redirect=0">[% oldid.replace('_', ' ') %]</a>)</div> [% END %]
-[% IF wgs84_lat AND wgs84_long AND display_google_maps and gmaps_api_key %] - <div id="map" style="float:right; width: 300px; height: 200px"></div> - <script defer="defer" type="text/javascript"> - //<![CDATA[ - var map = new GMap(document.getElementById("map")); - map.addControl(new GSmallMapControl()); - map.centerAndZoom(new GPoint([% wgs84_long %], [% wgs84_lat %]), 3); - var point0 = new GPoint([% wgs84_long %], [% wgs84_lat %]); - var marker0 = new GMarker(point0,baseIcon); - GEvent.addListener(marker0, "click", function() { - marker0.openInfoWindowHtml("[% node_name %]"); - }); - map.addOverlay(marker0); - //]]> - </script> +[% IF wgs84_lat AND wgs84_long AND display_google_maps %] + [% IF config.use_leaflet %] + <div id="node_map_canvas" style="float:right; width: 300px; height: 200px"></div> + <script type="text/javascript"> + map_div_id = 'node_map_canvas'; + centre_lat = [% wgs84_lat %]; + centre_long = [% wgs84_long %]; + function add_markers() { + var position = new L.LatLng( [% wgs84_lat %], [% wgs84_long %] ); + marker = new L.Marker( position, { icon: new gicon() } ); + map.addLayer( marker ); + marker.bindPopup( '[% node_name %]' ); + } + </script> + [% ELSIF gmaps_api_key %] + <div id="map" style="float:right; width: 300px; height: 200px"></div> + <script defer="defer" type="text/javascript"> + //<![CDATA[ + var map = new GMap(document.getElementById("map")); + map.addControl(new GSmallMapControl()); + map.centerAndZoom(new GPoint([% wgs84_long %], [% wgs84_lat %]), 3); + var point0 = new GPoint([% wgs84_long %], [% wgs84_lat %]); + var marker0 = new GMarker(point0,baseIcon); + GEvent.addListener(marker0, "click", function() { + marker0.openInfoWindowHtml("[% node_name %]"); + }); + map.addOverlay(marker0); + //]]> + </script> + [% END %] [% END %]
[% IF node_image %]
Modified: trunk/templates/preferences.tt =================================================================== --- trunk/templates/preferences.tt 2012-04-13 18:34:45 UTC (rev 1335) +++ trunk/templates/preferences.tt 2012-04-14 10:56:32 UTC (rev 1336) @@ -75,14 +75,15 @@ <label for="track_recent_changes_views">Track my visits to Recent Changes and offer me a link for “changes since I last viewed Recent Changes”.</label> </p>
- [% IF gmaps_api_key AND config.show_gmap_in_node_display %] + [% IF ( config.use_leaflet OR gmaps_api_key ) + AND config.show_gmap_in_node_display %] <p> [% IF prefs.display_google_maps %] <input type="checkbox" id="display_google_maps" name="display_google_maps" value="1" checked="1" /> [% ELSE %] <input type="checkbox" id="display_google_maps" name="display_google_maps" value="1" /> [% END %] - <label for="display_google_maps">Display Google Maps.</label> + <label for="display_google_maps">Display a map on every page with geodata.</label> </p> [% END %]
@@ -165,10 +166,11 @@ [% UNLESS prefs.track_recent_changes_views %] not [% END %] be tracked.</p>
- [% IF prefs.gmaps_api_key AND config.show_gmap_in_node_display %] - <p>Google Maps will - [% UNLESS display_google_maps %] not [% END %] - be displayed.</p> + [% IF ( config.use_leaflet OR gmaps_api_key ) + AND config.show_gmap_in_node_display %] + <p>Maps will + [% UNLESS prefs.display_google_maps %] not [% END %] + be displayed on pages with geodata.</p> [% END %]
<p>Default edit type set to