more basic framework
This commit is contained in:
parent
15f23469d9
commit
b4c0bfd8fa
20 changed files with 1084 additions and 448 deletions
181
README
181
README
|
@ -1,180 +1,13 @@
|
||||||
== Welcome to Rails
|
|
||||||
|
|
||||||
Rails is a web-application and persistence framework that includes everything
|
Task one
|
||||||
needed to create database-backed web-applications according to the
|
========
|
||||||
Model-View-Control pattern of separation. This pattern splits the view (also
|
|
||||||
called the presentation) into "dumb" templates that are primarily responsible
|
|
||||||
for inserting pre-built data in between HTML tags. The model contains the
|
|
||||||
"smart" domain objects (such as Account, Product, Person, Post) that holds all
|
|
||||||
the business logic and knows how to persist themselves to a database. The
|
|
||||||
controller handles the incoming requests (such as Save New Account, Update
|
|
||||||
Product, Show Post) by manipulating the model and directing data to the view.
|
|
||||||
|
|
||||||
In Rails, the model is handled by what's called an object-relational mapping
|
Get OSM on rails with a 0.4 API, without changing the db schema
|
||||||
layer entitled Active Record. This layer allows you to present the data from
|
|
||||||
database rows as objects and embellish these data objects with business logic
|
|
||||||
methods. You can read more about Active Record in
|
|
||||||
link:files/vendor/rails/activerecord/README.html.
|
|
||||||
|
|
||||||
The controller and view are handled by the Action Pack, which handles both
|
see db/README for how to create the db
|
||||||
layers by its two parts: Action View and Action Controller. These two layers
|
|
||||||
are bundled in a single package due to their heavy interdependence. This is
|
|
||||||
unlike the relationship between the Active Record and Action Pack that is much
|
|
||||||
more separate. Each of these packages can be used independently outside of
|
|
||||||
Rails. You can read more about Action Pack in
|
|
||||||
link:files/vendor/rails/actionpack/README.html.
|
|
||||||
|
|
||||||
|
Two
|
||||||
|
===
|
||||||
|
|
||||||
== Getting started
|
change the schema
|
||||||
|
|
||||||
1. Start the web server: <tt>ruby script/server</tt> (run with --help for options)
|
|
||||||
2. Go to http://localhost:3000/ and get "Welcome aboard: You’re riding the Rails!"
|
|
||||||
3. Follow the guidelines to start developing your application
|
|
||||||
|
|
||||||
|
|
||||||
== Web servers
|
|
||||||
|
|
||||||
Rails uses the built-in web server in Ruby called WEBrick by default, so you don't
|
|
||||||
have to install or configure anything to play around.
|
|
||||||
|
|
||||||
If you have lighttpd installed, though, it'll be used instead when running script/server.
|
|
||||||
It's considerably faster than WEBrick and suited for production use, but requires additional
|
|
||||||
installation and currently only works well on OS X/Unix (Windows users are encouraged
|
|
||||||
to start with WEBrick). We recommend version 1.4.11 and higher. You can download it from
|
|
||||||
http://www.lighttpd.net.
|
|
||||||
|
|
||||||
If you want something that's halfway between WEBrick and lighttpd, we heartily recommend
|
|
||||||
Mongrel. It's a Ruby-based web server with a C-component (so it requires compilation) that
|
|
||||||
also works very well with Windows. See more at http://mongrel.rubyforge.org/.
|
|
||||||
|
|
||||||
But of course its also possible to run Rails with the premiere open source web server Apache.
|
|
||||||
To get decent performance, though, you'll need to install FastCGI. For Apache 1.3, you want
|
|
||||||
to use mod_fastcgi. For Apache 2.0+, you want to use mod_fcgid.
|
|
||||||
|
|
||||||
See http://wiki.rubyonrails.com/rails/pages/FastCGI for more information on FastCGI.
|
|
||||||
|
|
||||||
== Example for Apache conf
|
|
||||||
|
|
||||||
<VirtualHost *:80>
|
|
||||||
ServerName rails
|
|
||||||
DocumentRoot /path/application/public/
|
|
||||||
ErrorLog /path/application/log/server.log
|
|
||||||
|
|
||||||
<Directory /path/application/public/>
|
|
||||||
Options ExecCGI FollowSymLinks
|
|
||||||
AllowOverride all
|
|
||||||
Allow from all
|
|
||||||
Order allow,deny
|
|
||||||
</Directory>
|
|
||||||
</VirtualHost>
|
|
||||||
|
|
||||||
NOTE: Be sure that CGIs can be executed in that directory as well. So ExecCGI
|
|
||||||
should be on and ".cgi" should respond. All requests from 127.0.0.1 go
|
|
||||||
through CGI, so no Apache restart is necessary for changes. All other requests
|
|
||||||
go through FCGI (or mod_ruby), which requires a restart to show changes.
|
|
||||||
|
|
||||||
|
|
||||||
== Debugging Rails
|
|
||||||
|
|
||||||
Have "tail -f" commands running on both the server.log, production.log, and
|
|
||||||
test.log files. Rails will automatically display debugging and runtime
|
|
||||||
information to these files. Debugging info will also be shown in the browser
|
|
||||||
on requests from 127.0.0.1.
|
|
||||||
|
|
||||||
|
|
||||||
== Breakpoints
|
|
||||||
|
|
||||||
Breakpoint support is available through the script/breakpointer client. This
|
|
||||||
means that you can break out of execution at any point in the code, investigate
|
|
||||||
and change the model, AND then resume execution! Example:
|
|
||||||
|
|
||||||
class WeblogController < ActionController::Base
|
|
||||||
def index
|
|
||||||
@posts = Post.find_all
|
|
||||||
breakpoint "Breaking out from the list"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
So the controller will accept the action, run the first line, then present you
|
|
||||||
with a IRB prompt in the breakpointer window. Here you can do things like:
|
|
||||||
|
|
||||||
Executing breakpoint "Breaking out from the list" at .../webrick_server.rb:16 in 'breakpoint'
|
|
||||||
|
|
||||||
>> @posts.inspect
|
|
||||||
=> "[#<Post:0x14a6be8 @attributes={\"title\"=>nil, \"body\"=>nil, \"id\"=>\"1\"}>,
|
|
||||||
#<Post:0x14a6620 @attributes={\"title\"=>\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]"
|
|
||||||
>> @posts.first.title = "hello from a breakpoint"
|
|
||||||
=> "hello from a breakpoint"
|
|
||||||
|
|
||||||
...and even better is that you can examine how your runtime objects actually work:
|
|
||||||
|
|
||||||
>> f = @posts.first
|
|
||||||
=> #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
|
|
||||||
>> f.
|
|
||||||
Display all 152 possibilities? (y or n)
|
|
||||||
|
|
||||||
Finally, when you're ready to resume execution, you press CTRL-D
|
|
||||||
|
|
||||||
|
|
||||||
== Console
|
|
||||||
|
|
||||||
You can interact with the domain model by starting the console through script/console.
|
|
||||||
Here you'll have all parts of the application configured, just like it is when the
|
|
||||||
application is running. You can inspect domain models, change values, and save to the
|
|
||||||
database. Starting the script without arguments will launch it in the development environment.
|
|
||||||
Passing an argument will specify a different environment, like <tt>script/console production</tt>.
|
|
||||||
|
|
||||||
|
|
||||||
== Description of contents
|
|
||||||
|
|
||||||
app
|
|
||||||
Holds all the code that's specific to this particular application.
|
|
||||||
|
|
||||||
app/controllers
|
|
||||||
Holds controllers that should be named like weblog_controller.rb for
|
|
||||||
automated URL mapping. All controllers should descend from
|
|
||||||
ActionController::Base.
|
|
||||||
|
|
||||||
app/models
|
|
||||||
Holds models that should be named like post.rb.
|
|
||||||
Most models will descend from ActiveRecord::Base.
|
|
||||||
|
|
||||||
app/views
|
|
||||||
Holds the template files for the view that should be named like
|
|
||||||
weblog/index.rhtml for the WeblogController#index action. All views use eRuby
|
|
||||||
syntax. This directory can also be used to keep stylesheets, images, and so on
|
|
||||||
that can be symlinked to public.
|
|
||||||
|
|
||||||
app/helpers
|
|
||||||
Holds view helpers that should be named like weblog_helper.rb.
|
|
||||||
|
|
||||||
app/apis
|
|
||||||
Holds API classes for web services.
|
|
||||||
|
|
||||||
config
|
|
||||||
Configuration files for the Rails environment, the routing map, the database, and other dependencies.
|
|
||||||
|
|
||||||
components
|
|
||||||
Self-contained mini-applications that can bundle together controllers, models, and views.
|
|
||||||
|
|
||||||
db
|
|
||||||
Contains the database schema in schema.rb. db/migrate contains all
|
|
||||||
the sequence of Migrations for your schema.
|
|
||||||
|
|
||||||
lib
|
|
||||||
Application specific libraries. Basically, any kind of custom code that doesn't
|
|
||||||
belong under controllers, models, or helpers. This directory is in the load path.
|
|
||||||
|
|
||||||
public
|
|
||||||
The directory available for the web server. Contains subdirectories for images, stylesheets,
|
|
||||||
and javascripts. Also contains the dispatchers and the default HTML files.
|
|
||||||
|
|
||||||
script
|
|
||||||
Helper scripts for automation and generation.
|
|
||||||
|
|
||||||
test
|
|
||||||
Unit and functional tests along with fixtures.
|
|
||||||
|
|
||||||
vendor
|
|
||||||
External libraries that the application depends on. Also includes the plugins subdirectory.
|
|
||||||
This directory is in the load path.
|
|
||||||
|
|
4
app/controllers/application.rb
Normal file
4
app/controllers/application.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Filters added to this controller will be run for all controllers in the application.
|
||||||
|
# Likewise, all the methods added will be available for all controllers.
|
||||||
|
class ApplicationController < ActionController::Base
|
||||||
|
end
|
2
app/controllers/trace_controller.rb
Normal file
2
app/controllers/trace_controller.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
class TraceController < ApplicationController
|
||||||
|
end
|
2
app/controllers/trace_points_controller.rb
Normal file
2
app/controllers/trace_points_controller.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
class TracePointsController < ApplicationController
|
||||||
|
end
|
6
app/controllers/user_controller.rb
Normal file
6
app/controllers/user_controller.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class UserController < ApplicationController
|
||||||
|
|
||||||
|
def new
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
3
app/helpers/application_helper.rb
Normal file
3
app/helpers/application_helper.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Methods added to this helper will be available to all templates in the application.
|
||||||
|
module ApplicationHelper
|
||||||
|
end
|
2
app/helpers/trace_helper.rb
Normal file
2
app/helpers/trace_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
module TraceHelper
|
||||||
|
end
|
2
app/helpers/trace_points_helper.rb
Normal file
2
app/helpers/trace_points_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
module TracePointsHelper
|
||||||
|
end
|
2
app/helpers/user_helper.rb
Normal file
2
app/helpers/user_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
module UserHelper
|
||||||
|
end
|
4
app/models/trace.rb
Normal file
4
app/models/trace.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
class Trace < ActiveRecord::Base
|
||||||
|
set_table_name 'gpx_files'
|
||||||
|
has_many :trace_points, :foreign_key => 'gpx_id'
|
||||||
|
end
|
4
app/models/trace_points.rb
Normal file
4
app/models/trace_points.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
class TracePoints < ActiveRecord::Base
|
||||||
|
set_table_name 'gps_points'
|
||||||
|
belongs_to :trace, :foreign_key => 'gpx_id'
|
||||||
|
end
|
3
app/models/user.rb
Normal file
3
app/models/user.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
class User < ActiveRecord::Base
|
||||||
|
has_many :traces
|
||||||
|
end
|
22
app/views/layouts/user.rhtml
Normal file
22
app/views/layouts/user.rhtml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<%= javascript_include_tag 'main.js' %>
|
||||||
|
<!--[if IE]><%= javascript_include_tag 'pngfix.js' %><![endif]--> <!-- thanks, microsoft! -->
|
||||||
|
<%= javascript_include_tag 'tile.js' %>
|
||||||
|
<%= javascript_include_tag 'site.js' %>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
lon = <% if cgi['lon'].length > 0 then print cgi['lon'].to_f else print '0' end %>;
|
||||||
|
lat = <% if cgi['lat'].length > 0 then print cgi['lat'].to_f else print '0' end %>;
|
||||||
|
zoom = <% if cgi['zoom'].length > 0 then print cgi['zoom'].to_f else print '0' end %>;
|
||||||
|
<% if cgi['scale'].length > 0 then %>
|
||||||
|
zoom = Math.log(360.0/(( <% print cgi['scale'].to_f() %> ) * 512.0)) / Math.log(2.0);
|
||||||
|
<% end %>
|
||||||
|
</script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/style.css" />
|
||||||
|
<title>OpenStreetMap</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%= @content_for_layout %>
|
||||||
|
</body>
|
||||||
|
</html>
|
4
app/views/user/new.rhtml
Normal file
4
app/views/user/new.rhtml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
create a user
|
||||||
|
|
||||||
|
|
|
@ -1,277 +1,5 @@
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
|
||||||
<title>Ruby on Rails: Welcome aboard</title>
|
|
||||||
<style type="text/css" media="screen">
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
padding: 0;
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana";
|
|
||||||
font-size: 13px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 28px;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {color: #03c}
|
|
||||||
a:hover {
|
|
||||||
background-color: #03c;
|
|
||||||
color: white;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#page {
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
width: 750px;
|
|
||||||
margin: 0;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#content {
|
|
||||||
float: left;
|
|
||||||
background-color: white;
|
|
||||||
border: 3px solid #aaa;
|
|
||||||
border-top: none;
|
|
||||||
padding: 25px;
|
|
||||||
width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar {
|
|
||||||
float: right;
|
|
||||||
width: 175px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer {
|
nuffin here
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#header, #about, #getting-started {
|
|
||||||
padding-left: 75px;
|
|
||||||
padding-right: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#header {
|
|
||||||
background-image: url("images/rails.png");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: top left;
|
|
||||||
height: 64px;
|
|
||||||
}
|
|
||||||
#header h1, #header h2 {margin: 0}
|
|
||||||
#header h2 {
|
|
||||||
color: #888;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#about h3 {
|
|
||||||
margin: 0;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#about-content {
|
|
||||||
background-color: #ffd;
|
|
||||||
border: 1px solid #fc0;
|
|
||||||
margin-left: -11px;
|
|
||||||
}
|
|
||||||
#about-content table {
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-size: 11px;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
#about-content td {
|
|
||||||
padding: 10px;
|
|
||||||
padding-top: 3px;
|
|
||||||
padding-bottom: 3px;
|
|
||||||
}
|
|
||||||
#about-content td.name {color: #555}
|
|
||||||
#about-content td.value {color: #000}
|
|
||||||
|
|
||||||
#about-content.failure {
|
|
||||||
background-color: #fcc;
|
|
||||||
border: 1px solid #f00;
|
|
||||||
}
|
|
||||||
#about-content.failure p {
|
|
||||||
margin: 0;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#getting-started {
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
margin-top: 25px;
|
|
||||||
padding-top: 15px;
|
|
||||||
}
|
|
||||||
#getting-started h1 {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
#getting-started h2 {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: normal;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
}
|
|
||||||
#getting-started ol {
|
|
||||||
margin-left: 0;
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
#getting-started li {
|
|
||||||
font-size: 18px;
|
|
||||||
color: #888;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
}
|
|
||||||
#getting-started li h2 {
|
|
||||||
margin: 0;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 18px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
#getting-started li p {
|
|
||||||
color: #555;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#search {
|
|
||||||
margin: 0;
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
#search input {
|
|
||||||
font-size: 11px;
|
|
||||||
margin: 2px;
|
|
||||||
}
|
|
||||||
#search-text {width: 170px}
|
|
||||||
|
|
||||||
|
|
||||||
#sidebar ul {
|
|
||||||
margin-left: 0;
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
#sidebar ul h3 {
|
|
||||||
margin-top: 25px;
|
|
||||||
font-size: 16px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
#sidebar li {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
#sidebar ul.links li {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
<script type="text/javascript" src="javascripts/prototype.js"></script>
|
|
||||||
<script type="text/javascript" src="javascripts/effects.js"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
function about() {
|
|
||||||
if (Element.empty('about-content')) {
|
|
||||||
new Ajax.Updater('about-content', 'rails/info/properties', {
|
|
||||||
method: 'get',
|
|
||||||
onFailure: function() {Element.classNames('about-content').add('failure')},
|
|
||||||
onComplete: function() {new Effect.BlindDown('about-content', {duration: 0.25})}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
new Effect[Element.visible('about-content') ?
|
|
||||||
'BlindUp' : 'BlindDown']('about-content', {duration: 0.25});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
$('search-text').value = '';
|
|
||||||
$('search').onsubmit = function() {
|
|
||||||
$('search-text').value = 'site:rubyonrails.org ' + $F('search-text');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="page">
|
|
||||||
<div id="sidebar">
|
|
||||||
<ul id="sidebar-items">
|
|
||||||
<li>
|
|
||||||
<form id="search" action="http://www.google.com/search" method="get">
|
|
||||||
<input type="hidden" name="hl" value="en" />
|
|
||||||
<input type="text" id="search-text" name="q" value="site:rubyonrails.org " />
|
|
||||||
<input type="submit" value="Search" /> the Rails site
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<h3>Join the community</h3>
|
|
||||||
<ul class="links">
|
|
||||||
<li><a href="http://www.rubyonrails.org/">Ruby on Rails</a></li>
|
|
||||||
<li><a href="http://weblog.rubyonrails.org/">Official weblog</a></li>
|
|
||||||
<li><a href="http://lists.rubyonrails.org/">Mailing lists</a></li>
|
|
||||||
<li><a href="http://wiki.rubyonrails.org/rails/pages/IRC">IRC channel</a></li>
|
|
||||||
<li><a href="http://wiki.rubyonrails.org/">Wiki</a></li>
|
|
||||||
<li><a href="http://dev.rubyonrails.org/">Bug tracker</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<h3>Browse the documentation</h3>
|
|
||||||
<ul class="links">
|
|
||||||
<li><a href="http://api.rubyonrails.org/">Rails API</a></li>
|
|
||||||
<li><a href="http://stdlib.rubyonrails.org/">Ruby standard library</a></li>
|
|
||||||
<li><a href="http://corelib.rubyonrails.org/">Ruby core</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="content">
|
|
||||||
<div id="header">
|
|
||||||
<h1>Welcome aboard</h1>
|
|
||||||
<h2>You’re riding the Rails!</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="about">
|
|
||||||
<h3><a href="rails/info/properties" onclick="about(); return false">About your application’s environment</a></h3>
|
|
||||||
<div id="about-content" style="display: none"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="getting-started">
|
|
||||||
<h1>Getting started</h1>
|
|
||||||
<h2>Here’s how to get rolling:</h2>
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>
|
|
||||||
<h2>Create your databases and edit <tt>config/database.yml</tt></h2>
|
|
||||||
<p>Rails needs to know your login and password.</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<h2>Use <tt>script/generate</tt> to create your models and controllers</h2>
|
|
||||||
<p>To see all available options, run it without parameters.</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<h2>Set up a default route and remove or rename this file</h2>
|
|
||||||
<p>Routes are setup in config/routes.rb.</p>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="footer"> </div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
72
public/javascripts/main.js
Normal file
72
public/javascripts/main.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2004-05 Nick Whitelegg, Hogweed Software, nick@hogweed.org
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the Lesser 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
|
||||||
|
Lesser 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 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// These are functions which manipulate the slippy map in various ways
|
||||||
|
// The idea has been to try and clean up the slippy map API and take code
|
||||||
|
// which does not manipulate it directly outside.
|
||||||
|
|
||||||
|
var view=0, tileURL, tile_engine;
|
||||||
|
|
||||||
|
function init()
|
||||||
|
{
|
||||||
|
tileURL = 'http://tile.openstreetmap.org/ruby/wmsmod.rbx';
|
||||||
|
tile_engine = new tile_engine_new('drag','FULL','',tileURL,lon,lat,zoom,700,500);
|
||||||
|
|
||||||
|
tile_engine.setURLAttribute("landsat",1);
|
||||||
|
|
||||||
|
document.getElementById('zoomout').onclick = zoomOut;
|
||||||
|
document.getElementById('zoomin').onclick = zoomIn;
|
||||||
|
/*
|
||||||
|
document.getElementById('landsat').onclick = landsatToggle;
|
||||||
|
*/
|
||||||
|
|
||||||
|
//document.getElementById('posGo').onclick = setPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
function zoomIn()
|
||||||
|
{
|
||||||
|
tile_engine.tile_engine_zoomin();
|
||||||
|
}
|
||||||
|
|
||||||
|
function zoomOut()
|
||||||
|
{
|
||||||
|
tile_engine.tile_engine_zoomout();
|
||||||
|
}
|
||||||
|
|
||||||
|
function enableTileEngine()
|
||||||
|
{
|
||||||
|
tile_engine.event_catch();
|
||||||
|
}
|
||||||
|
|
||||||
|
function landsatToggle()
|
||||||
|
{
|
||||||
|
var lsat = tile_engine.getURLAttribute("landsat");
|
||||||
|
tile_engine.setURLAttribute("landsat", (lsat) ? 0: 1);
|
||||||
|
tile_engine.forceRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPosition()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
var txtLat = document.getElementById("txtLat"),
|
||||||
|
txtLon = document.getElementById("txtLon");
|
||||||
|
|
||||||
|
tile_engine.setLatLon(txtLat, txtLon);
|
||||||
|
*/
|
||||||
|
}
|
25
public/javascripts/pngfix.js
Normal file
25
public/javascripts/pngfix.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
function correctPNG() // correctly handle PNG transparency in Win IE 5.5 or higher.
|
||||||
|
{
|
||||||
|
for(var i=0; i<document.images.length; i++)
|
||||||
|
{
|
||||||
|
var img = document.images[i]
|
||||||
|
var imgName = img.src.toUpperCase()
|
||||||
|
if (imgName.indexOf('.PNG') > 0)
|
||||||
|
{
|
||||||
|
var imgID = (img.id) ? "id='" + img.id + "' " : ""
|
||||||
|
var imgClass = (img.className) ? "class='" + img.className + "' " : ""
|
||||||
|
var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' "
|
||||||
|
var imgStyle = "display:inline-block;" + img.style.cssText
|
||||||
|
if (img.align == "left") imgStyle = "float:left;" + imgStyle
|
||||||
|
if (img.align == "right") imgStyle = "float:right;" + imgStyle
|
||||||
|
if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle
|
||||||
|
var strNewHTML = "<span " + imgID + imgClass + imgTitle
|
||||||
|
+ " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
|
||||||
|
+ "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
|
||||||
|
+ "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>"
|
||||||
|
img.outerHTML = strNewHTML
|
||||||
|
i = i-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.attachEvent("onload", correctPNG);
|
28
public/javascripts/site.js
Normal file
28
public/javascripts/site.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
function updatelinks(lon,lat,zoom) {
|
||||||
|
var links = new Array();
|
||||||
|
links['viewanchor'] = '/index.html';
|
||||||
|
//links['editanchor'] = 'edit.html';
|
||||||
|
links['uploadanchor'] = '/traces';
|
||||||
|
links['loginanchor'] = '/login.html';
|
||||||
|
links['logoutanchor'] = '/logout.html';
|
||||||
|
links['registeranchor'] = '/create-account.html';
|
||||||
|
|
||||||
|
var node;
|
||||||
|
var anchor;
|
||||||
|
for (anchor in links) {
|
||||||
|
node = document.getElementById(anchor);
|
||||||
|
if (! node) { continue; }
|
||||||
|
node.href = links[anchor] + "?lat=" + lat + "&lon=" + lon + "&zoom=" + zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = document.getElementById("editanchor");
|
||||||
|
if (node) {
|
||||||
|
if ( zoom >= 14) {
|
||||||
|
node.href = '/edit.html?lat=' + lat + '&lon=' + lon + "&zoom=" + zoom;
|
||||||
|
node.style.fontStyle = 'normal';
|
||||||
|
} else {
|
||||||
|
node.href = 'javascript:alert("zoom in to edit map");';
|
||||||
|
node.style.fontStyle = 'italic';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
889
public/javascripts/tile.js
Normal file
889
public/javascripts/tile.js
Normal file
|
@ -0,0 +1,889 @@
|
||||||
|
// June 20th 2005 http://civicactions.net anselm@hook.org public domain version 0.5
|
||||||
|
|
||||||
|
//
|
||||||
|
// miscellaneous
|
||||||
|
//
|
||||||
|
|
||||||
|
var netscape = ( document.getElementById && !document.all ) || document.layers;
|
||||||
|
var defaultEngine = null; // xxx for firefox keyboard events.
|
||||||
|
|
||||||
|
var PI = 3.14159265358979323846;
|
||||||
|
|
||||||
|
var lat_range = PI, lon_range = PI;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Utility - get div position - may not be accurate
|
||||||
|
//
|
||||||
|
|
||||||
|
function getCSSPositionX(parent)
|
||||||
|
{
|
||||||
|
var offset = parent.x ? parseInt(parent.x) : 0;
|
||||||
|
offset += parent.style.left ? parseInt(parent.style.left) : 0;
|
||||||
|
for(var node = parent; node ; node = node.offsetParent )
|
||||||
|
{
|
||||||
|
offset += node.offsetLeft;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCSSPositionY(parent)
|
||||||
|
{
|
||||||
|
var offset = parent.y ? parseInt(parent.y) : 0;
|
||||||
|
offset += parent.style.top ? parseInt(parent.style.top) : 0;
|
||||||
|
for(var node = parent; node ; node = node.offsetParent )
|
||||||
|
{
|
||||||
|
offset += node.offsetTop;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// initialize a new tile engine object
|
||||||
|
/// usage: var engine = new tile_engine_new(parentdiv,stylehints,wmssource,lon,lat,zoom,optional width, optional height)
|
||||||
|
///
|
||||||
|
function tile_engine_new(parentname,hints,feedurl,url,lon,lat,zoom,w,h)
|
||||||
|
{
|
||||||
|
// NW geocoder removed for now
|
||||||
|
|
||||||
|
this.timestamp = new Date().getTime();
|
||||||
|
this.urlAttr = new Array();
|
||||||
|
|
||||||
|
// NW Removed navigation buttons entirely for flexibility
|
||||||
|
|
||||||
|
this.lonPerPixel = function()
|
||||||
|
{ return (this.lon_quant/this.scale)/this.tilewidth; }
|
||||||
|
|
||||||
|
this.latPerPixel = function()
|
||||||
|
{ return (this.lat_quant/this.scale)/this.tileheight; }
|
||||||
|
|
||||||
|
this.xToLon = function(x)
|
||||||
|
{ return this.lon + (x-this.thewidth/2)*this.lonPerPixel(); }
|
||||||
|
|
||||||
|
this.yToLat = function(y)
|
||||||
|
{ return normallat(this.lat - (y-this.theheight/2)
|
||||||
|
*this.latPerPixel()); }
|
||||||
|
|
||||||
|
this.lonToX = function (lon)
|
||||||
|
{ return ((lon-this.lon)/this.lonPerPixel()) + this.thewidth/2;}
|
||||||
|
|
||||||
|
this.latToY = function(lat)
|
||||||
|
{ return ((this.lat-mercatorlat(lat))/this.latPerPixel()) +
|
||||||
|
this.theheight/2; }
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// it is possible that this collection is already in use - clean it
|
||||||
|
//
|
||||||
|
this.clean = function()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
while( this.parent.hasChildNodes() )
|
||||||
|
this.parent.removeChild( this.parent.firstChild );
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(var ct=0; ct<this.parent.childNodes.length; ct++)
|
||||||
|
{
|
||||||
|
if(this.parent.childNodes[ct].id != "controls")
|
||||||
|
this.parent.removeChild(this.parent.childNodes[ct]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// build inner tile container for theoretical speed improvement?
|
||||||
|
// center in parent for simplicity of math
|
||||||
|
// size of inner container is irrelevant since overflow is enabled
|
||||||
|
//
|
||||||
|
|
||||||
|
if( this.dragcontainer )
|
||||||
|
{
|
||||||
|
this.tiles = document.createElement('div');
|
||||||
|
this.tiles.style.position = 'absolute';
|
||||||
|
this.tiles.style.left = this.displaywidth/2 + 'px';
|
||||||
|
this.tiles.style.top = this.displayheight/2 + 'px';
|
||||||
|
this.tiles.style.width = '16px';
|
||||||
|
this.tiles.style.height = '16px';
|
||||||
|
if( this.debug )
|
||||||
|
{
|
||||||
|
this.tiles.style.border = 'dashed green 1px';
|
||||||
|
}
|
||||||
|
this.tiles.tile_engine = this;
|
||||||
|
this.parent.appendChild(this.tiles);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.tiles = this.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// focus over specified lon/lat and zoom
|
||||||
|
/// user should call this.drag(0,0) after this to force an initial refresh
|
||||||
|
///
|
||||||
|
|
||||||
|
this.performzoom = function(lon,lat,z)
|
||||||
|
{
|
||||||
|
// setup for zoom
|
||||||
|
// this engine operates at * scale to try avoid tile errors thrashing
|
||||||
|
// server cache
|
||||||
|
|
||||||
|
this.scale = 1000000;
|
||||||
|
this.lon_min_clamp = -180 * this.scale;
|
||||||
|
this.lon_max_clamp = 180 * this.scale;
|
||||||
|
this.lat_min_clamp = -180 * this.scale; //t
|
||||||
|
this.lat_max_clamp = 180 * this.scale; //t
|
||||||
|
this.lon_start_tile = 180 * this.scale;
|
||||||
|
this.lat_start_tile = 90 * this.scale; //t
|
||||||
|
this.zoom_power = 2;
|
||||||
|
this.lon_quant = this.lon_start_tile;
|
||||||
|
this.lat_quant = this.lat_start_tile;
|
||||||
|
this.lon = lon;
|
||||||
|
this.lat = lat;
|
||||||
|
|
||||||
|
// operational lat - = lat due to quirks in our engine and quirks in o
|
||||||
|
// lon/lat design
|
||||||
|
lat = -lat;
|
||||||
|
|
||||||
|
// divide tile size until reach requested zoom
|
||||||
|
// trying to guarantee consistency so as to not thrash the server side tile cache
|
||||||
|
while(z > 0)
|
||||||
|
{
|
||||||
|
this.lon_quant = this.lon_quant / this.zoom_power;
|
||||||
|
this.lat_quant = this.lat_quant / this.zoom_power;
|
||||||
|
z--;
|
||||||
|
}
|
||||||
|
this.lon_quant = Math.round( this.lon_quant );
|
||||||
|
this.lat_quant = Math.round( this.lat_quant );
|
||||||
|
|
||||||
|
// get user requested exact lon/lat
|
||||||
|
this.lon_scaled = Math.round( lon * this.scale );
|
||||||
|
this.lat_scaled = Math.round( lat * this.scale );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// convert requested exact lon/lat to quantized lon lat (rounding down
|
||||||
|
// or up as best suits)
|
||||||
|
this.lon_round = Math.round( this.lon_scaled / this.lon_quant ) *
|
||||||
|
this.lon_quant;
|
||||||
|
this.lat_round = Math.round( this.lat_scaled / this.lat_quant ) *
|
||||||
|
this.lat_quant;
|
||||||
|
|
||||||
|
//alert('lon_round=' + this.lon_round+ ' lat_round='+this.lat_round);
|
||||||
|
|
||||||
|
// calculate world extents [ this is the span of all tiles in lon/lat ]
|
||||||
|
this.lon_min = this.lon_round - this.lon_quant;
|
||||||
|
this.lon_max = this.lon_round + this.lon_quant;
|
||||||
|
this.lat_min = this.lat_round - this.lat_quant;
|
||||||
|
this.lat_max = this.lat_round + this.lat_quant;
|
||||||
|
|
||||||
|
// set tiled region details [ this is the span of all tiles in pixels ]
|
||||||
|
this.centerx = 0;
|
||||||
|
this.centery = 0;
|
||||||
|
this.tilewidth = 256;
|
||||||
|
this.tileheight = 128;
|
||||||
|
this.left = -this.tilewidth;
|
||||||
|
this.right = this.tilewidth;
|
||||||
|
this.top = -this.tileheight;
|
||||||
|
this.bot = this.tileheight;
|
||||||
|
|
||||||
|
|
||||||
|
// adjust the current center position slightly to reflect exact lat/lon
|
||||||
|
// not rounded
|
||||||
|
this.centerx -= (this.lon_scaled-this.lon_round)/
|
||||||
|
(this.lon_max-this.lon_min)*(this.right-this.left);
|
||||||
|
this.centery -= (this.lat_scaled-this.lat_round)/
|
||||||
|
(this.lat_max-this.lat_min)*(this.bot-this.top);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.update_perma_link = function() {
|
||||||
|
// because we're using mercator
|
||||||
|
updatelinks(this.lon,normallat(this.lat),this.zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// draw the spanning lon/lat range
|
||||||
|
/// drag is simply the mouse delta in pixels
|
||||||
|
///
|
||||||
|
|
||||||
|
this.drag = function(dragx,dragy)
|
||||||
|
{
|
||||||
|
var fred=true;
|
||||||
|
|
||||||
|
// move the drag offset
|
||||||
|
this.centerx += dragx;
|
||||||
|
this.centery += dragy;
|
||||||
|
|
||||||
|
// update where we think the user is actually focused
|
||||||
|
this.lon = ( this.lon_round - ( this.lon_max - this.lon_min ) /
|
||||||
|
( this.right - this.left ) * this.centerx ) / this.scale;
|
||||||
|
this.lat = - ( this.lat_round - ( this.lat_max - this.lat_min ) /
|
||||||
|
( this.bot - this.top ) * this.centery ) / this.scale;
|
||||||
|
|
||||||
|
this.update_perma_link();
|
||||||
|
|
||||||
|
// show it
|
||||||
|
var helper = this.navhelp;
|
||||||
|
|
||||||
|
// extend exposed sections
|
||||||
|
var dirty = false;
|
||||||
|
while( this.left + this.centerx > -this.displaywidth/2 &&
|
||||||
|
this.lon_min > this.lon_min_clamp )
|
||||||
|
{
|
||||||
|
this.left -= this.tilewidth;
|
||||||
|
this.lon_min -= this.lon_quant;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
while( this.right + this.centerx < this.displaywidth/2 &&
|
||||||
|
this.lon_max < this.lon_max_clamp )
|
||||||
|
{
|
||||||
|
this.right += this.tilewidth;
|
||||||
|
this.lon_max += this.lon_quant;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
while( this.top + this.centery > -this.displayheight/2 &&
|
||||||
|
this.lat_min > this.lat_min_clamp )
|
||||||
|
{
|
||||||
|
this.top -= this.tileheight;
|
||||||
|
this.lat_min -= this.lat_quant;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( this.bot + this.centery < this.displayheight/2 &&
|
||||||
|
this.lat_max < this.lat_max_clamp )
|
||||||
|
{
|
||||||
|
this.bot += this.tileheight;
|
||||||
|
this.lat_max += this.lat_quant;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// prepare to walk the container and assure that all nodes are correct
|
||||||
|
var containerx;
|
||||||
|
var containery;
|
||||||
|
|
||||||
|
// in drag container mode we do not have to move the children all the
|
||||||
|
// time
|
||||||
|
if( this.dragcontainer )
|
||||||
|
{
|
||||||
|
this.tiles.style.left = this.displaywidth / 2 + this.centerx + 'px';
|
||||||
|
this.tiles.style.top = this.displayheight / 2 + this.centery + 'px';
|
||||||
|
if( !dirty && this.tiles.hasChildNodes() )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
containerx = this.left;
|
||||||
|
containery = this.top;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
containerx = this.left + this.centerx;
|
||||||
|
containery = this.top + this.centery;
|
||||||
|
}
|
||||||
|
|
||||||
|
// walk all tiles and repair as needed
|
||||||
|
// xxx one bug is that it walks the _entire_ width and height...
|
||||||
|
// not just visible.
|
||||||
|
// xxx this makes cleanup harder and perhaps a bitmap is better
|
||||||
|
|
||||||
|
var removehidden = 1;
|
||||||
|
var removecolumn = 0;
|
||||||
|
var removerow = 0;
|
||||||
|
var containeryreset = containery;
|
||||||
|
|
||||||
|
for( var x = this.lon_min; x < this.lon_max ; x+= this.lon_quant )
|
||||||
|
{
|
||||||
|
// will this row be visible in the next round?
|
||||||
|
if( removehidden )
|
||||||
|
{
|
||||||
|
var rx = containerx + this.centerx;
|
||||||
|
if( rx > this.displaywidth / 2 )
|
||||||
|
{
|
||||||
|
removerow = 1;
|
||||||
|
// ideally i would truncate max width here
|
||||||
|
}
|
||||||
|
else if( rx + this.tilewidth < - this.displaywidth / 2 )
|
||||||
|
{
|
||||||
|
removerow = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
removerow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( var y = this.lat_min; y < this.lat_max ; y+= this.lat_quant )
|
||||||
|
{
|
||||||
|
// is this column visible?
|
||||||
|
if( removehidden )
|
||||||
|
{
|
||||||
|
var ry = containery + this.centery;
|
||||||
|
if( ry > this.displayheight / 2 )
|
||||||
|
{
|
||||||
|
removecolumn = 1;
|
||||||
|
}
|
||||||
|
else if( ry + this.tileheight < - this.displayheight/2)
|
||||||
|
{
|
||||||
|
removecolumn = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
removecolumn = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to WMS compliant coordinate system
|
||||||
|
var lt = x / this.scale;
|
||||||
|
var rt = lt + this.lon_quant / this.scale;
|
||||||
|
var tp = y / this.scale;
|
||||||
|
var bt = tp + this.lat_quant / this.scale;
|
||||||
|
var temp = bt;
|
||||||
|
var bt = -tp;
|
||||||
|
var tp = -temp;
|
||||||
|
|
||||||
|
// modify for mercator-projected tiles:
|
||||||
|
tp = 180/PI * (2 * Math.atan(Math.exp(tp * PI / 180)) - PI / 2);
|
||||||
|
bt = 180/PI * (2 * Math.atan(Math.exp(bt * PI / 180)) - PI / 2);
|
||||||
|
|
||||||
|
// make a key
|
||||||
|
var key = this.url + "?WIDTH="+(this.tilewidth)+"&HEIGHT="+
|
||||||
|
(this.tileheight)+"&BBOX="+lt+","+tp+","+rt+","+bt;
|
||||||
|
|
||||||
|
// see if our tile is already present
|
||||||
|
var node = document.getElementById(key);
|
||||||
|
|
||||||
|
// create if not present
|
||||||
|
if(!node)
|
||||||
|
{
|
||||||
|
if( this.debug > 0)
|
||||||
|
{
|
||||||
|
node = document.createElement('div');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node = document.createElement('img');
|
||||||
|
}
|
||||||
|
node.id = key;
|
||||||
|
node.className = 'tile';
|
||||||
|
node.style.position = 'absolute';
|
||||||
|
node.style.width = this.tilewidth + 'px';
|
||||||
|
node.style.height = this.tileheight + 'px';
|
||||||
|
node.style.left = containerx + 'px';
|
||||||
|
node.style.top = containery + 'px';
|
||||||
|
node.style.zIndex = 10; // to appear under the rss elements
|
||||||
|
node.tile_engine = this;
|
||||||
|
if( this.debug > 0)
|
||||||
|
{
|
||||||
|
node.style.border = "1px solid yellow";
|
||||||
|
node.innerHTML = key;
|
||||||
|
if( this.debug > 1 )
|
||||||
|
{
|
||||||
|
var img = document.createElement('img');
|
||||||
|
img.src = key;
|
||||||
|
node.appendChild(img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var goURL = key + "&zoom=" + this.zoom;
|
||||||
|
|
||||||
|
for(var k in this.urlAttr)
|
||||||
|
{
|
||||||
|
goURL += "&"+k+"="+this.urlAttr[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
node.src = goURL;
|
||||||
|
|
||||||
|
node.alt = "loading tile..";
|
||||||
|
node.style.color = "#ffffff";
|
||||||
|
this.tiles.appendChild(node);
|
||||||
|
}
|
||||||
|
// adjust if using active style
|
||||||
|
else if( !this.dragcontainer ) {
|
||||||
|
node.style.left = containerx + 'px';
|
||||||
|
node.style.top = containery + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
containery += this.tileheight;
|
||||||
|
}
|
||||||
|
containery = containeryreset;
|
||||||
|
containerx += this.tilewidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.zoomTo = function(zoom)
|
||||||
|
{
|
||||||
|
|
||||||
|
this.zoom = zoom;
|
||||||
|
|
||||||
|
if (this.zoom < this.minzoom) { this.zoom = this.minzoom; }
|
||||||
|
if (this.zoom > this.maxzoom) { this.zoom = this.maxzoom; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// immediately draw and or fit to feed
|
||||||
|
///
|
||||||
|
this.performzoom(this.lon,this.lat,zoom);
|
||||||
|
this.drag(0,0);
|
||||||
|
|
||||||
|
///
|
||||||
|
} // CLOSE ZOOM FUNCTION
|
||||||
|
|
||||||
|
this.setLatLon = function(lat,lon)
|
||||||
|
{
|
||||||
|
this.lon=lon;
|
||||||
|
this.lat=mercatorlat(lat);
|
||||||
|
this.clean();
|
||||||
|
this.performzoom(lon,mercatorlat(lat),this.zoom);
|
||||||
|
this.drag(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.forceRefresh = function()
|
||||||
|
{
|
||||||
|
this.clean();
|
||||||
|
this.performzoom(this.lon,this.lat,this.zoom);
|
||||||
|
this.drag(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// zoom a tile group
|
||||||
|
///
|
||||||
|
this.tile_engine_zoomout = function()
|
||||||
|
{
|
||||||
|
this.clean();
|
||||||
|
this.zoomTo(this.zoom-1);
|
||||||
|
|
||||||
|
return false; // or safari falls over
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// zoom a tile group
|
||||||
|
///
|
||||||
|
this.tile_engine_zoomin = function()
|
||||||
|
{
|
||||||
|
|
||||||
|
this.clean();
|
||||||
|
this.zoomTo(this.zoom+1);
|
||||||
|
|
||||||
|
return false; // or safari falls over
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setURL=function(url) { this.url=url; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// intercept context events to minimize out-of-browser interruptions
|
||||||
|
///
|
||||||
|
|
||||||
|
this.event_context = function(e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// keys
|
||||||
|
///
|
||||||
|
|
||||||
|
this.event_key = function(e)
|
||||||
|
{
|
||||||
|
var key = 0;
|
||||||
|
|
||||||
|
var hostengine = defaultEngine;
|
||||||
|
|
||||||
|
if( window && window.event && window.event.srcElement ) {
|
||||||
|
hostengine = window.event.srcElement.tile_engine;
|
||||||
|
} else if( e.target ) {
|
||||||
|
hostengine = e.target.tile_engine;
|
||||||
|
} else if( e.srcElement ) {
|
||||||
|
hostengine = e.srcElement.tile_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( hostengine == null ) {
|
||||||
|
hostengine = defaultEngine;
|
||||||
|
if( hostengine == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( e == null && document.all ) {
|
||||||
|
e = window.event;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( e ) {
|
||||||
|
if( e.keyCode ) {
|
||||||
|
key = e.keyCode;
|
||||||
|
}
|
||||||
|
else if( e.which ) {
|
||||||
|
key = e.which;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(key) {
|
||||||
|
case 97: // a = left
|
||||||
|
hostengine.drag(16,0);
|
||||||
|
break;
|
||||||
|
case 100: // d = right
|
||||||
|
hostengine.drag(-16,0);
|
||||||
|
break;
|
||||||
|
case 119: // w = up
|
||||||
|
hostengine.drag(0,16);
|
||||||
|
break;
|
||||||
|
case 120: // x = dn
|
||||||
|
hostengine.drag(0,-16);
|
||||||
|
break;
|
||||||
|
case 115: // s = center
|
||||||
|
new tile_engine_new(hostengine.parentname,
|
||||||
|
"FULL",
|
||||||
|
hostengine.feedurl, // xxx hrm, cache this?
|
||||||
|
hostengine.url,
|
||||||
|
hostengine.lon,
|
||||||
|
hostengine.lat,
|
||||||
|
hostengine.zoom,
|
||||||
|
0,0
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 122: // z = zoom
|
||||||
|
new tile_engine_new(hostengine.parentname,
|
||||||
|
"FULL",
|
||||||
|
hostengine.feedurl, // xxx hrm, cache this?
|
||||||
|
hostengine.url,
|
||||||
|
hostengine.lon,
|
||||||
|
hostengine.lat,
|
||||||
|
hostengine.zoom + 1,
|
||||||
|
0,0
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 99: // c = unzoom
|
||||||
|
new tile_engine_new(hostengine.parentname,
|
||||||
|
"FULL",
|
||||||
|
hostengine.feedurl, // xxx hrm, cache this?
|
||||||
|
hostengine.url,
|
||||||
|
hostengine.lon,
|
||||||
|
hostengine.lat,
|
||||||
|
hostengine.zoom - 1,
|
||||||
|
0,0
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// catch mouse move events
|
||||||
|
/// this routine _must_ return false or else the operating system outside-of-browser-scope drag and drop handler will interfere
|
||||||
|
///
|
||||||
|
|
||||||
|
this.event_mouse_move = function(e) {
|
||||||
|
|
||||||
|
var hostengine = null;
|
||||||
|
if( window && window.event && window.event.srcElement ) {
|
||||||
|
hostengine = window.event.srcElement.tile_engine;
|
||||||
|
} else if( e.target ) {
|
||||||
|
hostengine = e.target.tile_engine;
|
||||||
|
} else if( e.srcElement ) {
|
||||||
|
hostengine = e.srcElement.tile_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( hostengine && hostengine.drag ) {
|
||||||
|
if( hostengine.mousedown ) {
|
||||||
|
if( netscape ) {
|
||||||
|
hostengine.mousex = parseInt(e.pageX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(e.pageY) + 0.0;
|
||||||
|
} else {
|
||||||
|
hostengine.mousex = parseInt(window.event.clientX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(window.event.clientY) + 0.0;
|
||||||
|
}
|
||||||
|
hostengine.drag(hostengine.mousex-hostengine.lastmousex,hostengine.mousey-hostengine.lastmousey);
|
||||||
|
}
|
||||||
|
hostengine.lastmousex = hostengine.mousex;
|
||||||
|
hostengine.lastmousey = hostengine.mousey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// must return false to prevent operating system drag and drop from handling events
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// catch mouse down
|
||||||
|
///
|
||||||
|
|
||||||
|
this.event_mouse_down = function(e) {
|
||||||
|
|
||||||
|
var hostengine = null;
|
||||||
|
if( window && window.event && window.event.srcElement ) {
|
||||||
|
hostengine = window.event.srcElement.tile_engine;
|
||||||
|
} else if( e.target ) {
|
||||||
|
hostengine = e.target.tile_engine;
|
||||||
|
} else if( e.srcElement ) {
|
||||||
|
hostengine = e.srcElement.tile_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( hostengine ) {
|
||||||
|
if( netscape ) {
|
||||||
|
hostengine.mousex = parseInt(e.pageX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(e.pageY) + 0.0;
|
||||||
|
} else {
|
||||||
|
hostengine.mousex = parseInt(window.event.clientX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(window.event.clientY) + 0.0;
|
||||||
|
}
|
||||||
|
hostengine.lastmousex = hostengine.mousex;
|
||||||
|
hostengine.lastmousey = hostengine.mousey;
|
||||||
|
hostengine.mousedown = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// must return false to prevent operating system drag and drop from handling events
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// catch double click (use to center map)
|
||||||
|
///
|
||||||
|
|
||||||
|
this.event_double_click = function(e) {
|
||||||
|
|
||||||
|
var hostengine = null;
|
||||||
|
if( window && window.event && window.event.srcElement ) {
|
||||||
|
hostengine = window.event.srcElement.tile_engine;
|
||||||
|
} else if( e.target ) {
|
||||||
|
hostengine = e.target.tile_engine;
|
||||||
|
} else if( e.srcElement ) {
|
||||||
|
hostengine = e.srcElement.tile_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( hostengine ) {
|
||||||
|
if( netscape ) {
|
||||||
|
hostengine.mousex = parseInt(e.pageX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(e.pageY) + 0.0;
|
||||||
|
} else {
|
||||||
|
hostengine.mousex = parseInt(window.event.clientX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(window.event.clientY) + 0.0;
|
||||||
|
}
|
||||||
|
var dx = hostengine.mousex-(hostengine.displaywidth/2)-hostengine.parent_x;
|
||||||
|
var dy = hostengine.mousey-(hostengine.displayheight/2)-hostengine.parent_y;
|
||||||
|
hostengine.drag(-dx,-dy); // TODO smooth
|
||||||
|
}
|
||||||
|
|
||||||
|
// must return false to prevent operating system drag and drop from handling events
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// catch mouse up
|
||||||
|
///
|
||||||
|
|
||||||
|
this.event_mouse_up = function(e) {
|
||||||
|
|
||||||
|
var hostengine = null;
|
||||||
|
if( window && window.event && window.event.srcElement ) {
|
||||||
|
hostengine = window.event.srcElement.tile_engine;
|
||||||
|
} else if( e.target ) {
|
||||||
|
hostengine = e.target.tile_engine;
|
||||||
|
} else if( e.srcElement ) {
|
||||||
|
hostengine = e.srcElement.tile_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( hostengine ) {
|
||||||
|
if( netscape ) {
|
||||||
|
hostengine.mousex = parseInt(e.pageX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(e.pageY) + 0.0;
|
||||||
|
} else {
|
||||||
|
hostengine.mousex = parseInt(window.event.clientX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(window.event.clientY) + 0.0;
|
||||||
|
}
|
||||||
|
hostengine.mousedown = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// must return false to prevent operating system drag and drop from handling events
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// catch mouse out
|
||||||
|
///
|
||||||
|
|
||||||
|
this.event_mouse_out = function(e) {
|
||||||
|
|
||||||
|
var hostengine = null;
|
||||||
|
if( window && window.event && window.event.srcElement ) {
|
||||||
|
hostengine = window.event.srcElement.tile_engine;
|
||||||
|
} else if( e.target ) {
|
||||||
|
hostengine = e.target.tile_engine;
|
||||||
|
} else if( e.srcElement ) {
|
||||||
|
hostengine = e.srcElement.tile_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( hostengine ) {
|
||||||
|
if( netscape ) {
|
||||||
|
hostengine.mousex = parseInt(e.pageX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(e.pageY) + 0.0;
|
||||||
|
} else {
|
||||||
|
hostengine.mousex = parseInt(window.event.clientX) + 0.0;
|
||||||
|
hostengine.mousey = parseInt(window.event.clientY) + 0.0;
|
||||||
|
}
|
||||||
|
hostengine.mousedown = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// must return false to prevent operating system drag and drop from handling events
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// register new handlers to catch desired events
|
||||||
|
///
|
||||||
|
|
||||||
|
// NW removed parameter - always use parent
|
||||||
|
this.event_catch = function() {
|
||||||
|
|
||||||
|
this.parent.style.cursor = 'move';
|
||||||
|
|
||||||
|
if( netscape ) {
|
||||||
|
window.captureEvents(Event.MOUSEMOVE);
|
||||||
|
window.captureEvents(Event.KEYPRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parent.onmousemove = this.event_mouse_move;
|
||||||
|
this.parent.onmousedown = this.event_mouse_down;
|
||||||
|
this.parent.onmouseup = this.event_mouse_up;
|
||||||
|
this.parent.onkeypress = this.event_key;
|
||||||
|
window.ondblclick = this.event_double_click;
|
||||||
|
|
||||||
|
if( window ) {
|
||||||
|
window.onmousemove = this.event_mouse_move;
|
||||||
|
window.onmouseup = this.event_mouse_up;
|
||||||
|
window.ondblclick = this.event_double_click;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setURLAttribute = function(k,v)
|
||||||
|
{
|
||||||
|
this.urlAttr[k] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getURLAttribute = function(k)
|
||||||
|
{
|
||||||
|
return this.urlAttr[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getDownloadedTileBounds = function()
|
||||||
|
{
|
||||||
|
var bounds = new Array();
|
||||||
|
bounds.w=this.lon_min;
|
||||||
|
bounds.s=normallat(this.lat_min);
|
||||||
|
bounds.e=this.lon_max;
|
||||||
|
bounds.n=normallat(this.lat_max);
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getVisibleBounds = function()
|
||||||
|
{
|
||||||
|
var bounds = new Array();
|
||||||
|
bounds.w = this.xToLon(0);
|
||||||
|
bounds.s = this.yToLat(this.theheight);
|
||||||
|
bounds.e = this.xToLon(this.thewidth);
|
||||||
|
bounds.n = this.yToLat(0);
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// navout and navin stuff - START
|
||||||
|
// draw navigation buttons into the parent div
|
||||||
|
|
||||||
|
// ENTRY CODE BEGINS HERE....
|
||||||
|
|
||||||
|
|
||||||
|
// get parent div or fail
|
||||||
|
this.parent = document.getElementById(parentname);
|
||||||
|
if( this.parent == null ) {
|
||||||
|
alert('The tile map engine cannot find a parent container named ['
|
||||||
|
+parentname+']');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// store for later
|
||||||
|
//
|
||||||
|
|
||||||
|
this.parentname = parentname;
|
||||||
|
this.hints = hints;
|
||||||
|
this.feedurl = feedurl;
|
||||||
|
this.url = url;
|
||||||
|
this.lon = lon;
|
||||||
|
this.lat = mercatorlat(lat);
|
||||||
|
this.thewidth = w;
|
||||||
|
this.theheight = h;
|
||||||
|
this.dragcontainer = 1;
|
||||||
|
this.debug = 0;
|
||||||
|
|
||||||
|
// for firefox keyboard
|
||||||
|
defaultEngine = this;
|
||||||
|
document.engine = this;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// decide on display width and height
|
||||||
|
//
|
||||||
|
if( !w || !h )
|
||||||
|
{
|
||||||
|
w = parseInt(this.parent.style.width);
|
||||||
|
h = parseInt(this.parent.style.height);
|
||||||
|
if(!w || !h)
|
||||||
|
{
|
||||||
|
w = 512;
|
||||||
|
h = 256;
|
||||||
|
this.parent.style.width = w + 'px';
|
||||||
|
this.parent.style.height = h + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.parent.style.width = parseInt(w) + 'px';
|
||||||
|
this.parent.style.height = parseInt(h) + 'px';
|
||||||
|
}
|
||||||
|
this.displaywidth = w;
|
||||||
|
this.displayheight = h;
|
||||||
|
|
||||||
|
this.minzoom = 0;
|
||||||
|
this.maxzoom = 20;
|
||||||
|
|
||||||
|
//
|
||||||
|
// enforce parent div style?
|
||||||
|
// position absolute is really only required for firefox
|
||||||
|
// http://www.quirksmode.org/js/findpos.html
|
||||||
|
//
|
||||||
|
|
||||||
|
this.parent_x = getCSSPositionX(this.parent);
|
||||||
|
this.parent_y = getCSSPositionY(this.parent);
|
||||||
|
|
||||||
|
this.parent.style.position = 'relative';
|
||||||
|
this.parent.style.overflow = 'hidden';
|
||||||
|
this.parent.style.backgroundColor = '#000036';
|
||||||
|
|
||||||
|
|
||||||
|
// attach event capture parent div
|
||||||
|
this.event_catch();
|
||||||
|
|
||||||
|
this.clean();
|
||||||
|
//this.makeZoom();
|
||||||
|
|
||||||
|
this.zoomTo(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function normallat(mercatorlat)
|
||||||
|
{
|
||||||
|
var tp = 180/PI*(2 * Math.atan(Math.exp(mercatorlat * PI / 180)) - PI / 2);
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mercatorlat(normallat)
|
||||||
|
{
|
||||||
|
var lpi = 3.14159265358979323846;
|
||||||
|
return Math.log( Math.tan( (lpi / 4.0) + (normallat / 180.0 * lpi / 2.0))) *
|
||||||
|
180.0 / lpi ;
|
||||||
|
}
|
|
@ -1 +1,2 @@
|
||||||
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
|
User-agent: *
|
||||||
|
Disallow: /api/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue