// Power Twitter User Script for Safari
// Copyright (c) 2007-2010, Narendra Rocherolle, Nick Wilder
//
// ==UserScript==
// @name          Power Twitter
// @version       1.40
// @namespace     http://powertwitter.me
// @description   makes Twitter better
// @include       http://twitter.com/*
// @include	  https://twitter.com/*
// ==/UserScript==


// Need to provide GM_getValue and GM_setValue
if (!this.GM_getValue || this.GM_getValue.toString().indexOf("not supported")>-1) {
	this.GM_getValue=function (key,def) {
		return localStorage[key] || def;
	};
	this.GM_setValue=function (key,value) {
		return localStorage[key]=value;
	};
}


// rewrite some GM functions to work with GreaseKit
/*
if(typeof GM_getValue === "undefined") {
  GM_getValue = function(name){
    var nameEQ = escape("_greasekit" + name) + "=", ca = document.cookie.split(';');
    for (var i = 0, c; i < ca.length; i++) { 
      var c = ca[i]; 
      while (c.charAt(0) == ' ') c = c.substring(1, c.length); 
      if (c.indexOf(nameEQ) == 0) {
        var value = unescape(c.substring(nameEQ.length, c.length));
//        alert(name + ": " + value);
        return value;
      }
    } 
    return null; 
  }
}

if(typeof GM_setValue === "undefined") {
  GM_setValue = function( name, value, options ){ 
    options = (options || {}); 
//    if ( options.expiresInOneYear ){ 
      var today = new Date(); 
      today.setFullYear(today.getFullYear()+1, today.getMonth, today.getDay()); 
      options.expires = (new Date(new Date().getTime() + 365 * 1000 * 60 * 60 * 24)); 
//    } 
    var curCookie = escape("_greasekit" + name) + "=" + escape(value) + 
    ((options.expires) ? "; expires=" + options.expires.toGMTString() : "") + 
    ((options.path)    ? "; path="    + options.path : "") + 
    ((options.domain)  ? "; domain="  + options.domain : "") + 
    ((options.secure)  ? "; secure" : ""); 
    document.cookie = curCookie; 
  }
}
 */

if(typeof GM_xmlhttpRequest === "undefined") { 
  GM_xmlhttpRequest = function(/* object */ details) {
    details.method = details.method.toUpperCase() || "GET"; 
    if(!details.url) { 
      throw("GM_xmlhttpRequest requires an URL."); 
      return; 
    } 
    // build XMLHttpRequest object 
    var oXhr, aAjaxes = []; 
    if(typeof ActiveXObject !== "undefined") {
      var oCls = ActiveXObject; 
      aAjaxes[aAjaxes.length] = {cls:oCls, arg:"Microsoft.XMLHTTP"}; 
      aAjaxes[aAjaxes.length] = {cls:oCls, arg:"Msxml2.XMLHTTP"}; 
      aAjaxes[aAjaxes.length] = {cls:oCls, arg:"Msxml2.XMLHTTP.3.0"}; 
    } 
    if(typeof XMLHttpRequest !== "undefined") 
      aAjaxes[aAjaxes.length] = {cls:XMLHttpRequest, arg:undefined}; 
    for(var i=aAjaxes.length; i--; ) 
      try{ 
	oXhr = new aAjaxes[i].cls(aAjaxes[i].arg); 
	if(oXhr) break; 
      } catch(e) {} 
    // run it 
    if(oXhr) {
      if("onreadystatechange" in details) 
	oXhr.onreadystatechange = function() 
	  { details.onreadystatechange(oXhr) }; 
      if("onload" in details) 
	oXhr.onload = function() { details.onload(oXhr) }; 
      if("onerror" in details) 
	oXhr.onerror = function() { details.onerror(oXhr) }; 
      oXhr.open(details.method, details.url, true); 
      if("headers" in details)
	for(var header in details.headers) 
	  oXhr.setRequestHeader(header, details.headers[header]); 
      if("data" in details) 
	oXhr.send(details.data); 
      else 
	oXhr.send();
    }
    else {
      throw ("This Browser is not supported, please upgrade.");
    }
  } 
} 

if(typeof GM_addStyle === "undefined")
{
  addGlobalStyle = function(/* String */ styles) {
    var oStyle = document.createElement("style"); 
    oStyle.setAttribute("type", "text\/css"); 
    oStyle.appendChild(document.createTextNode(styles)); 
    document.getElementsByTagName("head")[0].appendChild(oStyle);
  }
    
} 

if(typeof GM_log === "undefined") { 
  GM_log = function(log) {
    if(console) 
      console.log(log); 
    else 
      alert(log); 
  }
}

  embedFunction = function(s) {
	var ptScriptObject = document.createElement('script');
	ptScriptObject.type = "text/javascript";
	document.body.appendChild(ptScriptObject).innerHTML=s.toString().replace(/([\s\S]*?return;){2}([\s\S]*)}/,'$2');
  }

  exportGlobal = function(name,value) {
	embedFunction("var "+ name +" = '" + value + "';");
  }    

var ptSandbox = 0;  // must set to 0 to publish!
var ptSandboxServer = '';
var ptServer = 'http://powertwitter.me/';
var ptScript = 'req.php';
var ptVersionNumber = '1.40';
var ptWarning = '';
if (ptSandbox == 1)
{
	ptServer = 'http://'+ ptSandboxServer + '.powertwitter.me/';
        ptWarning = '<div id="ptNotes" style="position: absolute; top: 10px; right: 10px; background-color: #eee; padding: 6px;"><h2>TESTING!</h2>'+ ptServer +'</div>';
}

// some globals
var ptLoggedInUserName = '';
var ptLoggedIn = false;
var ptViewingUser = '';
var ptGsTitle = window.location.href;
var ptGsNextPage = 2;
var ptIsStatusPage = false;
var ptIsUserPage = false;
var ptIsSearchPage = false;
var ptAttempts = 0;
var ptTimeOut = 0;
var ptDefaultPhotoService = 'yfrog';
var ptWaitingGif;
var ptLoadingMessage;
var ptListRegExp = new RegExp(/com\/.*?\/.+/);
var ptMaxCacheCount = 100;

// set up the cache system which has two layers
var ptCache = ptInitCache();

// add some html for sandbox notes, and message bar
var newElement;
newElement = document.createElement('div');
newElement.innerHTML = ptWarning;

// make sure we have a body
var ptInsertPoint;
if(document.getElementsByTagName("body")[0])
{
        ptInsertPoint = document.getElementsByTagName("body")[0];

        ptInsertPoint.appendChild(newElement);
        newElement = document.createElement('div');
        newElement.id = 'ptDataContainer';
        newElement.innerHTML = '<div id="ptCustomMessage" style="display: none; z-index: 10; width: 100%; text-align: center; position: fixed; bottom: 0px; left: 0px; background-color: #ffffcc; padding: 4px;"></div>';

        // used in case page is broken aka kill switch
        newElement.innerHTML += '<input id="ptPingStatus" type="hidden" value="0" />';
        // this status input is used across the GM sandbox to know when the xmlreq is finished
        newElement.innerHTML += '<input id="ptLinkUpdateStatus" type="hidden" value="0" />';
        // these are used for pagination and search across the GM sandbox
        newElement.innerHTML += '<input id="ptVar1" type="hidden" value="0" />';
        newElement.innerHTML += '<input id="ptVar2" type="hidden" value="0" />';
        newElement.innerHTML += '<input id="ptVar3" type="hidden" value="0" />';
        newElement.innerHTML += '<input id="ptVar4" type="hidden" value="0" />';
        newElement.innerHTML += '<input id="ptAuth" type="hidden" value="0" />';
        newElement.innerHTML += '<input id="ptPageNumber" type="hidden" value="0" />';
        newElement.innerHTML += '<input id="ptLastSearch" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptLatestTweetId" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptFirstTweetId" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptRestrictedSearch" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptClearTimeline" type="hidden" value="1" />';
        newElement.innerHTML += '<input id="ptCurrentService" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptSelectedTab" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptLinkParseService" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptDoNotParse" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptIncomingCache" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptDisableCache" type="hidden" value="0" />';
        newElement.innerHTML += '<input id="ptMaxCacheCount" type="hidden" value="100" />';
        newElement.innerHTML += '<input id="ptFunctionData" type="hidden" value="" />';
        newElement.innerHTML += '<input id="ptDefaultPhotoService" type="hidden" value="'+ptDefaultPhotoService+'" />';
        newElement.innerHTML += '<input id="ptPhotoServiceOptions" type="hidden" value="'+ptDefaultPhotoService+'" />';
        newElement.innerHTML += '<input id="ptMoodOptions" type="hidden" value="happy|sad|bored|busy|hungry|tired" />';
        newElement.innerHTML += '<div id="ptShade" style="position: absolute; top: 0; z-index: 999; display: none; background-color: #113344; opacity: 0.5;" />';
        newElement.innerHTML += '<iframe src="'+ptServer+ptScript+'?action=countPage" style="width: 1px; height: 1px; visibility: hidden;"></iframe>'
        ptInsertPoint.appendChild(newElement);

        // domains outside of twitter
        // not live yet
/*
        if(ptGsTitle.indexOf('google.com/search') != -1)
        {
                var ptGoogleSearchRegExp = new RegExp(/.q=(.*?)&/);
                if(ptGsTitle.match(ptGoogleSearchRegExp))
                        document.getElementById('prs').innerHTML += ' <a href="http://search.twitter.com/search?q='+ptGsTitle.match(ptGoogleSearchRegExp)[1]+'">Twitter</a>';
        }
*/
        // get base settings
        var ptPrefRM = (GM_getValue("ptPrefRM")) ? GM_getValue("ptPrefRM") : '';
        var ptPrefEX = (GM_getValue("ptPrefEX")) ? GM_getValue("ptPrefEX") : 'on';
        var ptPrefFB = (GM_getValue("ptPrefFB")) ? GM_getValue("ptPrefFB") : '';
        var ptPrefSB = (GM_getValue("ptPrefSB")) ? GM_getValue("ptPrefSB") : '';
        var ptPrefPR = (GM_getValue("ptPrefPR")) ? GM_getValue("ptPrefPR") : '';
        var ptPrefPH = (GM_getValue("ptPrefPH")) ? GM_getValue("ptPrefPH") : '';
        
        var ptPrefPassword = ptGetPassword();

        var ptJSON = document.createElement("script");
        ptJSON.type="text/javascript";
        ptJSON.src= ptServer + ptScript + "?action=ping&format=json&version="+ptVersionNumber;
        ptInsertPoint.appendChild(ptJSON);

        runPowerTwitter();
}
else
        document.location.href = 'http://twitter.com/home';


// --------------------------------------------------------------------
// start the script

function runPowerTwitter()
{

// see if we have a logged in twitter user
ptLoadUser();


if ((!ptLoggedIn)||(ptGsTitle.indexOf('oauth') != -1)) // don't do anything else unless the user is logged in
{
        if(document.getElementById('ptStatus'))
        	document.getElementById('ptStatus').style.display = 'none';
}
else
{
	var ptFormData=''; // used to collect links and stuff to send down to the server

        // add the graphic "power" to the logo and hidden divs for settings, media
        var ptLogo;
        ptLogo = document.getElementById('header');
        if(ptLogo)
        {
                var newDate = new Date();
                ptTimeString = newDate.getTime();
                newElement = document.createElement('div');
                newElement.innerHTML += '<img width="40" style="position: absolute; left: 10px; top: 0px; z-index: 10;" src="' +
                'data:image/png;base64,' +
                        'iVBORw0KGgoAAAANSUhEUgAAADYAAAARCAYAAACW7F9TAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lD' +
                        'Q1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQ' +
                        'SoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfA' +
                        'CAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH' +
                        '/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBb' +
                        'lCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7' +
                        'AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKB' +
                        'NA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl' +
                        '7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7i' +
                        'JIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k' +
                        '4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAA' +
                        'XkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv' +
                        '1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRR' +
                        'IkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQ' +
                        'crQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXA' +
                        'CTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPE' +
                        'NyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJA' +
                        'caT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgX' +
                        'aPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZ' +
                        'D5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2ep' +
                        'O6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2q' +
                        'qaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau' +
                        '7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6fe' +
                        'eb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYP' +
                        'jGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFos' +
                        'tqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuu' +
                        'tm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPj' +
                        'thPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofc' +
                        'n8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw3' +
                        '3jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5' +
                        'QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz' +
                        '30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7' +
                        'F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgq' +
                        'TXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+' +
                        'xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2' +
                        'pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWF' +
                        'fevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaq' +
                        'l+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7' +
                        'vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRS' +
                        'j9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtb' +
                        'Ylu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh' +
                        '0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L15' +
                        '8Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89Hc' +
                        'R/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfy' +
                        'l5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz' +
                        '/GMzLdsAAAAEZ0FNQQAAsY58+1GTAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAX' +
                        'b5JfxUYAAASRSURBVHja1JdRaFtVGMd/rZ2pdr3VlkVHExmagbmtiPQhoQriwy0UGY6lL2Mgdi/zaX1y' +
                        'T/q0PrW+pL5sCE198KHQqExk2jz0ZYZEiAh2N8gC6nJLt8yV5diuiW2sD/nu2U2a2m76oH8Il3vOud93' +
                        '/uf/fd/50razs4OgHTgMHAVCwHNAH+ADnpTnNnAHuAVsAk8B/cAR+X4dUEBV3neAiqxtBzqBNpnf8th+' +
                        'TN4BusXu48AGsAb8Lmt8QAdQk999YBW4AfwK3JNx2jzEfMAx4DXgLeBVoJfWuC0Ejsph7If7no0hzjeB' +
                        'LiH6qNgCvgeuAF8DP8lhNBB7GhgGzgEn+H/hR+BDICUK0uGZ7BLFXgeIz6Sx7RKm6ae720diLgfA+DtD' +
                        'nB0fAiCTLZJMLrOYKgBghv3EYgOMxQZ578JVlKpimn4mzg8DcHFyCccpY1khxmKD2PkS8XgagFhskGgk' +
                        'SHwmzWLqBkpVCQR6iJ0a0P7OvfsFAJYVAiCVKnD50kmAl4AXgEwrYp2AHzAAbLtEJlskky1ihv0YRieO' +
                        'UyY+k8Y0/Q2OAoEejG4fdr6EPVlCqSqG0cliqoCzopg4P4zjlFlILmtnY7FB7QNgYmKY02fmcZwyI1aI' +
                        'QKCHheQy8Zk68bPjQ3qtna/7aEKXl4+XWIeQa0A0EuTypZMoVeXNE5+gVJVUqoBSFU3qqy/f1oosJJdJ' +
                        'zOW0So5TxnHKelOu0gArK0ornckUcZwyZtjP9NSoXjubyJH87LpW7UFkDGIYbspSk4JWaUWsXRK8JQzD' +
                        'V99Attiw0dipAb3GskIsJJe1Yi7s/B2ysj4aCZLJFllMFbDtUn0sGtTzdr7Ey6981ODbccoN75FIkBEJ' +
                        'R8EVwAbKrYj9qzAMnyaRz5d0SFtWqGHM3ahL0s2rh8C3wOdCbP2hiSlVxc7XnZumX7/nZczNS2+4RITY' +
                        'bKJeeKKxICPWcS5OLukx9wCyks9KVRhrDLNdijXhGvCDhOIfBybmrChmEzmy2aJO2EgkSH+/gT1ZYjFV' +
                        'wJhcwjB8uji4G4tGg8RnHtgKh/06pN1DGrGO65CeTeRQqsrpM/NatVSqgGH43OrX6n4sAr958+tAxJSq' +
                        '6MoE8MH7bxCNBCESRKkqibncrmrnFg4z7CcQ6NEn7uaFZYU0sXD4iA7B6alR4jNpXX29NvfAqjQK280T' +
                        '3gv6RWAcuOCW8ky2SDQSZHpqFDtfItBvEAj07LLu5oopivxTeMv5PjbngY+B76TtaqnYdrOczYWgqZWp' +
                        'uddD0xySxPeAwAG5lKV/9LtkDoBF4BvgF/mWvYhVgJJIa7iXsPsU/AxclaazBjwLPC89YztwV+ZuSs/W' +
                        'J3O94lxJj/iENLs74vOWHNYzYu+YNArb0gSvSWFoFzsrwHWphLc9DXTLUNyvV8wBn0oVWgX+lM31ySbc' +
                        '7v6uKLAlBLpE2Zqnqz8k3TtyAOti77AcQq98W5P5DSHZJs8NiYh1sbnzd8T26u7XgLRcgtdE+k3Ppd4h' +
                        'F7vr1P1L8ShoE1uHxLY37B/KZts+/8cMCZ+bQEGUck/3P42/BgChbgReJkfijwAAAABJRU5ErkJggg=="' +
                        ' alt="powertwitter" />';

                ptWaitingGif = '<img width="12" src="data:image/gif;base64,' +
                        'R0lGODlhEAAQAPQAAP///6qqqvz8/Ly8vNXV1aurq7a2tvDw8OHh4bGxsdHR0cvLy/X19dzc3Ovr68HB' +
                        'wcbGxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBF' +
                        'Mi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAAFUCAg' +
                        'jmRpnqUwFGwhKoRgqq2YFMaRGjWA8AbZiIBbjQQ8AmmFUJEQhQGJhaKOrCksgEla+KIkYvC6SJKQOISo' +
                        'NSYdeIk1ayA8ExTyeR3F749CACH5BAkKAAAALAAAAAAQABAAAAVoICCKR9KMaCoaxeCoqEAkRX3AwMHW' +
                        'xQIIjJSAZWgUEgzBwCBAEQpMwIDwY1FHgwJCtOW2UDWYIDyqNVVkUbYr6CK+o2eUMKgWrqKhj0FrEM8j' +
                        'QQALPFA3MAc8CQSAMA5ZBjgqDQmHIyEAIfkECQoAAAAsAAAAABAAEAAABWAgII4j85Ao2hRIKgrEUBQJ' +
                        'LaSHMe8zgQo6Q8sxS7RIhILhBkgumCTZsXkACBC+0cwF2GoLLoFXREDcDlkAojBICRaFLDCOQtQKjmsQ' +
                        'SubtDFU/NXcDBHwkaw1cKQ8MiyEAIfkECQoAAAAsAAAAABAAEAAABVIgII5kaZ6AIJQCMRTFQKiDQx4G' +
                        'rBfGa4uCnAEhQuRgPwCBtwK+kCNFgjh6QlFYgGO7baJ2CxIioSDpwqNggWCGDVVGphly3BkOpXDrKfNm' +
                        '/4AhACH5BAkKAAAALAAAAAAQABAAAAVgICCOZGmeqEAMRTEQwskYbV0Yx7kYSIzQhtgoBxCKBDQCIOco' +
                        'LBimRiFhSABYU5gIgW01pLUBYkRItAYAqrlhYiwKjiWAcDMWY8QjsCf4DewiBzQ2N1AmKlgvgCiMjSQh' +
                        'ACH5BAkKAAAALAAAAAAQABAAAAVfICCOZGmeqEgUxUAIpkA0AMKyxkEiSZEIsJqhYAg+boUFSTAkiBiN' +
                        'Hks3sg1ILAfBiS10gyqCg0UaFBCkwy3RYKiIYMAC+RAxiQgYsJdAjw5DN2gILzEEZgVcKYuMJiEAOwAA' +
                        'AAAAAAAAAA==" />';
                        
                ptStarImage = 'data:image/png;base64,' +
		'iVBORw0KGgoAAAANSUhEUgAAAAkAAAANCAMAAABM3rQ0AAAAJFBMVEX8/vz8wjT8viT83pT8ylT88tz8' +
		'0mz8xkT82oT84pz8xjz81nwKqN0kAAAAAXRSTlMAQObYZgAAADVJREFUeF6VxjkCwCAMxEDt2lzJ//8b' +
		'XEAfNRr+tK580N1rkd4pA4arB0AHjCvrlQttArPxARdHAJ/MUWtxAAAAAElFTkSuQmCC';

                var ptAuthLink = '<a href="'+ptServer + 'oauth.php?action=reset">Authenticate Powertwitter</a>';

//                var ptAuthLink = '<a href=\'javascript:document.getElementById("ptAuthStatusHtml").innerHTML = "Authentication Requested";'+
//                'ptNewWindow("' + ptServer + 'oauth.php?action=reset","",800,500);\'>Authenticate Powertwitter</a>';
                var ptAuthStatusHtml = '<span id="ptAuthStatusHtml">'+ptAuthLink+'</span>';

                var ptSettingsHtml =  '<div style="font-size: 9px; z-index: 11; position: fixed; bottom: 0px; ' +
                        'right: 0px; background: #eee; border-left: 1px solid #ccc; border-top: 1px solid #ccc;' +
                        ' padding: 2px 11px 2px 8px;"> <a href="http://twitter.com/powertwitter" title="Follow Power Twitter!">@powertwitter</a>: <a id="ptSettingsLink" title="Power Twitter Settings" href="#">settings</a> | <a title="help with Power Twitter" ' +
                        ' id="ptHelpLink" href="http://getsatisfaction.com/83degrees/products/83degrees_power_twitter">help</a>' +
                        '</div><div id="ptStatus" style="position: fixed; bottom: 0px; right: 0px; display: block; ' +
                        'font-size: 9px; padding-bottom: 0px; z-index: 12;">'+ptWaitingGif+'</div><div id="ptSettings" style="padding: 6px; ' +
                        'font-size: 10px; border: 1px solid #999; background: #eee; position: fixed; bottom: 0px; ' +
                        'right: 0px; display: none; z-index: 100;"><div style="font-weight: bold;">Power Twitter ' +
                        'Settings (v'+ptVersionNumber+')<div style="font-weight: normal;">Note: authenticating lets PT do more behind ' +
                        'the scenes.</div></div><br /><table><tr><td valign="top">' +  ptAuthStatusHtml +
                        '<input type="hidden" id="ptSettingUserKey" />' +
                        '<div style="display: none;">Username<br /><input disabled="true" '+
                        'type="text" style="color: #999; width: 110px;" id="ptSettingUsername" /><br />Password<br /><input id="ptSettingPassword"'+
                        'type="password" style="padding: 1px; border: 1px solid #ccc;" size="14" /></div><br />' +
                        '<div style="margin: 8px 0px 8px 0px">Upload photos to:<br /><select id="ptSettingPH" name="ptSettingPH" style="margin-top: 3px;">'+
                        '</select><br /><input style="margin-top: 16px;" id="ptSettingSave" type="button" ' +
                        'value="Save/Update" /> <input type="button" style="margin-top: 16px;" value="Cancel" ' +
                        'onclick="document.getElementById(\'ptSettings\').style.display=\'none\'" /></td>' +
                        '<td valign="top"><input id="ptSettingRM" type="checkbox" style="display: none;" />' +
                        '<input id="ptSettingEX" type="checkbox" /> Powertwitter ON<br />' +
                        '<br />&nbsp;&nbsp;-<a id="ptClearCache" href="#">Clear Local Cache</a>' +
                        '</td></tr></table></div>';
                        
                var ptFormsHtml = '' +
                        '<form id="ptPostLinkForm" name="ptPostLinkForm" ' +
                        'action="'+ptServer + ptScript + '" method="post">' +
                        '<input type="hidden" name="action" value="postLink" />' +
                        '<input type="hidden" name="ptPostLink" id="ptPostLink" value="" />' +
                        '</form>';
                        
                var ptPhotoPostForm = '<div id="ptPostPhotoDiv" style="position: absolute; display: none;z-index: 1000;">' +
                        '<form id="ptPostPhotoForm" name="ptPostPhotoForm" ' +
                        'action="'+ptServer + ptScript + '" method="post" enctype="multipart/form-data">' +
                        '<input type="hidden" name="action" value="postPhotoOauth" />' +
                        '<input type="hidden" name="ptPostTo" id="ptPostTo" value="" />' +
                        '<div style="position: relative; margin: 0px 0px 0px 0px;">' +
                        '<div id="ptUploadingMsg" style="display: none; padding-left: 20px; height: 36px; z-index: 1003; position: absolute; left: 0px; width: 200px; background-color: #fff; font-size: 1.1em;">'+ptWaitingGif+' Uploading... <a style="font-size: 9px; color: #333; margin-left: 20px; background-color: #eee; padding: 4px; -moz-border-radius: 4px; border: 1px solid #ccc;" href="/">Cancel</a></div>' +
                        '<input type="button" name="choose" value="Choose File" style="z-index: 1001; position: absolute; left: 0px; width: 80px" />' +
                        '<input name="media" type="file" id="ptPhotoFile" size="1" style="width: 1px; cursor: pointer; position: absolute; left: 0px; z-index: 1002; opacity: 0;" onchange="document.getElementById(\'ptUploadingMsg\').style.display=\'block\';document.ptPostPhotoForm.submit();"/> ' +
                        '<input type="submit" style="margin-left: 180px; display: none;" name="submitBtn" value="Upload" id="ptUploadButton" />' +
                        '<input type="button" style="margin-left: 100px; z-index: 1004" value="Cancel" onclick="' +
                        'ptShowHideShade(\'ptPostPhotoDiv\',\'none\');' +
                        'ptShowHideShade(\'ptPostPhotoStub\',\'none\');' +
                        'document.getElementById(\'ptShade\').style.display=\'none\';" />' +
                        '<input type="hidden" name="username" id="ptPostPhotoUser" value="" />' +
                        '<input type="hidden" name="MAX_FILE_SIZE" value="5000" />' +
                        '<input type="password" id ="ptPostPhotoPass" style="visibility: hidden;" name="password" value="" />' +
                        '<input type="hidden" id ="ptPostPhotoUserKey" style="visibility: hidden;" name="sUserKey" value="" />' +
                        '</form></div></div>';
                        
                newElement.innerHTML += ptSettingsHtml + ptFormsHtml + ptPhotoPostForm;

                ptLogo.parentNode.insertBefore(newElement, ptLogo);
                document.getElementById('ptSettingsLink').addEventListener('click',ptShowSettings,true);
                document.getElementById('ptSettingSave').addEventListener('click',ptSaveSettings,true);
                document.getElementById('ptClearCache').addEventListener('click',ptClearCache,true);

        }

        if(document.getElementById('ptSettingUsername'))
        	document.getElementById('ptSettingUsername').value = ptLoggedInUserName;

        // get the current page and add more button listeners
        if(document.getElementById('pagination'))
                document.getElementById('pagination').addEventListener('click',ptParseMoreUpdates,true);
                
        if(document.getElementById('more'))
        {
                var ptPageRegExp = new RegExp(/.page=(.*?)&/);
                if(document.getElementById('more').href.match(ptPageRegExp))
                {
                        ptGsNextPage = document.getElementById('more').href.match(ptPageRegExp)[1];
//                        document.getElementById('more').addEventListener('click',ptParseMoreUpdates,true);
                }
                document.getElementById('pagination').addEventListener('click',ptParseMoreUpdates,true);
        }
        else if(document.getElementById('search_more'))
        {
                var ptPageRegExp = new RegExp(/.page=(.*?)&/);
                if(document.getElementById('search_more').href.match(ptPageRegExp))
                {
                        ptGsNextPage = document.getElementById('search_more').href.match(ptPageRegExp)[1];
                        document.getElementById('search_more').addEventListener('click',ptParseMoreUpdates,true);
                }
        }


        // is status page?
        if(ptGsTitle.indexOf('/status/') != -1)
        {
                ptIsStatusPage = true;
        }

        // is search page?
        if(ptGsTitle.indexOf('search?q') != -1)
        {
                ptIsSearchPage = true;
        }
        
        // check for alerts
        if(ptGsTitle.indexOf('ptAlert=') != -1)
        {
                // show an alert
                var ptAlertRegExp = new RegExp(/.ptAlert=(.*)/);
                if(ptGsTitle.match(ptAlertRegExp))
                        alert(unescape(ptGsTitle.match(ptAlertRegExp)[1]));

        }

        // check for searches
        if(ptGsTitle.indexOf('ptQ=') != -1)
        {
                var ptSearchRegExp = new RegExp(/.ptQ=(.*)/);
                if(ptGsTitle.match(ptSearchRegExp))
                        location.href = 'http://twitter.com/search?q='+ptGsTitle.match(ptSearchRegExp)[1];
        }

	// create an iframe for the page
	var ptIF, newElement;
	ptIF = document.getElementById('container');
	if (ptIF)
	{
		newElement = document.createElement('div');
		newElement.innerHTML = '<div id="ptIframeContainer" style="top: 30px; z-index: 200; border: 1px solid #ccc; visibility: hidden; position: absolute; display: none; background-color: #fff;"><iframe src="about:blank" width="220" height="280" id="ptIframe" scrolling="no" frameborder="0" /></div>';
		ptIF.parentNode.insertBefore(newElement, ptIF.nextSibling);
	}
	ptFormData += '&sViewingUser='+ptViewingUser+'&sLoggedInUser='+ptLoggedInUserName;

	// insert a sidebar container
	var ptSideBarInsertPoint = document.getElementById('profile');
	if (ptSideBarInsertPoint)
	{
		newElement = document.createElement('div');
		newElement.id = 'pt_sidebar_container';
                if(!ptViewingUser)
                        newElement.innerHTML = '<div id="ptPromoBlock"></div>';
		ptSideBarInsertPoint.parentNode.insertBefore(newElement,ptSideBarInsertPoint.nextSibling);
	}

	// insert a media bar for photos, etc.
	var ptMediaInsertPoint = document.getElementById('status');
	if (ptMediaInsertPoint)
	{
		newElement = document.createElement('div');
                newElement.id = 'ptMediaBar';
		newElement.innerHTML =  '<div style="padding: 4px 0px 4px 0px; text-align: left;">' +
                                        '<a id="ptPostPhotoBtn" style="cursor: pointer;"/>Post Photo</a> | ' +
                                        '<a id="ptPostLinkBtn" style="cursor: pointer;">Shorten Link</a>  | ' +
                                        '<a id="ptPostMoodBtn" style="cursor: pointer;">Update Mood</a> ' +
                                        '<div id="ptHiddenMedia"></div>';
		ptMediaInsertPoint.parentNode.insertBefore(newElement,ptMediaInsertPoint);
		document.getElementById('ptPostPhotoBtn').addEventListener('click',ptPostPhoto,true);
		document.getElementById('ptPostLinkBtn').addEventListener('click',ptPostLink,true);
		document.getElementById('ptPostMoodBtn').addEventListener('click',ptPostMood,true);
                
                var ptPhotoPostHtml = '<div id="ptPostPhotoStub" style="display: none; position: relative; height: 40px;"></div>';
                
                var ptLinkPostHtml = '<div id="ptPostLinkDiv" style="display: none; position: relative;">' +
                        '<div style="position: relative; margin: 10px 0px 14px 10px;">' +
                        '<div id="ptSqueezingMsg" style="text-align: center; display: none; padding-left: 10px; height: 36px; z-index: 1003; position: absolute; left: 0px; width: 360px; background-color: #fff; font-size: 1.1em;">'+ptWaitingGif+' Squeezing... <a style="font-size: 9px; color: #333; margin-left: 20px; background-color: #eee; padding: 4px; -moz-border-radius: 4px; border: 1px solid #ccc;" href="/">Cancel</a></div>' +
                        '<input type="text" name="ptPostLinkTemp" id="ptPostLinkTemp" value="Paste link here..." onfocus="this.value=\'\'" style="padding: 4px; width: 200px; font-size: 11px; border: 1px solid #ccc;" /> ' +
                        '<input type="button" value="Shorten" onclick="document.getElementById(\'ptPostLink\').value = document.getElementById(\'ptPostLinkTemp\').value;' +
                        'document.getElementById(\'ptSqueezingMsg\').style.display=\'block\';document.ptPostLinkForm.submit();"/> ' +
                        '<input type="button" style="margin-left: 4px;" value="Cancel" onclick="ptShowHideShade(\'ptPostLinkDiv\',\'none\');document.getElementById(\'ptShade\').style.display=\'none\';" />' +
                        '</form></div></div>';

                var ptMoodPostHtml = '<div id="ptPostMoodDiv" style=" z-index: 1000; display: none; ' +
                        'padding: 14px; position: relative; background-color: #fff;" class="round">' +
                        '<table><tr><td><h3>What is your mood? &nbsp;' +
                        '<select id="ptMoodChoices" name="ptMoodChoices"' +
                        'style="margin-top: 3px; font-size: 14px; padding: 3px;"></select></h3></td>' +
                        '<td><div style="margin-top: 6px;">' +
                        '&nbsp;&nbsp;<input type="button" value="Respond" onclick="document.getElementById(\'status\').value=ptCreateMood(document.getElementById(\'ptMoodChoices\').value);'+
                        'ptShowHideShade(\'ptPostMoodDiv\',\'none\'); document.getElementById(\'ptShade\').style.display=\'none\'; document.getElementById(\'status\').focus();"/> ' +
                        '<input type="button" style="margin-left: 4px;" value="Cancel" onclick="ptShowHideShade(\'ptPostMoodDiv\',\'none\');document.getElementById(\'ptShade\').style.display=\'none\';" />' +
                        '</div></td></tr></table></div>';

                var ptQuestionPostHtml = '<div id="ptPostQuestionDiv" style="z-index: 1000;">' +
                        '<span style="margin-top: 6px; text-align: left; display: none;" id="ptqod">' +
                        '<a onclick="document.getElementById(\'status\').value=document.getElementById(\'ptqod_start\').value; ptShowHideShade(\'ptPostQuestionDiv\',\'none\'); document.getElementById(\'ptShade\').style.display=\'none\'; document.getElementById(\'status\').focus();">Respond</a> ' +
                        '</span><input type="hidden" name="ptqod_start" id="ptqod_start" value="" />' +
                        '</div>';

                var ptHiddenMedia = document.getElementById('ptHiddenMedia');
                ptHiddenMedia.innerHTML += ptPhotoPostHtml;
                ptHiddenMedia.innerHTML += ptLinkPostHtml;
                ptHiddenMedia.innerHTML += ptMoodPostHtml;
                ptHiddenMedia.innerHTML += ptQuestionPostHtml;

	}

        
	// insert the search container
        thisUl = document.getElementById('primary_nav');
        if(     (thisUl)&&
                (ptGsTitle)&&
                (ptGsTitle != 'http://twitter.com/')&&
                (ptGsTitle != 'https://twitter.com/')&&
                (ptGsTitle.indexOf('favourites') == -1)&&
                (ptGsTitle.indexOf('favorites') == -1)&&
                (ptGsTitle.indexOf('#favorites') == -1)&&
                (ptGsTitle.indexOf('followers') == -1)&&
                (ptGsTitle.indexOf('following') == -1)&&
                (ptGsTitle.indexOf('public_timeline') == -1)&&
                (ptGsTitle.indexOf('direct_messages') == -1)&&
                (ptGsTitle.indexOf('#sent') == -1)&&
                (ptGsTitle.indexOf('#inbox') == -1)&&
                (ptGsTitle.indexOf('activity') == -1)&&
                (ptGsTitle.indexOf('#replies') == -1)&&
                (ptGsTitle.indexOf('replies') == -1)&&
                (ptGsTitle.indexOf('/#') == -1)&&
                (ptGsTitle.indexOf('status=') == -1)&&
                (!ptGsTitle.match(ptListRegExp))&&
                (ptGsTitle.indexOf('http://twitter.com/home') == -1 || ptGsTitle.indexOf('https://twitter.com/home') == -1)
                )
        {
                newElement = document.createElement('div');
		var ptSearchUserHtml = '';
                ptPromoDiv = (ptViewingUser) ? '<div id="ptPromoBlock"></div>' : '';
                ptSearchUserHtml = '<div style="margin-bottom: 3px;"><input type="hidden" id="ptThisUser" value="'+ptViewingUser+'" /><input type="checkbox" checked="checked" id="ptSearchRestrictUser" /> only ' + ptViewingUser + "'s updates</div>";
                // now insert an @reply link
                var allNavUls = document.evaluate(
                                '//ul[@class="sidebar-actions"]',
                                document,
                                null,
                                XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
                                null);
                thisNavUl = allNavUls.snapshotItem(0);
                if(allNavUls.snapshotItem(0))
                {
                        var newAtReply = document.createElement('li');
                        newAtReply.innerHTML = "<a href='/home?status=@"+ptViewingUser+" '>@reply</a> " + ptViewingUser;
                        thisNavUl.insertBefore(newAtReply,thisNavUl.firstChild);
                }

                if(ptViewingUser)
                {
                        addGlobalStyle('a#mentions_tab.hover, ul#tabMenu a:hover { background-image:url(http://static.twitter.com/images/pale.png) !important; }');
                        thisUl.innerHTML = thisUl.innerHTML + '<li id="ptMentions" style="display: block;"><a href="#" id="mentions_tab" style="background: none repeat scroll 0% 0%; margin-left:-1px; padding-left: 14px; cursor: pointer;">@'+ptViewingUser+'</a></li>';
                        document.getElementById('mentions_tab').addEventListener('click',ptGetUserMentions,true);
                        var allScreenNames = document.evaluate(
                                '//div[@class="screen-name"]',
                                document,
                                null,
                                XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
                                null);
                        thisScreenName = allScreenNames.snapshotItem(0);
                        if(allScreenNames.snapshotItem(0))
                        {
                                thisScreenName.innerHTML += ' &nbsp;<a style="font-size: 12px; cursor: pointer;" id="ptMentionsLink">see replies @'+ptViewingUser+'</a>';
                                document.getElementById('ptMentionsLink').addEventListener('click',ptGetUserMentions,true);
                        }
                        
                        
                }

                ptSbDisplay = 'block';
                if((ptPrefSB)&&(ptPrefSB.toString().indexOf('off') != -1))
                        ptSbDisplay = 'none';
		newElement.innerHTML = ptPromoDiv + '<div id="pt_search_container" style="display:'+ptSbDisplay +';text-align: right; width: 180px; margin: 0px auto 10px auto;"><form action="" onsubmit="return false;" id="ptSearchForm" method="get">' +
                        '<input style="margin: 0px 1px 4px 0px; width: 169px; padding: 3px;" autosave="com.twitter.search" id="ptSearchBox" name="ptSearchBox" placeholder="Enter your query" results="10" type="search" /><br />'+ptSearchUserHtml+'<input style="cursor: pointer;" type="button" id="ptSearchButton" value="Search" /></form></div>';
		thisUl.parentNode.insertBefore(newElement, thisUl);

        }
        
	// trap update form
	if((ptGsTitle)&&(ptGsTitle.indexOf('twitter.com/direct_messages') == -1))
        {
                ptUpdateButton = document.getElementById('update-submit');
                if(ptUpdateButton)
                        ptUpdateButton.addEventListener('click',ptUpdate,true);
        }


        // trap events with the new search form to process via ajax
        searchForm = document.getElementById('ptSearchForm');
        if(searchForm)
                searchForm.addEventListener('submit',ptPost, true);
        searchButton = document.getElementById('ptSearchButton');
        if(searchButton)
                searchButton.addEventListener('click',ptPost, true);


	// rewrite the home tab to enable a hard refresh
	var ptHomeTab = document.getElementById('home_tab');
	if (ptHomeTab)
		ptHomeTab.addEventListener('click',ptRefreshPage, true);

	// add @mentions
	ptRepliesTab = document.getElementById('replies_tab');
	var ptLastSearch = "@"+ptLoggedInUserName;
        document.getElementById('ptLastSearch').value = ptLastSearch;
	if(ptRepliesTab)
        {
                ptFbDisplay = 'block';
                if((ptPrefFB)&&(ptPrefFB.toString().indexOf('off') != -1))
                        ptFbDisplay = 'none';
                addGlobalStyle('ul#tabMenu a:hover { background-image:url(http://static.twitter.com/images/pale.png) !important; }');
                ptRepliesTab.parentNode.innerHTML = ptRepliesTab.parentNode.innerHTML + 
                '<li><a href="http://twitter.com/search?q=%23dailyquestion" class="in-page-link" style="padding-left: 14px;">#dailyquestion</a></li>';
        }

	// add the Power Twitter source to the update form
	ptUpdateSource = document.getElementById('source');
	if(ptUpdateSource)
		ptUpdateSource.value = 'powertwitter';

        // add a new more button and hide it at first
        if(document.getElementById('pagination'))
        {
//                var newElement = document.createElement('div');
                document.getElementById('pagination').innerHTML += '<div id="ptMoreContainer" style="display: none;"><div id="ptOlder" style="cursor: pointer;" class="ptMoreButton" />more</div></div>';
//                newElement.innerHTML = '<div id="ptMoreContainer" style="display: none;"><div id="ptOlder" style="cursor: pointer;" class="ptMoreButton" />more</div></div>';
//                if(document.getElementById('more').parentNode)
//                {
//                        document.getElementById('more').parentNode.insertBefore(newElement, document.getElementById('more').parentNode);
                        document.getElementById('ptOlder').addEventListener('click',ptGetOlderResults,true);
//                }
        }


        ptAddSearchListeners();
        ptAddListListeners();
        ptAddCacheListeners();

        // ad an id to twitter promo link
        var allUrls = document.evaluate(
		"//a[@class='definition']",
		document,
		null,
		XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
		null);
	for (var i = 0; i < allUrls.snapshotLength; i++)
	{
		thisUrl = allUrls.snapshotItem(i);
                thisUrl.id = 'ptDefinitionPromo';
        }

        
        // add some global css
        addGlobalStyle('.ptMoreButton { -moz-border-radius-bottomleft:5px; -moz-border-radius-bottomright:5px; -moz-border-radius-topleft:5px; -moz-border-radius-topright:5px; background-color:#FFFFFF; background-image:url(http://static.twitter.com/images/more.gif); background-position:left top; background-repeat:repeat-x; border-color:#DDDDDD #AAAAAA #AAAAAA #DDDDDD; border-style:solid; border-width:1px; display:block; font-size:14px; font-weight:bold; height:22px; line-height:1.5em; margin:4px; outline-color:-moz-use-text-color; outline-style:none; outline-width:medium; padding:6px 0; text-align:center; text-shadow:1px 1px 1px #FFFFFF; width:98%; }');

	// put some functions on the page so we have access to them
	embedFunction(ptCheckStatusLength);
	embedFunction(ptRelativeTime);
	embedFunction(ptShowHideShade);
	embedFunction(ptDisplayCenteredDiv);
	embedFunction(ptLogClick);
	embedFunction(ptLog);
	embedFunction(ptWait);
        embedFunction(ptIsImgUrl);
	embedFunction(getWinBottom);
	embedFunction(getWinHeight);
	embedFunction(getWinWidth);
	embedFunction(getWinLeft);
	embedFunction(getWinRight);
	embedFunction(getWinTop);
 	embedFunction(ptNewWindow);
        embedFunction(ptCreateMood);
	exportGlobal('ptServer',ptServer);
	exportGlobal('ptScript',ptScript);
	exportGlobal('ptViewingUser',ptViewingUser);
	exportGlobal('ptLoggedInUserName',ptLoggedInUserName);
	exportGlobal('ptPrefPR',ptPrefPR);
	exportGlobal('ptPrefPH',ptPrefPH);
	exportGlobal('ptStarImage',ptStarImage);
	exportGlobal('ptDefaultPhotoService',ptDefaultPhotoService);
        addGlobalStyle('.ptStreamLink {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAALHRFWHRDcmVhdGlvbiBUaW1lAEZyaSAzMCBKdW4gMjAwNiAxMjo1MTo1MiAtMDAwMAcGCaoAAAAHdElNRQfWBh4LNwyi0YNgAAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAERJREFUeNp1j1EOADAEQxFHc2vuZpJl1lj2PqS0IjgzCYiI1jw8TCgGzWwbJapqj3rjtu6eB9SFvBt9RcYxROiPjp+QBSNmN/gDGx1UAAAAAElFTkSuQmCC);background-repeat: no-repeat; background-position: 99% 4px; border: 1px solid rgb(204, 204, 204) !important; -moz-border-radius: 3px !important; -webkit-border-radius: 3px !important; margin: 10px 0px 10px 10px !important; padding: 5px 10px 5px 5px !important; line-height: 1.1em !important; font-size: 11px !important;background-color: rgb(247, 247, 247) !important;}');
                
        ptLoadingMessage = '<li><div id="ptLoadingMessage">'+ptWaitingGif+' Loading...</div></li>';        

        // swap links with the kill switch if needed
        ptWait(
                function() { return document.getElementById('ptPingStatus').value == 1},
                function() {
                                if(document.getElementById('ptMaxCacheCount'))
                                {
                                        if(document.getElementById('ptMaxCacheCount').value < ptMaxCacheCount)
                                                ptCache = ptInitCache();
                                }
                                // add retweet links
                                if((document.getElementById('status'))||(ptIsStatusPage)||(ptIsUserPage)||(ptIsSearchPage))
                                {
                                        if(ptIsSearchPage)
                                                ptAddRetweetLinks(1);
                                        else
                                                ptAddRetweetLinks();
                                }
                                ptUpdateLinks(ptFormData);
                                
                           }
        );

        // to have no kill switch comment out ptWait and uncomment direct function call
        // ptUpdateLinks(ptFormData);
}

} // end main function -- runPowerTwitter

// ---------------------------------------------------------------------
// functions

function ptLoadUser()
{
//        ptJsonObj = eval( "(" + document.getElementById('ptFunctionData').value + ")" );
//        if((ptJsonObj)&&(ptJsonObj !== 'undefined'))
//        {
//                ptRemoteFunction = eval( "(" + ptJsonObj.ptLoadUser + ")");
//        }
//        if(ptRemoteFunction !== 'undefined')
//        {
//                ptRemoteFunction();
//        }
//        else
//        {
                var ptMeta = document.getElementsByTagName("META");
                for(i=0;i<ptMeta.length;i++)
                {
                        var ptMetaTag=ptMeta.item(i);
                        if(ptMetaTag.name.toLowerCase() == 'session-user-screen_name' )
                        {
                             ptLoggedInUserName = ptMetaTag.content;
                             ptLoggedIn = true;
                        }
                        else if(ptMetaTag.name.toLowerCase() == 'page-user-screen_name' )
                        {
                                if (ptGsTitle.indexOf('/status/') != -1)
                                {
                                        ptViewingUser = ptMetaTag.content;
                                }
                                else if ((ptGsTitle.indexOf('favourites' ) == -1)&&
                                    (ptGsTitle.indexOf('favorites' ) == -1)&&
                                    (ptGsTitle.indexOf('followers' ) == -1)&&
                                    (ptGsTitle.indexOf('following' ) == -1)&&
                                    (ptGsTitle.indexOf('#favorites' ) == -1)&&
                                    (ptGsTitle.indexOf('public_timeline' ) == -1)&&
                                    (ptGsTitle.indexOf('direct_messages' ) == -1)&&
                                    (ptGsTitle.indexOf('#inbox' ) == -1)&&
                                    (ptGsTitle.indexOf('#sent' ) == -1)&&
                                    (ptGsTitle.indexOf('activity' ) == -1)&&
                                    (ptGsTitle.indexOf('replies' ) == -1)&&
                                    (ptGsTitle.indexOf('#replies' ) == -1)&&
                                    (!ptGsTitle.match(ptListRegExp))&&
                                    (ptGsTitle.indexOf('/#' ) == -1))
                                {
                                        ptViewingUser = ptMetaTag.content;
                                        ptIsUserPage = true;
                                }
                        }
                
                }
//        }
}

function ptTestFunction(ptRetweet,ptAtName)
{
        return 'rest';
        ptJsonObj = eval( "(" + document.getElementById('ptFunctionData').value + ")" );
        if(ptJsonObj !== undefined)
        {
                var myfunction = eval( "(" + ptJsonObj.ptSwap + ")");
                return myfunction(ptRetweet,ptAtName);
        }

}

function ptAddListListeners()
{
        var allUrls = document.evaluate(
		"//a[@data]",
		document,
		null,
		XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
		null);
	for (var i = 0; i < allUrls.snapshotLength; i++)
	{
		thisUrl = allUrls.snapshotItem(i);
                thisUrl.addEventListener('click',ptNewList,true);
        }
        
}

function ptAddSearchListeners()
{
        // do not think that this class is still there
        var allUrls = document.evaluate(
		"//a[@class='search-link']",
		document,
		null,
		XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
		null);
	for (var i = 0; i < allUrls.snapshotLength; i++)
	{
		thisUrl = allUrls.snapshotItem(i);
                thisUrl.addEventListener('click',ptNewSearch,true);
        }
        var allUrls = document.evaluate(
		"//a[@class='search_link']",
		document,
		null,
		XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
		null);
	for (var i = 0; i < allUrls.snapshotLength; i++)
	{
		thisUrl = allUrls.snapshotItem(i);
                thisUrl.addEventListener('click',ptNewSearch,true);
        }
        
        
        if(document.getElementById('sidebar_search'))
                document.getElementById('sidebar_search').addEventListener('submit',ptNewSearch,true);
        if(document.getElementById('sidebar_search_submit'))
                document.getElementById('sidebar_search_submit').addEventListener('click',ptNewSearch,true);
        if(document.getElementById('new_results_notification'))
                document.getElementById('new_results_notification').addEventListener('mousedown',ptUpdateLinks,true);

}

function ptNewList(e)
{
        // first to check to see if the page has been processed
        // if not then process it (prevents getting out of sync from a timeout)
        if(!document.getElementById('ptFirstEntry'))
        {
                ptAddRetweetLinks(1);
                ptUpdateLinks('');                
        }
        // hide our More button if shown
        if(document.getElementById('ptMoreContainer'))
                document.getElementById('ptMoreContainer').style.display = 'none';
       // show loading
        document.getElementById('ptStatus').style.display = 'block';

        ptWaitForNewTweets();
}

function ptNewSearch(e)
{
        // first to check to see if the page has been processed
        // if not then process it (prevents getting out of sync from a timeout)
        if(!document.getElementById('ptFirstEntry'))
        {
                ptAddRetweetLinks(1);
                ptUpdateLinks('');                
        }
        // hide our More button if shown
        if(document.getElementById('ptMoreContainer'))
                document.getElementById('ptMoreContainer').style.display = 'none';
       // show loading
        document.getElementById('ptStatus').style.display = 'block';
        if(document.getElementById('new_results_notification'))
                document.getElementById('new_results_notification').addEventListener('mousedown',ptUpdateLinks,true);

        ptWaitForNewTweets();
}

function ptWaitForNewTweets()
{
//        GM_log('waiting for new tweets');
        ptWait(
                function(){
                                
//                                if((document.getElementById('ptLatestTweetId'))&&(ptGetLatestTweetId() != '')&&
//                                   (ptGetLatestTweetId() != document.getElementById('ptLatestTweetId').value))
                                if(ptGetLatestTweetId() != document.getElementById('ptLatestTweetId').value)
                                {
                                        // results have changed
//                                        GM_log('results changed - '+ptGetLatestTweetId());
                                        ptAttempts = 0;
                                        return true;
                                }
                                else
                                {
                                        if(ptAttempts == 200)
                                        {
                                                ptTimeOut = 1;
                                                ptAttempts = 0;
                                                return true;
                                        }
                                        return false;
                                }
                                
                                },
                function(){
                                if(ptTimeOut == 0) // things have changed 
                                {
                                        ptGsNextPage = 2;
//                                        GM_log('new updates arrived');
                                }
                                else // timed out
                                {
                                        GM_log('time out looking for new updates');
                                }
                                ptTimeOut = 0;
                                ptAddRetweetLinks(1);
//                                GM_log('current value ' + document.getElementById('ptLatestTweetId').value);
                                ptUpdateLinks('');
                                if(document.getElementById('search_more'))
                                {
                                        document.getElementById('search_more').addEventListener('click',ptParseMoreUpdates,true);
                                        // twitter bug
                                        if(document.getElementById('search_more').innerHTML != 'more')
                                        {
                                                var ptPageRegExp = new RegExp(/.page=(.*?)&/);
                                                if(document.getElementById('search_more').href.match(ptPageRegExp))
                                                {
                                                        var ptPage = document.getElementById('search_more').href.match(ptPageRegExp)[1];
                                                        ptPage++;
                                                        document.getElementById('search_more').href = document.getElementById('search_more').href.replace(/page=(.*?)&/,'page='+ptPage+'&');                 
                                                        document.getElementById('search_more').innerHTML = 'more';
                                                        document.getElementById('search_more').style.backgroundImage = 'url()';
                                                }
                                        }
                                }
                                // log this
                                if((document.getElementById('sidebar_search_q'))&&(document.getElementById('sidebar_search_q').value != ''))
                                {
                                        var ptQ = document.getElementById('sidebar_search_q').value;
                                        ptData = 'q='+ptQ+'&action=ptLog&type=canned&sLoggedInUser='+ptLoggedInUserName+'&sViewingUser='+ptViewingUser;
                                        ptLog(ptData);
                                }
                                
                          }
        );
}

function ptGetLatestTweetId()
{
//        GM_log('getting latest...')
        ptAttempts++;
        var ptAllEntries = document.evaluate(
                '//span[@class="status-body"]',
                document,
                null,
                XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
                null);
        var ptThisEntry = ptAllEntries.snapshotItem(ptAllEntries.snapshotLength -1);
        
//        GM_log('attempt '+ptThisEntry.parentNode.id);
        if((ptThisEntry)&&(ptThisEntry.parentNode)&&(ptThisEntry.parentNode.id))
                return ptThisEntry.parentNode.id;
        else
                return '';
        
}

function ptNextSearch()
{
        var ptPageRegExp = new RegExp(/.q=(.*?)$/);
        if(location.href.match(ptPageRegExp))
                return location.href.match(ptPageRegExp)[1];
        else
                return '';
}

function ptCheckStatusLength(ptFeature)
{
        if(document.getElementById('status'))
        {
                if (document.getElementById('status').value.length > 1)
                {
                        if (ptFeature == 'photo')
                                return confirm("Right now, the post photo feature clears anything you have in your status box! It will insert a link that you can tweet about.\n\n Are you OK losing the text you already have?");
                        else if (ptFeature == 'link')
                                return confirm("Right now, the shorten link feature clears anything you have in your status box! Use the link shortener first and then you can add your tweet around it.\n\n Are you OK losing the text you already have?");
                        else if (ptFeature == 'mood')
                                return confirm("Right now, the mood feature clears anything you have in your status box! Use the link shortener first and then you can add your tweet around it.\n\n Are you OK losing the text you already have?");
                        else
                                return confirm("Right now, this feature clears anything you have in your status box! Use the link shortener first and then you can add your tweet around it.\n\n Are you OK losing the text you already have?");
                }
        }
        return true;
}

function ptAddCacheListeners()
{
        // make sure certain links will intelligently update the local cache
        // this also happens at other opportune moments
        if(document.getElementById('home_link'))
                document.getElementById('home_link').addEventListener('click',ptTransferCache,true);
        if(document.getElementById('home_tab'))
                document.getElementById('home_tab').addEventListener('mousedown',ptTransferCache,true);
        if(document.getElementById('replies_tab'))
                document.getElementById('replies_tab').addEventListener('mousedown',ptTransferCache,true);
        if(document.getElementById('direct_messages_tab'))
                document.getElementById('direct_messages_tab').addEventListener('mousedown',ptTransferCache,true);
        if(document.getElementById('favorites_tab'))
                document.getElementById('favorites_tab').addEventListener('mousedown',ptTransferCache,true);
        if(document.getElementById('tweets_tab'))
                document.getElementById('tweets_tab').addEventListener('mousedown',ptTransferCache,true);
}

function ptAddRetweetLinks(ptIsSearchResult)
{
        // 1) have the matching portion done as a pass in var
        // 2) first, last and processed done as pass in ptFirstLastProcessed
        // 3) pass in ptBuildRetweetText
        // 4) create container and add attributes pass in ptInsertRetweet
        var ptAllEntries = document.evaluate(
                '//span[@class="status-body"]',
                document,
                null,
                XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
                null);
        for (var i = 0; i < ptAllEntries.snapshotLength; i++)
        {
                var ptThisEntry = ptAllEntries.snapshotItem(i);
                if(i == 0)  // capture the first id so we can compare it later with ajax searches
                {
                        if((document.getElementById('ptFirstTweetId'))&&(ptThisEntry.parentNode.id))
                                document.getElementById('ptFirstTweetId').value = ptThisEntry.parentNode.id;
                                
                        ptThisEntry.id = 'ptFirstEntry';
                }
                else if(i == ptAllEntries.snapshotLength - 1)
                {
                        if((document.getElementById('ptLatestTweetId'))&&(ptThisEntry.parentNode.id))
                        {
//                                GM_log(ptThisEntry.parentNode.id);
                                document.getElementById('ptLatestTweetId').value = ptThisEntry.parentNode.id;
                        }
                        ptThisEntry.id = 'ptLastEntry';
                }
                if (ptThisEntry.getAttribute('processed'))
                        continue;
                ptThisEntry.setAttribute('processed','1');
                
//                if (ptThisEntry.title == 'processed')
//                        continue;
//                ptThisEntry.title = 'processed';
                
                var ptRetweet = ptThisEntry.innerHTML;
                var ptAtName = (ptViewingUser && ptIsSearchResult != 1) ? ptViewingUser+' ' : '';
                if(ptRetweet.indexOf('class="lock"') == -1) // don't retweet protected updates
                {
                        ptRetweet = ptRetweet.replace(/<strong.*?class=.screen.name.*?>(.*?)<.a><.strong>/gim,'$1 ');
                        ptRetweet = ptRetweet.replace(/<a.*?>(.*?)<.a>/gim,'$1 ');
                        ptRetweet = ptRetweet.replace(/\n/gim,'');
                        ptRetweet = ptRetweet.replace(/<b>/gim,'');
                        ptRetweet = ptRetweet.replace(/<.b>/gim,'');
/*                        ptJsonObj = eval( "(" + document.getElementById('ptFunctionData').value + ")" );
                        if(ptJsonObj !== 'undefined')
                        {
                                var myfunction = eval( "(" + ptJsonObj.ptCleanRetweet + ")");
                                myfunction(ptRetweet,ptAtName,ptThisEntry);
                        }
*/
                        ptRetweet = 'RT @'+ ptAtName + ptRetweet.replace(/<ul>|<li>|<\/li>|<\/ul>|<strong>|<.strong>|<a.href.*?>|<.a>|<span id=.msg.*?>|<span class=.entry.*?>|<span class=.actions.*?>|<span class=.meta.*\/span>|<\/span>|<div>|<\/div>|<b>|<.b>/gim,'');
                        ptRetweet = ptRetweet.replace(/\s{2,}/gim,'');
                        ptRetweet = ptRetweet.replace(/('|")/gim,'');
                        ptRetweet = ptRetweet.replace(/.nbsp..nbsp./gim,'');
                        if(ptIsStatusPage&&ptThisEntry)
                                ptThisEntry.innerHTML += ' <div style="font-size: 12px; margin-top: 10px; margin-right: -34px; float: right; color: #aaa; cursor: pointer;" onclick="document.location.href=\'/home?status='+ptRetweet+'\';">RT</div>';
                        else if(ptIsUserPage&&ptThisEntry.nextSibling) // likely inactive
                                ptThisEntry.nextSibling.innerHTML += ' <div style="font-size: 9px;text-align: right; float: right; margin-right: 0px; color: #aaa; cursor: pointer;" onclick="document.location.href=\'/home?status='+ptRetweet+'\';">RT</div>';
                        else if(ptIsUserPage&&ptThisEntry)
                                ptThisEntry.innerHTML += ' <div style="font-size: 9px; text-align: right; float: right; margin-right: 0px; color: #aaa; cursor: pointer;" onclick="document.location.href=\'/home?status='+ptRetweet+'\';">RT</div>';
                        else if((ptIsSearchResult == 1)&&(ptThisEntry.nextSibling)&&(ptThisEntry.nextSibling.nextSibling))
                                ptThisEntry.nextSibling.nextSibling.innerHTML += ' <div style="font-size: 9px; text-align: center; color: #aaa; cursor: pointer;" onclick="document.getElementById(\'status\').value=\''+ptRetweet+'\';document.getElementById(\'status\').focus();">RT</div>';
                        else if(ptThisEntry.nextSibling)
                                ptThisEntry.nextSibling.innerHTML += ' <div style="font-size: 9px; text-align: center; color: #aaa; cursor: pointer;" onclick="document.getElementById(\'status\').value=\''+ptRetweet+'\';document.getElementById(\'status\').focus();">RT</div>';
                        else if(ptThisEntry)
                                ptThisEntry.innerHTML += ' <div style="font-size: 9px; text-align: right; float: right; color: #aaa; margin-right: 20px; cursor: pointer;" onclick="document.getElementById(\'status\').value=\''+ptRetweet+'\';document.getElementById(\'status\').focus();">RT</div>';

                }
        }

}

function ptPostLink()
{
        if(ptCheckStatusLength('link'))
        {
 //               ptShowHideShade('ptShade','block');
                var el = document.getElementById('ptPostLinkDiv');
                el.style.display = 'block';
        }
}

function ptPostQuestion()
{
        if(ptCheckStatusLength('question'))
        {
                ptShowHideShade('ptShade','block');
                var el = document.getElementById('ptPostQuestionDiv');
                ptDisplayCenteredDiv(el, 120);
        }
}
function ptPostMood()
{
        if(ptCheckStatusLength('mood'))
        {
 //               ptShowHideShade('ptShade','block');
                var el = document.getElementById('ptPostMoodDiv');
                el.style.display = 'block';
                ptShowMoods();
        }
}

function ptCreateMood(mood)
{
        if(mood)       
                return '#mood I am *'+mood+'*';
        else
                return '';
}

function ptPostPhoto()
{
        // make sure we have a user/password or else show settings
        document.getElementById('ptPostPhotoUser').value = ptLoggedInUserName;
        if (document.getElementById('ptSettingUserKey').value.length > 1)
        {
                if(ptCheckStatusLength('photo'))
                {
                        document.getElementById('ptPostPhotoPass').value = ptPrefPassword;
                        document.getElementById('ptPostPhotoUserKey').value = document.getElementById('ptSettingUserKey').value;
                        document.getElementById('ptPostTo').value = (ptPrefPH.length) ? ptPrefPH : document.getElementById('ptDefaultPhotoService').value;
                        document.getElementById('ptPostPhotoStub').style.display = 'block';
                        var el = document.getElementById('ptPostPhotoDiv');
                	el.style.display = 'block';
                        el.style.left = document.getElementById('ptMediaBar').style.left + 20 + 'px';
                        el.style.top = document.getElementById('ptMediaBar').style.top + 130 + 'px';
//                        ptDisplayCenteredDiv(el, 120);
                }
        }
        else
        {
                alert('To post photos, you must authenticate Power Twitter.');
                ptShowSettings();
        }

}

function ptUpdateLinks(ptFormData)
{
	// if replace links setting is on, then collect all the links to process them
        if(ptPrefEX.toString().indexOf('on') != -1)  
        {
                var ptAllLinks = document.evaluate(
                        '//a[@href]',
                        document,
                        null,
                        XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
                        null);
                for (var i = 0; i < ptAllLinks.snapshotLength; i++)
                {
                        
                        ptThisLink = ptAllLinks.snapshotItem(i);
                        if((ptThisLink.href.indexOf('category=saved_search') != -1)||(ptThisLink.href.indexOf('category=trends') != -1))
                        {
                                // track saved searches so we can update them
                                ptThisLink.addEventListener('click',ptNewSearch,true);                   
                        }
                        
                        
                        // do something with thisLink
                        if ((ptThisLink.target == '_blank')||(location.href.indexOf('search?') != -1))
                        {
                                if(ptThisLink.rel.indexOf('me') != -1)
                                        continue;
                                if(ptThisLink.title && ptThisLink.title == '.')
                                        continue;
                                if(ptThisLink.processed)
                                        continue;
                                // multithreaded script insertions
                                // do not replace: twitter, links that have already been done, or the help link
                                if((ptThisLink.href.indexOf('twitter.com') != -1)||
                                   (ptThisLink.href.indexOf('oauth.php') != -1)||
                                   (ptThisLink.id.indexOf('ptLink_') != -1)||
                                   (document.getElementById('ptDoNotParse').value.indexOf(ptThisLink.href) != -1)||
                                   (ptThisLink.href.indexOf('javascript') != -1)||
                                   (ptThisLink.className.indexOf('definition') != -1)||
                                   (ptThisLink.className.indexOf('noparse') != -1)||
                                   (ptThisLink.className.indexOf('geocoded') != -1)||
                                   (ptThisLink.rel == 'nofollow')&&(ptThisLink.target != '_blank')||
                                   (ptThisLink.id == 'ptHelpLink'))
                                        continue;
                                ptThisLink.id = 'ptLink_' + i;
                                ptThisLink.innerHTML = ptWaitingGif + ptThisLink.innerHTML;
                                
                                // now check the cache
                                if((ptCache)&&(ptCache[ptThisLink.href]))
                                {
//                                        GM_log('in cache '+ptThisLink.href);
                                        ptJsonObj = eval( "(" + ptCache[ptThisLink.href] + ")" );
                                        if(ptJsonObj !== undefined)
                                        {
                                                var ptReplacementHtml = ptJsonObj.results;
                                                var ptNum = ptJsonObj.num;
                                                var ptType = ptJsonObj.type;
                                                var ptOriginalUrl = ptJsonObj.url;
                                        
                                                if(ptType == 'generic')
                                                {
                                                        ptThisLink.innerHTML = ptReplacementHtml;
                                                }
                                                else
                                                {
                                                        var ptReplaceWith = document.createElement("div");
                                                        ptThisLink.parentNode.replaceChild(ptReplaceWith,ptThisLink);
                                                        ptReplaceWith.innerHTML = ptReplacementHtml;
                                                        if(ptOriginalUrl)
                                                        {
                                                                ptReplaceWith.title = ptOriginalUrl;
                                                                ptReplaceWith.addEventListener('mousedown',ptLogClick,true);
                                                        }
                                                }
                                                continue;
                                        }                                
                                }
                                
                                var ptPreferences = '';
                                if(ptPrefEX.toString().indexOf('off') != -1)
                                        ptPreferences += '&ptPrefEX=off';
                                if(ptPrefRM.toString().indexOf('off') != -1)
                                        ptPreferences += '&ptPrefRM=off';
        
                                var twitter_JSON = document.createElement("script");
                                twitter_JSON.type="text/javascript";
                                var ptLinkParseService = ptServer + ptScript;
                                if(document.getElementById('ptLinkParseService').value != '')
                                        ptLinkParseService = document.getElementById('ptLinkParseService').value;
        //                        ptLinkParseService = 'http://linkmapper.codingsocial.com/map.powertwitter/';
        //                        ptLinkParseService = 'http://localhost:8080/map.powertwitter/';
                                twitter_JSON.src= ptLinkParseService + "?action=parseLink&version="+ptVersionNumber+"&format=json&linkNumber="+i+ptPreferences+"&url="+escape(ptThisLink.href);
                                document.getElementsByTagName("head")[0].appendChild(twitter_JSON);
        
                                ptThisLink.addEventListener('mousedown',ptLogClick,true);
                        }
                }
        }
        
	// check for dynamic insertions
	if (ptFormData.length > 1)
	{
		var ptPreferences = '';
                if(ptPrefEX.toString().indexOf('off') == -1)
                        ptPreferences += '&ptPrefEX=off';
                if(ptPrefRM.toString().indexOf('off') == -1)
                        ptPreferences += '&ptPrefRM=off';
                ptFormData += '&sViewingUser='+ptViewingUser+'&sLoggedInUser='+ptLoggedInUserName+ptPreferences;

                var twitter_JSON = document.createElement("script");
                twitter_JSON.type="text/javascript";
                twitter_JSON.src= ptServer + ptScript + "?agent=safari&action=userPage&version="+ptVersionNumber+'&'+ptFormData;
                document.getElementsByTagName("head")[0].appendChild(twitter_JSON);
	}
	else
	{
                ptStatusDiv = document.getElementById('ptStatus');
		if(ptStatusDiv)
			ptStatusDiv.style.display = 'none';
	}

        document.getElementById('ptLinkUpdateStatus').value = 1;

}


function ptRefreshPage(ptType)
{
        if(ptType == 'hard')
                document.location.href = 'http://twitter.com/home';
        else if(ptGsTitle)
        {
                if(ptGsTitle.indexOf('ptAlert=') != -1)
                {
                	document.location.href = 'http://twitter.com/home';
                }
                else if(ptGsTitle.indexOf('ptQ=') != -1)
                {
                	document.location.href = 'http://twitter.com/home';
                }
                else if(ptGsTitle == 'http://twitter.com/#')
                {
                	document.location.href = 'http://twitter.com/home';
                }
                else
                {
                        ptPage = ptGsTitle.replace('http://twitter.com/','');
                        ptPage = ptGsTitle.replace('https://twitter.com/','');
                        ptPage = ptPage.replace('#','');
                	document.location.href = 'http://twitter.com/'+ptPage;
                }

        }
        else
        	document.location.href = 'http://twitter.com/home';
}

function ptSaveSettings()
{

        var ptCloseWindow = 'none';
        var ptSaving = 0;

        if (document.getElementById('ptSettingEX').checked)
                GM_setValue("ptPrefEX","on");
        else
                GM_setValue("ptPrefEX","off");
                
        if (document.getElementById('ptSettingPH'))
        {
                GM_setValue("ptPrefPH",document.getElementById('ptSettingPH').value);
        }
        
        ptRefreshPage('hard');
        
                
/*
        if (document.getElementById('ptSettingRM').checked)
                GM_setValue("ptPrefRM","on");
        else
                GM_setValue("ptPrefRM","off");



        if (document.getElementById('ptSettingPR').checked)
        {
                GM_setValue("ptPrefPR","on");
                if(document.getElementById('ptPromoBlock'))
                {
                        document.getElementById('ptPromoBlock').style.display = 'block';
                }
        }
        else
        {
                GM_setValue("ptPrefPR","off");
                if(document.getElementById('ptPromoBlock'))
                {
                        document.getElementById('ptPromoBlock').style.display = 'none';
                }
        }
        
        
        if (document.getElementById('ptSettingPassword') !== undefined)
        {
                if (document.getElementById('ptSettingPassword').value.length > 0)
                {
                        ptSaving = 1;
                        var ptSaveSettings_JSON = document.createElement("script");
                        ptSaveSettings_JSON.type="text/javascript";
                        ptSaveSettings_JSON.src=ptServer + ptScript + "?agent=greasemonkey&action=auth&u="+ptLoggedInUserName+"&p="+document.getElementById('ptSettingPassword').value;
                        document.getElementsByTagName("head")[0].appendChild(ptSaveSettings_JSON);
                        document.getElementById('ptLinkUpdateStatus').value = 1;
                        ptWait(
                                function(){ return document.getElementById('ptLinkUpdateStatus').value == 0},
                                function()
                                {
                                      if(document.getElementById('ptAuth').value == 1)
                                      {
                                          GM_setValue("ptPrefPassword",ptLoggedInUserName+'|'+document.getElementById('ptSettingPassword').value);
                                          ptPrefPassword = ptGetPassword();
                                          document.getElementById('ptSettings').style.display = ptCloseWindow;
                                      }
                                      else
                                      {
                                          alert('Sorry, your twitter user/pass was not valid.');
                                          ptCloseWindow = 'block';
                                      }    
                                }
                        );
                }
                else if (document.getElementById('ptSettingPassword').value == '')
                {
                        GM_setValue("ptPrefPassword",ptLoggedInUserName+'|'+document.getElementById('ptSettingPassword').value);
                        ptPrefPassword = ptGetPassword();
                }
        }

  
        if(ptPrefEX != GM_getValue("ptPrefEX"))
                ptRefreshPage('hard'); // need to reset mouseovers


        ptPrefRM = GM_getValue("ptPrefRM");
        ptPrefEX = GM_getValue("ptPrefEX");
        ptPrefFB = GM_getValue("ptPrefFB");
        ptPrefSB = GM_getValue("ptPrefSB");
        ptPrefPR = GM_getValue("ptPrefPR");
        ptPrefPH = GM_getValue("ptPrefPH");

        if(ptSaving == 0)
        {
                ptPrefPassword = ptGetPassword();
                document.getElementById('ptSettings').style.display = ptCloseWindow;
        }
*/
}

function ptGetPassword()
{
        if(GM_getValue("ptPrefPassword"))
        {
                var ptUserPass = GM_getValue("ptPrefPassword").split('|');
                return ptUserPass[1];
        }
        else
                return '';
}

function ptShowMoods()
{
        var ptAMoodOptions = document.getElementById('ptMoodOptions').value.split('|');
        var ptOptionHtml = '';
        for(i=0;i<ptAMoodOptions.length;i++)
        {
                ptMood = ptAMoodOptions[i];
                ptOptionHtml += '<option value="'+ptAMoodOptions[i]+'" id="pt_'+ptAMoodOptions[i]+'">'+ptAMoodOptions[i]+'</option>';
        }
        document.getElementById('ptMoodChoices').innerHTML = ptOptionHtml;        
}

function ptShowSettings()
{
        ptTransferCache();
//        if(ptPrefRM.toString().indexOf('off') == -1)
//                document.getElementById('ptSettingRM').checked = 'true';
        if(ptPrefEX.toString().indexOf('off') == -1)
                document.getElementById('ptSettingEX').checked = 'true';
//        if(ptPrefSB.toString().indexOf('off') == -1)
//                document.getElementById('ptSettingSB').checked = 'true';
//        if(ptPrefPR.toString().indexOf('off') == -1)
//                document.getElementById('ptSettingPR').checked = 'true';
                
        if(document.getElementById('ptSettingPH'))
        {
                var ptAServiceOptions = document.getElementById('ptPhotoServiceOptions').value.split('|');
                var ptOptionHtml = '';
                for(i=0;i<ptAServiceOptions.length;i++)
                {
                        ptService = ptAServiceOptions[i];
                        ptOptionHtml += '<option value="'+ptAServiceOptions[i]+'" id="pt_'+ptAServiceOptions[i]+'">'+ptAServiceOptions[i]+'</option>';
                }
                document.getElementById('ptSettingPH').innerHTML = ptOptionHtml;
                
        }
        
        if((ptPrefPH !== undefined)&&(ptPrefPH.toString()))
                document.getElementById('pt_'+ptPrefPH.toString()).selected = 'true';
        else
                document.getElementById('pt_'+document.getElementById('ptDefaultPhotoService').value).selected = 'true';
                

       if (document.getElementById('ptSettingPassword') !== undefined)
       {
                document.getElementById('ptSettingPassword').value = ptPrefPassword;
       }

        document.getElementById('ptSettings').style.display = 'block';
}


function ptParseMoreUpdates()
{
//        GM_log('parse more updates');
        ptWaitForNewTweets();
        return;

/*
        if(document.getElementById('search_more'))
                ptWaitForNewTweets();
        else
                ptWait(
                        function(){
                                        var ptIsSearch = (document.getElementById('search_more')) ? 1 : '';
                                        if(ptNextPage(ptIsSearch) > ptGsNextPage)
                                                return true;
                                        else
                                                return false;
                                },
                        function(){
                                        ptGsNextPage++;
                                        var ptIsSearch = (document.getElementById('search_more')) ? 1 : '';
                                        ptAddRetweetLinks(ptIsSearch);
                                        if(document.getElementById('pagination'))
                                                document.getElementById('pagination').addEventListener('click',ptParseMoreUpdates,true);
                                        if(document.getElementById('more'))
                                                document.getElementById('more').addEventListener('click',ptParseMoreUpdates,true);
                                        if(document.getElementById('search_more'))
                                                document.getElementById('search_more').addEventListener('click',ptParseMoreUpdates,true);
                                        ptTransferCache();
                                        ptUpdateLinks('');
                                }
                );
*/

}

function ptNextPage(ptIsSearch)
{
        var thisId = (ptIsSearch == 1) ? 'search_more' : 'more';
        if(document.getElementById(thisId))
        {
                var ptPageRegExp = new RegExp(/.page=(.*?)&/);
                if(document.getElementById(thisId).href.match(ptPageRegExp))
                {
//                        GM_log('regexp '+document.getElementById(thisId).href.match(ptPageRegExp)[1]);
//                        alert('regexp '+document.getElementById(thisId).href.match(ptPageRegExp)[1]);
                        return document.getElementById(thisId).href.match(ptPageRegExp)[1];
                }
                else if(documentgetElementById(thisId).href.indexOf('undefined') != -1)
                {
//                        alert('gs '+ptGsNextPage++);
                        return ptGsNextPage++;
                }
                else
                {
//                        alert('just 2');
                        return 2;
                }
        }
        else
                return 2;
}

function ptUpdate(evt)
{
        // when update button is pushed this fork lets us log
        // and then wait so we can embed the media if needed
	ptLog('action=ptLog&type=update&sLoggedInUser='+ptLoggedInUserName);
        // if img/media preview - clear it
        if(document.getElementById('ptImgThumb'))
        {
                document.getElementById('ptImgThumb').style.display = 'none';
                document.getElementById('status').style.width = '508px';
        }
        ptTransferCache();
        ptWait(
                function(){ return document.getElementById('status').value ==''},
                function(){ ptUpdateLinks(''); }
        );
}

function ptLogClick()
{
        if(this.href)
                ptLog('action=ptLog&type=click&sLoggedInUser='+ptLoggedInUserName+'&sViewingUser='+ptViewingUser+'&url='+this.href);
        else if(this.title)
                ptLog('action=ptLog&type=click&sLoggedInUser='+ptLoggedInUserName+'&sViewingUser='+ptViewingUser+'&url='+this.title);
}

function ptLog(ptData)
{
        var pt_LOG = document.createElement("script");
	pt_LOG.type="text/javascript";
	pt_LOG.src= ptServer + ptScript + '?' + ptData;;
	document.getElementsByTagName("head")[0].appendChild(pt_LOG);
        ptTransferCache();
}

function ptPost() // ajax engine for getting and displaying search results
{
	if(document.getElementById('ptSearchBox').value.length == 0)
	{
		alert('Please enter a search term!');
		return;
	}

	resultsContainer = document.getElementById('ptSearchResults');
	ptQ = document.getElementById('ptSearchBox').value;
        ptQ = ptQ.replace('#','%23');
	var ptRestrictTo = '';
	if((document.getElementById('ptSearchRestrictUser'))&&(document.getElementById('ptSearchRestrictUser').checked)) // restrict search to the twitter page user
	{
		ptRestrictTo = document.getElementById('ptThisUser').value;
                document.getElementById('ptRestrictedSearch').value = ptRestrictTo;
	}
        document.getElementById('ptLastSearch').value = ptQ;
        document.getElementById('ptPageNumber').value = 1;

	// log
	ptData = 'q='+ptQ+'&action=ptLog&type=search&sLoggedInUser='+ptLoggedInUserName+'&sViewingUser='+ptViewingUser;
        ptLog(ptData);

        // display
	ptGetSearchResults(ptQ,1,ptRestrictTo);
	return;

};

function ptWait(c,f)
{
        if (c())
                f()
        else
                window.setTimeout(function () { ptWait(c,f) }, 50, false);
}

function ptGetUserMentions()
{
        ptQ = '@'+ptViewingUser;
        var twitter_JSON = document.createElement("script");
	twitter_JSON.type="text/javascript";
	ptPage = "&page=1";
        document.getElementById('ptPageNumber').value = 1; // reset the page count
        document.getElementById('ptLastSearch').value = ptQ; // set the hidden input to make this a "search" for older/newer
	twitter_JSON.src="http://search.twitter.com/search.json?callback=ptCbShowResults&q="+ptQ + ptPage;
	document.getElementsByTagName("head")[0].appendChild(twitter_JSON);
        document.getElementById('ptStatus').style.display = 'block';
        ptWait(
                function(){ return document.getElementById('ptLinkUpdateStatus').value == 0},
                function(){ ptUpdateLinks(''); }
        );
}

function ptToggleLoadingMessage(ptClear)
{
        if(ptClear)
        {
                if(document.getElementById('timeline'))
                        document.getElementById('timeline').innerHTML = ptLoadingMessage;
        }
        else
        {
                if(document.getElementById('timeline'))
                        document.getElementById('timeline').innerHTML = ptLoadingMessage + document.getElementById('timeline').innerHTML;
       
                if(document.getElementById('results_update'))
                        document.getElementById('results_update').style.display = 'none';
        }
        
}

function ptUnHighlightTab(id)
{
        if(document.getElementById(id))
        {
                document.getElementById(id).firstChild.style.fontWeight = 'normal';
                document.getElementById(id).firstChild.style.background = 'transparent';
                document.getElementById(id).style.background = 'transparent';
        }
}

function ptHighlightTab(id)
{
        document.getElementById(id).style.background = '#f7f7f7';
        document.getElementById(id).firstChild.style.background = '#f7f7f7';
        document.getElementById(id).firstChild.style.fontWeight = 'bold';
}

function ptResetMaxIds(id)
{
        var ptAMaxIdTitles = new Array('ptInteresting');
        for (i=0;i<ptAMaxIdTitles.length;i++)
        {
                if(id != ptAMaxIdTitles[i])
                {
                        if(document.getElementById(ptAMaxIdTitles[i]+'MaxId'))
                                document.getElementById(ptAMaxIdTitles[i]+'MaxId').value = '0';                        
                }
        }
}                

function ptGetMentions()
{
        ptQ = '@'+ptLoggedInUserName;
        var twitter_JSON = document.createElement("script");
	twitter_JSON.type="text/javascript";
	ptPage = "&page=1";
        document.getElementById('ptPageNumber').value = 1; // reset the page count
        document.getElementById('ptLastSearch').value = ptQ; // set the hidden input to make this a "search" for older/newer
	twitter_JSON.src="http://search.twitter.com/search.json?callback=ptCbShowResults&q="+ptQ + ptPage;
	document.getElementsByTagName("head")[0].appendChild(twitter_JSON);
        document.getElementById('ptStatus').style.display = 'block';
        ptWait(
                function(){ return document.getElementById('ptLinkUpdateStatus').value == 0},
                function(){ ptUpdateLinks(''); }
        );
}

function ptGetOlderResults()
{
        document.getElementById('ptClearTimeline').value = '0';
                var twitter_JSON = document.createElement("script");
                twitter_JSON.type="text/javascript";
                ptPageNumber = parseInt(document.getElementById('ptPageNumber').value);
                ptPage = "&page=" + ptPageNumber;
                ptQ = document.getElementById('ptLastSearch').value;
                document.getElementById('ptPageNumber').value = ptPageNumber; // increment the page count
                if(document.getElementById('ptRestrictedSearch').value.length)
                        twitter_JSON.src="http://search.twitter.com/search.json?callback=ptCbShowResults&q="+ptQ+"%20from%3A"+document.getElementById('ptRestrictedSearch').value + ptPage;
                else
                        twitter_JSON.src="http://search.twitter.com/search.json?callback=ptCbShowResults&q="+ptQ + ptPage;
                document.getElementsByTagName("head")[0].appendChild(twitter_JSON);
                // now we need to wait for the ptCbShowResults to finish
                document.getElementById('ptStatus').style.display = 'block';
                ptWait(
                        function(){ return document.getElementById('ptLinkUpdateStatus').value == 0},
                        function(){ ptUpdateLinks(''); }
                );
}

function ptGetSearchResults(ptQ,ptP,ptRestrictTo)
{
	var twitter_JSON = document.createElement("script");
	twitter_JSON.type="text/javascript";
	ptPage = "&page=" + ptP;
	ptPageNumber = ptP;
	if(ptRestrictTo)
		twitter_JSON.src="http://search.twitter.com/search.json?callback=ptCbShowResults&q="+ptQ+"%20from%3A"+ptRestrictTo + ptPage;
	else
		twitter_JSON.src="http://search.twitter.com/search.json?callback=ptCbShowResults&q="+ptQ + ptPage;
	document.getElementsByTagName("head")[0].appendChild(twitter_JSON);
        // now we need to wait for the ptCbShowResults to finish
        document.getElementById('ptStatus').style.display = 'block';
        ptWait(
                function(){ return document.getElementById('ptLinkUpdateStatus').value == 0},
                function(){ ptUpdateLinks(''); }
        );

}


// utility functions

function logToConsole(s)
{
	var logger = document.createElement("script");
        logger.src= 'http://localhost:8081/abc/write/?logthis=' + s;
        document.getElementsByTagName("head")[0].appendChild(logger);
}

function embedFunction(s)
{
	var ptScriptObject = document.createElement('script');
	ptScriptObject.type = "text/javascript";
	document.body.appendChild(ptScriptObject).innerHTML=s.toString().replace(/([\s\S]*?return;){2}([\s\S]*)}/,'$2');
}

function exportGlobal(name,value)
{
	embedFunction("var "+ name +" = '" + value + "';");
}

function addGlobalStyle(css)
{
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;
    head.appendChild(style);
}

function ptIsImgUrl(s)
{
        if(s&&s.indexOf('flickr.com') != -1)
                return true;
        else if(s&&s.indexOf('twitpic') != -1)
                return true;
        else if(s&&s.indexOf('yfrog') != -1)
                return true;
        else
                return false;
}

function ptRelativeTime(time_value)
{
	var parsed_date = Date.parse(time_value);
	var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
	var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
	if(delta < 60) {
		return 'less than a minute ago';
	} else if(delta < 120) {
		return 'about a minute ago';
	} else if(delta < (45*60)) {
		return (parseInt(delta / 60)).toString() + ' minutes ago';
	} else if(delta < (90*60)) {
		return 'about an hour ago';
	} else if(delta < (24*60*60)) {
		return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
	} else if(delta < (48*60*60)) {
		return '1 day ago';
	} else if(delta < (48*60*60*7)) {
		return (parseInt(delta / 86400)).toString() + ' days ago';
	} else {
		ptOldDate = new Date(parsed_date);
		return ptOldDate.toString();
	}
}

function getWinWidth()
{
	if (window.innerWidth)
	{
		w = window.innerWidth;
		if (document.body.scrollHeight && document.body.scrollHeight >= getWinHeight())
			w-=16;
		return w;
	}
	else if (document.documentElement && document.documentElement.clientWidth)
		return document.documentElement.clientWidth;
	else if (document.body && document.body.clientWidth)
		return document.body.clientWidth;
	else if (document.body && document.body.parentNode && document.body.parentNode.clientWidth)
		return document.body.parentNode.clientWidth;

	return false;
}

function getWinHeight()
{
	if (window.innerHeight) return window.innerHeight;
	else if (document.documentElement && document.documentElement.clientHeight)
		return document.documentElement.clientHeight;
	else if (document.body && document.body.clientHeight)
		return document.body.clientHeight;
	else if (document.body && document.body.parentNode && document.body.parentNode.clientHeight)
		return document.body.parentNode.clientHeight;
	return false;
}

function ptShowHideShade(id, displayMode) // block or none
{
	el = document.getElementById(id);

	if (!el || el.style.display == displayMode)
		return;

	if (displayMode == 'block')
	{
		var biggestHeight = document.body.scrollHeight;
		if (getWinHeight() > biggestHeight)
			biggestHeight = getWinHeight();

		el.style.width=document.body.scrollWidth+'px';
		el.style.height=biggestHeight+'px';
	}

	el.style.display = displayMode;
}

function ptDisplayCenteredDiv(el,offsetTop)
{
	el.style.display = 'inline';
	winTop = getWinTop();
	if (offsetTop > 20)
		el.style.top = winTop + offsetTop + 'px';
	else
		el.style.top = winTop + 20 + 'px';
	el.style.left= (getWinWidth()/2 - el.offsetWidth/2)/2 +'px';
	el.style.visibility = 'visible';
}

function getWinLeft() {return typeof window.pageXOffset != 'undefined' ? window.pageXOffset:document.documentElement && document.documentElement.scrollLeft? document.documentElement.scrollLeft:document.body.scrollLeft? document.body.scrollLeft:0;}
function getWinTop() {return typeof window.pageYOffset != 'undefined' ? window.pageYOffset:document.documentElement && document.documentElement.scrollTop? document.documentElement.scrollTop: document.body.scrollTop?document.body.scrollTop:0;}
function getWinRight() {return getWinLeft()+getWinWidth();}
function getWinBottom() {return getWinTop()+getWinHeight();}

function ptNewWindow(url,name,w,h,scroll,additionalSettings)
{
  var left = (screen.width-w)/2;
  var top = (screen.height-h)/2;
  var settings  ='height='+h+',';
      settings +='width='+w+',';
      settings +='top='+top+',';
      settings +='left='+left+',';
      settings +='resizable,scrollbars,';
  win = window.open(url,name,settings+additionalSettings);
  win.focus();
}


Array.prototype.unique = function () {
	var r = new Array();
	o:for(var i = 0, n = this.length; i < n; i++)
	{
		for(var x = 0, y = r.length; x < y; x++)
		{
			if(r[x]==this[i])
			{
				continue o;
			}
		}
		r[r.length] = this[i];
	}
	return r;
}

// Chrome (and technically Safari) do not have object.toSource()
// so it has been replaced by a local function
function ptStringify(o)
{
        return JSON.stringify(o);       
}

function ptClearCache()
{
        var _cache = {};
//        GM_setValue('cache', _cache.toSource());
        ptShowCache();
        GM_setValue('cache', '');
        ptCache = _cache;
        alert("The Power Twitter Link Cache has been cleared.");
}

function ptShowCache()
{
        var _counter = 0;
        GM_log('==== Cached URLs are shown below: ====');
        for (key in ptCache) {
            GM_log(key + ' --> ' + ptCache[key]);
            _counter++;
        }
//        GM_log(document.getElementById('ptIncomingCache').value);
//        GM_log('saved value is '+ GM_getValue('cache'));
        GM_log('====  These ' + _counter + ' URLs are cached. ====');
}

function ptTransferCache()
{
        // look for incoming cache and then merge and save
        GM_log('transferring cache...');
        var ptIncomingCache = {};
        ptIncomingStrings = document.getElementById("ptIncomingCache").value.split('|||');
//        GM_log(ptIncomingStrings);
        for(i=0;i<ptIncomingStrings.length;i++)
        {
                if(ptIncomingStrings[i].length > 10)
                {
                        ptJsonObj = eval( "(" + ptIncomingStrings[i] + ")" );
                        if(ptJsonObj.url !== undefined)
                        {
//                                GM_log(ptJsonObj.url);
                                ptIncomingCache[ptJsonObj.url] = ptIncomingStrings[i];
                        }
                }
        }
        for (key in ptIncomingCache)
        {
                if(ptCache)
                {
                        ptCache[key] = ptIncomingCache[key];
//                        GM_log('adding '+key);
                }
                else
                {
                        ptCache = {};
                        ptCache[key] = ptIncomingCache[key];
//                        GM_log('adding first '+key);
                }
        }
	if(ptCache)
        {
//                GM_log('saving cache in browser');
//                GM_log('string ' + ptStringify(ptCache));
                GM_setValue('cache', ptStringify(ptCache));
//              GM_setValue('cache', ptCache.toSource());
        }

//        ptShowCache();

}

function ptInitCache()
{
        var _cache = GM_getValue('cache');
        if ((typeof _cache == 'undefined')||(_cache == ''))
        {
//                GM_log('cache was undefined');
                _cache = {};
        }
        else
        {
//                GM_log('cache ' + _cache);
//                _cache = eval(_cache);
                _cache = JSON.parse(_cache);
         
                var _counter = 0;
                for (c in _cache) _counter++;
         
                var maxlength = ptMaxCacheCount;
                if(document.getElementById('ptMaxCacheCount'))
                        maxlength = document.getElementById('ptMaxCacheCount').value;
                        
//                GM_log('max cache count is '+maxlength);

                var oversize =  _counter - maxlength;
                if (oversize > 0)
                {
                        var __cache = {};
                        for (key in _cache)
                                if (oversize > 0)
                                        oversize--;
                                else
                                        __cache[key] = _cache[key];
                        _cache = __cache;
                }
        }
        return _cache;
}

// end
// ---------------------------------------------------------------------


// ---------------------------------------------------------------------
// ChangeLog
// 2007-03-14 - 0.1 - first release
// 2007-03-16 - 0.2
// 2008-11-13 - 0.9 - submitting Power Twitter to Mozilla repository
// 2008-12-13 - 1.0 - full upgrade and update (added search and peek)
// 2009-01-05 - 1.01 - fix & posting bug
// 2009-01-14 - 1.02 - fix escaped character bug that truncated and didn't allow international characters
// 2009-02-03 - 1.03 - twitter.com update broke some features, emergency update
// 2009-02-22 - 1.1 - major update including settings, photo posting, link shortening, multi threaded
// 2009-03-01 - 1.12 - minor tweaks to fix bugs
// 2009-03-12 - 1.13/4 - dropped kill switch for speed, upgraded for new facebook page, showing media on new twitter search, fixed in_reply_to
// 2009-03-18 - 1.15/6 - restored ajax updating, replaced some GM xhttp in favor of script appends.  Updated for new twitter pagination
// 2009-03-23 - 1.17 - more fixes for twitter and facebook updates
// 2009-03-28 - 1.18 - refactoring for speed, facebook profile pics added
// 2009-04-02 - 1.19 - updating for the next version of twitter, removed @mentions
// 2009-04-26 - 1.20/1 - bug fixes, Interesting tab, backend improvements for speed
// 2009-05-01 - 1.22 - updates to the profile page
// 2009-06-25 - 1.30 - major update, https support, top friends, fixed some search box bugs, added yfrog, question of the day, open links in new windows, settings
// 2009-07-01 - 1.31 - minor bug fixes
// 2009-07-02 - 1.32 - fixed bugs with link updating after searching
// 2009-07-28 - 1.33 - the universal multi browser edition. pushed ptCbX functions to server, allows sync of Top Friends, fixed several bugs
// 2009-09-21 - 1.34 - lots of bug fixes
// 2009-10-08 - 1.35 - critical bug fix
// 2009-10-15 - 1.36 - added local cache, additional bug fixes
// 2009-11-01 - 1.37 - emergency bug fixes
// 2010-08-20 - 1.40 - FIRST CHROME RELEASE streamlining and oauth, removed Facebook, Interesting, Top Friends