Oct 27, 2006
Phonemap script

// phonemap: For Description See http://userscripts.org/scripts/show/3792

// This file is licensed under the BSD-new license:
// http://www.opensource.org/licenses/bsd-license.php
//
//
// Built with: Open source and "Don't repeat yourself" principles in mind...
//
// Tested with: Firefox 1.5.x (GM 0.6.4) and IE 6.x (Turnabout plug-in)

// ==UserScript==
// @name          phonemap
// @namespace     http://paperless.blogdrive.com
// @description   Lookup address of US phone number on a map, with a call option
// @include       *
// ==/UserScript==


(function ()
{

//patern for US phone numbers (only) with & without area code
var phoneRE = /(s| |.|;|:|>)?(d{3}(-|.|s)d{3}(-|.)d{4}|(d{3})(s||)d{3}(-|.)d{4}|(s| |.|;|:|>)d{3}-d{4})/;
var DialDefault = '+1';                // set to US for Skype calling
var ACDefault = '207';                // set your own default area code for ###-#### phones
var GoogleMatchRE = /Phonebook results/ig;
var GoogleSearchUrl = 'http://www.google.com/search?q=';
var MapsUrl = 'http://maps.google.com/maps?li=';
var UrlParms = 'bwp&q=';                // Google search parms
var ExhcSearchUrl = 'http://www.telcodata.us/query/queryexchangexml.html?npa=';  
var Pics =
{
    upA: "data:image/gif;base64,R0lGODlhDwAPAPMAAKbK8ABgwCBgwACAwCCAwECAwGCAwICAwECgwGCgwICgwP//AP///wAAAAAAAAAAACH5BAUAAAwALAAAAAAPAA8AAARWkMlJazUpGytPKkQgEMVGKQihIkFLmFKiEsgStsWktAGR2AOXKcEjLI43QSLGCxyBrSWDGH2mRNJd64nswaiAcJgwyOmoLlWposgg3ogEjN1WKDj4SgQAOw==",
    downA: "data:image/gif;base64,R0lGODlhDwAPAPMAAKbK8ABgwCBgwACAwCCAwECAwGCAwICAwECgwGCgwICgwP//AP///wAAAAAAAAAAACH5BAUAAAwALAAAAAAPAA8AAARWkMlJa1UqYStNQiCSaJVREGigBuRUDAQgy2oyGURALDy/KpKEQIfoJVY2xjEA661YwaGul6t1qs1ENQCUFFY7BIqQvK7EKET3dhoSCokDh+EZGeb4SQQAOw==",
    lookup: "data:image/gif;base64,R0lGODlhDwAPAPMAAABgwCBgwACAwCCAwICAwICgwP//AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAUAAAcALAAAAAAPAA8AAAQ58MhJKx0BhGEn+KDQfUZZAlxFGoWpUQRQtq3xenLN2gEFmq6eTwa0ESoxzelmATk7zQ9UJZ3irJ0IADs=",
    CellImg: "data:image/gif;base64,R0lGODlhDwAPAPMAAKbK8ABgwCBgwACAwCCAwECAwGCAwICAwGCgwICgwP//AP///wAAAAAAAAAAAAAAACH5BAUAAAsALAAAAAAPAA8AAARScMlJazUoGytNUUogEMVGGUQArkNJFSogywpBTGg8AzWRSAiBbtb7LRABQm2ptCGAtp6t6esUmiFmFdobKZOUg3K1EggqCYI3JTBazGY3Zy6JAAA7"
};

var nonIE = document.getElementById && !document.all;
var topelement = nonIE ? 'HTML' : 'BODY';
var mHeight = nonIE ? '45px' : '50px';
var openToggle=true;
var isdrag=false;
var x,y;
var dobj;


function movemouse(e)
{
  if (isdrag)
  {
    dobj.style.left = nonIE ? tx + e.clientX - x : tx + event.clientX - x;
    dobj.style.top  = nonIE ? ty + e.clientY - y : ty + event.clientY - y;
    return false;
  }
}

function stopmove(e)
{isdrag=false; return false;}

function selectmouse(e)
{
  var fobj = nonIE ? e.target : event.srcElement;
  while (fobj.tagName != topelement && fobj.id != 'phonePopZ') //e.target.id != 'PhoneMap'fobj.className != "dragme"
  {
    fobj = nonIE ? fobj.parentNode : fobj.parentElement;
  }
  if (fobj.id == 'phonePopZ')
  {
    isdrag = true;
    dobj = fobj;
    tx = parseInt(dobj.style.left+0);
    ty = parseInt(dobj.style.top+0);
    x = nonIE ? e.clientX : event.clientX;
    y = nonIE ? e.clientY : event.clientY;
    return false;
  }
}

function openclosePopup()
{
      var m = document.getElementById('phonePopZ');
      var oc =document.getElementById('OpenICgwP');
      var p = document.getElementById('MapICgwP');
      var c = document.getElementById('CallgwICgwP');
      if (openToggle)
      {
          oc.src = Pics.upA; oc.title ='Close';
          m.style.height = mHeight; m.style.backgroundColor = "#abc";
          p.style.display = 'inline'; c.style.display = 'inline';
      }
      else
      {
          oc.src = Pics.downA; oc.title ='Open or Hold & Drag';
          m.style.height = '14px'; m.style.backgroundColor = "#cfc";
          p.style.display = 'none'; c.style.display = 'none';
        }
      openToggle = !openToggle;
}

function closeit()
{
    var m = document.getElementById('phonePopZ'); m.style.height = '0px'; m.style.display = 'none';
}

function checkSelected(e)
{

    phone = nonIE ? e.target.id : e.srcElement.id;
    if (phone != 'MapICgwP')
        return;
    phone = (window.getSelection ? window.getSelection() : document.getSelection ? document.getSelection() : document.selection.createRange().text);
    var m = document.getElementById('MapICgwP');
    if (phone == '')
         phone = m.title;                        // check last selected phone again
    phoneRE.lastIndex = 0;
    var is = phoneRE.exec(' '+phone.toString().replace(/[ ]/g,''));
    if (is)
    {
        document.getElementById('phonePopZ').style.backgroundColor = "#cfc";
        document.getElementById('CallgwICgwP').style.display = 'none';
        var phoneOrig = is[0].replace(/^[ds.]/,'');
        m.title = phoneOrig;
        mapPhone.lookupPhoneMap(phoneOrig);
    }
}

function annotate(phoneOrig, href)
{
    if (href)
    {
        document.getElementById('phonePopZ').style.backgroundColor = (href.split(',').length > 2)?"#cfc" : "#abc";
        document.getElementById('MapICgwP').title = phoneOrig+' : '+href.substr(href.indexOf('q=')+2).replace(/[s+]/g,' ');
        skypePhone(phoneOrig, href);
        window.open(href,'','top=50,width=400,height=400,resizable=yes');
    }
}

function setupEvent(elm, fName)
{  if (window.getSelection)
      elm.addEventListener('click', fName, true);
  else
      elm.attachEvent('onclick', fName);        // IE handler
}

function menupop(title)
{
  var dd=document;
  var ww=window;
  while (parent.dd) dd=parent.dd;
  while (parent.ww) ww=parent.ww;
  var menu = dd.createElement("span");
  menu.id = "phonePopZ";
  menu.title = title;
  var winWidth= dd.body.clientWidth;
  var winHeight=(nonIE)?ww.innerHeight :(ww.document.documentElement && ww.document.documentElement.clientHeight)?ww.document.documentElement.clientHeight:ww.document.body.clientHeight;
    with (menu.style)
    {
        position  =  "absolute";  height = "14px"; width = nonIE? "15px" : "21px";
        backgroundColor = "#cfc"; padding = "2px";border = "1px solid green";
        top = Math.round(winHeight/2).toString()+"px";
        left = (winWidth-22).toString()+"px";        //dd.body.clientWidth
        opacity = "0.85"; filter = "alpha(opacity=90)";
    }

    if (nonIE)
    {
        menu.addEventListener('mousedown', selectmouse, false);
        menu.addEventListener('mousemove', movemouse, false);
        menu.addEventListener('mouseup', stopmove, false);
        menu.addEventListener('mouseout', stopmove, false);
        menu.addEventListener('dblclick', closeit, false);
    }
      else
    {// IE handler
        menu.attachEvent('onmousedown', selectmouse);
        menu.attachEvent('onmousemove', movemouse);
        menu.attachEvent('onmouseup', stopmove);
        menu.attachEvent('onmouseout', stopmove);
        menu.attachEvent('ondblclick', closeit);
    }

  var openclose = dd.createElement("img");
  openclose.id = "OpenICgwP";
  openclose.src = Pics.downA;
  openclose.title="Open";
  with (openclose.style)
      { position = "absolute"; left = "2px"; top = "1px"; margin = "0px"; width = "14px"; border = "none"; cursor = "pointer"; }
  setupEvent(openclose, openclosePopup);
  menu.appendChild( openclose );

  var lookup = dd.createElement("a");
  var lookupImg = dd.createElement("img");
  lookupImg.src = Pics.lookup;
  lookupImg.style.border = "none";
  lookupImg.id = "MapICgwP";
  lookupImg.title="Lookup Selected Phone";
  lookup.appendChild(lookupImg);
  with (lookupImg.style)
      {position = "absolute"; cursor = 'pointer'; left = "3px"; height = "16px"; top = "18px"; width = "14px"; border = "none"; display = 'none' }
  setupEvent(lookupImg, checkSelected);

  menu.appendChild(lookup);

  var call = dd.createElement("a");
  var callImg = dd.createElement("img");
  with (callImg.style)
      {position = "absolute"; left = "2px"; width = "14px"; top = "33px"; margin = "0px";  border = "none"; display = 'none' }
  callImg.src = Pics.CellImg;
  callImg.id = "CallgwICgwP";
  callImg.title="Call";
  call.appendChild(callImg);
  call.href = "callto:";
  call.style.height = "12px";
  menu.appendChild( call );

  return menu;
}

function getPhone(phone)
{
    // Saving time looking up same phone number(s)
    var Cached = GM_getValue("phoneZ");
    if (!Cached)
        return null;
    var ix = Cached.indexOf(phone.replace(/[-]/g, ''));
    if (ix == -1)
        return null;
    return Cached.substr(ix).split('|',2)[1];
}

function getExchange(phone)
{
    // Saving time looking up same exchange(s)
    var Cached = GM_getValue("phoneZ");
    if (!Cached)
        return null;
    var ix = Cached.indexOf(phone.substr(0,6));
    if (ix == -1)
        return null;
    Cached = Cached.substr(ix).split('|',2)[1].split(',');
    if (Cached.length > 2)
        return Cached[1]+','+Cached[2];
    return Cached.join(',');
}

function putPhone(phone, href)
{
    if (!href)
        return;

    var Cached = GM_getValue("phoneZ");
    if (Cached && Cached.length > 1000)                // Cache holds info on about 25 phones
    {    // remove some older phones
         var cp = Cached.split('|');
         cp.splice(0,10);
         Cached = cp.join('|');
    }
    Cached = Cached + phone.replace(/[-]/g, '') + '|' + href.substr(href.indexOf('q=')+2)+ '|';
    GM_setValue("phoneZ", Cached);
}

function skypePhone(phone, href)
{
    var c = document.getElementById('CallgwICgwP');
    c.style.display = 'inline';
    c.title = 'Call '+phone;
    if (href && href.indexOf(' ') > 0)
        c.title += ' (Cell)';
    c.parentNode.href='callto://' +DialDefault + formatUSTel(phone);
}

function formatUSTel(phoneOrig)
{
    var phone = phoneOrig.replace(/[^d]/g, '');
    if (phone.length == 7)
        return ACDefault+'-'+phone.substr(0,3)+'-'+phone.substr(3,4)
    else
        return phone.substr(0,3)+'-'+phone.substr(3,3)+'-'+phone.substr(6,4);
}

var mapPhone =
{
    xpath: function(expr, doc)             // mimics simple xpath processing that IE dosn't support
    {
      var ret = [];
      if (!expr)
        return ret;
      if (!doc)
        doc = document;
      var args = expr.replace(/[.[]/()',]/g, "").split("@").join("=").split("=");
      var items = doc.getElementsByTagName(args[0]);
      for (var i = 0; i < items.length; ++i)
      {
        if (args.length > 1)
        {    // check for attribute match
            for (var x = 0; x < items[i].attributes.length; x++)
                if (items[i].attributes[x].nodeName == args[1])
                {
                    ret.push(items[i]); break; break;
                }
        }
        else
          ret.push(items[i]);
      }
      return ret;
    },

    lookupPhoneMap: function(phoneOrig)
    {
        var phone = formatUSTel(phoneOrig);
        var ac = phone.substr(0,3);
        if (ac == '800' || ac == '888' || ac == '877' || ac == '866')
        {
            skypePhone(phoneOrig, null);
            return;
        }
        var href = getPhone(phone);

        // check if phone info is cached
        if (href)
        {
            annotate(phoneOrig, MapsUrl+UrlParms+href);
            return;
        }
        // get phone address from Google
        GM_xmlhttpRequest
          (
           {
            method:  'GET',
            url:     GoogleSearchUrl + encodeURIComponent(phone),
            onload:  function(results)
            {
              if (!GoogleMatchRE.test(results.responseText) )
                mapPhone.lookupExchange(phoneOrig);
              else
              { // look for 1st http://maps.google.com/maps reference
                //turn the text into a dom object

                var doc = document.createElement('div');
                doc.innerHTML = results.responseText;
                var xpathVar = ".//a[@href]";
                var links = mapPhone.xpath(xpathVar, doc);
                if (links)
                    for (var n in links)
                    {
                        var href = links[n].getAttribute('href');
                        if (href.indexOf(MapsUrl) != -1)
                        {
                             putPhone(phone, href);            // save time and cache phone info
                             annotate(phoneOrig, href);
                             break;
                        }
                    } // end for
               } // end if
             }
            }
        ) // end GM_xmlhttpRequest
    },

    lookupExchange: function(phoneOrig)
    {
        var phone = formatUSTel(phoneOrig);
        var href = getExchange(phone);        // check if exchange info is cached
        if (href)
            annotate(phoneOrig, MapsUrl+UrlParms+href);
        else
        // get US town, state based on area code & exchange
        GM_xmlhttpRequest
          (
           {
            method:  'GET',
            url:     ExhcSearchUrl + phone.substr(0,3) +'&nxx='+phone.substr(4,3),
            onload:  function(results)
            {
                if (results.responseText.indexOf('<valid>YES') > 0)
                {
                    //turn the text into a dom object and extract US town and state
                    var doc = document.createElement('div');
                    doc.innerHTML = results.responseText;
                    var xpathVar = ".//englishname";
                    var nodes = mapPhone.xpath(xpathVar, doc);
                    if (nodes[0].firstChild == null)
                    {    // try other name
                        xpathVar = ".//ratecenter";
                        nodes = mapPhone.xpath(xpathVar, doc);
                    }
                    var href = MapsUrl+UrlParms;
                    if (nodes)
                        href = href + nodes[0].firstChild.textContent.replace(/[ ]/g, '+');
                    xpathVar = ".//state";
                    nodes = mapPhone.xpath(xpathVar, doc);
                    if (nodes)
                        href = href +',+' + nodes[0].firstChild.textContent;
                    xpathVar = ".//companytype";
                    nodes = mapPhone.xpath(xpathVar, doc);
                    if (nodes && nodes[0].firstChild.textContent == 'WIRELESS')
                        href = href + ' ';
                    annotate(phoneOrig, href);
                    putPhone(phone, href);
                } // end if
             }
            }
        ) // end GM_xmlhttpRequest
    }

} // end mapPhone


document.getElementsByTagName(topelement)[0].appendChild(menupop('Select a phone to map or Double Click to Exit'));


})();

Posted at 12:44 pm by paperless
Make a comment  

Jun 8, 2006
Ajaxian entries


Posted at 05:23 pm by paperless
Make a comment  

Apr 8, 2006
Browser phone lookup script

Lookup address of US phone number on a map, with a call option

Lets you locate a phone number on a map and call it via your VOIP provider.  Toll free numbers are excluded. Cell phones are located by state/town.

Tested with: Firefox 1.5.01 (requires GreaseMonkey 0.6.4 plug-in) and IE 6.x (requires Turnabout plug-in @ http://www.reifysoft.com & simple edit of their config.xml)

Less effort - More fun - Enjoy!

Posted at 12:11 pm by paperless
Comments (4)  



<< June 2009 >>
Sun Mon Tue Wed Thu Fri Sat
 01 02 03 04 05 06
07 08 09 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30


If you want to be updated on this weblog Enter your email here:




rss feed