// This JavaScript file is automatically generated by js-tool.
// Do NOT read it! Do NOT edit it! Edit the source code instead.
// Show Coordinates in Google Maps 0.0.1 (alpha) 2008-01-23
// ------------------------------------------
// Copyright (c) 2008 Ilya Dogolazky
// Released under the GPL license, see http://www.gnu.org/copyleft/gpl.html for details
// ------------------------------------------
// ==UserScript==
// @name Show Coordinates in Google Maps
// @namespace http://www.math.uni-bonn.de/people/ilyad/gm/coordinates
// @include http://maps.google.tld/*
// ==/UserScript==
const nbsp = String.fromCharCode(160) ;
// File Debug.js
Debug.level = function(l) // 0:nothing, 1:alerts only; 2:errors+alerts 3: alerts, errors and warnings 4:all messages
{
Debug.current_level = l ;
}
Debug.gm = function(level, cl, msg)
{
if(cl>level)
{
for(var i=0, ar=[]; i<msg.length; ++i)
ar.push(msg[i]) ;
var message = ar.join("") ;
// GM_log(message, 3-level) ;
// oops! GM_log accepts only one parameter!
// http://wiki.greasespot.net/index.php?title=GM_log&diff=1764&oldid=1762 :-(
if(level==3) GM_log(message) ;
else if(level==2) GM_log("WARNING: "+message) ;
else if(level==1) GM_log("ERROR!\n"+message) ;
else if(level==0)
{
var answer = window.confirm(message+"\n\n---------------\n\n"+"Click 'ok' to continue, 'cancel' to abort script") ;
if(!answer)
throw new Error("Aborted: "+message) ;
}
else
window.alert("Debug.gm(): Invalid debugging level ("+level+") Message:\n"+message) ;
}
}
Debug.level(4) ;
Debug.log = function() { Debug.gm(3, Debug.current_level, arguments) ; }
Debug.warn = function() { Debug.gm(2, Debug.current_level, arguments) ; }
Debug.error = function() { Debug.gm(1, Debug.current_level, arguments) ; }
Debug.alert = function() { Debug.gm(0, Debug.current_level, arguments) ; }
Debug.prototype.log = function() { this.log_member(3, arguments) ; }
Debug.prototype.warn = function() { this.log_member(2, arguments) ; }
Debug.prototype.error = function() { this.log_member(1, arguments) ; }
Debug.prototype.alert = function() { this.log_member(0, arguments) ; }
Debug.prototype.log_member = function(level, msg)
{
Debug.gm(level, this.enabled(), msg) ;
}
Debug.prototype.enabled = function()
{
if(this.absolute)
return this.current_level ;
else
return Math.min(this.current_level, Debug.current_level) ;
}
function Debug(level)
{
this.absolute = (level<0) ;
if(this.absolute)
level = -level ;
this.current_level = level ;
}
// vim:tw=0:smartindent
// End of file Debug.js
// File Xpath.js
Xpath.list = function(xpath, root, order)
{
if(!root)
root = window.document ;
var result = [] ;
var snapshot = document.evaluate(xpath, root, null, (order ? XPathResult.ORDERED_NODE_SNAPSHOT_TYPE : XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE), null) ;
for(var i=0; i<snapshot.snapshotLength; ++i)
result.push(snapshot.snapshotItem(i)) ;
return result ;
}
Xpath.node = function(xpath, root)
{
return Xpath.list(xpath, root, false)[0] ;
}
Xpath.aNode = function (hash, root)
{
var list = Xpath.aList(hash, root) ;
if(list.length==0)
return null ;
if(list.length>1)
GM_log("Multiply nodes found in Xpath.aNode("+hash+")") ;
return list[0] ;
}
Xpath.aList = function(list, root, order)
{
var xpath = Xpath.aXpath(list) ;
return Xpath.list(xpath, root, order) ;
}
Xpath.aXpath = function (list)
{
var s = [] ;
while(list.length>0)
{
var key = list.shift() ;
var value = list.shift() ;
var at = "@" + key ;
s.push((value==null || value=="*") ? at : at+"='" + value + "'") ;
}
return "descendant::*["+s.join(" and ")+"]" ;
}
function Xpath()
{}
// End of file Xpath.js
// File Coordinates.js
// File Vector.js
function Vector(object, first, second)
{
if(object instanceof Array)
{
this.values = [object[0], object[1]] ;
this.names = [first || "_x", second || "_y"] ;
}
else
{
this.names = [first, second] ;
this.values = [] ;
for(var i=0; i<2; ++i)
{
var x = this.names[i];
if(object[x]!=null)
var re = object[x].match("(?:^| )(-?\\d+)(?:px)?(?: |$)") ;
else
var re = object.toString().match("(?:^| )"+x+": (-?\\d+)px;(?: |$)") ;
if(!re)
return null ;
var v = parseInt(re[1]) ;
if(isNaN(v))
return null ;
this.values.push(v) ;
}
}
// Debug.log("Vector constructed from object ", object, "\n", this.names.toString(), "\n", this.values.toString())
// Debug.log("Vector constructed from object ", object, "\n", this.toString())
}
Vector.prototype.x = function()
{
return this.values[0] ;
}
Vector.prototype.y = function()
{
return this.values[1] ;
}
Vector.prototype.plus = function(w)
{
return new Vector([this.x()+w.x(), this.y()+w.y()]) ;
}
Vector.prototype.minus = function(w)
{
return new Vector([this.x()-w.x(), this.y()-w.y()]) ;
}
Vector.prototype.toString = function()
{
return "(" + this.names[0] + ": " + this.values[0] + ", " +
this.names[1] + ": " + this.values[1] +
")" ;
}
// vim:tw=0:smartindent
// End of file Vector.js
// File Tile.js
// File Uri.js
function Uri(str)
{
var t = str.match(/^(.*?)#(.*)$/) ;
if(t)
{
str = t[1] ;
this.fragment = t[2] ;
}
this.location = str ;
t = str.match(/^(.*?)\?(.*)$/) ;
if(t)
{
str = t[1] ;
var q = t[2] ;
}
this.path = str ;
this.query = new Object ;
if(q)
{
for each(var qq in q.split('&'))
{
var i = qq.search("=") ;
if(i==-1)
{
var key = qq ;
var value = undefined
}
else
{
var key = qq.substr(0,i) ;
var value = qq.substr(i+1) ;
}
this.query[key] = value ;
}
}
}
Uri.prototype.originalLocation = function()
{
return this.location ;
}
Uri.prototype.toString = function()
{
var res = this.path ;
var qq = [] ;
for(var key in this.query)
{
var q = key+'' ;
var value = this.query[key] ;
if(value!=undefined)
q += '=' + value ;
qq.push(q)
}
if(qq.length)
res += "?" + qq.join("&") ;
if(this.fragment)
res += "#" + this.fragment ;
return res ;
}
if(new Debug(0).enabled())
{
var u = new Uri(window.location.toString()) ;
alert(Dumper(u)+"\n----\n"+u.toString()) ;
}
// End of file Uri.js
// use Debug: already included
// use Vector: already included
Tile.rad2deg = function(x) { return x*(180/Math.PI); }
Tile.deg2rad = function(x) { return x/(180/Math.PI); }
// (-pi/2, pi/2) --> (-infty,+infty)
Tile.f1 = function(x) { return 0.5 * Math.log((1+Math.sin(x))/(1-Math.sin(x))) ; }
// (-pi/2, pi/2) <-- (-infty,+infty)
Tile.f2 = function(x) { return Math.asin((Math.exp(2*x)-1)/(Math.exp(2*x)+1)) ; }
Tile.TILE_SIZE = 256 ;
Tile.MAXZOOM = 21 ; // Can be changed
Tile.MAX_MAP_ZOOM = 17 ; // Do not change!
Tile.TOTAL = (1<<Tile.MAXZOOM) * Tile.TILE_SIZE ;
Tile.MAX_LATITUDE = Tile.rad2deg(Tile.f2(Math.PI)) ;
Tile.grain2latitude = function(y2)
{
var y1 = (Tile.TOTAL / 2) - y2 ;
var f1 = y1 * Math.PI / (Tile.TOTAL / 2) ;
return Tile.rad2deg(Tile.f2(f1)) ;
}
Tile.grain2longitude = function(g)
{
return (g-(Tile.TOTAL/2)) / (Tile.TOTAL / 360) ;
}
Tile.xy={q:{x:0,y:0}, r:{x:1,y:0}, t:{x:0,y:1}, s:{x:1,y:1}} ;
Tile.qrst2xyz = function(qrst)
{
var s = {x:0, y:0, z:qrst.length} ;
for(var i=0; i<qrst.length; ++i)
{
var p = qrst.charAt(i) ;
for each(var v in ["x", "y"])
{
s[v] <<= 1 ;
s[v] += Tile.xy[p][v] ;
}
}
return s ;
}
function Tile(url)
{
var query = new Uri(url).query ;
if(query.t!=null)
{
var qrst = query.t.substr(1, query.t.length-1) ;
var xyz = Tile.qrst2xyz(qrst) ;
}
else
{
var xyz = {
x: parseInt(query.x),
y: parseInt(query.y),
z:Tile.MAX_MAP_ZOOM-parseInt(query.zoom)
} ;
}
for each(var v in ["x", "y", "z"])
if(isNaN(this[v] = xyz[v]))
return null ;
}
Tile.prototype.pixel2lonlat = function (v)
{
var grain_x = ((this.x * Tile.TILE_SIZE) + v.x()) * (1<<(Tile.MAXZOOM-this.z)) ;
var grain_y = ((this.y * Tile.TILE_SIZE) + v.y()) * (1<<(Tile.MAXZOOM-this.z)) ;
var lon = Tile.grain2longitude(grain_x) ;
var lat = Tile.grain2latitude(grain_y) ;
while(lon>180)
lon -= 360 ;
while(lon<-180)
lon += 360 ;
return new Vector([lon, lat], "lon", "lat") ;
}
Tile.precision = function(z, unit) // z is the same as "z" property, unit = 1 for degrees or 1/3600 for seconds
{
var units_in_pixel = (360/unit) / (Tile.TILE_SIZE*(1<<z)) ;
var prec = 0 ;
while(units_in_pixel < 1)
{
++ prec ;
units_in_pixel *= 10 ;
}
return prec ;
}
Tile.format_deg = function(lonlat, prec)
{
var x = lonlat.x() ;
var y = lonlat.y() ;
var dot = (prec>0) ? 1 : 0 ;
return print_s(x.toFixed(prec), prec+dot+4) + nbsp + print_s(y.toFixed(prec), prec+dot+3) ;
}
function print_s(str, prec)
{
var res = "" ;
for(var i=0; i<prec-str.length; ++i)
res += nbsp;
return res + str ;
}
// vim:tw=0:smartindent
// End of file Tile.js
const image_o_png ="%89%50%4e%47%0d%0a%1a%0a%00%00%00%0d%49%48%44%52%00%00%00%0d%00%00%00%0d%08%06%00%00%00%72%eb%e4%7c%00%00%00%06%62%4b%47%44%00%00%00%00%00%00%f9%43%bb%7f%00%00%00%09%70%48%59%73%00%00%0b%13%00%00%0b%13%01%00%9a%9c%18%00%00%00%07%74%49%4d%45%07%d8%01%17%14%36%15%3d%f9%0c%46%00%00%00%1d%74%45%58%74%43%6f%6d%6d%65%6e%74%00%43%72%65%61%74%65%64%20%77%69%74%68%20%54%68%65%20%47%49%4d%50%ef%64%25%6e%00%00%00%55%49%44%41%54%28%cf%b5%92%41%0e%80%40%08%03%a7%86%0f%ec%ff%1f%5b%0f%1e%44%57%c9%86%e8%1c%49%d3%42%03%9c%d8%b6%01%73%65%9a%6f%34%88%07%e7%0a%03%c4%91%bc%a0%4e%3a%bd%24%e9%ee%fe%1f%1e%e3%db%84%d6%4d%53%7b%92%ca%e6%00%22%8b%aa%fa%b3%2e%d2%2a%5e%3c%a7%f7%46%3b%27%fe%24%26%00%d7%4a%70%00%00%00%00%49%45%4e%44%ae%42%60%82";
function Coordinates(o)
{
for each(var key in ['anchor', 'map'])
this[key] = o[key] ;
this.container = Xpath.node("./div[1]/div[1]", this.map) ;
this.lala = document.createTextNode("lala") ;
var space = document.createTextNode(" " + String.fromCharCode(0x263A)+ " ")
var tt = document.createElement("tt") ;
tt.appendChild(this.lala) ;
this.anchor.parentNode.appendChild(space) ;
this.anchor.parentNode.appendChild(tt) ;
this.origin = document.createElement("img") ;
// this.origin.innerHTML = "O" ;
this.origin.src = "data:image/png," + image_o_png ;
this.origin.style.position = "absolute" ;
this.origin.style.left = "200px" ;
this.origin.style.top = "100px" ;
this.origin.id = "OOO" ;
var s = window.getComputedStyle(this.map, "") ;
var m = new Vector(s, "width", "height") ;
this.origin.style.left = Math.floor(m.x()/2)+"px" ;
this.origin.style.top = Math.floor(m.y()/2)+"px" ;
// Debug.alert("h", s.height, "w", s.width ) ;
this.map.appendChild(this.origin) ;
this.img = null ;
for each(var i in Xpath.list('./div[1]/div[1]/div[2]/div[1]/img',this.map))
{
if(this.isImageOfMain(i, i.src))
{
this.img = i ;
this.compute(i.src, i.style, this.container.style) ;
break ;
}
}
}
Coordinates.prototype.isImageOfMain = function(image, src)
{
if(src.match(/transparent.png$/))
return false ;
if(image.parentNode.parentNode.parentNode.parentNode.parentNode!=this.map)
return false ;
var tile = new Tile(src) ;
if(tile)
{
this.tile = tile ;
return true ;
}
else
return false ;
}
Coordinates.prototype.compute = function(tile_src, tile_sty, cont_sty)
{
if(tile_src == null)
{
var txt = "" ;
for(var i=0; i<this.lala.nodeValue.length; ++i)
txt += nbsp ;
}
else
{
var t = new Vector(tile_sty, "left", "top") ;
// Debug.log("t=", t) ;
var c = new Vector(cont_sty, "left", "top") ;
// Debug.log("c=", c) ;
var o = new Vector(this.origin.style, "left", "top") ;
// Debug.log("o=", o) ;
var o_middle = new Vector([6,6]) ;
var sum = o.minus(c).minus(t).plus(o_middle) ;
// txt = ("["+sum.x()+","+sum.y()+"]") + " in " + (tile_src) ;
// var tile = new Tile(tile_src) ;
var lonlat = this.tile.pixel2lonlat(sum) ;
// txt = ("["+lonlat.x()+","+lonlat.y()+"]") ;
// txt += " " + Tile.precision(this.tile.z, 1) + " " + Tile.precision(this.tile.z, 1.0/3600) + " " ;
// txt = Tile.format(lonlat, Tile.precision(this.tile.z, 1), true) ;
txt = Tile.format_deg(lonlat, Tile.precision(this.tile.z, 1)) ;
}
this.lala.nodeValue = txt ;
}
/*
function parseStyleValue(str, id)
{
var x = str.match("\\b"+id+"\\b: (-?\\d+)px") ;
var value = parseInt(x[1]) ;
return value ;
}
*/
Coordinates.prototype.handleEvent = function(event)
{
var et = event.target ;
switch(event.type)
{
/*
case "DOMNodeInserted":
if(et.nodeName.toLowerCase()=="img")
this.lala.nodeValue = "Inserted: " + et.nodeName + " src=" + et.src ;
break ;
*/
case "DOMNodeRemoved":
if(et==this.img)
{
Debug.log("Removed NODE: ", this.img.src) ;
this.img = null ;
this.compute(null) ;
}
/*
if(et.nodeName.toLowerCase()=="img")
this.lala.nodeValue = "Remove " + et.nodeName + " src=" + et.src ;
*/
break ;
case "DOMAttrModified":
if(!this.img)
{
if(et.nodeName.toLowerCase()=="img" && event.attrName.toLowerCase()=="src" && this.isImageOfMain(et, event.newValue)) // && event.newValue.match("^http://mt"))
{
this.img = et ;
this.compute(event.newValue, this.img.style, this.container.style) ;
// Global.container = Global.img.parentNode.parentNode.parentNode ;
Debug.log("Loaded: ", event.newValue) ;
}
}
if(this.img && this.container==et && event.attrName.toLowerCase()=="style")
{
// Debug.log(event.attrName, " := ", event.newValue) ;
this.compute(this.img.src, this.img.style, event.newValue) ;
// Debug.log("Moved: ", event.attrName, "-->", event.newValue, "\nimg.src=Röttgen, Bonn, Germany", this.img.src) ;
}
if(this.img && et==this.img && event.attrName.toLowerCase()=="style")
{
Debug.log(this.img.src, " --- this.img.style:\n", "from ", event.oldValue, "\n", "to ", event.newValue) ;
}
/*
if(this.img && this.image==et && event.attrName.toLowerCase()=="src")
{
Debug.log("Reloaded: ", event.newValue) ;
}
if(this.img && this.image==et)
{
this.lala.nodeValue = event.attrName+ " := " + event.newValue ;
}
*/
if(event.attrName.toLowerCase() == "src" && et==this.img) // && !event.newValue.match(/transparent.png$/))
{
if(!this.isImageOfMain(this.img, event.newValue))
{
Debug.log("Removed: ", event.oldValue) ;
this.img = null ;
this.compute(null) ;
}
else
{
Debug.log("Reloaded: ", event.newValue) ;
this.compute(event.newValue, this.img.style, this.container.style) ;
}
}
//this.lala.nodeValue = ()et.nodeName + "." + event.attrName + " := " + event.newValue ;
break ;
}
}
// vim:tw=0:smartindent
// End of file Coordinates.js
Debug.level(0) ;
window.addEventListener("load", function(){setTimeout(Main,1000);}, false) ;
function Main()
{
if(window.parent!=window)
return ;
var anchor = Xpath.node('//a/img[@class="bar_icon_link"]/..') ;
var map = Xpath.node('//div[@id="map"]') ;
var co = new Coordinates({anchor: anchor, map: map}) ;
document.addEventListener("DOMAttrModified", co, false) ;
document.addEventListener("DOMNodeRemoved", co, false) ;
document.addEventListener('DOMNodeInserted', co, false) ;
Main.coordinates = co ;
}
// vim:tw=0:smartindent