more basic framework
authorSteve Coast <steve@asklater.com>
Fri, 28 Jul 2006 21:53:30 +0000 (21:53 +0000)
committerSteve Coast <steve@asklater.com>
Fri, 28 Jul 2006 21:53:30 +0000 (21:53 +0000)
20 files changed:
README
app/controllers/application.rb [new file with mode: 0644]
app/controllers/trace_controller.rb [new file with mode: 0644]
app/controllers/trace_points_controller.rb [new file with mode: 0644]
app/controllers/user_controller.rb [new file with mode: 0644]
app/helpers/application_helper.rb [new file with mode: 0644]
app/helpers/trace_helper.rb [new file with mode: 0644]
app/helpers/trace_points_helper.rb [new file with mode: 0644]
app/helpers/user_helper.rb [new file with mode: 0644]
app/models/trace.rb [new file with mode: 0644]
app/models/trace_points.rb [new file with mode: 0644]
app/models/user.rb [new file with mode: 0644]
app/views/layouts/user.rhtml [new file with mode: 0644]
app/views/user/new.rhtml [new file with mode: 0644]
public/index.html
public/javascripts/main.js [new file with mode: 0644]
public/javascripts/pngfix.js [new file with mode: 0644]
public/javascripts/site.js [new file with mode: 0644]
public/javascripts/tile.js [new file with mode: 0644]
public/robots.txt

diff --git a/README b/README
index b8e3569..74c8ed1 100644 (file)
--- a/README
+++ b/README
-== Welcome to Rails
 
-Rails is a web-application and persistence framework that includes everything
-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.
+Task one
+========
 
-In Rails, the model is handled by what's called an object-relational mapping
-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.
+Get OSM on rails with a 0.4 API, without changing the db schema
 
-The controller and view are handled by the Action Pack, which handles both
-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.
+see db/README for how to create the db
 
+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.
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
new file mode 100644 (file)
index 0000000..537de40
--- /dev/null
@@ -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
\ No newline at end of file
diff --git a/app/controllers/trace_controller.rb b/app/controllers/trace_controller.rb
new file mode 100644 (file)
index 0000000..7420ea5
--- /dev/null
@@ -0,0 +1,2 @@
+class TraceController < ApplicationController
+end
diff --git a/app/controllers/trace_points_controller.rb b/app/controllers/trace_points_controller.rb
new file mode 100644 (file)
index 0000000..be34cd2
--- /dev/null
@@ -0,0 +1,2 @@
+class TracePointsController < ApplicationController
+end
diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb
new file mode 100644 (file)
index 0000000..da27a95
--- /dev/null
@@ -0,0 +1,6 @@
+class UserController < ApplicationController
+
+  def new
+
+  end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
new file mode 100644 (file)
index 0000000..22a7940
--- /dev/null
@@ -0,0 +1,3 @@
+# Methods added to this helper will be available to all templates in the application.
+module ApplicationHelper
+end
diff --git a/app/helpers/trace_helper.rb b/app/helpers/trace_helper.rb
new file mode 100644 (file)
index 0000000..278c6c4
--- /dev/null
@@ -0,0 +1,2 @@
+module TraceHelper
+end
diff --git a/app/helpers/trace_points_helper.rb b/app/helpers/trace_points_helper.rb
new file mode 100644 (file)
index 0000000..0252b91
--- /dev/null
@@ -0,0 +1,2 @@
+module TracePointsHelper
+end
diff --git a/app/helpers/user_helper.rb b/app/helpers/user_helper.rb
new file mode 100644 (file)
index 0000000..0147c3f
--- /dev/null
@@ -0,0 +1,2 @@
+module UserHelper
+end
diff --git a/app/models/trace.rb b/app/models/trace.rb
new file mode 100644 (file)
index 0000000..a7e19be
--- /dev/null
@@ -0,0 +1,4 @@
+class Trace < ActiveRecord::Base
+  set_table_name 'gpx_files'
+  has_many :trace_points, :foreign_key => 'gpx_id'
+end
diff --git a/app/models/trace_points.rb b/app/models/trace_points.rb
new file mode 100644 (file)
index 0000000..56703a2
--- /dev/null
@@ -0,0 +1,4 @@
+class TracePoints < ActiveRecord::Base
+  set_table_name 'gps_points'
+  belongs_to :trace, :foreign_key => 'gpx_id'
+end
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644 (file)
index 0000000..cfcbfd3
--- /dev/null
@@ -0,0 +1,3 @@
+class User < ActiveRecord::Base
+  has_many :traces
+end
diff --git a/app/views/layouts/user.rhtml b/app/views/layouts/user.rhtml
new file mode 100644 (file)
index 0000000..1bd916a
--- /dev/null
@@ -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>
diff --git a/app/views/user/new.rhtml b/app/views/user/new.rhtml
new file mode 100644 (file)
index 0000000..4e1ca5f
--- /dev/null
@@ -0,0 +1,4 @@
+
+create a user
+
+
index a2daab7..b484546 100644 (file)
@@ -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 {
-        clear: both;
-      }
-      
+nuffin here
 
-      #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&rsquo;re riding the Rails!</h2>
-        </div>
-
-        <div id="about">
-          <h3><a href="rails/info/properties" onclick="about(); return false">About your application&rsquo;s environment</a></h3>
-          <div id="about-content" style="display: none"></div>
-        </div>
-        
-        <div id="getting-started">
-          <h1>Getting started</h1>
-          <h2>Here&rsquo;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">&nbsp;</div>
-    </div>
-  </body>
-</html>
\ No newline at end of file
diff --git a/public/javascripts/main.js b/public/javascripts/main.js
new file mode 100644 (file)
index 0000000..fc888d4
--- /dev/null
@@ -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);
+       */
+}
diff --git a/public/javascripts/pngfix.js b/public/javascripts/pngfix.js
new file mode 100644 (file)
index 0000000..0fdefc6
--- /dev/null
@@ -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);
diff --git a/public/javascripts/site.js b/public/javascripts/site.js
new file mode 100644 (file)
index 0000000..75c3eb5
--- /dev/null
@@ -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';
+    }
+    }
+}
diff --git a/public/javascripts/tile.js b/public/javascripts/tile.js
new file mode 100644 (file)
index 0000000..069767d
--- /dev/null
@@ -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 ;
+}
index 4ab9e89..d346249 100644 (file)
@@ -1 +1,2 @@
-# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
\ No newline at end of file
+User-agent: *
+Disallow: /api/