diff options
Diffstat (limited to 'web')
-rwxr-xr-x | web/ajax.cgi | 2 | ||||
-rwxr-xr-x | web/alert.cgi | 48 | ||||
-rwxr-xr-x | web/confirm.cgi | 10 | ||||
-rwxr-xr-x | web/contact.cgi | 2 | ||||
-rwxr-xr-x | web/import.cgi | 1 | ||||
-rwxr-xr-x | web/index.cgi | 254 | ||||
-rw-r--r-- | web/js.js | 322 | ||||
-rw-r--r-- | web/js/OpenLayers.Projection.OrdnanceSurvey.js | 489 | ||||
-rw-r--r-- | web/js/map-OpenStreetMap.js | 150 | ||||
-rw-r--r-- | web/js/map-bing-ol.js | 96 | ||||
-rw-r--r-- | web/js/map-bing.js | 21 | ||||
-rw-r--r-- | web/js/map-google.js | 22 | ||||
-rw-r--r-- | web/js/map-streetview.js | 88 | ||||
-rw-r--r-- | web/js/map-tilma-ol.js | 42 | ||||
-rw-r--r-- | web/js/map-tilma.js | 320 | ||||
-rwxr-xr-x | web/questionnaire.cgi | 15 | ||||
-rwxr-xr-x | web/reports.cgi | 4 | ||||
-rw-r--r-- | web/robots.txt | 5 | ||||
-rwxr-xr-x | web/rss.cgi | 38 | ||||
-rwxr-xr-x | web/tms-signup.cgi | 1 |
20 files changed, 1423 insertions, 507 deletions
diff --git a/web/ajax.cgi b/web/ajax.cgi index fff437846..fa722f02e 100755 --- a/web/ajax.cgi +++ b/web/ajax.cgi @@ -35,7 +35,7 @@ sub main { unless ($input{all_pins}) { $interval = '6 months'; } - my ($pins, $on_map, $around_map, $dist) = Page::map_pins($q, $x, $y, $sx, $sy, $interval); + my ($pins, $on_map, $around_map, $dist) = FixMyStreet::Map::map_pins($q, $x, $y, $sx, $sy, $interval); my $cobrand = Page::get_cobrand($q); my $list = ''; my $link = ''; diff --git a/web/alert.cgi b/web/alert.cgi index 108a02683..71249759e 100755 --- a/web/alert.cgi +++ b/web/alert.cgi @@ -13,7 +13,8 @@ use Standard; use Digest::SHA1 qw(sha1_hex); use Error qw(:try); use CrossSell; -use mySociety::Alert; +use FixMyStreet::Alert; +use FixMyStreet::Geocode; use mySociety::AuthToken; use mySociety::Config; use mySociety::DBHandle qw(select_all); @@ -55,7 +56,7 @@ EOF } elsif ($q->param('type') && $q->param('feed')) { $title = _('Local RSS feeds and email alerts'); $out = alert_local_form($q); - } elsif ($q->param('pc') || ($q->param('x') && $q->param('y'))) { + } elsif ($q->param('pc') || ($q->param('e') && $q->param('n'))) { $title = _('Local RSS feeds and email alerts'); $out = alert_list($q); } else { @@ -63,7 +64,7 @@ EOF $out = alert_front_page($q); } - print Page::header($q, title => $title); + print Page::header($q, title => $title, robots => 'noindex,nofollow'); print $out; print Page::footer($q); } @@ -71,25 +72,22 @@ Page::do_fastcgi(\&main); sub alert_list { my ($q, @errors) = @_; - my @vars = qw(pc rznvy x y); + my @vars = qw(pc rznvy e n); my %input = map { $_ => scalar $q->param($_) } @vars; my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars; my($error, $e, $n); - my $x = $input{x}; my $y = $input{y}; - $x ||= 0; $x += 0; - $y ||= 0; $y += 0; - if ($x || $y) { - $e = Page::tile_to_os($input{x}); - $n = Page::tile_to_os($input{y}); + if ($input{e} || $input{n}) { + $e = $input{e}; + $n = $input{n}; } else { try { - ($x, $y, $e, $n, $error) = Page::geocode($input{pc}, $q); + ($e, $n, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q); } catch Error::Simple with { $error = shift; }; } - return Page::geocode_choice($error, '/alert', $q) if ref($error) eq 'ARRAY'; + return FixMyStreet::Geocode::list_choices($error, '/alert', $q) if ref($error) eq 'ARRAY'; return alert_front_page($q, $error) if $error; my $pretty_pc = $input_h{pc}; @@ -273,8 +271,8 @@ EOF rss_feed_5k => $rss_feed_5k, rss_feed_10k => $rss_feed_10k, rss_feed_20k => $rss_feed_20k, - x => $x, - y => $y, + e => $e, + n => $n, options => $options ); my $cobrand_page = Page::template_include('alert-options', $q, Page::template_root($q), %vars); $out = $cobrand_page if ($cobrand_page); @@ -446,8 +444,8 @@ sub alert_signed_input { my $out; my $cobrand = Page::get_cobrand($q); if ($signed_email eq sha1_hex("$id-$email-$salt-$secret")) { - my $alert_id = mySociety::Alert::create($email, 'new_updates', $cobrand, '', $id); - mySociety::Alert::confirm($alert_id); + my $alert_id = FixMyStreet::Alert::create($email, 'new_updates', $cobrand, '', $id); + FixMyStreet::Alert::confirm($alert_id); $out = $q->p(_('You have successfully subscribed to that alert.')); my $cobrand = Page::get_cobrand($q); my $display_advert = Cobrand::allow_crosssell_adverts($cobrand); @@ -476,14 +474,14 @@ sub alert_token { my $message; my $display_advert = Cobrand::allow_crosssell_adverts($cobrand); if ($type eq 'subscribe') { - mySociety::Alert::confirm($id); + FixMyStreet::Alert::confirm($id); $message = _('You have successfully confirmed your alert.'); $out = $q->p($message); if ($display_advert) { $out .= CrossSell::display_advert($q, $email); } } elsif ($type eq 'unsubscribe') { - mySociety::Alert::delete($id); + FixMyStreet::Alert::delete($id); $message = _('You have successfully deleted your alert.'); $out = $q->p($message); if ($display_advert) { @@ -517,22 +515,22 @@ sub alert_do_subscribe { my $cobrand_data = Cobrand::extra_alert_data($cobrand, $q); if ($type eq 'updates') { my $id = $q->param('id'); - $alert_id = mySociety::Alert::create($email, 'new_updates', $cobrand, $cobrand_data, $id); + $alert_id = FixMyStreet::Alert::create($email, 'new_updates', $cobrand, $cobrand_data, $id); } elsif ($type eq 'problems') { - $alert_id = mySociety::Alert::create($email, 'new_problems', $cobrand, $cobrand_data); + $alert_id = FixMyStreet::Alert::create($email, 'new_problems', $cobrand, $cobrand_data); } elsif ($type eq 'local') { my $feed = $q->param('feed'); if ($feed =~ /^area:(?:\d+:)?(\d+)/) { - $alert_id = mySociety::Alert::create($email, 'area_problems', $cobrand, $cobrand_data, $1); + $alert_id = FixMyStreet::Alert::create($email, 'area_problems', $cobrand, $cobrand_data, $1); } elsif ($feed =~ /^council:(\d+)/) { - $alert_id = mySociety::Alert::create($email, 'council_problems', $cobrand, $cobrand_data, $1, $1); + $alert_id = FixMyStreet::Alert::create($email, 'council_problems', $cobrand, $cobrand_data, $1, $1); } elsif ($feed =~ /^ward:(\d+):(\d+)/) { - $alert_id = mySociety::Alert::create($email, 'ward_problems', $cobrand, $cobrand_data, $1, $2); + $alert_id = FixMyStreet::Alert::create($email, 'ward_problems', $cobrand, $cobrand_data, $1, $2); } elsif ($feed =~ /^local:(\d+):(\d+)/) { - $alert_id = mySociety::Alert::create($email, 'local_problems', $cobrand, $cobrand_data, $1, $2); + $alert_id = FixMyStreet::Alert::create($email, 'local_problems', $cobrand, $cobrand_data, $1, $2); } } else { - throw mySociety::Alert::Error('Invalid type'); + throw FixMyStreet::Alert::Error('Invalid type'); } my %h = (); diff --git a/web/confirm.cgi b/web/confirm.cgi index cd874e9f0..daa260d65 100755 --- a/web/confirm.cgi +++ b/web/confirm.cgi @@ -12,7 +12,7 @@ use strict; use Standard; use Digest::SHA1 qw(sha1_hex); use CrossSell; -use mySociety::Alert; +use FixMyStreet::Alert; use mySociety::AuthToken; use mySociety::Random qw(random_bytes); @@ -115,8 +115,8 @@ sub confirm_update { # Subscribe updater to email updates if requested if ($add_alert) { - my $alert_id = mySociety::Alert::create($email, 'new_updates', $cobrand, $cobrand_data, $problem_id); - mySociety::Alert::confirm($alert_id); + my $alert_id = FixMyStreet::Alert::create($email, 'new_updates', $cobrand, $cobrand_data, $problem_id); + FixMyStreet::Alert::confirm($alert_id); } return $out; @@ -182,8 +182,8 @@ $q->p('<a href="/report/' . $id . '">' . _('View your report') . '</a>.'); } # Subscribe problem reporter to email updates - my $alert_id = mySociety::Alert::create($email, 'new_updates', $cobrand, $cobrand_data, $id); - mySociety::Alert::confirm($alert_id); + my $alert_id = FixMyStreet::Alert::create($email, 'new_updates', $cobrand, $cobrand_data, $id); + FixMyStreet::Alert::confirm($alert_id); return $out; } diff --git a/web/contact.cgi b/web/contact.cgi index 0b1a27c9f..fd0043d94 100755 --- a/web/contact.cgi +++ b/web/contact.cgi @@ -19,7 +19,7 @@ use mySociety::Random qw(random_bytes); # Main code for index.cgi sub main { my $q = shift; - print Page::header($q, title=>_('Contact Us'), context=>'contact'); + print Page::header($q, title=>_('Contact Us'), context=>'contact', robots => 'noindex,nofollow'); my $out = ''; if ($q->param('submit_form')) { $out = contact_submit($q); diff --git a/web/import.cgi b/web/import.cgi index f839bd5f5..2aede1697 100755 --- a/web/import.cgi +++ b/web/import.cgi @@ -11,6 +11,7 @@ use strict; use Error qw(:try); use Standard; +use Utils; use mySociety::AuthToken; use mySociety::EmailUtil; use mySociety::EvEl; diff --git a/web/index.cgi b/web/index.cgi index dcbec5a1c..83b3b421c 100755 --- a/web/index.cgi +++ b/web/index.cgi @@ -8,6 +8,7 @@ use strict; use Standard; +use Utils; use Error qw(:try); use File::Slurp; use LWP::Simple; @@ -16,6 +17,7 @@ use CGI::Carp; use URI::Escape; use CrossSell; +use FixMyStreet::Geocode; use mySociety::AuthToken; use mySociety::Config; use mySociety::DBHandle qw(select_all); @@ -80,7 +82,7 @@ sub main { } elsif ($q->param('id')) { ($out, %params) = display_problem($q, [], {}); $params{title} .= ' - ' . _('Viewing a problem'); - } elsif ($q->param('pc') || ($q->param('x') && $q->param('y'))) { + } elsif ($q->param('pc') || ($q->param('x') && $q->param('y')) || ($q->param('e') && $q->param('n'))) { ($out, %params) = display_location($q); $params{title} = _('Viewing a location'); } else { @@ -457,50 +459,34 @@ sub display_form { return display_location($q, @errors) unless ($pin_x && $pin_y) || ($input{easting} && $input{northing}) - || ($input{skipped} && $input{x} && $input{y}) || ($input{skipped} && $input{pc}) || ($input{partial} && $input{pc}); # Work out some co-ordinates from whatever we've got - my ($px, $py, $easting, $northing); + my ($easting, $northing); if ($input{skipped}) { # Map is being skipped - if ($input{x} && $input{y}) { - $easting = Page::tile_to_os($input{x}); - $northing = Page::tile_to_os($input{y}); + if ($input{easting} && $input{northing}) { + $easting = $input{easting}; + $northing = $input{northing}; } else { - my ($x, $y, $e, $n, $error) = Page::geocode($input{pc}, $q); + my ($e, $n, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q); $easting = $e; $northing = $n; } } elsif ($pin_x && $pin_y) { - # Map was clicked on - $pin_x = Page::click_to_tile($pin_tile_x, $pin_x); - $pin_y = Page::click_to_tile($pin_tile_y, $pin_y, 1); - $input{x} ||= int($pin_x); - $input{y} ||= int($pin_y); - $px = Page::tile_to_px($pin_x, $input{x}); - $py = Page::tile_to_px($pin_y, $input{y}, 1); - $easting = Page::tile_to_os($pin_x); - $northing = Page::tile_to_os($pin_y); + # tilma map was clicked on + ($easting, $northing) = FixMyStreet::Map::click_to_os($pin_tile_x, $pin_x, $pin_tile_y, $pin_y); } elsif ($input{partial} && $input{pc} && !$input{easting} && !$input{northing}) { - my ($x, $y, $error); + my $error; try { - ($x, $y, $easting, $northing, $error) = Page::geocode($input{pc}, $q); + ($easting, $northing, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q); } catch Error::Simple with { $error = shift; }; - return Page::geocode_choice($error, '/', $q) if ref($error) eq 'ARRAY'; + return FixMyStreet::Geocode::list_choices($error, '/', $q) if ref($error) eq 'ARRAY'; return front_page($q, $error) if $error; - $input{x} = int(Page::os_to_tile($easting)); - $input{y} = int(Page::os_to_tile($northing)); - $px = Page::os_to_px($easting, $input{x}); - $py = Page::os_to_px($northing, $input{y}, 1); } else { # Normal form submission - my ($x, $y, $tile_x, $tile_y); - ($x, $y, $tile_x, $tile_y, $px, $py) = Page::os_to_px_with_adjust($q, $input{easting}, $input{northing}, undef, undef); - $input{x} = $tile_x; - $input{y} = $tile_y; $easting = $input_h{easting}; $northing = $input_h{northing}; } @@ -589,22 +575,22 @@ please specify the closest point on land.')) unless %$all_councils; $vars{form_start} = <<EOF; <form action="$form_action" method="post" name="mapSkippedForm"$enctype> <input type="hidden" name="pc" value="$input_h{pc}"> -<input type="hidden" name="x" value="$input_h{x}"> -<input type="hidden" name="y" value="$input_h{y}"> <input type="hidden" name="skipped" value="1"> $cobrand_form_elements <div id="skipped-map"> EOF } else { - my $pins = Page::display_pin($q, $px, $py, 'purple'); my $type; if ($allow_photo_upload) { $type = 2; } else { $type = 1; } - $vars{form_start} = Page::display_map($q, x => $input{x}, 'y' => $input{y}, type => $type, - pins => $pins, px => $px, py => $py ); + $vars{form_start} = FixMyStreet::Map::display_map($q, + easting => $easting, northing => $northing, + type => $type, + pins => [ [ $easting, $northing, 'purple' ] ], + ); my $partial_id; if (my $token = $input{partial}) { $partial_id = mySociety::AuthToken::retrieve('partial', $token); @@ -770,41 +756,43 @@ EOF %vars = (%vars, category => $category, - map_end => Page::display_map_end(1), + map_end => FixMyStreet::Map::display_map_end(1), url_home => Cobrand::url($cobrand, '/', $q), submit_button => _('Submit') ); - return (Page::template_include('report-form', $q, Page::template_root($q), %vars)); + return (Page::template_include('report-form', $q, Page::template_root($q), %vars), robots => 'noindex,nofollow'); } sub display_location { my ($q, @errors) = @_; my $cobrand = Page::get_cobrand($q); - my @vars = qw(pc x y all_pins no_pins); + my @vars = qw(pc x y e n all_pins no_pins); my %input = map { $_ => $q->param($_) || '' } @vars; my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars; - if ($input{y} =~ /favicon/) { - my $base = mySociety::Config::get('BASE_URL'); - print $q->redirect(-location => $base . '/favicon.ico', -status => 301); - return ''; - } - my($error, $easting, $northing); + + (my $easting) = $input{e} =~ /^(\d+)/; $easting ||= 0; + (my $northing) = $input{n} =~ /^(\d+)/; $northing ||= 0; + + # X/Y referring to tiles old-school (my $x) = $input{x} =~ /^(\d+)/; $x ||= 0; (my $y) = $input{y} =~ /^(\d+)/; $y ||= 0; - return front_page($q, @errors) unless $x || $y || $input{pc}; - if (!$x && !$y) { + return front_page($q, @errors) unless $x || $y || $input{pc} || $easting || $northing; + + if ($x && $y) { + # Convert the tile co-ordinates to real ones. + $easting = FixMyStreet::Map::tile_to_os($x); + $northing = FixMyStreet::Map::tile_to_os($y); + } elsif ($easting && $northing) { + # Don't need to do anything + } else { + my $error; try { - ($x, $y, $easting, $northing, $error) = Page::geocode($input{pc}, $q); + ($easting, $northing, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q); } catch Error::Simple with { $error = shift; }; - } - return Page::geocode_choice($error, '/', $q) if (ref($error) eq 'ARRAY'); - return front_page($q, $error) if ($error); - - if (!$easting || !$northing) { - $easting = Page::tile_to_os($x); - $northing = Page::tile_to_os($y); + return FixMyStreet::Geocode::list_choices($error, '/', $q) if (ref($error) eq 'ARRAY'); + return front_page($q, $error) if $error; } # Check this location is okay to be displayed for the cobrand @@ -821,16 +809,12 @@ sub display_location { $all_text = _('Include stale reports'); $interval = '6 months'; } - my ($pins, $on_map, $around_map, $dist) = Page::map_pins($q, $x, $y, $x, $y, $interval); - if ($input{no_pins}) { - $hide_link = NewURL($q, -retain=>1, no_pins=>undef); - $hide_text = _('Show pins'); - $pins = ''; - } else { - $hide_link = NewURL($q, -retain=>1, no_pins=>1); - $hide_text = _('Hide pins'); + + my ($on_map_all, $on_map, $around_map, $dist) = FixMyStreet::Map::map_features($q, $easting, $northing, $interval); + my @pins; + foreach (@$on_map_all) { + push @pins, [ $_->{easting}, $_->{northing}, $_->{state} eq 'fixed' ? 'green' : 'red' ]; } - my $map_links = "<p id='sub_map_links'><a id='hide_pins_link' rel='nofollow' href='$hide_link'>$hide_text</a> | <a id='all_pins_link' rel='nofollow' href='$all_link'>$all_text</a></p> <input type='hidden' id='all_pins' name='all_pins' value='$input_h{all_pins}'>"; my $on_list = ''; foreach (@$on_map) { my $report_url = NewURL($q, -retain => 1, -url => '/report/' . $_->{id}, pc => undef, x => undef, 'y' => undef); @@ -854,18 +838,38 @@ sub display_location { $around_list .= '</a>'; $around_list .= ' <small>' . _('(fixed)') . '</small>' if $_->{state} eq 'fixed'; $around_list .= '</li>'; + push @pins, [ $_->{easting}, $_->{northing}, $_->{state} eq 'fixed' ? 'green' : 'red' ]; } $around_list = $q->li(_('No problems found.')) unless $around_list; - my $url_skip = NewURL($q, -retain=>1, 'submit_map'=>1, skipped=>1); + if ($input{no_pins}) { + $hide_link = NewURL($q, -retain=>1, no_pins=>undef); + $hide_text = _('Show pins'); + @pins = (); + } else { + $hide_link = NewURL($q, -retain=>1, no_pins=>1); + $hide_text = _('Hide pins'); + } + my $map_links = "<p id='sub_map_links'><a id='hide_pins_link' rel='nofollow' href='$hide_link'>$hide_text</a> | <a id='all_pins_link' rel='nofollow' href='$all_link'>$all_text</a></p> <input type='hidden' id='all_pins' name='all_pins' value='$input_h{all_pins}'>"; + + my $url_skip = NewURL($q, -retain=>1, pc => undef, + x => undef, 'y' => undef, + easting => $easting, northing => $northing, + 'submit_map'=>1, skipped=>1 + ); my $pc_h = ent($q->param('pc') || ''); my %vars = ( - 'map' => Page::display_map($q, x => $x, 'y' => $y, type => 1, pins => $pins, post => $map_links ), - map_end => Page::display_map_end(1), + 'map' => FixMyStreet::Map::display_map($q, + easting => $easting, northing => $northing, + type => 1, + pins => \@pins, + post => $map_links + ), + map_end => FixMyStreet::Map::display_map_end(1), url_home => Cobrand::url($cobrand, '/', $q), url_rss => Cobrand::url($cobrand, NewURL($q, -retain => 1, -url=> "/rss/n/$easting,$northing", pc => undef, x => undef, 'y' => undef), $q), - url_email => Cobrand::url($cobrand, NewURL($q, -retain => 1, pc => undef, -url=>'/alert', x=>$x, 'y'=>$y, feed=>"local:$easting:$northing"), $q), + url_email => Cobrand::url($cobrand, NewURL($q, -retain => 1, pc => undef, -url=>'/alert', e=>$easting, 'n'=>$northing, feed=>"local:$easting:$northing"), $q), url_skip => $url_skip, email_me => _('Email me new local problems'), rss_alt => _('RSS feed'), @@ -885,7 +889,8 @@ sub display_location { ); my %params = ( - rss => [ _('Recent local problems, FixMyStreet'), "/rss/n/$easting,$northing" ] + rss => [ _('Recent local problems, FixMyStreet'), "/rss/n/$easting,$northing" ], + robots => 'noindex,nofollow', ); return (Page::template_include('map', $q, Page::template_root($q), %vars), %params); @@ -898,11 +903,9 @@ sub display_problem { my $cobrand = Page::get_cobrand($q); push @errors, _('There were problems with your update. Please see below.') if (scalar keys %field_errors); - my @vars = qw(id name rznvy update fixed add_alert upload_fileid x y submit_update); + my @vars = qw(id name rznvy update fixed add_alert upload_fileid submit_update); my %input = map { $_ => $q->param($_) || '' } @vars; my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars; - ($input{x}) = $input{x} =~ /^(\d+)/; $input{x} ||= 0; - ($input{y}) = $input{y} =~ /^(\d+)/; $input{y} ||= 0; my $base = Cobrand::base_url($cobrand); # Some council with bad email software @@ -923,62 +926,70 @@ sub display_problem { my $problem = Problems::fetch_problem($input{id}); return display_location($q, _('Unknown problem ID')) unless $problem; return front_page($q, _('That report has been removed from FixMyStreet.'), '410 Gone') if $problem->{state} eq 'hidden'; - my ($x, $y, $x_tile, $y_tile, $px, $py) = Page::os_to_px_with_adjust($q, $problem->{easting}, $problem->{northing}, $input{x}, $input{y}); - - # Try and have pin near centre of map - if (!$input{x} && $x - $x_tile > 0.5) { - $x_tile += 1; - $px = Page::os_to_px($problem->{easting}, $x_tile); - } - if (!$input{y} && $y - $y_tile > 0.5) { - $y_tile += 1; - $py = Page::os_to_px($problem->{northing}, $y_tile, 1); - } - my %vars; my $extra_data = Cobrand::extra_data($cobrand, $q); my $google_link = Cobrand::base_url_for_emails($cobrand, $extra_data) . '/report/' . $problem->{id}; my ($lat, $lon) = mySociety::GeoUtil::national_grid_to_wgs84($problem->{easting}, $problem->{northing}, 'G'); - my $map_links = "<p id='sub_map_links'><a href='http://maps.google.co.uk/maps?output=embed&z=16&q=" - . URI::Escape::uri_escape_utf8($problem->{title} . ' - ' . $google_link) . "\@$lat,$lon'>View on Google Maps</a></p>"; - my $pins = Page::display_pin($q, $px, $py, 'blue'); - $vars{map_start} = Page::display_map($q, x => $x_tile, 'y' => $y_tile, type => 0, - pins => $pins, px => $px, py => $py, post => $map_links ); + my $map_links = "<p id='sub_map_links'><a href=\"http://maps.google.co.uk/maps?output=embed&z=16&q=" + . URI::Escape::uri_escape_utf8($problem->{title} . ' - ' . $google_link) . "\@$lat,$lon\">View on Google Maps</a></p>"; + my $banner; if ($q->{site} ne 'emptyhomes' && $problem->{state} eq 'confirmed' && $problem->{duration} > 8*7*24*60*60) { - $vars{banner} = $q->p({id => 'unknown'}, _('This problem is old and of unknown status.')) + $banner = $q->p({id => 'unknown'}, _('This problem is old and of unknown status.')); } if ($problem->{state} eq 'fixed') { - $vars{banner} = $q->p({id => 'fixed'}, _('This problem has been fixed') . '.') + $banner = $q->p({id => 'fixed'}, _('This problem has been fixed') . '.'); } - $vars{problem_title} = ent($problem->{title}); - $vars{problem_meta} = Page::display_problem_meta_line($q, $problem); - $vars{problem_detail} = Page::display_problem_detail($problem); - $vars{problem_photo} = Page::display_problem_photo($q, $problem); - - my $contact_url = Cobrand::url($cobrand, NewURL($q, -retain => 1, pc => undef, -url=>'/contact?id=' . $input{id}), $q); - $vars{unsuitable} = $q->a({rel => 'nofollow', href => $contact_url}, _('Offensive? Unsuitable? Tell us')); - - my $back = Cobrand::url($cobrand, NewURL($q, -url => '/', 'x' => $x_tile, 'y' => $y_tile, -retain => 1, pc => undef, id => undef ), $q); - $vars{more_problems} = '<a href="' . $back . '">' . _('More problems nearby') . '</a>'; + my $contact_url = Cobrand::url($cobrand, NewURL($q, -retain => 1, pc => undef, x => undef, 'y' => undef, -url=>'/contact?id=' . $input{id}), $q); + my $back = Cobrand::url($cobrand, NewURL($q, -url => '/', + 'e' => int($problem->{easting}), 'n' => int($problem->{northing}), + -retain => 1, pc => undef, x => undef, 'y' => undef, id => undef + ), $q); + my $fixed = ($input{fixed}) ? ' checked' : ''; - $vars{url_home} = Cobrand::url($cobrand, '/', $q), + my %vars = ( + banner => $banner, + map_start => FixMyStreet::Map::display_map($q, + easting => $problem->{easting}, northing => $problem->{northing}, + type => 0, + pins => [ [ $problem->{easting}, $problem->{northing}, 'blue' ] ], + post => $map_links + ), + map_end => FixMyStreet::Map::display_map_end(0), + problem_title => ent($problem->{title}), + problem_meta => Page::display_problem_meta_line($q, $problem), + problem_detail => Page::display_problem_detail($problem), + problem_photo => Page::display_problem_photo($q, $problem), + problem_updates => Page::display_problem_updates($input{id}, $q), + unsuitable => $q->a({rel => 'nofollow', href => $contact_url}, _('Offensive? Unsuitable? Tell us')), + more_problems => '<a href="' . $back . '">' . _('More problems nearby') . '</a>', + url_home => Cobrand::url($cobrand, '/', $q), + alert_link => Cobrand::url($cobrand, NewURL($q, -url => '/alert?type=updates;id='.$input_h{id}, -retain => 1, pc => undef, x => undef, 'y' => undef ), $q), + alert_text => _('Email me updates'), + email_label => _('Email:'), + subscribe => _('Subscribe'), + blurb => _('Receive email when updates are left on this problem'), + cobrand_form_elements1 => Cobrand::form_elements($cobrand, 'alerts', $q), + form_alert_action => Cobrand::url($cobrand, '/alert', $q), + rss_url => Cobrand::url($cobrand, NewURL($q, -retain=>1, -url => '/rss/'.$input_h{id}, pc => undef, x => undef, 'y' => undef, id => undef), $q), + rss_title => _('RSS feed'), + rss_alt => _('RSS feed of updates to this problem'), + update_heading => $q->h2(_('Provide an update')), + field_errors => \%field_errors, + add_alert_checked => ($input{add_alert} || !$input{submit_update}) ? ' checked' : '', + fixedline_box => $problem->{state} eq 'fixed' ? '' : qq{<input type="checkbox" name="fixed" id="form_fixed" value="1"$fixed>}, + fixedline_label => $problem->{state} eq 'fixed' ? '' : qq{<label for="form_fixed">} . _('This problem has been fixed') . qq{</label>}, + name_label => _('Name:'), + update_label => _('Update:'), + alert_label => _('Alert me to future updates'), + post_label => _('Post'), + cobrand_form_elements => Cobrand::form_elements($cobrand, 'updateForm', $q), + form_action => Cobrand::url($cobrand, '/', $q), + input_h => \%input_h, + ); - $vars{alert_link} = Cobrand::url($cobrand, NewURL($q, -url => '/alert?type=updates;id='.$input_h{id}, -retain => 1, pc => undef ), $q); - $vars{alert_text} = _('Email me updates'); - $vars{email_label} = _('Email:'); - $vars{subscribe} = _('Subscribe'); - $vars{blurb} = _('Receive email when updates are left on this problem'); - $vars{cobrand_form_elements1} = Cobrand::form_elements($cobrand, 'alerts', $q); - $vars{form_alert_action} = Cobrand::url($cobrand, '/alert', $q); - $vars{rss_url} = Cobrand::url($cobrand, NewURL($q, -retain=>1, -url => '/rss/'.$input_h{id}, pc => undef, id => undef), $q); - $vars{rss_title} = _('RSS feed'); - $vars{rss_alt} = _('RSS feed of updates to this problem'); - - $vars{problem_updates} = Page::display_problem_updates($input{id}, $q); - $vars{update_heading} = $q->h2(_('Provide an update')); $vars{update_blurb} = $q->p($q->small(_('Please note that updates are not sent to the council. If you leave your name it will be public. Your information will only be used in accordance with our <a href="/faq#privacy">privacy policy</a>'))) unless $q->{site} eq 'emptyhomes'; # No council blurb @@ -986,22 +997,10 @@ sub display_problem { $vars{errors} = '<ul class="error"><li>' . join('</li><li>', @errors) . '</li></ul>'; } - $vars{field_errors} = \%field_errors; - - my $fixed = ($input{fixed}) ? ' checked' : ''; - $vars{add_alert_checked} = ($input{add_alert} || !$input{submit_update}) ? ' checked' : ''; - $vars{fixedline_box} = $problem->{state} eq 'fixed' ? '' - : qq{<input type="checkbox" name="fixed" id="form_fixed" value="1"$fixed>}; - $vars{fixedline_label} = $problem->{state} eq 'fixed' ? '' - : qq{<label for="form_fixed">} . _('This problem has been fixed') . qq{</label>}; - $vars{name_label} = _('Name:'); - $vars{update_label} = _('Update:'); - $vars{alert_label} = _('Alert me to future updates'); - $vars{post_label} = _('Post'); - $vars{cobrand_form_elements} = Cobrand::form_elements($cobrand, 'updateForm', $q); my $allow_photo_upload = Cobrand::allow_photo_upload($cobrand); if ($allow_photo_upload) { my $photo_label = _('Photo:'); + $vars{enctype} = ' enctype="multipart/form-data"'; $vars{photo_element} = <<EOF; <div id="fileupload_normalUI"> <label for="form_photo">$photo_label</label> @@ -1010,17 +1009,12 @@ sub display_problem { EOF } - $vars{form_action} = Cobrand::url($cobrand, '/', $q); - if ($allow_photo_upload) { - $vars{enctype} = ' enctype="multipart/form-data"'; - } - $vars{map_end} = Page::display_map_end(0); my %params = ( rss => [ _('Updates to this problem, FixMyStreet'), "/rss/$input_h{id}" ], + robots => 'index, nofollow', title => $problem->{title} ); - $vars{input_h} = \%input_h; my $page = Page::template_include('problem', $q, Page::template_root($q), %vars); return ($page, %params); } @@ -1,12 +1,6 @@ /* * js.js * FixMyStreet JavaScript - * - * TODO - * Investigate jQuery - * Tidy it all up - * Selection of pin doesn't really need a server request, but I don't really care - * */ @@ -16,41 +10,6 @@ YAHOO.util.Event.onContentReady('pc', function() { } }); -function compass_pan(e, a) { - YAHOO.util.Event.preventDefault(e); - if (a.home) { - a.x = a.orig_x-drag_x; - a.y = a.orig_y-drag_y; - } - pan(a.x, a.y); -} - -YAHOO.util.Event.onContentReady('compass', function() { - var ua=navigator.userAgent.toLowerCase(); - // if (document.getElementById('mapForm') && (/safari/.test(ua) || /Konqueror/.test(ua))) return; - if (document.getElementById('map').offsetWidth > 510) return; - - var points = this.getElementsByTagName('a'); - YAHOO.util.Event.addListener(points[1], 'click', compass_pan, { x:0, y:fixmystreet.tileheight }); - YAHOO.util.Event.addListener(points[3], 'click', compass_pan, { x:fixmystreet.tilewidth, y:0 }); - YAHOO.util.Event.addListener(points[5], 'click', compass_pan, { x:-fixmystreet.tilewidth, y:0 }); - YAHOO.util.Event.addListener(points[7], 'click', compass_pan, { x:0, y:-fixmystreet.tileheight }); - YAHOO.util.Event.addListener(points[0], 'click', compass_pan, { x:fixmystreet.tilewidth, y:fixmystreet.tileheight }); - YAHOO.util.Event.addListener(points[2], 'click', compass_pan, { x:-fixmystreet.tilewidth, y:fixmystreet.tileheight }); - YAHOO.util.Event.addListener(points[6], 'click', compass_pan, { x:fixmystreet.tilewidth, y:-fixmystreet.tileheight }); - YAHOO.util.Event.addListener(points[8], 'click', compass_pan, { x:-fixmystreet.tilewidth, y:-fixmystreet.tileheight }); - YAHOO.util.Event.addListener(points[4], 'click', compass_pan, { home:1, orig_x:drag_x, orig_y:drag_y }); -}); - -YAHOO.util.Event.onContentReady('map', function() { - var ua=navigator.userAgent.toLowerCase(); - // if (document.getElementById('mapForm') && (/safari/.test(ua) || /Konqueror/.test(ua))) return; - if (document.getElementById('map').offsetWidth > 510) return; - new YAHOO.util.DDMap('map'); - update_tiles(fixmystreet.start_x, fixmystreet.start_y, true); -}); - - YAHOO.util.Event.onContentReady('mapForm', function() { this.onsubmit = function() { if (this.submit_problem) { @@ -119,52 +78,6 @@ YAHOO.util.Event.onContentReady('email_alert_box', function() { }); }); -YAHOO.util.Event.addListener('hide_pins_link', 'click', function(e) { - YAHOO.util.Event.preventDefault(e); - if (this.innerHTML == 'Show pins') { - YAHOO.util.Dom.setStyle('pins', 'display', 'block'); - this.innerHTML = 'Hide pins'; - } else if (this.innerHTML == 'Dangos pinnau') { - YAHOO.util.Dom.setStyle('pins', 'display', 'block'); - this.innerHTML = 'Cuddio pinnau'; - } else if (this.innerHTML == 'Cuddio pinnau') { - YAHOO.util.Dom.setStyle('pins', 'display', 'none'); - this.innerHTML = 'Dangos pinnau'; - } else if (this.innerHTML == 'Hide pins') { - YAHOO.util.Dom.setStyle('pins', 'display', 'none'); - this.innerHTML = 'Show pins'; - } -}); -YAHOO.util.Event.addListener('all_pins_link', 'click', function(e) { - YAHOO.util.Event.preventDefault(e); - YAHOO.util.Dom.setStyle('pins', 'display', 'block'); - var welsh = 0; - if (this.innerHTML == 'Include stale reports') { - this.innerHTML = 'Hide stale reports'; - document.getElementById('all_pins').value = '1'; - load_pins(fixmystreet.x, fixmystreet.y); - } else if (this.innerHTML == 'Cynnwys hen adroddiadau') { - this.innerHTML = 'Cuddio hen adroddiadau'; - document.getElementById('all_pins').value = '1'; - welsh = 1; - load_pins(fixmystreet.x, fixmystreet.y); - } else if (this.innerHTML == 'Cuddio hen adroddiadau') { - this.innerHTML = 'Cynnwys hen adroddiadau'; - welsh = 1; - document.getElementById('all_pins').value = ''; - load_pins(fixmystreet.x, fixmystreet.y); - } else if (this.innerHTML == 'Hide stale reports') { - this.innerHTML = 'Include stale reports'; - document.getElementById('all_pins').value = ''; - load_pins(fixmystreet.x, fixmystreet.y); - } - if (welsh) { - document.getElementById('hide_pins_link').innerHTML = 'Cuddio pinnau'; - } else { - document.getElementById('hide_pins_link').innerHTML = 'Hide pins'; - } -}); - /* File upload */ /* function doSubmit(e) { @@ -250,238 +163,3 @@ var swfu_settings = { } }; */ - -// I love the global -var tile_x = 0; -var tile_y = 0; - -var myAnim; -function pan(x, y) { - if (!myAnim || !myAnim.isAnimated()) { - myAnim = new YAHOO.util.Motion('drag', { points:{by:[x,y]} }, 10, YAHOO.util.Easing.easeOut); - myAnim.useSeconds = false; - //myAnim.onTween.subscribe(function(){ update_tiles(x/10, y/10, false); }); - myAnim.onComplete.subscribe(function(){ - update_tiles(x, y, false); - cleanCache(); - }); - myAnim.animate(); - } -} - -var drag_x = 0; -var drag_y = 0; -function update_tiles(dx, dy, force) { - dx = getInt(dx); dy = getInt(dy); - if (!dx && !dy && !force) return; - var old_drag_x = drag_x; - var old_drag_y = drag_y; - drag_x += dx; - drag_y += dy; - - var drag = document.getElementById('drag'); - drag.style.left = drag_x + 'px'; - drag.style.top = drag_y + 'px'; - - var horizontal = Math.floor(old_drag_x/fixmystreet.tilewidth) - Math.floor(drag_x/fixmystreet.tilewidth); - var vertical = Math.floor(old_drag_y/fixmystreet.tileheight) - Math.floor(drag_y/fixmystreet.tileheight); - if (!horizontal && !vertical && !force) return; - fixmystreet.x += horizontal; - - tile_x += horizontal; - fixmystreet.y -= vertical; - tile_y += vertical; - var url = [ root_path + '/tilma/tileserver/' + fixmystreet.tile_type + '/', fixmystreet.x, '-', (fixmystreet.x+5), ',', fixmystreet.y, '-', (fixmystreet.y+5), '/JSON' ].join(''); - YAHOO.util.Connect.asyncRequest('GET', url, { - success: urls_loaded, failure: urls_not_loaded, - argument: [tile_x, tile_y] - }); - - if (force) return; - load_pins(fixmystreet.x, fixmystreet.y); -} - -function load_pins(x, y) { - if (document.getElementById('formX')) { - all_pins = ''; - if (document.getElementById('all_pins')) { - all_pins = document.getElementById('all_pins').value; - } - var ajax_params = [ 'sx=' + document.getElementById('formX').value, - 'sy=' + document.getElementById('formY').value, - 'x=' + (x+3), - 'y=' + (y+3), - 'all_pins=' + all_pins ]; - - if (document.getElementById('extra_param')) { - ajax_params.push(document.getElementById('extra_param').name + '=' + document.getElementById('extra_param').value); - } - - var url = [ root_path , '/ajax?', ajax_params.join(';')].join(''); - YAHOO.util.Connect.asyncRequest('GET', url, { - success: pins_loaded - }); - } -} - -function pins_loaded(o) { - var data = eval(o.responseText); - document.getElementById('pins').innerHTML = data.pins; - if (typeof(data.current) != 'undefined') - document.getElementById('current').innerHTML = data.current; - if (typeof(data.current_near) != 'undefined') - document.getElementById('current_near').innerHTML = data.current_near; - if (typeof(data.fixed_near) != 'undefined') - document.getElementById('fixed_near').innerHTML = data.fixed_near; -} - -function urls_not_loaded(o) { /* Nothing yet */ } - -// Load 6x6 grid of tiles around current 2x2 -function urls_loaded(o) { - var tiles = eval(o.responseText); - var drag = document.getElementById('drag'); - for (var i=0; i<6; i++) { - var ii = (i + o.argument[1]); - for (var j=0; j<6; j++) { - if (tiles[i][j] == null) continue; - var jj = (j + o.argument[0]); - var id = [ 't', ii, '.', jj ].join(''); - var xx = fixmystreet.x+j; - var yy = fixmystreet.y+5-i; - var img = document.getElementById(id); - if (img) { - if (!img.galleryimg) { img.galleryimg = false; } - img.onclick = drag_check; - tileCache[id] = { x: xx, y: yy, t: img }; - continue; - } - img = cloneNode(); - img.style.top = ((ii-2)*fixmystreet.tileheight) + 'px'; - img.style.left = ((jj-2)*fixmystreet.tilewidth) + 'px'; - img.name = [ 'tile_', xx, '.', yy ].join('') - img.id = id; - if (browser) { - img.style.visibility = 'hidden'; - img.onload=function() { this.style.visibility = 'visible'; } - } - img.src = 'http://tilma.mysociety.org/tileserver/' + fixmystreet.tile_type + '/' + tiles[i][j]; - tileCache[id] = { x: xx, y: yy, t: img }; - drag.appendChild(img); - } - } -} - -var imgElCache; -function cloneNode() { - var img = null; - if (!imgElCache) { - var form = document.getElementById('mapForm'); - if (form) { - img = imgElCache = document.createElement('input'); - img.type = 'image'; - } else { - img = imgElCache = document.createElement('img'); - } - img.onclick = drag_check; - img.style.position = 'absolute'; - img.style.width = fixmystreet.tilewidth + 'px'; - img.style.height = fixmystreet.tileheight + 'px'; - img.galleryimg = false; - img.alt = 'Loading...'; - } else { - img = imgElCache.cloneNode(true); - } - return img; -} - -var tileCache=[]; -function cleanCache() { - for (var i in tileCache) { - if (tileCache[i].x < fixmystreet.x || tileCache[i].x > fixmystreet.x+5 || tileCache[i].y < fixmystreet.y || tileCache[i].y > fixmystreet.y+5) { - var t = tileCache[i].t; - t.parentNode.removeChild(t); // de-leak? - delete tileCache[i]; - } - } -} - -/* Called every mousemove, so on first call, overwrite itself with quicker version */ -function get_posn(ev) { - var posx, posy; - if (ev.pageX || ev.pageY) { - get_posn = function(e) { - return { x: e.pageX, y: e.pageY }; - }; - } else if (ev.clientX || ev.clientY) { - get_posn = function(e) { - return { - x: e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft, - y: e.clientY + document.body.scrollTop + document.documentElement.scrollTop - }; - }; - } else { - get_posn = function(e) { - return { x: undef, y: undef }; - }; - } - return get_posn(ev); -} - -function setCursor(s) { - var drag = document.getElementById('drag'); - var inputs = drag.getElementsByTagName('input'); - for (var i=0; i<inputs.length; i++) { - inputs[i].style.cursor = s; - } -} - -var in_drag = false; -function drag_check(e) { - if (in_drag) { - in_drag = false; - return false; - } - return true; -} - -/* Simpler version of DDProxy */ -var mouse_pos = {}; -YAHOO.util.DDMap = function(id, sGroup, config) { - this.init(id, sGroup, config); -}; -YAHOO.extend(YAHOO.util.DDMap, YAHOO.util.DD, { - scroll: false, - b4MouseDown: function(e) { }, - startDrag: function(x, y) { - mouse_pos = { x: x, y: y }; - setCursor('move'); - in_drag = true; - }, - b4Drag: function(e) { }, - onDrag: function(e) { - var point = get_posn(e); - if (point == mouse_pos) return false; - var dx = point.x-mouse_pos.x; - var dy = point.y-mouse_pos.y; - mouse_pos = point; - update_tiles(dx, dy, false); - }, - endDrag: function(e) { - setCursor('crosshair'); - cleanCache(); - }, - toString: function() { - return ("DDMap " + this.id); - } -}); - -var browser = 1; -var ua=navigator.userAgent.toLowerCase(); -if (!/opera|safari|gecko/.test(ua) && typeof document.all!='undefined') - browser=0; - -function getInt(n) { - n = parseInt(n); return (isNaN(n) ? 0 : n); -} - diff --git a/web/js/OpenLayers.Projection.OrdnanceSurvey.js b/web/js/OpenLayers.Projection.OrdnanceSurvey.js new file mode 100644 index 000000000..bb596d3bf --- /dev/null +++ b/web/js/OpenLayers.Projection.OrdnanceSurvey.js @@ -0,0 +1,489 @@ +/** + * OpenLayers OSGB Grid Projection Transformations + * + * Conversion to OpenLayers by Thomas Wood (grand.edgemaster@gmail.com) + * + * this program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * this program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * --------------------------------------------------------------------------- + * + * PLEASE DO NOT HOTLINK THIS, save this onto your own server + * - I cannot guarantee this file will remain here forever. + * + * --------------------------------------------------------------------------- + * + * Credits: + * Based from the geotools js library by Paul Dixon + * GeoTools javascript coordinate transformations + * http://files.dixo.net/geotools.html + * + * Portions of this file copyright (c)2005 Paul Dixon (paul@elphin.com) + * + * The algorithm used by the script for WGS84-OSGB36 conversions is derived + * from an OSGB spreadsheet (www.gps.gov.uk) with permission. This has been + * adapted into Perl by Ian Harris, and into PHP by Barry Hunter. Conversion + * accuracy is in the order of 7m for 90% of Great Britain, and should be + * be similar to the conversion made by a typical GPSr + * + */ + +OpenLayers.Projection.OS = { + + /** + * Method: projectForwardBritish + * Given an object with x and y properties in EPSG:4326, modify the x,y + * properties on the object to be the OSGB36 (transverse mercator) + * projected coordinates. + * + * Parameters: + * point - {Object} An object with x and y properties. + * + * Returns: + * {Object} The point, with the x and y properties transformed to spherical + * mercator. + */ + projectForwardBritish: function(point) { + var x1 = OpenLayers.Projection.OS.Lat_Long_H_to_X(point.y,point.x,0,6378137.00,6356752.313); + var y1 = OpenLayers.Projection.OS.Lat_Long_H_to_Y(point.y,point.x,0,6378137.00,6356752.313); + var z1 = OpenLayers.Projection.OS.Lat_H_to_Z (point.y, 0,6378137.00,6356752.313); + + var x2 = OpenLayers.Projection.OS.Helmert_X(x1,y1,z1,-446.448,-0.2470,-0.8421,20.4894); + var y2 = OpenLayers.Projection.OS.Helmert_Y(x1,y1,z1, 125.157,-0.1502,-0.8421,20.4894); + var z2 = OpenLayers.Projection.OS.Helmert_Z(x1,y1,z1,-542.060,-0.1502,-0.2470,20.4894); + + var lat2 = OpenLayers.Projection.OS.XYZ_to_Lat (x2,y2,z2,6377563.396,6356256.910); + var lon2 = OpenLayers.Projection.OS.XYZ_to_Long(x2,y2); + + point.x = OpenLayers.Projection.OS.Lat_Long_to_East (lat2,lon2,6377563.396,6356256.910,400000,0.999601272,49.00000,-2.00000); + point.y = OpenLayers.Projection.OS.Lat_Long_to_North(lat2,lon2,6377563.396,6356256.910,400000,-100000,0.999601272,49.00000,-2.00000); + + return point; + }, + + /** + * Method: projectInverseBritish + * Given an object with x and y properties in OSGB36 (transverse mercator), + * modify the x,y properties on the object to be the unprojected coordinates. + * + * Parameters: + * point - {Object} An object with x and y properties. + * + * Returns: + * {Object} The point, with the x and y properties transformed from + * OSGB36 to unprojected coordinates.. + */ + projectInverseBritish: function(point) { + var lat1 = OpenLayers.Projection.OS.E_N_to_Lat (point.x,point.y,6377563.396,6356256.910,400000,-100000,0.999601272,49.00000,-2.00000); + var lon1 = OpenLayers.Projection.OS.E_N_to_Long(point.x,point.y,6377563.396,6356256.910,400000,-100000,0.999601272,49.00000,-2.00000); + + var x1 = OpenLayers.Projection.OS.Lat_Long_H_to_X(lat1,lon1,0,6377563.396,6356256.910); + var y1 = OpenLayers.Projection.OS.Lat_Long_H_to_Y(lat1,lon1,0,6377563.396,6356256.910); + var z1 = OpenLayers.Projection.OS.Lat_H_to_Z (lat1, 0,6377563.396,6356256.910); + + var x2 = OpenLayers.Projection.OS.Helmert_X(x1,y1,z1,446.448 ,0.2470,0.8421,-20.4894); + var y2 = OpenLayers.Projection.OS.Helmert_Y(x1,y1,z1,-125.157,0.1502,0.8421,-20.4894); + var z2 = OpenLayers.Projection.OS.Helmert_Z(x1,y1,z1,542.060 ,0.1502,0.2470,-20.4894); + + var lat = OpenLayers.Projection.OS.XYZ_to_Lat(x2,y2,z2,6378137.000,6356752.313); + var lon = OpenLayers.Projection.OS.XYZ_to_Long(x2,y2); + + point.x = lon; + point.y = lat; + return point; + }, + + goog2osgb: function(point) { + return OpenLayers.Projection.OS.projectForwardBritish(OpenLayers.Layer.SphericalMercator.projectInverse(point)); + }, + + osgb2goog: function(point) { + return OpenLayers.Layer.SphericalMercator.projectForward(OpenLayers.Projection.OS.projectInverseBritish(point)); + }, + + /***** + * Mathematical functions + *****/ + E_N_to_Lat: function(East, North, a, b, e0, n0, f0, PHI0, LAM0) { + //Un-project Transverse Mercator eastings and northings back to latitude. + //eastings (East) and northings (North) in meters; _ + //ellipsoid axis dimensions (a & b) in meters; _ + //eastings (e0) and northings (n0) of false origin in meters; _ + //central meridian scale factor (f0) and _ + //latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees. + + //Convert angle measures to radians + var Pi = 3.14159265358979; + var RadPHI0 = PHI0 * (Pi / 180); + var RadLAM0 = LAM0 * (Pi / 180); + + //Compute af0, bf0, e squared (e2), n and Et + var af0 = a * f0; + var bf0 = b * f0; + var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); + var n = (af0 - bf0) / (af0 + bf0); + var Et = East - e0; + + //Compute initial value for latitude (PHI) in radians + var PHId = OpenLayers.Projection.OS.InitialLat(North, n0, af0, RadPHI0, n, bf0); + + //Compute nu, rho and eta2 using value for PHId + var nu = af0 / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(PHId),2))))); + var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(PHId),2))); + var eta2 = (nu / rho) - 1; + + //Compute Latitude + var VII = (Math.tan(PHId)) / (2 * rho * nu); + var VIII = ((Math.tan(PHId)) / (24 * rho * Math.pow(nu,3))) * (5 + (3 * (Math.pow(Math.tan(PHId),2))) + eta2 - (9 * eta2 * (Math.pow(Math.tan(PHId),2)))); + var IX = ((Math.tan(PHId)) / (720 * rho * Math.pow(nu,5))) * (61 + (90 * ((Math.tan(PHId)) ^ 2)) + (45 * (Math.pow(Math.tan(PHId),4)))); + + var E_N_to_Lat = (180 / Pi) * (PHId - (Math.pow(Et,2) * VII) + (Math.pow(Et,4) * VIII) - ((Et ^ 6) * IX)); + + return (E_N_to_Lat); + }, + + E_N_to_Long: function(East, North, a, b, e0, n0, f0, PHI0, LAM0) { + //Un-project Transverse Mercator eastings and northings back to longitude. + //eastings (East) and northings (North) in meters; _ + //ellipsoid axis dimensions (a & b) in meters; _ + //eastings (e0) and northings (n0) of false origin in meters; _ + //central meridian scale factor (f0) and _ + //latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees. + + //Convert angle measures to radians + var Pi = 3.14159265358979; + var RadPHI0 = PHI0 * (Pi / 180); + var RadLAM0 = LAM0 * (Pi / 180); + + //Compute af0, bf0, e squared (e2), n and Et + var af0 = a * f0; + var bf0 = b * f0; + var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); + var n = (af0 - bf0) / (af0 + bf0); + var Et = East - e0; + + //Compute initial value for latitude (PHI) in radians + var PHId = OpenLayers.Projection.OS.InitialLat(North, n0, af0, RadPHI0, n, bf0); + + //Compute nu, rho and eta2 using value for PHId + var nu = af0 / (Math.sqrt(1 - (e2 * (Math.pow(Math.sin(PHId),2))))); + var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(PHId),2))); + var eta2 = (nu / rho) - 1; + + //Compute Longitude + var X = (Math.pow(Math.cos(PHId),-1)) / nu; + var XI = ((Math.pow(Math.cos(PHId),-1)) / (6 * Math.pow(nu,3))) * ((nu / rho) + (2 * (Math.pow(Math.tan(PHId),2)))); + var XII = ((Math.pow(Math.cos(PHId),-1)) / (120 * Math.pow(nu,5))) * (5 + (28 * (Math.pow(Math.tan(PHId),2))) + (24 * (Math.pow(Math.tan(PHId),4)))); + var XIIA = ((Math.pow(Math.cos(PHId),-1)) / (5040 * Math.pow(nu,7))) * (61 + (662 * (Math.pow(Math.tan(PHId),2))) + (1320 * (Math.pow(Math.tan(PHId),4))) + (720 * (Math.pow(Math.tan(PHId),6)))); + + var E_N_to_Long = (180 / Pi) * (RadLAM0 + (Et * X) - (Math.pow(Et,3) * XI) + (Math.pow(Et,5) * XII) - (Math.pow(Et,7) * XIIA)); + + return E_N_to_Long; + }, + + InitialLat: function(North, n0, afo, PHI0, n, bfo) { + //Compute initial value for Latitude (PHI) IN RADIANS. + //northing of point (North) and northing of false origin (n0) in meters; _ + //semi major axis multiplied by central meridian scale factor (af0) in meters; _ + //latitude of false origin (PHI0) IN RADIANS; _ + //n (computed from a, b and f0) and _ + //ellipsoid semi major axis multiplied by central meridian scale factor (bf0) in meters. + + //First PHI value (PHI1) + var PHI1 = ((North - n0) / afo) + PHI0; + + //Calculate M + var M = OpenLayers.Projection.OS.Marc(bfo, n, PHI0, PHI1); + + //Calculate new PHI value (PHI2) + var PHI2 = ((North - n0 - M) / afo) + PHI1; + + //Iterate to get final value for InitialLat + while (Math.abs(North - n0 - M) > 0.00001) + { + PHI2 = ((North - n0 - M) / afo) + PHI1; + M = OpenLayers.Projection.OS.Marc(bfo, n, PHI0, PHI2); + PHI1 = PHI2; + } + return PHI2; + }, + + Lat_Long_H_to_X: function(PHI, LAM, H, a, b) { + // Convert geodetic coords lat (PHI), long (LAM) and height (H) to cartesian X coordinate. + // Input: - _ + // Latitude (PHI)& Longitude (LAM) both in decimal degrees; _ + // Ellipsoidal height (H) and ellipsoid axis dimensions (a & b) all in meters. + + // Convert angle measures to radians + var Pi = 3.14159265358979; + var RadPHI = PHI * (Pi / 180); + var RadLAM = LAM * (Pi / 180); + + // Compute eccentricity squared and nu + var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); + var V = a / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(RadPHI),2))))); + + // Compute X + return (V + H) * (Math.cos(RadPHI)) * (Math.cos(RadLAM)); + }, + + + Lat_Long_H_to_Y: function(PHI, LAM, H, a, b) { + // Convert geodetic coords lat (PHI), long (LAM) and height (H) to cartesian Y coordinate. + // Input: - _ + // Latitude (PHI)& Longitude (LAM) both in decimal degrees; _ + // Ellipsoidal height (H) and ellipsoid axis dimensions (a & b) all in meters. + + // Convert angle measures to radians + var Pi = 3.14159265358979; + var RadPHI = PHI * (Pi / 180); + var RadLAM = LAM * (Pi / 180); + + // Compute eccentricity squared and nu + var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); + var V = a / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(RadPHI),2))) )); + + // Compute Y + return (V + H) * (Math.cos(RadPHI)) * (Math.sin(RadLAM)); + }, + + + Lat_H_to_Z: function(PHI, H, a, b) { + // Convert geodetic coord components latitude (PHI) and height (H) to cartesian Z coordinate. + // Input: - _ + // Latitude (PHI) decimal degrees; _ + // Ellipsoidal height (H) and ellipsoid axis dimensions (a & b) all in meters. + + // Convert angle measures to radians + var Pi = 3.14159265358979; + var RadPHI = PHI * (Pi / 180); + + // Compute eccentricity squared and nu + var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); + var V = a / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(RadPHI),2)) ))); + + // Compute X + return ((V * (1 - e2)) + H) * (Math.sin(RadPHI)); + }, + + + Helmert_X: function(X,Y,Z,DX,Y_Rot,Z_Rot,s) { + + // (X, Y, Z, DX, Y_Rot, Z_Rot, s) + // Computed Helmert transformed X coordinate. + // Input: - _ + // cartesian XYZ coords (X,Y,Z), X translation (DX) all in meters ; _ + // Y and Z rotations in seconds of arc (Y_Rot, Z_Rot) and scale in ppm (s). + + // Convert rotations to radians and ppm scale to a factor + var Pi = 3.14159265358979; + var sfactor = s * 0.000001; + + var RadY_Rot = (Y_Rot / 3600) * (Pi / 180); + + var RadZ_Rot = (Z_Rot / 3600) * (Pi / 180); + + //Compute transformed X coord + return (X + (X * sfactor) - (Y * RadZ_Rot) + (Z * RadY_Rot) + DX); + }, + + + Helmert_Y: function(X,Y,Z,DY,X_Rot,Z_Rot,s) { + // Computed Helmert transformed Y coordinate. + // Input: - _ + // cartesian XYZ coords (X,Y,Z), Y translation (DY) all in meters ; _ + // X and Z rotations in seconds of arc (X_Rot, Z_Rot) and scale in ppm (s). + + // Convert rotations to radians and ppm scale to a factor + var Pi = 3.14159265358979; + var sfactor = s * 0.000001; + var RadX_Rot = (X_Rot / 3600) * (Pi / 180); + var RadZ_Rot = (Z_Rot / 3600) * (Pi / 180); + + // Compute transformed Y coord + return (X * RadZ_Rot) + Y + (Y * sfactor) - (Z * RadX_Rot) + DY; + }, + + + + Helmert_Z: function(X, Y, Z, DZ, X_Rot, Y_Rot, s) { + // Computed Helmert transformed Z coordinate. + // Input: - _ + // cartesian XYZ coords (X,Y,Z), Z translation (DZ) all in meters ; _ + // X and Y rotations in seconds of arc (X_Rot, Y_Rot) and scale in ppm (s). + // + // Convert rotations to radians and ppm scale to a factor + var Pi = 3.14159265358979; + var sfactor = s * 0.000001; + var RadX_Rot = (X_Rot / 3600) * (Pi / 180); + var RadY_Rot = (Y_Rot / 3600) * (Pi / 180); + + // Compute transformed Z coord + return (-1 * X * RadY_Rot) + (Y * RadX_Rot) + Z + (Z * sfactor) + DZ; + } , + + XYZ_to_Lat: function(X, Y, Z, a, b) { + // Convert XYZ to Latitude (PHI) in Dec Degrees. + // Input: - _ + // XYZ cartesian coords (X,Y,Z) and ellipsoid axis dimensions (a & b), all in meters. + + // this FUNCTION REQUIRES THE "Iterate_XYZ_to_Lat" FUNCTION + // this FUNCTION IS CALLED BY THE "XYZ_to_H" FUNCTION + + var RootXYSqr = Math.sqrt(Math.pow(X,2) + Math.pow(Y,2)); + var e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); + var PHI1 = Math.atan2(Z , (RootXYSqr * (1 - e2)) ); + + var PHI = OpenLayers.Projection.OS.Iterate_XYZ_to_Lat(a, e2, PHI1, Z, RootXYSqr); + + var Pi = 3.14159265358979; + + return PHI * (180 / Pi); + }, + + + Iterate_XYZ_to_Lat: function(a, e2, PHI1, Z, RootXYSqr) { + // Iteratively computes Latitude (PHI). + // Input: - _ + // ellipsoid semi major axis (a) in meters; _ + // eta squared (e2); _ + // estimated value for latitude (PHI1) in radians; _ + // cartesian Z coordinate (Z) in meters; _ + // RootXYSqr computed from X & Y in meters. + + // this FUNCTION IS CALLED BY THE "XYZ_to_PHI" FUNCTION + // this FUNCTION IS ALSO USED ON IT'S OWN IN THE _ + // "Projection and Transformation Calculations.xls" SPREADSHEET + + + var V = a / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2)))); + var PHI2 = Math.atan2((Z + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr); + + while (Math.abs(PHI1 - PHI2) > 0.000000001) { + PHI1 = PHI2; + V = a / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2)))); + PHI2 = Math.atan2((Z + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr); + } + + return PHI2; + }, + + + XYZ_to_Long: function (X, Y) { + // Convert XYZ to Longitude (LAM) in Dec Degrees. + // Input: - _ + // X and Y cartesian coords in meters. + + var Pi = 3.14159265358979; + return Math.atan2(Y , X) * (180 / Pi); + }, + + Marc: function (bf0, n, PHI0, PHI) { + //Compute meridional arc. + //Input: - _ + // ellipsoid semi major axis multiplied by central meridian scale factor (bf0) in meters; _ + // n (computed from a, b and f0); _ + // lat of false origin (PHI0) and initial or final latitude of point (PHI) IN RADIANS. + + //this FUNCTION IS CALLED BY THE - _ + // "Lat_Long_to_North" and "InitialLat" FUNCTIONS + // this FUNCTION IS ALSO USED ON IT'S OWN IN THE "Projection and Transformation Calculations.xls" SPREADSHEET + + return bf0 * (((1 + n + ((5 / 4) * Math.pow(n,2)) + ((5 / 4) * Math.pow(n,3))) * (PHI - PHI0)) - (((3 * n) + (3 * Math.pow(n,2)) + ((21 / 8) * Math.pow(n,3))) * (Math.sin(PHI - PHI0)) * (Math.cos(PHI + PHI0))) + ((((15 / 8 + ) * Math.pow(n,2)) + ((15 / 8) * Math.pow(n,3))) * (Math.sin(2 * (PHI - PHI0))) * (Math.cos(2 * (PHI + PHI0)))) - (((35 / 24) * Math.pow(n,3)) * (Math.sin(3 * (PHI - PHI0))) * (Math.cos(3 * (PHI + PHI0))))); + }, + + Lat_Long_to_East: function (PHI, LAM, a, b, e0, f0, PHI0, LAM0) { + //Project Latitude and longitude to Transverse Mercator eastings. + //Input: - _ + // Latitude (PHI) and Longitude (LAM) in decimal degrees; _ + // ellipsoid axis dimensions (a & b) in meters; _ + // eastings of false origin (e0) in meters; _ + // central meridian scale factor (f0); _ + // latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees. + + // Convert angle measures to radians + var Pi = 3.14159265358979; + var RadPHI = PHI * (Pi / 180); + var RadLAM = LAM * (Pi / 180); + var RadPHI0 = PHI0 * (Pi / 180); + var RadLAM0 = LAM0 * (Pi / 180); + + var af0 = a * f0; + var bf0 = b * f0; + var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); + var n = (af0 - bf0) / (af0 + bf0); + var nu = af0 / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(RadPHI),2) ))); + var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(RadPHI),2) )); + var eta2 = (nu / rho) - 1; + var p = RadLAM - RadLAM0; + + var IV = nu * (Math.cos(RadPHI)); + var V = (nu / 6) * ( Math.pow(Math.cos(RadPHI),3)) * ((nu / rho) - (Math.pow(Math.tan(RadPHI),2))); + var VI = (nu / 120) * (Math.pow(Math.cos(RadPHI),5)) * (5 - (18 * (Math.pow(Math.tan(RadPHI),2))) + (Math.pow(Math.tan(RadPHI),4)) + (14 * eta2) - (58 * (Math.pow(Math.tan(RadPHI),2)) * eta2)); + + return e0 + (p * IV) + (Math.pow(p,3) * V) + (Math.pow(p,5) * VI); + }, + + Lat_Long_to_North: function (PHI, LAM, a, b, e0, n0, f0, PHI0, LAM0) { + // Project Latitude and longitude to Transverse Mercator northings + // Input: - _ + // Latitude (PHI) and Longitude (LAM) in decimal degrees; _ + // ellipsoid axis dimensions (a & b) in meters; _ + // eastings (e0) and northings (n0) of false origin in meters; _ + // central meridian scale factor (f0); _ + // latitude (PHI0) and longitude (LAM0) of false origin in decimal degrees. + + // REQUIRES THE "Marc" FUNCTION + + // Convert angle measures to radians + var Pi = 3.14159265358979; + var RadPHI = PHI * (Pi / 180); + var RadLAM = LAM * (Pi / 180); + var RadPHI0 = PHI0 * (Pi / 180); + var RadLAM0 = LAM0 * (Pi / 180); + + var af0 = a * f0; + var bf0 = b * f0; + var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); + var n = (af0 - bf0) / (af0 + bf0); + var nu = af0 / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(RadPHI),2)))); + var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(RadPHI),2))); + var eta2 = (nu / rho) - 1; + var p = RadLAM - RadLAM0; + var M = OpenLayers.Projection.OS.Marc(bf0, n, RadPHI0, RadPHI); + + var I = M + n0; + var II = (nu / 2) * (Math.sin(RadPHI)) * (Math.cos(RadPHI)); + var III = ((nu / 24) * (Math.sin(RadPHI)) * (Math.pow(Math.cos(RadPHI),3))) * (5 - (Math.pow(Math.tan(RadPHI),2)) + (9 * eta2)); + var IIIA = ((nu / 720) * (Math.sin(RadPHI)) * (Math.pow(Math.cos(RadPHI),5))) * (61 - (58 * (Math.pow(Math.tan(RadPHI),2))) + (Math.pow(Math.tan(RadPHI),4))); + + return I + (Math.pow(p,2) * II) + (Math.pow(p,4) * III) + (Math.pow(p,6) * IIIA); + } + +}; + +/** + * Note: Two transforms declared + * Transforms from EPSG:4326 to EPSG:27700 and from EPSG:27700 to EPSG:4326 + * are set by this class. + */ +OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:27700", + OpenLayers.Projection.OS.projectForwardBritish); +OpenLayers.Projection.addTransform("EPSG:27700", "EPSG:4326", + OpenLayers.Projection.OS.projectInverseBritish); +OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:27700", + OpenLayers.Projection.OS.goog2osgb); +OpenLayers.Projection.addTransform("EPSG:27700", "EPSG:900913", + OpenLayers.Projection.OS.osgb2goog); diff --git a/web/js/map-OpenStreetMap.js b/web/js/map-OpenStreetMap.js new file mode 100644 index 000000000..04237e075 --- /dev/null +++ b/web/js/map-OpenStreetMap.js @@ -0,0 +1,150 @@ +YAHOO.util.Event.onContentReady('map', function() { + var map = new OpenLayers.Map("map", { + controls: [ + new OpenLayers.Control.ArgParser(), + //new OpenLayers.Control.LayerSwitcher(), + new OpenLayers.Control.Navigation(), + new OpenLayers.Control.PanZoom() + ], + displayProjection: new OpenLayers.Projection("EPSG:4326") + }); + var streetview = new fixmystreet.map_type("", { + zoomOffset: 14, + numZoomLevels: 4 + }); + map.addLayer(streetview); + + var centre = new OpenLayers.LonLat( fixmystreet.easting, fixmystreet.northing ); + centre.transform( + new OpenLayers.Projection("EPSG:27700"), + map.getProjectionObject() + ); + map.setCenter(centre, 2); +}); + + +// http://www.openstreetmap.org/openlayers/OpenStreetMap.js (added maxResolution) + +/** + * Namespace: Util.OSM + */ +OpenLayers.Util.OSM = {}; + +/** + * Constant: MISSING_TILE_URL + * {String} URL of image to display for missing tiles + */ +OpenLayers.Util.OSM.MISSING_TILE_URL = "http://www.openstreetmap.org/openlayers/img/404.png"; + +/** + * Property: originalOnImageLoadError + * {Function} Original onImageLoadError function. + */ +OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError; + +/** + * Function: onImageLoadError + */ +OpenLayers.Util.onImageLoadError = function() { + if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) { + this.src = OpenLayers.Util.OSM.MISSING_TILE_URL; + } else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) { + // do nothing - this layer is transparent + } else { + OpenLayers.Util.OSM.originalOnImageLoadError; + } +}; + +/** + * Class: OpenLayers.Layer.OSM.Mapnik + * + * Inherits from: + * - <OpenLayers.Layer.OSM> + */ +OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.Mapnik + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://b.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://c.tile.openstreetmap.org/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + /* Below line added to OSM's file in order to allow minimum zoom level */ + maxResolution: 156543.0339/Math.pow(2, options.zoomOffset || 0), + numZoomLevels: 19, + buffer: 0 + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik" +}); + +/** + * Class: OpenLayers.Layer.OSM.Osmarender + * + * Inherits from: + * - <OpenLayers.Layer.OSM> + */ +OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.Osmarender + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", + "http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", + "http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ numZoomLevels: 18, buffer: 0 }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender" +}); + +/** + * Class: OpenLayers.Layer.OSM.CycleMap + * + * Inherits from: + * - <OpenLayers.Layer.OSM> + */ +OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.CycleMap + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", + "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", + "http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + /* Below line added to OSM's file in order to allow minimum zoom level */ + maxResolution: 156543.0339/Math.pow(2, options.zoomOffset || 0), + numZoomLevels: 19, + buffer: 0 + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap" +}); diff --git a/web/js/map-bing-ol.js b/web/js/map-bing-ol.js new file mode 100644 index 000000000..ba9445326 --- /dev/null +++ b/web/js/map-bing-ol.js @@ -0,0 +1,96 @@ +YAHOO.util.Event.onContentReady('map', function() { + var map = new OpenLayers.Map("map", { + controls: [ + new OpenLayers.Control.ArgParser(), + //new OpenLayers.Control.LayerSwitcher(), + new OpenLayers.Control.Navigation(), + new OpenLayers.Control.PanZoom() + ], + displayProjection: new OpenLayers.Projection("EPSG:4326") + }); + var bing = new OpenLayers.Layer.Bing("", { + zoomOffset: 13, + numZoomLevels: 4 + }); + map.addLayer(bing); + + var centre = new OpenLayers.LonLat( fixmystreet.easting, fixmystreet.northing ); + centre.transform( + new OpenLayers.Projection("EPSG:27700"), + map.getProjectionObject() + ); + map.setCenter(centre, 3); +}); + +OpenLayers.Util.OS = {}; +OpenLayers.Util.OS.MISSING_TILE_URL = "http://openstreetmap.org/openlayers/img/404.png"; +OpenLayers.Util.OS.originalOnImageLoadError = OpenLayers.Util.onImageLoadError; +OpenLayers.Util.onImageLoadError = function() { + OpenLayers.Util.OS.originalOnImageLoadError; +}; + +OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, { + initialize: function(name, options) { + var url = []; + options = OpenLayers.Util.extend({ + /* Below line added to OSM's file in order to allow minimum zoom level */ + maxResolution: 156543.0339/Math.pow(2, options.zoomOffset || 0), + numZoomLevels: 18, + transitionEffect: "resize", + sphericalMercator: true, + attribution: "© Microsoft / OS 2010" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArguments); + }, + + get_quadkey: function(x, y, level) { + var key = ''; + for (var i = level; i > 0; i--) { + var digit = 0; + var mask = 1 << (i - 1); + if ((x & mask) != 0) { + digit++; + } + if ((y & mask) != 0) { + digit += 2; + } + key += digit; + } + return key; + }, + + getURL: function (bounds) { + var res = this.map.getResolution(); + var x = Math.round((bounds.left - this.maxExtent.left) + / (res * this.tileSize.w)); + var y = Math.round((this.maxExtent.top - bounds.top) + / (res * this.tileSize.h)); + var z = this.serverResolutions != null ? + OpenLayers.Util.indexOf(this.serverResolutions, res) : + this.map.getZoom() + this.zoomOffset; + + if (z == 16) { + var url = [ + "http://a.os.openstreetmap.org/sv/${z}/${x}/${y}.png", + "http://b.os.openstreetmap.org/sv/${z}/${x}/${y}.png", + "http://c.os.openstreetmap.org/sv/${z}/${x}/${y}.png" + ]; + } else { + var url = [ + "http://ecn.t0.tiles.virtualearth.net/tiles/r${id}.png?g=587&productSet=mmOS", + "http://ecn.t1.tiles.virtualearth.net/tiles/r${id}.png?g=587&productSet=mmOS", + "http://ecn.t2.tiles.virtualearth.net/tiles/r${id}.png?g=587&productSet=mmOS", + "http://ecn.t3.tiles.virtualearth.net/tiles/r${id}.png?g=587&productSet=mmOS" + ]; + } + var s = '' + x + y + z; + url = this.selectUrl(s, url); + + var id = this.get_quadkey(x, y, z); + var path = OpenLayers.String.format(url, {'id': id, 'x': x, 'y': y, 'z': z}); + return path; + }, + + CLASS_NAME: "OpenLayers.Layer.Bing" +}); diff --git a/web/js/map-bing.js b/web/js/map-bing.js new file mode 100644 index 000000000..fbbbcc676 --- /dev/null +++ b/web/js/map-bing.js @@ -0,0 +1,21 @@ +YAHOO.util.Event.onContentReady('map', function() { + var centre = new Microsoft.Maps.Location( fixmystreet.lat, fixmystreet.lon ); + var map = new Microsoft.Maps.Map(document.getElementById("map"), { + mapTypeId: Microsoft.Maps.MapTypeId.ordnanceSurvey, + center: centre, + zoom: 15, + enableClickableLogo: false, + enableSearchLogo: false, + showCopyright: false, + showDashboard: true, + showLogo: false, + showScalebar: false + }); + //minZoomLevel: 14, + //numZoomLevels: 4 + + Microsoft.Maps.Events.addHandler(map, "viewchangestart", function(e) { + /* Doesn't work */ + if (map.getTargetZoom() < 12) return false; + }); +}); diff --git a/web/js/map-google.js b/web/js/map-google.js new file mode 100644 index 000000000..77e54ab7c --- /dev/null +++ b/web/js/map-google.js @@ -0,0 +1,22 @@ +YAHOO.util.Event.onContentReady('map', function() { + var centre = new google.maps.LatLng( fixmystreet.lat, fixmystreet.lon ); + var map = new google.maps.Map(document.getElementById("map"), { + mapTypeId: google.maps.MapTypeId.ROADMAP, + center: centre, + zoom: 16, + disableDefaultUI: true, + navigationControl: true, + navigationControlOptions: { + style: google.maps.NavigationControlStyle.SMALL + }, + mapTypeControl: true, + mapTypeControlOptions: { + style: google.maps.MapTypeControlStyle.DROPDOWN_MENU + } + }); + + google.maps.event.addListener(map, "zoom_changed", function() { + if (map.getZoom() < 13) map.setZoom(13); + if (map.getZoom() > 17) map.setZoom(17); + }); +}); diff --git a/web/js/map-streetview.js b/web/js/map-streetview.js new file mode 100644 index 000000000..088e5b6a2 --- /dev/null +++ b/web/js/map-streetview.js @@ -0,0 +1,88 @@ +YAHOO.util.Event.onContentReady('map', function() { + var map = new OpenLayers.Map("map", { + controls: [ + new OpenLayers.Control.ArgParser(), + //new OpenLayers.Control.LayerSwitcher(), + new OpenLayers.Control.Navigation(), + new OpenLayers.Control.PanZoom() + ], + displayProjection: new OpenLayers.Projection("EPSG:4326") + }); + var streetview = new OpenLayers.Layer.StreetView("OS StreetView (1:10000)", { + zoomOffset: 14, + numZoomLevels: 4 + }); + map.addLayer(streetview); + + var centre = new OpenLayers.LonLat( fixmystreet.easting, fixmystreet.northing ); + centre.transform( + new OpenLayers.Projection("EPSG:27700"), + map.getProjectionObject() + ); + map.setCenter(centre, 2); +}); + + +// http://os.openstreetmap.org/openlayers/OS.js (added one line) + +/** + * Namespace: Util.OS + */ +OpenLayers.Util.OS = {}; + +/** + * Constant: MISSING_TILE_URL + * {String} URL of image to display for missing tiles + */ +OpenLayers.Util.OS.MISSING_TILE_URL = "http://openstreetmap.org/openlayers/img/404.png"; + +/** + * Property: originalOnImageLoadError + * {Function} Original onImageLoadError function. + */ +OpenLayers.Util.OS.originalOnImageLoadError = OpenLayers.Util.onImageLoadError; + +/** + * Function: onImageLoadError + */ +OpenLayers.Util.onImageLoadError = function() { + OpenLayers.Util.OS.originalOnImageLoadError; +}; + +/** + * @requires OpenLayers/Layer/XYZ.js + * + * Class: OpenLayers.Layer.StreetView + * + * Inherits from: + * - <OpenLayers.Layer.XYZ> + */ +OpenLayers.Layer.StreetView = OpenLayers.Class(OpenLayers.Layer.XYZ, { + /** + * Constructor: OpenLayers.Layer.StreetView + * + * Parameters: + * name - {String} + * url - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.os.openstreetmap.org/sv/${z}/${x}/${y}.png", + "http://b.os.openstreetmap.org/sv/${z}/${x}/${y}.png", + "http://c.os.openstreetmap.org/sv/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + /* Below line added to OSM's file in order to allow minimum zoom level */ + maxResolution: 156543.0339/Math.pow(2, options.zoomOffset || 0), + numZoomLevels: 18, + transitionEffect: "resize", + sphericalMercator: true, + attribution: "Contains Ordnance Survey data © Crown copyright and database right 2010" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.StreetView" +}); diff --git a/web/js/map-tilma-ol.js b/web/js/map-tilma-ol.js new file mode 100644 index 000000000..cfd196c1d --- /dev/null +++ b/web/js/map-tilma-ol.js @@ -0,0 +1,42 @@ +YAHOO.util.Event.onContentReady('map', function() { + var map = new OpenLayers.Map("map", { + controls: [ + new OpenLayers.Control.ArgParser(), + new OpenLayers.Control.Navigation(), + new OpenLayers.Control.PanPanel() + ] + }); + var tilma = new OpenLayers.Layer.Tilma("Tilma", { + maxResolution: fixmystreet.maxResolution, + tileSize: new OpenLayers.Size(fixmystreet.tilewidth, fixmystreet.tileheight), + map_type: fixmystreet.tile_type + }); + map.addLayer(tilma); + + var centre = new OpenLayers.LonLat( fixmystreet.easting, fixmystreet.northing ); + map.setCenter(centre); +}); + +OpenLayers.Layer.Tilma = OpenLayers.Class(OpenLayers.Layer.XYZ, { + initialize: function(name, options) { + var url = "http://tilma.mysociety.org/tileserver/${type}/${x},${y}/png"; + options = OpenLayers.Util.extend({ + transitionEffect: "resize", + numZoomLevels: 1, + units: "m", + maxExtent: new OpenLayers.Bounds(0, 0, 700000, 1300000), + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArguments); + }, + + getURL: function (bounds) { + var res = this.map.getResolution(); + var x = Math.round(bounds.left / (res * this.tileSize.w)); + var y = Math.round(bounds.bottom / (res * this.tileSize.h)); + var path = OpenLayers.String.format(this.url, {'x': x, 'y': y, 'type': this.map_type}); + return path; + }, + + CLASS_NAME: "OpenLayers.Layer.Tilma" +}); diff --git a/web/js/map-tilma.js b/web/js/map-tilma.js new file mode 100644 index 000000000..1ae38cff1 --- /dev/null +++ b/web/js/map-tilma.js @@ -0,0 +1,320 @@ +/* + * map-tilma.js + * JavaScript specifically for the tilma based maps + */ + +function compass_pan(e, a) { + YAHOO.util.Event.preventDefault(e); + if (a.home) { + a.x = a.orig_x-drag_x; + a.y = a.orig_y-drag_y; + } + pan(a.x, a.y); +} + +YAHOO.util.Event.onContentReady('compass', function() { + var ua=navigator.userAgent.toLowerCase(); + // if (document.getElementById('mapForm') && (/safari/.test(ua) || /Konqueror/.test(ua))) return; + if (document.getElementById('map').offsetWidth > 510) return; + + var points = this.getElementsByTagName('a'); + YAHOO.util.Event.addListener(points[1], 'click', compass_pan, { x:0, y:fixmystreet.tileheight }); + YAHOO.util.Event.addListener(points[3], 'click', compass_pan, { x:fixmystreet.tilewidth, y:0 }); + YAHOO.util.Event.addListener(points[5], 'click', compass_pan, { x:-fixmystreet.tilewidth, y:0 }); + YAHOO.util.Event.addListener(points[7], 'click', compass_pan, { x:0, y:-fixmystreet.tileheight }); + YAHOO.util.Event.addListener(points[0], 'click', compass_pan, { x:fixmystreet.tilewidth, y:fixmystreet.tileheight }); + YAHOO.util.Event.addListener(points[2], 'click', compass_pan, { x:-fixmystreet.tilewidth, y:fixmystreet.tileheight }); + YAHOO.util.Event.addListener(points[6], 'click', compass_pan, { x:fixmystreet.tilewidth, y:-fixmystreet.tileheight }); + YAHOO.util.Event.addListener(points[8], 'click', compass_pan, { x:-fixmystreet.tilewidth, y:-fixmystreet.tileheight }); + YAHOO.util.Event.addListener(points[4], 'click', compass_pan, { home:1, orig_x:drag_x, orig_y:drag_y }); +}); + +YAHOO.util.Event.onContentReady('map', function() { + var ua=navigator.userAgent.toLowerCase(); + // if (document.getElementById('mapForm') && (/safari/.test(ua) || /Konqueror/.test(ua))) return; + if (document.getElementById('map').offsetWidth > 510) return; + new YAHOO.util.DDMap('map'); + update_tiles(fixmystreet.start_x, fixmystreet.start_y, true); +}); + + +YAHOO.util.Event.addListener('hide_pins_link', 'click', function(e) { + YAHOO.util.Event.preventDefault(e); + if (this.innerHTML == 'Show pins') { + YAHOO.util.Dom.setStyle('pins', 'display', 'block'); + this.innerHTML = 'Hide pins'; + } else if (this.innerHTML == 'Dangos pinnau') { + YAHOO.util.Dom.setStyle('pins', 'display', 'block'); + this.innerHTML = 'Cuddio pinnau'; + } else if (this.innerHTML == 'Cuddio pinnau') { + YAHOO.util.Dom.setStyle('pins', 'display', 'none'); + this.innerHTML = 'Dangos pinnau'; + } else if (this.innerHTML == 'Hide pins') { + YAHOO.util.Dom.setStyle('pins', 'display', 'none'); + this.innerHTML = 'Show pins'; + } +}); +YAHOO.util.Event.addListener('all_pins_link', 'click', function(e) { + YAHOO.util.Event.preventDefault(e); + YAHOO.util.Dom.setStyle('pins', 'display', 'block'); + var welsh = 0; + if (this.innerHTML == 'Include stale reports') { + this.innerHTML = 'Hide stale reports'; + document.getElementById('all_pins').value = '1'; + load_pins(fixmystreet.x, fixmystreet.y); + } else if (this.innerHTML == 'Cynnwys hen adroddiadau') { + this.innerHTML = 'Cuddio hen adroddiadau'; + document.getElementById('all_pins').value = '1'; + welsh = 1; + load_pins(fixmystreet.x, fixmystreet.y); + } else if (this.innerHTML == 'Cuddio hen adroddiadau') { + this.innerHTML = 'Cynnwys hen adroddiadau'; + welsh = 1; + document.getElementById('all_pins').value = ''; + load_pins(fixmystreet.x, fixmystreet.y); + } else if (this.innerHTML == 'Hide stale reports') { + this.innerHTML = 'Include stale reports'; + document.getElementById('all_pins').value = ''; + load_pins(fixmystreet.x, fixmystreet.y); + } + if (welsh) { + document.getElementById('hide_pins_link').innerHTML = 'Cuddio pinnau'; + } else { + document.getElementById('hide_pins_link').innerHTML = 'Hide pins'; + } +}); + +// I love the global +var tile_x = 0; +var tile_y = 0; + +var myAnim; +function pan(x, y) { + if (!myAnim || !myAnim.isAnimated()) { + myAnim = new YAHOO.util.Motion('drag', { points:{by:[x,y]} }, 10, YAHOO.util.Easing.easeOut); + myAnim.useSeconds = false; + //myAnim.onTween.subscribe(function(){ update_tiles(x/10, y/10, false); }); + myAnim.onComplete.subscribe(function(){ + update_tiles(x, y, false); + cleanCache(); + }); + myAnim.animate(); + } +} + +var drag_x = 0; +var drag_y = 0; +function update_tiles(dx, dy, force) { + dx = getInt(dx); dy = getInt(dy); + if (!dx && !dy && !force) return; + var old_drag_x = drag_x; + var old_drag_y = drag_y; + drag_x += dx; + drag_y += dy; + + var drag = document.getElementById('drag'); + drag.style.left = drag_x + 'px'; + drag.style.top = drag_y + 'px'; + + var horizontal = Math.floor(old_drag_x/fixmystreet.tilewidth) - Math.floor(drag_x/fixmystreet.tilewidth); + var vertical = Math.floor(old_drag_y/fixmystreet.tileheight) - Math.floor(drag_y/fixmystreet.tileheight); + if (!horizontal && !vertical && !force) return; + fixmystreet.x += horizontal; + + tile_x += horizontal; + fixmystreet.y -= vertical; + tile_y += vertical; + var url = [ root_path + '/tilma/tileserver/' + fixmystreet.tile_type + '/', fixmystreet.x, '-', (fixmystreet.x+5), ',', fixmystreet.y, '-', (fixmystreet.y+5), '/JSON' ].join(''); + YAHOO.util.Connect.asyncRequest('GET', url, { + success: urls_loaded, failure: urls_not_loaded, + argument: [tile_x, tile_y] + }); + + if (force) return; + load_pins(fixmystreet.x, fixmystreet.y); +} + +function load_pins(x, y) { + if (document.getElementById('formX')) { + all_pins = ''; + if (document.getElementById('all_pins')) { + all_pins = document.getElementById('all_pins').value; + } + var ajax_params = [ 'sx=' + document.getElementById('formX').value, + 'sy=' + document.getElementById('formY').value, + 'x=' + (x+3), + 'y=' + (y+3), + 'all_pins=' + all_pins ]; + + if (document.getElementById('extra_param')) { + ajax_params.push(document.getElementById('extra_param').name + '=' + document.getElementById('extra_param').value); + } + + var url = [ root_path , '/ajax?', ajax_params.join(';')].join(''); + YAHOO.util.Connect.asyncRequest('GET', url, { + success: pins_loaded + }); + } +} + +function pins_loaded(o) { + var data = eval(o.responseText); + document.getElementById('pins').innerHTML = data.pins; + if (typeof(data.current) != 'undefined') + document.getElementById('current').innerHTML = data.current; + if (typeof(data.current_near) != 'undefined') + document.getElementById('current_near').innerHTML = data.current_near; + if (typeof(data.fixed_near) != 'undefined') + document.getElementById('fixed_near').innerHTML = data.fixed_near; +} + +function urls_not_loaded(o) { /* Nothing yet */ } + +// Load 6x6 grid of tiles around current 2x2 +function urls_loaded(o) { + var tiles = eval(o.responseText); + var drag = document.getElementById('drag'); + for (var i=0; i<6; i++) { + var ii = (i + o.argument[1]); + for (var j=0; j<6; j++) { + if (tiles[i][j] == null) continue; + var jj = (j + o.argument[0]); + var id = [ 't', ii, '.', jj ].join(''); + var xx = fixmystreet.x+j; + var yy = fixmystreet.y+5-i; + var img = document.getElementById(id); + if (img) { + if (!img.galleryimg) { img.galleryimg = false; } + img.onclick = drag_check; + tileCache[id] = { x: xx, y: yy, t: img }; + continue; + } + img = cloneNode(); + img.style.top = ((ii-2)*fixmystreet.tileheight) + 'px'; + img.style.left = ((jj-2)*fixmystreet.tilewidth) + 'px'; + img.name = [ 'tile_', xx, '.', yy ].join('') + img.id = id; + if (browser) { + img.style.visibility = 'hidden'; + img.onload=function() { this.style.visibility = 'visible'; } + } + img.src = 'http://tilma.mysociety.org/tileserver/' + fixmystreet.tile_type + '/' + tiles[i][j]; + tileCache[id] = { x: xx, y: yy, t: img }; + drag.appendChild(img); + } + } +} + +var imgElCache; +function cloneNode() { + var img = null; + if (!imgElCache) { + var form = document.getElementById('mapForm'); + if (form) { + img = imgElCache = document.createElement('input'); + img.type = 'image'; + } else { + img = imgElCache = document.createElement('img'); + } + img.onclick = drag_check; + img.style.position = 'absolute'; + img.style.width = fixmystreet.tilewidth + 'px'; + img.style.height = fixmystreet.tileheight + 'px'; + img.galleryimg = false; + img.alt = 'Loading...'; + } else { + img = imgElCache.cloneNode(true); + } + return img; +} + +var tileCache=[]; +function cleanCache() { + for (var i in tileCache) { + if (tileCache[i].x < fixmystreet.x || tileCache[i].x > fixmystreet.x+5 || tileCache[i].y < fixmystreet.y || tileCache[i].y > fixmystreet.y+5) { + var t = tileCache[i].t; + t.parentNode.removeChild(t); // de-leak? + delete tileCache[i]; + } + } +} + +/* Called every mousemove, so on first call, overwrite itself with quicker version */ +function get_posn(ev) { + var posx, posy; + if (ev.pageX || ev.pageY) { + get_posn = function(e) { + return { x: e.pageX, y: e.pageY }; + }; + } else if (ev.clientX || ev.clientY) { + get_posn = function(e) { + return { + x: e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft, + y: e.clientY + document.body.scrollTop + document.documentElement.scrollTop + }; + }; + } else { + get_posn = function(e) { + return { x: undef, y: undef }; + }; + } + return get_posn(ev); +} + +function setCursor(s) { + var drag = document.getElementById('drag'); + var inputs = drag.getElementsByTagName('input'); + for (var i=0; i<inputs.length; i++) { + inputs[i].style.cursor = s; + } +} + +var in_drag = false; +function drag_check(e) { + if (in_drag) { + in_drag = false; + return false; + } + return true; +} + +/* Simpler version of DDProxy */ +var mouse_pos = {}; +YAHOO.util.DDMap = function(id, sGroup, config) { + this.init(id, sGroup, config); +}; +YAHOO.extend(YAHOO.util.DDMap, YAHOO.util.DD, { + scroll: false, + b4MouseDown: function(e) { }, + startDrag: function(x, y) { + mouse_pos = { x: x, y: y }; + setCursor('move'); + in_drag = true; + }, + b4Drag: function(e) { }, + onDrag: function(e) { + var point = get_posn(e); + if (point == mouse_pos) return false; + var dx = point.x-mouse_pos.x; + var dy = point.y-mouse_pos.y; + mouse_pos = point; + update_tiles(dx, dy, false); + }, + endDrag: function(e) { + setCursor('crosshair'); + cleanCache(); + }, + toString: function() { + return ("DDMap " + this.id); + } +}); + +var browser = 1; +var ua=navigator.userAgent.toLowerCase(); +if (!/opera|safari|gecko/.test(ua) && typeof document.all!='undefined') + browser=0; + +function getInt(n) { + n = parseInt(n); return (isNaN(n) ? 0 : n); +} + diff --git a/web/questionnaire.cgi b/web/questionnaire.cgi index 1da410b80..33e823560 100755 --- a/web/questionnaire.cgi +++ b/web/questionnaire.cgi @@ -10,6 +10,7 @@ use strict; use Standard; +use Utils; use Error qw(:try); use CrossSell; use mySociety::AuthToken; @@ -213,17 +214,19 @@ sub display_questionnaire { return $error; } my $reported_date_time = Page::prettify_epoch($q, $problem->{time}); - my ($x, $y, $x_tile, $y_tile, $px, $py) = Page::os_to_px_with_adjust($q, $problem->{easting}, $problem->{northing}, undef, undef); - - my $pins = Page::display_pin($q, $px, $py, $problem->{state} eq 'fixed'?'green':'red'); my $problem_text = Page::display_problem_text($q, $problem); my $updates = Page::display_problem_updates($problem->{id}, $q); my %vars = ( input_h => \%input_h, - map_start => Page::display_map($q, x => $x_tile, y => $y_tile, pins => $pins, - px => $px, py => $py, pre => $problem_text, post => $updates ), - map_end => Page::display_map_end(0), + map_start => FixMyStreet::Map::display_map($q, + easting => $problem->{easting}, northing => $problem->{northing}, + pins => [ + [ $problem->{easting}, $problem->{northing}, $problem->{state} eq 'fixed'?'green':'red' ], + ], + pre => $problem_text, post => $updates + ), + map_end => FixMyStreet::Map::display_map_end(0), heading => _('Questionnaire'), yes => _('Yes'), no => _('No'), diff --git a/web/reports.cgi b/web/reports.cgi index 4faee63f9..fe4213be4 100755 --- a/web/reports.cgi +++ b/web/reports.cgi @@ -12,7 +12,7 @@ use strict; use Standard; use URI::Escape; -use mySociety::Alert; +use FixMyStreet::Alert; use mySociety::MaPit; use mySociety::Web qw(ent NewURL); use mySociety::VotingArea; @@ -117,7 +117,7 @@ sub main { } print $q->header( -type => 'application/xml; charset=utf-8' ); my $xsl = Cobrand::feed_xsl($cobrand); - my $out = mySociety::Alert::generate_rss($type, $xsl, "/$url", \@params, \%title_params, $cobrand, $q); + my $out = FixMyStreet::Alert::generate_rss($type, $xsl, "/$url", \@params, \%title_params, $cobrand, $q); $out =~ s/matthew.fixmystreet/emptyhomes.matthew.fixmystreet/g if $q->{site} eq 'emptyhomes'; print $out; return; diff --git a/web/robots.txt b/web/robots.txt index e69de29bb..53675186c 100644 --- a/web/robots.txt +++ b/web/robots.txt @@ -0,0 +1,5 @@ +User-agent: msnbot +Crawl-delay: 3 + +User-agent: bingbot +Crawl-delay: 3 diff --git a/web/rss.cgi b/web/rss.cgi index a2d9bcb4f..a716d93e9 100755 --- a/web/rss.cgi +++ b/web/rss.cgi @@ -12,7 +12,8 @@ use strict; use Error qw(:try); use Standard; use URI::Escape; -use mySociety::Alert; +use FixMyStreet::Alert; +use FixMyStreet::Geocode; use mySociety::MaPit; use mySociety::GeoUtil; use mySociety::Gaze; @@ -34,20 +35,20 @@ sub main { return; } my $qs = 'report/' . $id; - $out = mySociety::Alert::generate_rss($type, $xsl, $qs, [$id], undef, $cobrand, $q); + $out = FixMyStreet::Alert::generate_rss($type, $xsl, $qs, [$id], undef, $cobrand, $q); } elsif ($type eq 'new_problems' || $type eq 'new_fixed_problems') { - $out = mySociety::Alert::generate_rss($type, $xsl, '', undef, undef, $cobrand, $q); + $out = FixMyStreet::Alert::generate_rss($type, $xsl, '', undef, undef, $cobrand, $q); } elsif ($type eq 'council_problems') { my $id = $q->param('id'); my $qs = '/'.$id; - $out = mySociety::Alert::generate_rss($type, $xsl, $qs, [$id], undef, $cobrand. $q); + $out = FixMyStreet::Alert::generate_rss($type, $xsl, $qs, [$id], undef, $cobrand. $q); } elsif ($type eq 'area_problems') { my $id = $q->param('id'); my $va_info = mySociety::MaPit::call('area', $id); my $qs = '/'.$id; - $out = mySociety::Alert::generate_rss($type, $xsl, $qs, [$id], { NAME => $va_info->{name} }, $cobrand, $q); + $out = FixMyStreet::Alert::generate_rss($type, $xsl, $qs, [$id], { NAME => $va_info->{name} }, $cobrand, $q); } elsif ($type eq 'all_problems') { - $out = mySociety::Alert::generate_rss($type, $xsl, '', undef, undef, $cobrand, $q); + $out = FixMyStreet::Alert::generate_rss($type, $xsl, '', undef, undef, $cobrand, $q); } else { my $base = mySociety::Config::get('BASE_URL'); print $q->redirect($base . '/alert'); @@ -71,6 +72,13 @@ sub rss_local_problems { $d = '' unless $d =~ /^\d+$/; my $d_str = ''; $d_str = "/$d" if $d; + my $state = $q->param('state') || 'all'; + $state = 'all' unless $state =~ /^(all|open|fixed)$/; + + # state is getting lost in the redirects. Add it on to the end as a query + my $state_qs = "?state=$state" unless $state eq 'all'; + + $state = 'confirmed' if $state eq 'open'; my $cobrand = Page::get_cobrand($q); my $base = Cobrand::base_url($cobrand); @@ -78,33 +86,31 @@ sub rss_local_problems { ($e, $n) = mySociety::GeoUtil::wgs84_to_national_grid($lat, $lon, 'G'); $e = int($e + 0.5); $n = int($n + 0.5); - print $q->redirect(-location => "$base/rss/n/$e,$n$d_str"); + print $q->redirect(-location => "$base/rss/n/$e,$n$d_str$state_qs"); return ''; } elsif ($x && $y) { # 5000/31 as initial scale factor for these RSS feeds, now variable so redirect. $e = int( ($x * 5000/31) + 0.5 ); $n = int( ($y * 5000/31) + 0.5 ); - print $q->redirect(-location => "$base/rss/n/$e,$n$d_str"); + print $q->redirect(-location => "$base/rss/n/$e,$n$d_str$state_qs"); return ''; } elsif ($e && $n) { - $x = int(Page::os_to_tile($e)); - $y = int(Page::os_to_tile($n)); ($lat, $lon) = mySociety::GeoUtil::national_grid_to_wgs84($e, $n, 'G'); } elsif ($pc) { my $error; try { - ($x, $y, $e, $n, $error) = Page::geocode($pc, $q); + ($e, $n, $error) = FixMyStreet::Geocode::lookup($pc, $q); } catch Error::Simple with { $error = shift; }; unless ($error) { - print $q->redirect(-location => "$base/rss/n/$e,$n$d_str"); + print $q->redirect(-location => "$base/rss/n/$e,$n$d_str$state_qs"); } return ''; } else { die "Missing E/N, x/y, lat/lon, or postcode parameter in RSS feed"; } - my $qs = "?x=$x;y=$y"; + my $qs = '?e=' . int($e) . ';n=' . int($n); if ($d) { $qs .= ";d=$d"; $d = 100 if $d > 100; @@ -114,6 +120,10 @@ sub rss_local_problems { } my $xsl = Cobrand::feed_xsl($cobrand); - return mySociety::Alert::generate_rss('local_problems', $xsl, $qs, [$e, $n, $d], undef, $cobrand, $q); + if ($state eq 'all') { + return FixMyStreet::Alert::generate_rss('local_problems', $xsl, $qs, [$e, $n, $d], undef, $cobrand, $q); + } else { + return FixMyStreet::Alert::generate_rss('local_problems_state', $xsl, $qs, [$e, $n, $d, $state], undef, $cobrand, $q); + } } diff --git a/web/tms-signup.cgi b/web/tms-signup.cgi index 2bafd1543..44099417f 100755 --- a/web/tms-signup.cgi +++ b/web/tms-signup.cgi @@ -12,7 +12,6 @@ use strict; use Standard; use Digest::SHA1 qw(sha1_hex); use CrossSell; -use mySociety::Alert; use mySociety::AuthToken; use mySociety::Config; use mySociety::EmailUtil qw(is_valid_email); |