There are 6 previous versions of this script.
Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)
/*
Geocaching VIP List
http://www.lildevil.org/greasemonkey/vip-list
--------------------------------------------------------------------------------
This is a Greasemonkey user script.
Follow the instructions on http://www.lildevil.org/greasemonkey/
to install Greasemonkey and this user script.
--------------------------------------------------------------------------------
*/
// ==UserScript==
// @name GC VIP List
// @description Add links to VIP logs. Show only the logs you want to see.
// @namespace http://www.lildevil.org/greasemonkey/
// @version 3.3
// @copyright 2008-2011 Lil Devil
// @license Attribution-Noncommercial-Share Alike; http://creativecommons.org/licenses/by-nc-sa/3.0/
// @icon http://www.lildevil.org/greasemonkey/images/VIP-icon.png
// @include http://*.geocaching.com/seek/cache_details.aspx?*
// @include http://*.geocaching.com/my/myfriends.aspx*
// @include http://*.geocaching.com/profile*
// @include http://*.geocaching.com/account/default.aspx
// @include http://*.geocaching.com/account/ManageFriends.aspx
// @include http://*.geocaching.com/seek/cache_favorited.aspx*
// @include http://*.geocaching.com/my/favorites.aspx
// ==/UserScript==
// the following is for http://www.jslint.com/
/*jslint browser: true, undef: true, nomen: true, bitwise: true, immed: false */
/*global $ GM_addStyle GM_getValue GM_log GM_openInTab GM_setValue GM_xmlhttpRequest XPathResult window Check_for_Update Main Refresh_VIP_Display Reload_Cache_Page_With_All_Logs Toggle_Cache_Logs_Table */
(function(){
var SCRIPT_NAME = 'GC VIP List';
var SCRIPT_VERSION = '3.3';
var Page_URL = document.location.toString();
try {
if (window != window.top) { return; } // abort if running in an iframe
} catch(err) { return; } // Greasemonkey throws a security error when accessing window.top from an iframe
// Do this before anything else to reduce overhead
if (GM_getValue('Always_Load_All_Logs', false)) {
// If this is the cache page, reload to show all logs
if (Page_URL.match(/geocaching\.com\/seek\/cache_details\.aspx/i)) { // Cache page
if (Reload_Cache_Page_With_All_Logs()) { return; }
}
}
Check_for_Update(SCRIPT_NAME, SCRIPT_VERSION);
var SCRIPT_START_TIME = new Date();
var MAX_SCRIPT_TIME = 17; // set MAX_SCRIPT_TIME to 3 seconds less than
// about:config:dom.max_chrome_script_run_time (default: 20)
MAX_SCRIPT_TIME *= 1000; // convert to milliseconds
var DEBUG = false; // set to 'true' to enable debugging output to the console
var USE_STORAGE = false;
try {
USE_STORAGE = (typeof(window.localStorage) != 'undefined');
} catch (err) {}
var VIP_Working_List = [];
var VIP_Displayed_List = [];
var Add_List = [];
var Log_List = [];
var Multi_Log_Owners = [];
var First_Logs = [];
var NextRowClass = '';
var My_Logs = { findStatus : -1,
findLogID : '' };
var Cache_Owner = '';
var Count_Logs_Aborted = false;
var All_Logs_Shown = false;
var More_Logs_URL = '';
var Timeout_Timer = 0;
var Page_Name, Login_Name = '', Login_Name_Link;
var Displayed_Prefs = {};
var Working_Prefs = {};
var Default_Prefs = { ShowBadges: true,
ShowHelp: true,
ShowVIPs: true,
ShowMine: true,
ShowMineAlways: true,
ShowOwner: true,
ShowOwnerAlways: false,
ShowMulti: false,
ShowMultiAlways: false,
ShowImages: true,
ShowImagesAlways: false,
AlwaysLoadAllLogs: false,
Position: 1,
DateTab: false,
DateFormatList: 'm/dY{/yy}Y',
DateFormatLogs: 'MM dY{, yyyy}Y',
DateFormatHide: 'RR, MM dY{, yyyy}Y'
};
String.prototype.trim = function() {
if (!this.length) { return ''; }
// remove leading and trailing spaces
var s = this.replace(/^(\s|\ |\xA0)+/i, '');
return s.replace(/(\s|\ |\xA0)+$/i, '');
};
String.prototype.parseHTMLentities = function() {
var d = document.createElement('div');
d.innerHTML = this;
return d.textContent;
};
String.prototype.repeat = function(len) {
var s = '', i = 0;
while (i++ < len) {
s += this;
}
return s;
};
String.prototype.zeroPad = function(len) {
return '0'.repeat(len - this.length) + this;
};
Number.prototype.zeroPad = function(len) {
return this.toString().zeroPad(len);
};
String.prototype.quotemeta = function() {
return (this+'').replace(/([\$\(\)\*\+\-\.\/\?\[\\\]\^\{\|\}])/g, '\\$1');
};
var Month_Names = ['January','February','March','April','May','June',
'July','August','September','October','November','December'];
var Day_Names = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
Date.prototype.format = function(f) {
// adapted from http://www.codeproject.com/KB/scripting/dateformat.aspx
if (!this.valueOf() || !f) { return ' '; }
var d = this;
// y{...}y include stuff between brackets only if current year
// Y{...}Y include stuff between brackets only if not current year
if (d.getFullYear() == SCRIPT_START_TIME.getFullYear()) {
f = f.replace(/y\{(.*?)\}y/g, '$1');
f = f.replace(/Y\{(.*?)\}Y/g, '');
} else {
f = f.replace(/y\{(.*?)\}y/g, '');
f = f.replace(/Y\{(.*?)\}Y/g, '$1');
}
// w{...}w include stuff between brackets only if within the last week (less than 7 days ago)
// W{...}W include stuff between brackets only if not within the last week
var oneDay = 1000*60*60*24;
var RR = Day_Names[d.getDay()];
var R = RR.substr(0, 3);
var delta = Math.ceil((d.getTime() - SCRIPT_START_TIME.getTime()) / oneDay);
if (Math.abs(delta) < 7) {
if (delta < -1) {
RR = 'Last ' + RR;
R = 'Last ' + R;
} else if (delta == -1) {
RR = R = 'Yesterday';
} else if (delta === 0) {
RR = R = 'Today';
} else if (delta == 1) {
RR = R = 'Tomorrow';
} else {
RR = 'Next ' + RR;
R = 'Next ' + R;
}
f = f.replace(/w\{(.*?)\}w/g, '$1');
f = f.replace(/W\{(.*?)\}W/g, '');
} else {
f = f.replace(/w\{(.*?)\}w/g, '');
f = f.replace(/W\{(.*?)\}W/g, '$1');
}
// https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/String/Replace#Specifying_a_function_as_a_parameter
return f.replace(/(yyyy|yy|y|MM|M|mm|m|DD|D|RR|R|dd|d|s)/g,
function (str, m1) {
switch (m1) {
case 'yyyy' : return d.getFullYear();
case 'yy' : return d.getFullYear().toString().substr(2);
case 'y' : return d.getFullYear().toString().substr(2) - 0;
case 'MM' : return Month_Names[d.getMonth()];
case 'M' : return Month_Names[d.getMonth()].substr(0, 3);
case 'mm' : return (d.getMonth() + 1).zeroPad(2);
case 'm' : return (d.getMonth() + 1);
case 'DD' : return Day_Names[d.getDay()];
case 'D' : return Day_Names[d.getDay()].substr(0, 3);
case 'RR' : return RR;
case 'R' : return R;
case 'dd' : return d.getDate().zeroPad(2);
case 'd' : return d.getDate();
case 's' : return '<sup>' +(d.getDate() % 10 == 1 && d.getDate() !== 11 ? 'st' :
(d.getDate() % 10 == 2 && d.getDate() !== 12 ? 'nd' :
(d.getDate() % 10 == 3 && d.getDate() !== 13 ? 'rd' : 'th'))) +
'</sup>';
}
}
);
};
Array.prototype.duplicates = function() {
this.sort();
var dups = [], i, len = this.length - 1;
for (i=0; i<len; i++ ) {
if (this[i] == this[i+1]) {
if (dups.indexOf(this[i]) == -1) {
dups.push(this[i]);
}
}
}
return dups;
};
// Log types and image icons to be counted.
var Img_Files = [];
var Img_Desc = [];
Img_Desc[ 0] = 'Attended'; Img_Files[ 0] = 'icon_attended.gif';
Img_Desc[ 1] = 'Webcam Photo Taken'; Img_Files[ 1] = 'icon_camera.gif';
Img_Desc[ 2] = 'Found'; Img_Files[ 2] = 'icon_smile.gif';
Img_Desc[ 3] = 'Did Not Find'; Img_Files[ 3] = 'icon_sad.gif';
Img_Desc[ 4] = 'Will Attend'; Img_Files[ 4] = 'icon_rsvp.gif';
Img_Desc[ 5] = 'Note'; Img_Files[ 5] = 'icon_note.gif';
Img_Desc[ 6] = 'Review Note'; Img_Files[ 6] = 'big_smile.gif';
Img_Desc[ 7] = 'Retracted'; Img_Files[ 7] = 'icon_redlight.gif';
Img_Desc[ 8] = 'Published'; Img_Files[ 8] = 'icon_greenlight.gif';
Img_Desc[ 9] = 'Disabled'; Img_Files[ 9] = 'icon_disabled.gif';
Img_Desc[10] = 'Enabled'; Img_Files[10] = 'icon_enabled.gif';
Img_Desc[11] = 'Performed Maintenance'; Img_Files[11] = 'icon_maint.gif';
Img_Desc[12] = 'Needs Maintenance'; Img_Files[12] = 'icon_needsmaint.gif';
Img_Desc[13] = 'Needs Archived'; Img_Files[13] = 'icon_remove.gif';
Img_Desc[14] = 'Archived/Unarchived'; Img_Files[14] = 'traffic_cone.gif';
Img_Desc[15] = 'Update Coordinates'; Img_Files[15] = 'coord_update.gif';
Img_Desc[16] = 'Announcement'; Img_Files[16] = 'icon_announcement.gif';
var Icon = {};
Icon.Warning = 'data:image/gif;base64,' +
'R0lGODlhEAAQAOMPAAgFN0k7RGleI2VigIJ8LqeVLcmoB9/GCeTRNf3WAergB//mBP7zDPb1Lf/+Cf8A' +
'ACH5BAEAAA8ALAAAAAAQABAAAARn8Mn5Gr23OYW70kRHIYyziZOiCIYTiogLBKeoOMVsvhdyH4CC6dA5' +
'LBaKgIHBWPAmieNCYFwwiJRq1KBIJJo8RNR7IBgWUYZhcvBGCTP0OIRouw2BgttbkBj+gIGAAgMTA4eI' +
'iYcPEQA7';
Icon.GrayVIP = 'data:image/gif;base64,' + // not on list
'R0lGODlhDwAKAOMKADw8PJeXl7q6usDAwMbGxszMzNLS0tjY2N7e3uTk5P//////////////////////' +
'/yH5BAEKAA8ALAAAAAAPAAoAAAQ+8IVJK5Up660nAkgIjiAyHcChpix6TIYByPFsG1NRALvOA7zChEAE' +
'EAlGI3EyaAKag+ezORFYr9hrQGLpbiMAOw==';
Icon.GreenVIP = 'data:image/gif;base64,' + // VIP
'R0lGODlhDwAKAOMKAABmAGbMAJnjOqHnRKrrTrLvWLvzYsP3bMz7dtT/f9X/gNX/gNX/gNX/gNX/gNX/' +
'gCH5BAEKAA8ALAAAAAAPAAoAAAQ+8IVJK5Up660nAkgIjiAyHcChpix6TIYByPFsG1NRALvOA7zChEAE' +
'EAlGI3EyaAKag+ezORFYr9hrQGLpbiMAOw==';
Icon.BlueVIP = 'data:image/gif;base64,' + // cache owner
'R0lGODlhDwAKAOMMAAAyZheK/1Wp/1eq/1+u/2Wx/2u0/3W5/4C+/ovE/5XJ/53N////////////////' +
'/yH5BAEKAA8ALAAAAAAPAAoAAAQ/8IVJK5Ur662nAkoIjqAyJUCipmyRTggCyPEMDPN0HAC/94DeYWIo' +
'AoqG47E4ITgBTgIU6pwIrtgsNiCxeLkRADs=';
Icon.RedVIP = 'data:image/gif;base64,' + // logged-in user
'R0lGODlhDwAKAOMKAIAAAP8AAP9jY/90dP+Fhf+Wlv+np/+4uP/Jyf/b2//y8v/y8v/y8v/y8v/y8v/y' +
'8iH5BAEKAA8ALAAAAAAPAAoAAAQ+8IVJK5Up660nAkgIjiAyHcChpix6TIYByPFsG1NRALvOA7zChEAE' +
'EAlGI3EyaAKag+ezORFYr9hrQGLpbiMAOw==';
Icon.RedDot = 'data:image/gif;base64,' +
'R0lGODdhAQABAIABAP8AAP///ywAAAAAAQABAAACAkQBADs=';
Icon.Pencil = 'data:image/gif;base64,' +
'R0lGODlhDgALAKU6AFU9EYdfKIFkLaRiI756GqqJQ7eISb2IScmFQbyNQseMSMWYSdSRRtKWUdiVR9Cd' +
'Rt+ZQNKbXdiaVNOfZtejY9ilWNW2etuxhdO4dtG3kOe+d+TJVefAi+fLd+3Kbe3QePnHlOvTfu7TefnJ' +
'kfDTee7UffHUe/LWevXcXvXcX+/SrPXfW/DStPbdbPffY/fhWvbTrvfiW/jiXfnjsvzgxP32wv32xP33' +
'x//y4P/z5f///////////////////////yH5BAEKAD8ALAAAAAAOAAsAAAZKwJ9wKKxcHsTkT8PKqRRK' +
'YWjGgdEm0ZKt5aFEoqJbKnaCRDs31MvEiGJqLhnJEbVkNqtPI1rASQgLBlE/AiAjCAODPwABBwmKP0EA' +
'Ow==';
Icon.Wrench = 'data:image/gif;base64,' +
'R0lGODlhDQALAKU3AEN50Ul90U1/01GD1VOD1YSEhIWFhYiIiGKN1YmJiY2NjWeT246Ojo+Pj5GRkZKS' +
'kpSUlJaWlnSb3HWd3ZmZmZubm5ycnHuh33yh3Xyh3p2dnaCgoJWlvIep4Kampo2r3ZGw46OvxLKyspy4' +
'5rW1taO+6bu7u6W/6anB6sDAwK3E67DH67DH7LLI7MbGxrXK7cnJycvLy9LS0tXV1dbW1uHh4ebm5v//' +
'/////////////////////////////////yH5BAEKAD8ALAAAAAANAAsAAAZHwJ9wqKlQhkihpSaLJJEk' +
'G+TRUDx/IpqDkUo8ITEZTOYyJD+hmcmzKSQ7KwzncL2wXiXEdaJqoTIEVwsjJxICV0IDAQCIP0EAOw==';
Icon.CollapseGray = 'data:image/gif;base64,' +
'R0lGODlhDAAMAOMMAIqvwoywwo6xxJG0xZO1xpa3x5i4yJq6yZ27y5+9zKG+zaTAzqXBz6XBz6XBz6XB' +
'zyH5BAEAAA8ALAAAAAAMAAwAAAQt8IFJ6wsv6x3E/o8wgNtAkBpRPEXrtqzxGHRNzweaHYj+IAlfQuEj' +
'Lo7I5CMCADs=';
Icon.CollapseHover = 'data:image/gif;base64,' +
'R0lGODlhDAAMAIQUAEt6qWCPvXWgy4au14mw2I2z2Y+02pO325S425a53Jm73Zu83p6+36LB4KbD4anG' +
'4q3J5LHL5b7U6f///6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBzyH5BAEAAB8ALAAA' +
'AAAMAAwAAAVB4BeMZClKaJoiQCBF0NMsyWEI7RvP9Z3DMpoN55oYj0aiBIlUOhoMxaFAGDihUqo194xO' +
'q0SGYEwmAz6AtHr9CQEAOw==';
Icon.ExpandGray = 'data:image/gif;base64,' +
'R0lGODlhDAAMAOMMAIqvwoywwo6xxJG0xZO1xpa3x5i4yJq6yZ27y5+9zKG+zaTAzqXBz6XBz6XBz6XB' +
'zyH5BAEAAA8ALAAAAAAMAAwAAAQ58IFJ6wsv6x3EFp4mDNtAagOxEapGFE8hz3JsPEau5/ixHT7NAbFB' +
'EDWIxCah1CQUm+gDuqhar48IADs=';
Icon.ExpandHover = 'data:image/gif;base64,' +
'R0lGODlhDAAMAIQSAEt6qWCPvXWgy4au14mw2I2z2Y+02pO325S425a53J6+36LB4KbD4anG4q3J5LHL' +
'5b7U6f///6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBz6XBzyH5BAEAAB8ALAAA' +
'AAAMAAwAAAU+4BeMZClCaJoiQAA9ThNFyWEI7RvP9Z3DMpoN55oZjUTI8ZhkLBSzAmHQfEanVWhESm0p' +
'BOBwGPABmM/oTwgAOw==';
Icon.Help = 'data:image/png;base64,' +
'iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAABmJLR0QA/wD/AP+gvaeTAAACrUlEQVR4' +
'2q2TS2hUdxTGf/dmJhESnJhEM8lI0/howAhGsPjAx8YiUmjBoKCNj+LKhQtB14JIKaWbIi50Ib4QUUZw' +
'o4JSrWJailWDMT6qRqPm4WgmJnPvnXvv/39OF26USRSKZ3vO+fEdzvc5qsrnqMREjeuPopmiukFEN4lq' +
'WkSwooMictSKnvi2LfX4/XlnPEVXHgTtIrqvqTbR4KjFWguA67pEFnpe+ANWZPu6xdOyE4Iu3fXarciR' +
'lnSy8m0h4N5zj743HlaUaalyWjOTqameROf9Ec9a2bx15RfZEtC5rtEZInJtTqaicSjvc7E7R0Mqyer5' +
'jSjKjUd5/ukdZkVLHZm6Si51veq3Vpbt+P6rJ+77aoph1NE8Ndk4MhZy4fYQfiHkh2VN1FSVU1tVwaq2' +
'esod5Y+eIYbHQuY3pxq9IOwA+ADkF+ONSVfp6h0hKEbEYhkei7h8Z5C//83hAMtb6xgpeNzsfU11VQIv' +
'iDaOA4oyDsrT3CjGWiIT8XP2Nq4jzPtyCqN+TN+rAtYITwfyJFyXQhBmSt7vByGqYBQiE6KiqMLSOWny' +
'hZBfT9+iGBkUMI6gjuIFUamPvCB6GVk7K1M9idExHxGDiLDz4HUAbGxABUVpSNcShDF+EL4sOa0QhMf6' +
'cx5tzVNIOu8W1Qo//biIvVsWYsRgVHDU8nVLPQ+f5fGL0bESkBdEx8929vYnXFi9YDrJhIMxMScv3+fU' +
'lQfvTCkxqxbOJlnmcvjC3X6/GB8f15Bbfvm93Ygc2fbd3MrYCp3dL+gbzCNGyNSnWNKaIZEoY8/hvzwr' +
'svnqb+uyE0Zkze5z7VZk39oVsxpammqoKC8DICgauh/nOHS+e0BEt/+5f332o1kD+GbXmZlWdIOIbLJW' +
'0iKKFRkU1aMieuLGgY5Ph/b/1H9M6pYknjzwKwAAAABJRU5ErkJggg==';
Icon.Logbook = 'data:image/gif;base64,R0lGODlhEAAQAKIGABobAAgICPr7odfZAPH0AAAAAP///wA' +
'AACH5BAEAAAYALAAAAAAQABAAAANJaBpa/cqUSWtto4y8NXfSQIxkmWHjlAEicYappo6vRm44DdqEOru' +
'7lo9Xa5VMweOxmBJMnDoUQUCtRmG9gnNy9eC+uJ1lPDEkAAA7';
Icon.GroupEdit = 'http://www.geocaching.com/images/silk/group_edit.png';
Icon.Single = 'http://www.geocaching.com/images/silk/user.png';
Icon.Group = 'http://www.geocaching.com/images/silk/group.png';
var Tooltip = {ShowBadges: 'This option controls whether the VIP badges are shown on each cache log.',
ShowVIPs: 'Include logs by cachers on your VIP List in the Logs display.',
ShowMine: 'Highlight your own logs in red.',
ShowMineAlways: 'Always include your own logs in the VIP Logs display, even if you are not on the VIP List.',
ShowOwner: 'Highlight the cache owner’s logs in green.',
ShowOwnerAlways:'Always include the cache owner’s logs in the VIP Logs display, even if the cache owner is not on the VIP List.',
ShowMulti: 'Highlight multiple “found” logs by the same person in bold.',
ShowMultiAlways:'Always include multiple logs in the VIP Logs display, even if the logger is not on the VIP List.',
ShowImages: 'Indicate which VIP logs have images with them.',
ShowImagesAlways:'Always include logs with images in the VIP Logs display, even if the logger is not on the VIP List.',
AlwaysLoadAllLogs:'Always re-load the page to show all logs. Also re-writes links on other pages to load cache pages with all logs.',
ShowHelp: 'If there are no VIP logs, show some brief instructions on how to add cachers to the VIP list. ' +
'These instructions automatically disappear if there are any VIP logs.',
Position: 'Use this menu to choose where the VIP List will appear.',
Legend: '<center><b>VIP Legend</b></center>' +
'<span class="VIP_log">VIP logs</span><br/>' +
'<span class="logged_in_user">Your logs</span><br/>' +
'<span class="cache_owner_log">Cache owner’s logs</span><br/>' +
'<span class="ordinary_log">Other logs</span><br/>' +
'<span class="multiple_logs">Multiple “found” logs</span>',
DateFormatList: 'Specify the format for dates in the logs display.',
DateFormatLogs: 'Specify the date format on the actual cache logs.',
DateFormatHide: 'Specify the date format for the cache’s hide date.',
DateFormatHelp: '<table cellspacing="1" cellpadding="1">' +
'<tr><th>Token</th><th>Description</th><th>Example</th></tr>' +
'<tr><td>d</td><td>Day of month.</td><td>1-31</td></tr>' +
'<tr><td>dd</td><td>Day of month with leading zero.</td><td>01-31</td></tr>' +
'<tr><td>s</td><td>The date’s ordinal suffix.</td><td>st, nd, rd, th</td></tr>' +
'<tr><td>DD</td><td>Day name.</td><td>Sunday, Monday</td></tr>' +
'<tr><td>D</td><td>Abbreviated day name.</td><td>Sun, Mon</td></tr>' +
'<tr><td>RR</td><td>Relative day name.</td><td>Last Tuesday,<br/>Yesterday,<br/>Today</td></tr>' +
'<tr><td>R</td><td>Abbreviated relative day name.</td><td>Last Tue</td></tr>' +
'<tr><td>m</td><td>Month number.</td><td>1-12</td></tr>' +
'<tr><td>mm</td><td>Month number with leading zero.</td><td>01-12</td></tr>' +
'<tr><td>MM</td><td>Month name.</td><td>January, February</td></tr>' +
'<tr><td>M</td><td>Abbreviated month name.</td><td>Jan, Feb</td></tr>' +
'<tr><td>yy</td><td>Two digit year.</td><td>00-99</td></tr>' +
'<tr><td>yyyy</td><td>Four digit year.</td><td>1999-2010</td></tr>' +
'<tr><td colspan=3><br/><b>Meta-tokens</b> - These special codes will include any<br/>tokens between their brackets <u>only</u> if …</td></tr>' +
'<tr><td>w{…}w</td><td colspan=2>… the date is within a week of today’s date.</td></tr>' +
'<tr><td>W{…}W</td><td colspan=2>… the date is <u>not</u> within a week of today’s date.</td></tr>' +
'<tr><td>y{…}y</td><td colspan=2>… the date is in the current calendar year.</td></tr>' +
'<tr><td>Y{…}Y</td><td colspan=2>… the date is <u>not</u> in the current calendar year.</td></tr>' +
'<tr><td colspan=3><br/><b>Examples</b><br/>' +
'M dY{, yy}Y - "Aug 10" if in current year, or "Aug 10, 08" if previous year<br/>' +
'RR, MM dsY{, yyyy}Y - "Friday, May 25th, 2007" or "Yesterday, April 1st"<br/>' +
'm/d/yy - short U.S. date format<br/>' +
'd/m/yy - short euro date format' +
'</td></tr></table>',
DateFormatSample:'This is an example of what a date will look like using the above format.',
ThisCacheFound: 'You %s this %s. Click to scroll to your log.',
ThisCacheIsMine:'',
ClickToAdd: 'Click to add %s to the VIP list.',
ClickToRemove: 'Click to remove %s from the VIP list.',
AddedToList: ' added to the VIP list.',
RemovedFromList:' removed from the VIP list.',
EditListLink: 'Click to edit the VIP list.',
OptionsLink: 'Click to change the VIP list options.',
AddLink: 'Click to add a username to the VIP list.',
AddName: 'Enter a username to add to the VIP list.',
AlreadyOnList: ' is already on the VIP list.',
AlreadyAdded: ' has already been added to the VIP list.',
ClickLogType: 'Click an icon above to scroll to the first log of that type.',
HeaderIcon: 'Click to scroll to the first VIP log.',
ClickToScroll: 'Click to scroll to this “%s” log.',
PictureFrame: 'Click to show the %s image%s for this log.',
HowToAdd: 'Add geocachers to the VIP list by clicking on the ' +
'<span style="white-space:nowrap">' +
'<img src="' + Icon.GrayVIP + '" title="VIP" /> ' +
'icon</span> next to their logs.'
};
Main();
// ---------------------------------- Functions ---------------------------------- //
function LD_removeStyle(theID) {
var styleSheet = document.getElementById(theID);
if (styleSheet) {
styleSheet.parentNode.removeChild(styleSheet);
}
}
function LD_addStyle(css, theID) {
var head = document.getElementsByTagName('head');
if (!head) { return; }
var styleSheet = document.createElement('style');
styleSheet.type = 'text/css';
try {
styleSheet.innerHTML = css;
} catch(err) {
styleSheet.innerText = css;
}
if (theID) {
LD_removeStyle(theID); // no duplicate IDs
styleSheet.id = theID;
styleSheet.title = theID;
}
head[0].appendChild(styleSheet);
}
function LD_disableStyle(theID, mode) { // true=disable, false=enable
if (typeof(mode) != 'boolean') { mode = true; }
var matchType = typeof(theID);
for (var i=document.styleSheets.length-1; i>=0; i--) {
if ( document.styleSheets[i].title &&
((matchType == 'string') && (theID == document.styleSheets[i].title)) ||
((matchType == 'object') && theID.test(document.styleSheets[i].title)) ) {
document.styleSheets[i].disabled = mode;
}
}
}
function LD_enableStyle(theID) {
LD_disableStyle(theID, false);
}
function Add_Styles() {
// use !important to force override of other styles
GM_addStyle('#VIP_table { z-index:85; position:relative; }' +
'#VIP_table li { text-indent:-20px; padding-left:20px; }' +
'#VIP_table li.subordinate { padding-left:40px; }');
GM_addStyle('.VIP_warning_row { background:#FFFE09 !important; }' +
'.WidgetBody img { vertical-align:middle; }' +
'.CacheDetailNavigationWidget .WidgetBody { padding:0.5em !important; }' +
'#VIP_options { margin-right:0.5em !important; }' +
'#VIP_original_DateHidden { display:none; }');
GM_addStyle('#VIP_white { background-color:white;' +
' left:0; top:0; position:absolute;' +
' width:2000px; height:2000px; z-index:82; }' +
'#VIP_black { background-color:black; opacity:0.75;' +
' left:0; top:0; position:absolute;' +
' width:2000px; height:2000px; z-index:80; }');
// styles for the tabs in the options dialog - pure CSS!
// http://code.google.com/p/css-trees-and-tabs/
GM_addStyle('#VIP_options > input[type="radio"] { display:none; }' +
'#VIP_options > input[type="radio"] + label {' +
' background-color:#EDF1F8; border:1px solid #C0CEE3;' +
' -moz-border-radius-topleft:5px;' +
' -moz-border-radius-topright:5px;' +
' font-weight:bold; font-size:smaller;' +
' margin:0 0.5em 0 0.5em; padding:0.1em 0.7em 3px 0.7em; }' +
'#VIP_options > input[type="radio"]:checked + label {' +
' margin:0 0.3em 0 0.3em; padding:0.3em 0.9em 3px 0.9em;' +
' background-color:white; border-bottom-color:white; }' +
'#VIP_options > input[type="radio"]:not(:checked) + label:hover {' +
' cursor:pointer; background-color:#C0CEE3; }' +
'#VIP_options > input[type="radio"]:checked + label + .VIP_tab' +
' { display:block; }' +
'#VIP_options > .VIP_tab { display:none; float:left; width:100%;' +
' margin-top:3px; margin-bottom:0.3em;' +
' padding:2px; border:1px solid #C0CEE3; }');
// other styles for the options dialog
GM_addStyle('#VIP_options input[type="checkbox"]:disabled + label { color:lightgray; }' +
'#VIP_options select { font-size:90%; }' +
'#VIP_options input[type="text"] { font-size:90%; width:97%; }' +
'#VIP_options label { font-weight:normal; }' +
'#VIP_table button { font-family:Verdana,Tahoma,Arial,sans-serif; font-size:80%; }' +
'#VIP_date_options li { text-indent:0; padding-left:0; }');
// styles for javascript <img> and <span> links
GM_addStyle('img.link { cursor:pointer; }' +
'span.link { cursor:pointer; color:#003399; font-size:90%;' +
' padding-right:1px; white-space:nowrap; background-color:inherit; }' +
'span.link:hover { color:#FF6600; text-decoration:underline; }' +
'span.link > img { vertical-align:text-bottom; background-color:inherit; }');
// styles for javascript links on the Friends page
GM_addStyle('#VIP_add_all_friends { cursor:pointer; white-space:nowrap; margin-right:1em;' +
' font-size:x-small; font-weight:normal;' +
' color:#003399; text-decoration:underline; }' +
'#VIP_add_all_friends:hover { color:#FF6600; text-decoration:none; }' +
'#VIP_add_all_friends > img { background-color:white; }');
// styles for editing the VIP list
GM_addStyle('.VIP_disabled_text { cursor:pointer; color:red;' +
' background-color:transparent;' +
' background-image:url(' + Icon.RedDot + ');' +
' background-repeat:repeat-x;' +
' background-position:left 60%; }' +
'.VIP_disabled_text:hover { text-decoration:underline; }' +
'.VIP_enabled_text { cursor:pointer; }' +
'.VIP_enabled_text:hover { text-decoration:underline; }');
// VIP list styles for each reason a log is on the list
GM_addStyle('.ordinary_log { color:#777777 !important; }' +
'.VIP_log { color:#003399 !important; }' +
'.logged_in_user { color:maroon !important; }' +
'.cache_owner_log { color:darkgreen !important; }' +
'.multiple_logs { font-weight:bold !important; }');
// styles for the hide/show cache log buttons
GM_addStyle('#VIP_collapse_cache_logs, #VIP_expand_cache_logs ' +
'{ width:12px; height:12px; margin:4px 3px 0 0; float:right; cursor:pointer; }' +
'#VIP_collapse_cache_logs { background-image:url(' + Icon.CollapseGray + '); }' +
'#VIP_collapse_cache_logs:hover { background-image:url(' + Icon.CollapseHover + '); }' +
'#VIP_expand_cache_logs { background-image:url(' + Icon.ExpandGray + '); }' +
'#VIP_expand_cache_logs:hover { background-image:url(' + Icon.ExpandHover + '); }');
LD_addStyle('#VIP_cache_logs_table_body > tr { display:none; }', 'VIP_hide_all_logs');
LD_addStyle('#VIP_cache_logs_table_body > tr[isVIP] { display:table-row; }', 'VIP_show_VIP_logs');
LD_addStyle('#VIP_cache_logs_table_body > tr[multi] { display:table-row; }', 'VIP_show_multi_logs');
LD_addStyle('#VIP_cache_logs_table_body > tr[logimages] { display:table-row; }', 'VIP_show_pix_logs');
LD_disableStyle('VIP_hide_all_logs');
// add a bottom border to the cache logs rows so when some are hidden there will be a line
GM_addStyle('table.LogsTable td { border-bottom: 1px solid #D7D7D7; }');
// tooltip styles - adapted from http://psacake.com/web/jl.asp
GM_addStyle('#VIP_tooltip { position:relative; }' +
'#VIP_tooltip > span{ display:none; z-index:200; white-space:nowrap;' +
' line-height:normal; padding:2px 4px; text-align:left;' +
' font-weight:normal; font-size:smaller;' +
' background:lightyellow; color:black; border:thin solid black; }' +
'#VIP_tooltip:hover > span { display:block; position:absolute; right:16px; bottom:0; }' +
'#VIP_tooltip:hover > span#VIP_date_format_help { bottom:-120px; right:20px; }' +
'#VIP_tooltip:hover > span#VIP_date_format_help td { border-top:thin solid lightgrey; }');
}
function Debug_Log(str, funcName) {
if (DEBUG) {
if (!funcName) {
funcName = arguments.callee.caller.toString().match(/function\s+([^\s\(]+)/);
funcName = funcName ? funcName[1] : 'anonymous';
}
var now = new Date();
GM_log(now.toLocaleTimeString().slice(0, -3) + '.' + now.getMilliseconds().zeroPad(3) +
': ' + Page_Name +
': ' + funcName +
'(): ' + str);
}
}
function $() {
if (arguments.length==1) {
return document.getElementById(arguments[0]);
}
var elements = [];
for (var i = 0; i < arguments.length; i++) {
var e = arguments[i];
if (typeof e == 'string') {
e = document.getElementById(e);
}
elements.push(e);
}
return elements;
}
function newElement() {
if(arguments.length == 1) {
return document.createTextNode(arguments[0]);
} else {
var newNode = document.createElement(arguments[0]),
newProperties = arguments[1];
for (var prop in newProperties) {
if ((prop.indexOf('on') === 0) && (typeof(newProperties[prop]) == 'function')) {
newNode.addEventListener(prop.substring(2), newProperties[prop], false);
} else if (',innerHTML,textContent'.indexOf(','+prop) != -1) {
newNode[prop] = newProperties[prop];
} else if ((',checked,disabled,selected'.indexOf(','+prop) != -1) && !newProperties[prop]) {
// value is false, which browsers do not support, so don't set the property at all
} else if (/\&/.test(newProperties[prop])) {
newNode.setAttribute(prop, newProperties[prop].parseHTMLentities());
} else {
newNode.setAttribute(prop, newProperties[prop]);
}
}
for(var i=2, len=arguments.length; i<len; i++) {
newNode.appendChild(arguments[i]);
}
return newNode;
}
}
function firstElementChild(p) {
if (typeof(p.firstElementChild) != 'undefined') {
return p.firstElementChild;
} else {
var child = p.firstChild;
while (child && child.nodeType !== 1) {
child = child.nextSibling;
}
return child;
}
}
function nextElementSibling(p) {
if (typeof(p.nextElementSibling) != 'undefined') {
return p.nextElementSibling;
} else {
var sibling = p.nextSibling;
while (sibling && sibling.nodeType !== 1) {
sibling = sibling.nextSibling;
}
return sibling;
}
}
function previousElementSibling(p) {
if (typeof(p.previousElementSibling) != 'undefined') {
return p.previousElementSibling;
} else {
var sibling = p.previousSibling;
while (sibling && sibling.nodeType !== 1) {
sibling = sibling.previousSibling;
}
return sibling;
}
}
function xPath(expr, context, typ) {
var result = document.evaluate( (expr || '//body'),
(context || document),
null,
(typ || XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE),
null);
switch (typ) {
case XPathResult.NUMBER_TYPE: return result.numberValue;
case XPathResult.STRING_TYPE: return result.stringValue;
case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
case XPathResult.ANY_UNORDERED_NODE_TYPE:
case XPathResult.FIRST_ORDERED_NODE_TYPE: return result.singleNodeValue;
default: return result;
}
}
function Get_Offsets(obj) {
var top = 0, left = 0;
do {
top += obj.offsetTop;
left += obj.offsetLeft;
} while ((obj = obj.offsetParent));
return {top : top,
left : left };
}
// return a node's parent of a certain type. if not found, return null
function Get_Parent(thisNode) {
if (!thisNode || !thisNode.parentNode) { return thisNode; }
if (arguments.length < 2) { return thisNode.parentNode; }
for (var i=1; i < arguments.length; i++) {
var nodeNameToLookFor = arguments[i].toLowerCase();
do {
thisNode = thisNode.parentNode;
} while (thisNode && (thisNode.nodeName.toLowerCase() !== nodeNameToLookFor));
}
return thisNode;
}
function Get_URL_Parameter(fieldName, theUrl) {
var parts = (theUrl || document.location).toString().split(/[?#]/);
var queryString = parts[1];
var re = new RegExp('(^|&)' + fieldName + '=(.*?)(&|$)', 'i');
if (queryString.match(re)) {
return RegExp.$2;
}
return '';
}
function Reload_Cache_Page_With_All_Logs() {
var parts = document.location.toString().split(/[?#]/);
var queryString = parts[1];
// if already viewing all logs, don't do anything.
if (queryString.match(/(^|&)log=y(&|$)/i)) { return false; }
// Remove any existing log parms.
queryString = queryString.replace(/(^|&)log=.*?(?=&|$)/ig, '');
queryString = queryString.replace(/^&+/, '');
// Add all-logs parm to URL and reload page.
document.location.replace(parts[0] + '?' + queryString + '&log=y' + (parts[2] ? ('#' + parts[2]) : ''));
return true;
}
function Case_Insensitive_Sort(a, b) {
var aLow = a.toLowerCase();
var bLow = b.toLowerCase();
if (aLow < bLow) { return -1; }
if (aLow > bLow) { return 1; }
return 0;
}
function encodeName(str) {
return encodeURIComponent(str).replace(/%20/g, '+');
}
function decodeName(str) {
return decodeURIComponent(str.replace(/\+/g, ' '));
}
function List_to_String(arr) {
return arr.sort(Case_Insensitive_Sort).map(encodeName).join(',');
}
function String_to_List(str) {
var arr;
if (str.indexOf('#:#') == -1) {
return str.split(',').map(decodeName);
} else {
return decodeURI(str).split('#:#'); // backwards compatibility
}
}
function Read_VIP_List(compare) {
// permanent storage - data stored in About:Config
// VIP_Working_List - global variable used to store working array
// VIP_Displayed_List - working array is saved here when it is displayed
// compare = false or undefined
// read permament storage and save in working array, return true
// compare = true - compare Displayed list to permanent storage
// changed = true - read permament storage and save in working array, return true
// changed = false - return false
var storedVal = GM_getValue('VIP_List', '');
var changed = true;
if (compare) {
changed = (List_to_String(VIP_Displayed_List) !== storedVal);
}
if (changed) {
VIP_Working_List = storedVal.length ? String_to_List(storedVal) : [];
}
return changed;
}
function Write_VIP_List() {
// use encodeURI so unicode characters will be saved properly
GM_setValue('VIP_List', List_to_String(VIP_Working_List));
// if using FF 3.5 or greater, trigger a storage event
// which will be caught by other windows and they will update with new data.
// otherwise set a local value
var now = new Date().getTime().toString();
if (USE_STORAGE) {
window.localStorage.setItem('VIP_Update_Message', now + '\t' + Working_Prefs.AlwaysLoadAllLogs);
} else {
GM_setValue('Update_Message', now + '\t' + Working_Prefs.AlwaysLoadAllLogs);
}
}
function Prefs_Object_to_String(obj) {
return '' + obj.ShowVIPs + obj.ShowHelp +
obj.ShowMine + obj.ShowMineAlways +
obj.ShowOwner + obj.ShowOwnerAlways +
obj.ShowMulti + obj.ShowMultiAlways +
obj.ShowImages + obj.ShowImagesAlways +
obj.Position + obj.ShowBadges +
obj.AlwaysLoadAllLogs +
obj.DateFormatList +
obj.DateFormatLogs + obj.DateFormatHide;
}
function Read_VIP_Prefs(compare) {
var newPrefs = {
ShowBadges : GM_getValue('Show_Badges', Default_Prefs.ShowBadges),
ShowHelp : GM_getValue('Show_Help', Default_Prefs.ShowHelp),
ShowVIPs : GM_getValue('Show_VIPs', Default_Prefs.ShowVIPs),
ShowMine : GM_getValue('Show_Mine', Default_Prefs.ShowMine),
ShowMineAlways : GM_getValue('Show_Mine_Always', Default_Prefs.ShowMineAlways),
ShowOwner : GM_getValue('Show_Owner', Default_Prefs.ShowOwner),
ShowOwnerAlways : GM_getValue('Show_Owner_Always', Default_Prefs.ShowOwnerAlways),
ShowMulti : GM_getValue('Show_Multi', Default_Prefs.ShowMulti),
ShowMultiAlways : GM_getValue('Show_Multi_Always', Default_Prefs.ShowMultiAlways),
ShowImages : GM_getValue('Show_Images', Default_Prefs.ShowImages),
ShowImagesAlways : GM_getValue('Show_Images_Always', Default_Prefs.ShowImagesAlways),
AlwaysLoadAllLogs : GM_getValue('Always_Load_All_Logs',Default_Prefs.AlwaysLoadAllLogs),
Position : GM_getValue('Position', Default_Prefs.Position),
DateTab : GM_getValue('Date_Tab', Default_Prefs.DateTab),
DateFormatList : GM_getValue('Date_Format_List', Default_Prefs.DateFormatList),
DateFormatLogs : GM_getValue('Date_Format_Logs', Default_Prefs.DateFormatLogs),
DateFormatHide : GM_getValue('Date_Format_Hidden', Default_Prefs.DateFormatHide)
};
var changed = true;
if (compare) {
changed = (Prefs_Object_to_String(Displayed_Prefs) !== Prefs_Object_to_String(newPrefs));
}
if (changed) {
Working_Prefs = newPrefs;
}
return changed;
}
function Write_VIP_Prefs() {
GM_setValue('Show_Badges', Working_Prefs.ShowBadges);
GM_setValue('Show_Help', Working_Prefs.ShowHelp);
GM_setValue('Show_VIPs', Working_Prefs.ShowVIPs);
GM_setValue('Show_Mine', Working_Prefs.ShowMine);
GM_setValue('Show_Mine_Always', Working_Prefs.ShowMineAlways);
GM_setValue('Show_Owner', Working_Prefs.ShowOwner);
GM_setValue('Show_Owner_Always', Working_Prefs.ShowOwnerAlways);
GM_setValue('Show_Multi', Working_Prefs.ShowMulti);
GM_setValue('Show_Multi_Always', Working_Prefs.ShowMultiAlways);
GM_setValue('Show_Images', Working_Prefs.ShowImages);
GM_setValue('Show_Images_Always', Working_Prefs.ShowImagesAlways);
GM_setValue('Always_Load_All_Logs', Working_Prefs.AlwaysLoadAllLogs);
GM_setValue('Position', Working_Prefs.Position);
GM_setValue('Date_Tab', Working_Prefs.DateTab);
GM_setValue('Date_Format_List', Working_Prefs.DateFormatList);
GM_setValue('Date_Format_Logs', Working_Prefs.DateFormatLogs);
GM_setValue('Date_Format_Hidden', Working_Prefs.DateFormatHide);
// if using FF 3.5 or greater, trigger a storage event
// which will be caught by other windows and they will update with new data.
// otherwise set a local value
var now = new Date().getTime().toString();
if (USE_STORAGE) {
window.localStorage.setItem('VIP_Update_Message', now + '\t' + Working_Prefs.AlwaysLoadAllLogs);
} else {
GM_setValue('Update_Message', now + '\t' + Working_Prefs.AlwaysLoadAllLogs);
}
}
function Background_Hide(displayTable) {
// put a white border around the table
var liteOverlay = $('VIP_white');
if (!liteOverlay) {
liteOverlay = document.createElement('div');
liteOverlay.id = 'VIP_white';
document.body.appendChild(liteOverlay);
}
var offsets = Get_Offsets(displayTable);
liteOverlay.style.top = (offsets.top - 5) + 'px';
liteOverlay.style.left = (offsets.left - 5) + 'px';
liteOverlay.style.height= (displayTable.offsetHeight + 10) + 'px';
liteOverlay.style.width = (displayTable.offsetWidth + 10) + 'px';
liteOverlay.style.display= '';
// gray out everything else around the table and border
var darkOverlay = $('VIP_black');
if (!darkOverlay) {
darkOverlay = document.createElement('div');
darkOverlay.id = 'VIP_black';
document.body.appendChild(darkOverlay);
}
darkOverlay.style.height = document.body.scrollHeight + 'px';
darkOverlay.style.width = document.body.scrollWidth + 'px';
darkOverlay.style.display = '';
// offsetHeight and offsetWidth: total size of object
// clientHeight and clientWidth: total size of content area in view
// scrollHeight and scrollWidth: total size of content, some may not be visible due to scrollbars
}
function Background_Show() {
$('VIP_black').style.display = 'none';
$('VIP_white').style.display = 'none';
}
function Count_Visible_Logs() {
var cacheLogsTable = $('VIP_cache_logs_table_body');
if (!cacheLogsTable) { return; }
var totalLogs = parseInt($('NumVisits').textContent.replace(',',''), 10);
Debug_Log('totalLogs=' + totalLogs);
var header = 'No Cache Logs';
if (totalLogs) {
var visibleLogs = 0;
for (var i=0; i<cacheLogsTable.rows.length; i++) {
if (cacheLogsTable.rows[i].offsetHeight > 0) {
visibleLogs++;
}
}
Debug_Log('visibleLogs=' + visibleLogs);
if (visibleLogs == totalLogs) {
header = totalLogs + ' Cache Logs';
} else {
header = visibleLogs + ' of ' + totalLogs + ' Cache Logs';
}
}
// replace the Cache Logs title
$('VIP_cache_logs_header').innerHTML = header;
}
function Show_Log_Row(theID) {
var newRule = '#VIP_cache_logs_table_body > tr[logid="' + theID + '"] { display:table-row; }',
i = document.styleSheets.length - 1,
thisSheet;
for ( ; i>=0; i--) {
thisSheet = document.styleSheets[i];
if (thisSheet.title == 'VIP_show_specific_logs') {
break;
}
}
if (i >= 0) {
thisSheet.insertRule(newRule, thisSheet.cssRules.length);
} else {
LD_addStyle(newRule, 'VIP_show_specific_logs');
}
LD_enableStyle('VIP_show_specific_logs');
}
function Show_and_Navigate() {
// 'this' is the link that was clicked
var logID = this.href.split('#')[1];
if (this.hasAttribute('logtype')) {
var logType = this.getAttribute('logtype');
if ((logType >= 0) && (logType < Img_Files.length)) {
// show all logs of a certain type
LD_enableStyle('VIP_show_logtype_' + logType);
} else if (logType == -1) {
// first hide all logs
Toggle_Cache_Logs_Table(true);
// show all VIP logs
if (Working_Prefs.ShowVIPs) {
LD_enableStyle('VIP_show_VIP_logs');
}
if (Working_Prefs.ShowMine && Working_Prefs.ShowMineAlways) {
LD_enableStyle('VIP_show_my_logs');
}
if (Working_Prefs.ShowOwner && Working_Prefs.ShowOwnerAlways) {
LD_enableStyle('VIP_show_CO_logs');
}
if (Working_Prefs.ShowMulti && Working_Prefs.ShowMultiAlways) {
LD_enableStyle('VIP_show_multi_logs');
}
if (Working_Prefs.ShowImages && Working_Prefs.ShowImagesAlways) {
LD_enableStyle('VIP_show_pix_logs');
}
}
} else {
// show just this one log
Show_Log_Row(logID);
}
Count_Visible_Logs();
// if (document.location.hash) { // this may be needed for Opera, doesn't matter on Firefox
// window.setTimeout(function() {
// document.location.hash = document.location.hash;
// }, 10);
// }
}
function Add_Found_Indicator() {
// xpath to find new checkmark
// //a[contains(@href, "log.aspx")]/following-sibling::img[contains(@src, "check.gif")]
if ($('VIP_goto_my_log')) { return; } // abort if icon already added
if (My_Logs.findStatus >= 0) {
var iconPath = 'http://www.geocaching.com/images/icons/' + Img_Files[My_Logs.findStatus];
var cacheType = 'cache';
var cacheNameSpan = $('ctl00_ContentBody_CacheName');
if (cacheNameSpan) {
cacheType = firstElementChild(Get_Parent(cacheNameSpan, 'tr').cells[0]).firstChild.alt.toLowerCase();
cacheType = cacheType.trim() // remove leading and trailing spaces
.replace(/^an?\s*/, '') // remove leading A or An
.replace(/\s{2,}/g, ' '); // remove double spaces
}
var logType = Img_Desc[My_Logs.findStatus].toLowerCase();
var tip = Tooltip.ThisCacheFound.replace(/%s/, logType).replace(/%s/, cacheType);
// create the new element
var statusIcon = newElement('a', { id : 'VIP_goto_my_log',
href : '#' + My_Logs.findLogID,
onclick : Show_and_Navigate },
newElement('img', { src : iconPath,
title : tip } ));
var cacheNameSpan = $('ctl00_ContentBody_CacheName');
cacheNameSpan.parentNode.appendChild(document.createTextNode(' '));
cacheNameSpan.parentNode.appendChild(statusIcon);
}
}
function Add_Owner_Indicator(ownerName) {
// abort if not my cache or icon already added
if ((ownerName !== Login_Name) || $('VIP_this_is_my_cache')) { return; }
// create the new element
var statusIcon = newElement('img', {id : 'VIP_this_is_my_cache',
src : 'http://www.geocaching.com/images/WptTypes/name_tag.gif',
title : Tooltip.ThisCacheIsMine });
var cacheNameSpan = $('ctl00_ContentBody_CacheName');
cacheNameSpan.parentNode.insertBefore(statusIcon, cacheNameSpan.parentNode.firstChild);
}
function Show_Wait_Cursor() {
document.body.style.cursor = 'wait';
}
function Hide_Wait_Cursor(ms) {
window.setTimeout(function () { document.body.style.cursor = 'default'; }, ms || 10);
}
function Toggle_Cache_Logs_Table(mode) { // true=collapse, false=show
if (typeof(mode) != 'boolean') {
mode = /collapse/i.test(this.id);
}
if (mode) {
LD_enableStyle('VIP_hide_all_logs');
LD_disableStyle('VIP_show_VIP_logs');
LD_disableStyle('VIP_show_CO_logs');
LD_disableStyle('VIP_show_my_logs');
LD_disableStyle('VIP_show_multi_logs');
LD_disableStyle('VIP_show_pix_logs');
LD_disableStyle(/^VIP_show_logtype_/);
LD_removeStyle('VIP_show_specific_logs');
Count_Visible_Logs();
} else {
Show_Wait_Cursor();
window.setTimeout(function () { LD_disableStyle('VIP_hide_all_logs');
Hide_Wait_Cursor(10);
Count_Visible_Logs();
}, 10);
}
}
function Add_Collapse_Button_to_Cache_Logs_Table() {
var cacheLogsTable = xPath('.//table[contains(@class, "LogsTable")]',
$('Content'), XPathResult.FIRST_ORDERED_NODE_TYPE);
if (!cacheLogsTable) { return; }
// create button to collapse block
var collapseButtonDiv = newElement('div', { id : 'VIP_collapse_cache_logs',
title : 'Hide all Cache Logs',
onclick : Toggle_Cache_Logs_Table });
// create button to expand block
var expandButtonDiv = newElement('div', { id : 'VIP_expand_cache_logs',
title : 'Show all Cache Logs',
onclick : Toggle_Cache_Logs_Table });
var headerSpan = newElement('span', { id : 'VIP_cache_logs_header' },
newElement('Cache Logs'));
var headerTH = newElement('th', {},
expandButtonDiv,
collapseButtonDiv,
newElement('img', { src : Icon.Logbook }),
newElement(' '),
headerSpan);
// create a header cell and add expand and collapse buttons to it
cacheLogsTable.createTHead().insertRow(-1).appendChild(headerTH);
// delete the empty last row
cacheLogsTable.deleteRow(-1);
// give the tBody an ID so other functions can find it quickly
cacheLogsTable.tBodies[0].id = 'VIP_cache_logs_table_body';
Count_Visible_Logs();
}
function On_VIP_List(theName, theList, mode) { // if mode == true return index
theName = theName.toLowerCase();
theList = theList || VIP_Working_List;
var regex = new RegExp('^' + theName.quotemeta() + '$', 'i');
for (var i=0; i < theList.length; i++) {
if (regex.test(theList[i])) {
return mode ? i : true;
}
}
return mode ? -1 : false;
}
function Toggle_VIP_in_List(newVIP, mode) {
// mode = true = add only
// mode = false = remove only
// mode = undefined or null = toggle
// return value = true = he's now in the list
// return value = false = he's no longer in the list
// read list first in case it was changed in another window or tab.
Read_VIP_List();
var VIPindex = On_VIP_List(newVIP, null, true);
if (VIPindex >= 0) {
// he's in the list
if (mode === true) {
// add only but he's already here. do nothing.
return true;
} else {
// mode === false (remove) or mode === null (toggle)
VIP_Working_List.splice(VIPindex, 1);
Write_VIP_List();
return false;
}
} else {
// he's NOT in the list
if (mode === false) {
// remove only but he's already NOT here. do nothing.
return false;
} else {
// mode === true (add) or mode === null (toggle)
VIP_Working_List.push(newVIP);
Write_VIP_List();
return true;
}
}
}
function Toggle_VIP() { // VIP image clicked.
var VIPname = this.getAttribute('logowner');
var iconSrc = Icon.BlueVIP;
if (VIPname == Login_Name) { iconSrc = Icon.RedVIP; }
else if (VIPname == Cache_Owner) { iconSrc = Icon.GreenVIP; }
if (Toggle_VIP_in_List(VIPname, null)) {
this.src = iconSrc;
window.status = VIPname + Tooltip.AddedToList;
window.setTimeout(function(){ window.status=''; }, 2000);
}
else {
this.src = Icon.GrayVIP;
window.status = VIPname + Tooltip.RemovedFromList;
window.setTimeout(function(){ window.status=''; }, 2000);
}
// if not using FF 3.5 or greater, can't trigger a storage event
// so just force an update of this one window
if (!USE_STORAGE) {
Refresh_VIP_Display(true);
}
}
function Add_or_Remove_Badge(onList, loggedInLog, ownerLog, badgeID, badgeOwner, parentObj, insertBeforeObj) {
var badge = $(badgeID);
if (Working_Prefs.ShowBadges) {
var badgeTitle = Tooltip.ClickToAdd.replace(/%s/, badgeOwner);
var badgeSrc = Icon.GrayVIP;
if ( onList ) {
badgeTitle = Tooltip.ClickToRemove.replace(/%s/, badgeOwner);
if (loggedInLog && Working_Prefs.ShowMine){
badgeSrc = Icon.RedVIP;
} else if (ownerLog && Working_Prefs.ShowOwner) {
badgeSrc = Icon.GreenVIP;
} else {
badgeSrc = Icon.BlueVIP;
}
}
if (badge) {
// change it
badge.title = badgeTitle;
badge.src = badgeSrc;
} else {
// add it
badge = newElement('img', { id : badgeID,
title : badgeTitle,
src : badgeSrc,
logOwner: badgeOwner,
'class' : 'link',
onclick : Toggle_VIP
});
// if insertBeforeObj is null, will act like appendChild
parentObj.insertBefore(document.createTextNode(' '), insertBeforeObj);
parentObj.insertBefore(badge, insertBeforeObj);
}
}
else if (badge) { // ! Working_Prefs.ShowBadges
// remove it
badge.parentNode.removeChild(badge);
}
}
function Change_Hidden_Date_Format() {
var hideDateFormatted = $('VIP_formatted_DateHidden'),
hideSecs;
if (hideDateFormatted) {
hideSecs = hideDateFormatted.getAttribute('value') - 0;
} else {
var cacheOwnerSpan = xPath('.//span[a[contains(@href, "/profile/")]]',
$('Content'), XPathResult.FIRST_ORDERED_NODE_TYPE),
hideDateSpan = nextElementSibling(cacheOwnerSpan),
m = hideDateSpan.firstChild.textContent.indexOf(':');
if (m < 0) { return; }
var hideDateOriginal = hideDateSpan.firstChild.splitText(m + 2),
hideDateText = hideDateOriginal.textContent.trim();
hideSecs = Date.parse(hideDateText);
hideDateFormatted = document.createElement('span');
hideDateFormatted.id = 'VIP_formatted_DateHidden';
hideDateFormatted.setAttribute('value', hideSecs);
hideDateFormatted.innerHTML = hideDateText;
var temp = document.createElement('span');
temp.id = 'VIP_original_DateHidden';
temp.innerHTML = hideDateText;
hideDateSpan.replaceChild(temp, hideDateOriginal);
hideDateSpan.insertBefore(hideDateFormatted, temp.nextSibling);
}
if (!isNaN(hideSecs)) {
hideDateFormatted.innerHTML = new Date(hideSecs).format(Working_Prefs.DateFormatHide);
}
}
function Add_All_Friends_to_VIP_List() {
var friendsPanel = $('ctl00_ContentBody_pnlMyFriends') || // my friends page
$('ctl00_ContentBody_pnlPending') || // pending friends page
$('displayfriends'); // manage friends page
if (!friendsPanel) { return; }
var friends = xPath('.//a[@logowner]', friendsPanel, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
var total = 0;
for (var i=0; i < friends.snapshotLength; i++) {
var friendLink = friends.snapshotItem(i);
var friendName = friendLink.getAttribute('logowner');
if (On_VIP_List(friendName)) { continue; }
VIP_Working_List.push(friendName);
Add_or_Remove_Badge(true, (friendName == Login_Name), false, friendLink.id + '_VIP',
friendName, friendLink.parentNode, friendLink.nextSibling);
total++;
}
Write_VIP_List();
this.blur();
var p = '';
if (this.textContent.match(/Pending/i)) { p = ' pending'; }
if (total) {
var s = 's were';
if (total == 1) { s = ' was'; }
window.alert(total + p + ' friend' + s + Tooltip.AddedToList);
} else if (friends.snapshotLength > 0) {
window.alert('All your' + p + ' friends are already on the VIP List.');
} else {
window.alert('You have no' + p + ' friends.');
}
}
function Add_Badges_to_Friends_List() {
var friendsPanel = $('ctl00_ContentBody_pnlMyFriends') || // my friends page
$('ctl00_ContentBody_pnlPending') || // pending friends page
$('displayfriends') || // manage friends page
$('ctl00_ContentBody_uxMyFriendsPanel'); // my profile page
if (!friendsPanel) { return; }
var whichFriendsPage, xPathSearch, xPathSearch2, pending = '';
switch (friendsPanel.id) {
case 'ctl00_ContentBody_pnlMyFriends' :
whichFriendsPage = 'myfriends';
xPathSearch = './/h4/a[contains(@href, ".geocaching.com/profile/?guid=")]';
xPathSearch2 = './/h3[contains(text(), "My Friends")]' +
'|.//h3[contains(text(), "Your Friends")]';
break;
case 'ctl00_ContentBody_pnlPending' :
whichFriendsPage = 'pendingfriends';
xPathSearch = './/td/a[contains(@href, ".geocaching.com/profile/?guid=")]';
xPathSearch2 = './/h3[text()="Pending Friend Requests"]';
pending = 'pending ';
break;
case 'displayfriends' :
whichFriendsPage = 'managefriends';
xPathSearch = './/h4/a[contains(@href, "/profile/default.aspx?guid=")]';
xPathSearch2 = './../..//h3[contains(text(), "My Friends")]' +
'|./../..//h3[contains(text(), "Your Friends")]';
break;
case 'ctl00_ContentBody_uxMyFriendsPanel' :
whichFriendsPage = 'myaccount';
xPathSearch = './/p/a[contains(@href, "/profile/default.aspx?guid=")]';
}
var friends = xPath(xPathSearch, friendsPanel, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
Debug_Log(friends.snapshotLength + ' friends found.');
for (var i=0 ; i < friends.snapshotLength; i++ ) {
var friendLink = friends.snapshotItem(i);
var friendID = friendLink.id || 'friend_' + i; // create an ID if one doesn't exist (manage friends page)
if (! friendID.match(/(_lnkName|_uxFriendLink|friend_)/)) { continue; }
friendID += '_VIP';
var friendName = friendLink.textContent.trim();
friendLink.setAttribute('logowner', friendName); // used to "add all friends to VIP list"
var onVIPlist = On_VIP_List(friendName);
Add_or_Remove_Badge(onVIPlist, (friendName == Login_Name), false, friendID, friendName,
friendLink.parentNode, friendLink.nextSibling);
}
if (friends.snapshotLength === 0 || !xPathSearch2) { return; }
// if we already added the "add all friends" link, we're done.
if ($('VIP_add_all_friends')) { return; }
// find a place to add a link to "add all friends to VIP list"
var friendsHeader = xPath(xPathSearch2, friendsPanel, XPathResult.FIRST_ORDERED_NODE_TYPE);
if (!friendsHeader) { return; }
// we found a place to put it, so create the link
var newSpan = document.createElement('span');
newSpan.id = 'VIP_add_all_friends';
newSpan.innerHTML = '<img src="http://www.geocaching.com/images/silk/group.png" ' +
'align="absmiddle"/>Add all ' + pending + 'friends to the VIP List';
newSpan.addEventListener('click', Add_All_Friends_to_VIP_List, false);
// find (or create) the proper place to add the link
var h3 = friendsHeader;
var parentObj = h3.parentNode; // h3.div
var newTD;
if (parentObj.nodeName == 'DIV') { // this script is running first
var newTable = document.createElement('table');
newTable.id = 'friendsHeaderTable';
newTable.style.width = '100%';
newTable.className = h3.className;
h3.style.borderBottomStyle = 'none';
var dest = h3.nextSibling; // save the insert location
var newTR = newTable.insertRow(-1);
newTR.insertCell(-1).appendChild(h3); // move the h3 element into the new table
newTD = newTR.insertCell(-1);
newTD.style.textAlign = 'right';
newTD.appendChild(newSpan);
parentObj.insertBefore(newTable, dest);
} else if (parentObj.nodeName == 'TD') { // Friends List Enhancement script ran first
newTD = Get_Parent(h3, 'tr').insertCell(-1);
newTD.style.textAlign = 'right';
newTD.appendChild(newSpan);
}
}
function Add_Badges_to_Favorite_List() {
var favPanel = $('ctl00_ContentBody_pnlPremiumMembers') ||
$('ctl00_ContentBody_pnlUsers');
var profiles = xPath('.//td/a[contains(@href, "/profile/?guid=")]',
favPanel, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
Debug_Log(Page_Name == 'favoritesList' ?
profiles.snapshotLength + ' caches found.' :
(profiles.snapshotLength / 2) + ' users found.');
for (var i=0 ; i < profiles.snapshotLength; i++ ) {
var profileLink = profiles.snapshotItem(i);
if (profileLink.firstChild.nodeName == 'IMG') { continue; } // skip avatars
var profileID = 'VIP_' + Get_URL_Parameter('guid', profileLink.href);
var profileName = profileLink.textContent.trim();
var onVIPlist = On_VIP_List(profileName);
Add_or_Remove_Badge(onVIPlist, (profileName == Login_Name), false, profileID, profileName,
profileLink.parentNode, profileLink.nextSibling);
}
}
function Parse_Date(dateString) {
dateString = dateString.replace(' by ', '').trim();
if (! dateString.match(/\s\d{4}$/)) {
dateString += ', ' + SCRIPT_START_TIME.getFullYear();
}
var secs = Date.parse(dateString);
if (isNaN(secs)) {
return NaN;
}
return secs;
}
function Prepare_Logs() {
// check that we have a logs table to work with
var logsTable = $('VIP_cache_logs_table_body');
if (!logsTable) { return; }
// store the start time
var startTime = new Date().getTime(), midTime;
// Execute xpath query to get the list of logs
var logsList = xPath(
'./tr/td/strong[img[contains(@src, "/images/icons/")]]',
logsTable, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
if (DEBUG) {
midTime = new Date().getTime();
Debug_Log('xpath time: ' + (midTime - startTime));
Debug_Log('logs found: ' + logsList.snapshotLength);
}
// make a first pass to do stuff that never changes
var logsListLength = logsList.snapshotLength;
for (var i = 0; i < logsListLength; i++ ) {
var strongObj = logsList.snapshotItem(i);
// get the filename part of the image src
var path = strongObj.childNodes[0].src;
path = path.substr(path.lastIndexOf('/')+1);
// extract some information
var trObj = Get_Parent(strongObj, 'tr');
var imgID = Img_Files.indexOf(path);
var logDateObj = strongObj.childNodes[1]; // #text node
var logDateSecs = Parse_Date(logDateObj.textContent);
var logOwnerObj = strongObj.getElementsByTagName('a')[0];
var logID = logOwnerObj.id;
var logOwner = logOwnerObj.textContent;
if (imgID < 0) {
GM_log('Log icon not recognized: ' + path + ' on log' + logDateObj.textContent + logOwner);
continue;
}
// keep track of all the owners of "found" logs so we can look for multis later
if ((imgID >= 0) && (imgID <= 2)) {
Multi_Log_Owners.push(logOwner);
}
// put the log date in its own span for ease of changing format
var logDateSpan = document.createElement('span');
logDateSpan.setAttribute('value', logDateSecs);
logDateSpan.innerHTML = logDateObj.textContent;
strongObj.replaceChild(logDateSpan, logDateObj);
// mark the very first log date so we can use it as a sample in the options dialog
if (i === 0) {
logDateSpan.id = 'VIP_first_log';
}
// store link to the first log of this type
if (!First_Logs[imgID]) {
First_Logs[imgID] = logID;
}
//Set some attributes on the table row for easier filtering
trObj.setAttribute('logid', logID);
trObj.setAttribute('logtype', imgID);
trObj.setAttribute('logowner', logOwner);
// determine if this log has images
var logImages = xPath(
'./table//a[contains(@rel, "tb_images") and img]',
// look for the "rel" attribute for compatiblity with geothumbs which changes everything else
strongObj.parentNode,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
if (logImages.snapshotLength) {
//Debug_Log(logImages.snapshotLength + ' images found for log' + logDateObj.textContent + logOwner);
trObj.setAttribute('logimages', logImages.snapshotLength);
logImages.snapshotItem(0).id = 'VIP_image_' + logID;
}
// if the log was entered by the logged-in user, determine whether to add an indicator
if (logOwner == Login_Name) {
// if we have NOT already run across one of the "found" type of logs...
if ((My_Logs.findStatus < 0) || (My_Logs.findStatus > 2)) {
// have I found the cache?
if (imgID < 3) { // found, attended, webcam photo taken
My_Logs.findStatus = imgID;
My_Logs.findLogID = logID;
}
// if we have NOT already run across a "DNF" log...
else if (My_Logs.findStatus != 3) {
// have I DNF'd the cache?
if (imgID == 3) { // DNF
My_Logs.findStatus = 3;
My_Logs.findLogID = logID;
}
}
}
}
} // for
Multi_Log_Owners = Multi_Log_Owners.duplicates(); // get the duplicates
if (DEBUG) {
var endTime = new Date().getTime();
Debug_Log('loop time: ' + (endTime - midTime));
}
}
function Count_Logs() {
// check that we have a logs table to work with
var logsTable = $('VIP_cache_logs_table_body');
if (!logsTable) { return; }
// store the start time
var startTime = new Date().getTime(), midTime;
Count_Logs_Aborted = false;
// empty the arrays
Log_List = [];
// Execute xpath query to get the list of log images.
var logsList = xPath(
'./tr/td/strong[img[contains(@src, "/images/icons/")]]',
logsTable, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
if (DEBUG) {
midTime = new Date().getTime();
Debug_Log('xpath time: ' + (midTime - startTime));
Debug_Log('logs found: ' + logsList.snapshotLength);
}
// determine if the log date format needs updating
var updateLogDates = (Displayed_Prefs.DateFormatLogs != Working_Prefs.DateFormatLogs);
for (var i = 0; i < logsList.snapshotLength; i++) {
var now = new Date().getTime();
if ((now - startTime) > MAX_SCRIPT_TIME) {
GM_log('Script is running too long. Probably because too many logs. Aborting.');
Count_Logs_Aborted = true;
break;
}
var strongObj = logsList.snapshotItem(i);
// get the filename part of the image src
var path = strongObj.childNodes[0].src;
path = path.substr(path.lastIndexOf('/')+1);
// extract some information
var trObj = Get_Parent(strongObj, 'tr');
var imgID = Img_Files.indexOf(path);
var logDateSpan = strongObj.childNodes[1];
var logDateSecs = logDateSpan.getAttribute('value') - 0;
var logOwnerObj = strongObj.getElementsByTagName('a')[0];
var logID = logOwnerObj.id;
var logOwner = logOwnerObj.textContent;
if (imgID < 0) {
continue;
}
// update the log date format
if (updateLogDates) {
logDateSpan.innerHTML = ' ' + new Date(logDateSecs).format(Working_Prefs.DateFormatLogs) + ' by ';
}
// we already determined if this log has images, so just get those results
var logHasImages = 0;
if (Working_Prefs.ShowImages && trObj.hasAttribute('logimages')) {
logHasImages = trObj.getAttribute('logimages');
}
// is this a qualifying log?
var onVIPlist = On_VIP_List(logOwner);
var myLog = (logOwner == Login_Name);
var ownerLog = (logOwner == Cache_Owner);
var multiLog = ( (imgID <= 2) && (Multi_Log_Owners.indexOf(logOwner) >= 0) );
// set an attribute on VIP logs to make it easy to show them later
if (onVIPlist) {
trObj.setAttribute('isVIP', '1');
} else if (trObj.hasAttribute('isVIP')) {
trObj.removeAttribute('isVIP');
}
// set an attribute on multi logs to make it easy to show them later
if (Working_Prefs.ShowMulti && Working_Prefs.ShowMultiAlways && multiLog) {
trObj.setAttribute('multi', '1');
} else if (trObj.hasAttribute('multi')) {
trObj.removeAttribute('multi');
}
// how should this log be highlighted?
var hiliteclass = 'ordinary_log';
if (onVIPlist) { hiliteclass = 'VIP_log'; }
if (Working_Prefs.ShowOwner && ownerLog) { hiliteclass = 'cache_owner_log'; }
if (Working_Prefs.ShowMine && myLog) { hiliteclass = 'logged_in_user'; }
if (Working_Prefs.ShowMulti && multiLog) { hiliteclass += ' multiple_logs'; }
// if log is by one of our VIPs, or special case to display, push it on to the array
if ((Working_Prefs.ShowVIPs && onVIPlist) ||
(Working_Prefs.ShowImages && Working_Prefs.ShowImagesAlways && logHasImages)||
(Working_Prefs.ShowOwner && Working_Prefs.ShowOwnerAlways && ownerLog) ||
(Working_Prefs.ShowMine && Working_Prefs.ShowMineAlways && myLog) ||
(Working_Prefs.ShowMulti && Working_Prefs.ShowMultiAlways && multiLog) ) {
Log_List.push(logDateSecs.zeroPad(16) + '\t' +
logID.zeroPad(12) + '\t' +
imgID + '\t' + logOwner + '\t' +
logHasImages + '\t' + hiliteclass);
}
// add, update, or remove the image
Add_or_Remove_Badge(onVIPlist, myLog, ownerLog, 'Toggle_VIP_'+logID, logOwner, strongObj);
} // for
if (DEBUG) {
var endTime = new Date().getTime();
Debug_Log('loop time: ' + (endTime - midTime));
}
}
function Determine_Logged_In_User() {
var loginLogoutLink = $('ctl00_LoginUrl') || $('ctl00_ContentLogin_uxLoginStatus_uxLoginURL');
Login_Name_Link = loginLogoutLink.parentNode.getElementsByTagName('a')[0];
// if logged in, Login_Name_Link will be the link to the username
// if not logged in, Login_Name_Link will be the same as loginLogoutLink
if (loginLogoutLink != Login_Name_Link) {
Login_Name = Login_Name_Link.textContent.trim();
loginLogoutLink.previousSibling.textContent = ' | '; // replace . with |
LD_addStyle('#VIP_cache_logs_table_body > tr[logowner="' + Login_Name + '"] { display:table-row; }',
'VIP_show_my_logs');
}
}
function Add_Badge_to_Logged_In_User() {
if (Login_Name) {
var onVIPlist = On_VIP_List(Login_Name);
Add_or_Remove_Badge(onVIPlist, true, false, 'Toggle_Logged_In_User',
Login_Name, Login_Name_Link.parentNode, Login_Name_Link.nextSibling);
}
}
function Add_Badge_to_Cache_Owner() {
var cacheOwnerElement = xPath('.//a[contains(@href, "/profile")]',
$('Content'), XPathResult.FIRST_ORDERED_NODE_TYPE);
if (cacheOwnerElement && Cache_Owner) {
var cell = cacheOwnerElement.parentNode,
onVIPlist = On_VIP_List(Cache_Owner);
Add_or_Remove_Badge(onVIPlist, (Cache_Owner == Login_Name), true,
'Toggle_Cache_Owner', Cache_Owner, cell);
}
}
function Add_Badge_to_Profile_Page() {
var profileHeader = $('ctl00_ContentBody_lblUserProfile');
var fields = profileHeader.textContent.split(':');
if (fields.length > 1) {
var userName = fields[1].trim();
var onVIPlist = On_VIP_List(userName);
Debug_Log(userName + ' is ' + (onVIPlist ? '' : 'not ') + 'on the VIP list.');
Add_or_Remove_Badge(onVIPlist, (userName == Login_Name), false,
'toggle_VIP', userName, profileHeader);
}
}
function Display_Log_Totals() {
var totals_obj = $('ctl00_ContentBody_lblFindCounts');
if (!totals_obj.firstChild) { return; }
var totalsIcons = totals_obj.firstChild.getElementsByTagName('img');
for (var i=0; i < totalsIcons.length; i++) {
var thisImage = totalsIcons[i];
var thisImageFileName = thisImage.src;
thisImageFileName = thisImageFileName.substr(thisImageFileName.lastIndexOf('/')+1);
var imgID = Img_Files.indexOf(thisImageFileName);
if (imgID < 0) { continue; }
var newAnchor = newElement('a', { href : '#' + First_Logs[imgID],
logtype : imgID,
onclick : Show_and_Navigate
});
thisImage.parentNode.replaceChild(newAnchor, thisImage);
newAnchor.appendChild(thisImage);
newAnchor.nextSibling.insertData(0, ' ');
// create styles for later un-hiding
LD_addStyle('#VIP_cache_logs_table_body > tr[logtype="' + imgID + '"] { display:table-row; }',
'VIP_show_logtype_' + imgID);
LD_disableStyle('VIP_show_logtype_' + imgID);
}
// add instructions
var newInstructs = newElement('small', { innerHTML : Tooltip.ClickLogType });
totals_obj.firstChild.appendChild(newElement('br', {}));
totals_obj.firstChild.appendChild(newInstructs);
}
function Next_Row_Class(init) {
if (init === true) { // start over - output ignored
NextRowClass = 'AlternatingRow';
} else if (init === false) { // return same as last
} else { // init undefined - toggle
if (NextRowClass != 'AlternatingRow') {
NextRowClass = 'AlternatingRow';
} else {
NextRowClass = '';
}
}
return NextRowClass;
}
function Swap_Row_Class(obj) {
var currentClass = obj.className;
Debug_Log('current: ' + currentClass);
if (currentClass.match(/AlternatingRow/)) {
Debug_Log('was Alt');
obj.className = currentClass.replace(/AlternatingRow/, '').replace(/\s\s/, ' ');
} else {
Debug_Log('was not Alt');
obj.className = currentClass + ' AlternatingRow';
}
}
function Simulate_Click() {
var targetID = this.previousSibling.previousSibling.hash.substr(1);
var evt = document.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
var pic = document.getElementById('VIP_image_' + targetID);
if (pic) {
pic.dispatchEvent(evt);
}
}
function Determine_Table_Position(desiredPoint) {
var xPathStrings = ['./div[h3[img[contains(@src, "/stockholm/16x16/home.gif")]]]', // top
'./p', // after Nav (before map)
'./div[img[contains(@src, "/images/attributes/")]]', // after map (before attributes)
'./div[h3[img[contains(@src, "/WptTypes/sm/tb_coin.gif")]]]', // after attributes and ad (before inventory)
'./div[h3[img[contains(@src, "/stockholm/16x16/pages.gif")]]]' // after inventory (before bookmarks)
];
// Table normally contains Nav, Map, watchers, Facebook, Attributes, advertisement, Inventory, Bookmarks, My Bookmarks
var oResult = null;
var navColumnTD = $('ctl00_ContentBody_lnkTravelBugs').parentNode;
while (!oResult && (desiredPoint < xPathStrings.length)) {
oResult = xPath(xPathStrings[desiredPoint], navColumnTD, XPathResult.FIRST_ORDERED_NODE_TYPE);
desiredPoint++;
}
return oResult;
}
function Display_VIP_Table(tableType, VIPdiv) {
// set attributes on main DIV
VIPdiv.id = 'VIP_table';
VIPdiv.className = 'CacheDetailNavigationWidget ' +
((Working_Prefs.Position===0) ? 'Reverse' : '') + 'Spacing';
// is there already a VIP table?
var oldTable = $('VIP_table');
var nextSib = Determine_Table_Position(Working_Prefs.Position);
var addTable = true;
if (oldTable && (oldTable.nextSibling == nextSib)) {
oldTable.parentNode.replaceChild(VIPdiv, oldTable);
addTable = false;
}
else if (oldTable) {
oldTable.parentNode.removeChild(oldTable);
}
oldTable = null;
if (addTable) {
// get a reference to the table cell that contains the "Navigation" table, map, inventory, etc.
var navColumnTD = $('ctl00_ContentBody_lnkTravelBugs').parentNode;
// insert the new VIP table
navColumnTD.insertBefore(VIPdiv, nextSib);
}
// if options or edit display, gray out the rest of the window
if (tableType !== 'VIP') {
Background_Hide(VIPdiv);
}
}
function Set_Display_Update_Time() {
var now = new Date().getTime().toString();
Login_Name_Link.setAttribute('last_display_time', now);
}
function Edit_VIP_List_Toggle_Member() {
var indexToToggle = this.id.match(/^VIP_toggle_(img|name)_(\d+)$/)[2];
var img_obj = $('VIP_toggle_img_' + indexToToggle);
var name_obj = $('VIP_toggle_name_' + indexToToggle);
if (name_obj) {
if (name_obj.className == 'VIP_enabled_text') {
name_obj.className = 'VIP_disabled_text';
name_obj.title = 'Click to add ' + VIP_Working_List[indexToToggle];
img_obj.title = 'Click to add ' + VIP_Working_List[indexToToggle];
img_obj.src = Icon.GrayVIP;
} else {
name_obj.className = 'VIP_enabled_text';
name_obj.title = 'Click to remove ' + VIP_Working_List[indexToToggle];
img_obj.title = 'Click to remove ' + VIP_Working_List[indexToToggle];
img_obj.src = Icon.BlueVIP;
}
}
}
function Edit_VIP_List_New_Row(rowName, rowNum, rowClass) {
return newElement('li', { 'class' : rowClass },
newElement('img', { title : 'Click to remove ' + rowName,
'class' : 'link',
src : Icon.BlueVIP,
id : 'VIP_toggle_img_' + rowNum,
onclick : Edit_VIP_List_Toggle_Member
}),
newElement(' '),
newElement('span', {title : 'Click to remove ' + rowName,
'class' : 'VIP_enabled_text',
id : 'VIP_toggle_name_' + rowNum,
onclick : Edit_VIP_List_Toggle_Member
},
newElement(rowName)
)
);
}
function Add_VIP_during_Edit() {
var newName = window.prompt(Tooltip.AddName, '');
if (newName.length) {
newName = newName.trim();
}
if (newName.length) {
if (On_VIP_List(newName)) {
window.alert(newName + Tooltip.AlreadyOnList);
}
else if (On_VIP_List(newName, Add_List)) {
window.alert(newName + Tooltip.AlreadyAdded);
}
else {
Add_List.push(newName);
var addButton = $('add_VIP');
var VIP_table = $('VIP_table');
var listParent = $('VIP_list');
var nextRow = addButton.getAttribute('nextrow');
var newLI = Edit_VIP_List_New_Row(newName, nextRow, Next_Row_Class());
listParent.appendChild(newLI);
Background_Hide(VIP_table);
Swap_Row_Class(addButton.parentNode);
nextRow++;
addButton.setAttribute('nextrow', nextRow);
}
}
}
function Storage_Event_Trigger() {
var lastDisplay = Login_Name_Link.getAttribute('last_display_time') || 0,
updateTrigger = 0;
if (USE_STORAGE) {
updateTrigger = window.localStorage.getItem('VIP_Update_Message');
} else {
updateTrigger = GM_getValue('Update_Message');
}
if (updateTrigger) {
updateTrigger = updateTrigger.split('\t')[0];
}
Debug_Log('updateTrigger = ' + updateTrigger);
Debug_Log('lastDisplay = ' + lastDisplay);
if (updateTrigger > lastDisplay) { Refresh_VIP_Display(); }
}
function Start_Update_Thread() {
if (USE_STORAGE) {
document.addEventListener('storage', Storage_Event_Trigger, false);
} else {
Timeout_Timer = window.setInterval(Storage_Event_Trigger, 2000);
}
}
function Stop_Update_Thread() {
if (USE_STORAGE) {
document.removeEventListener('storage', Storage_Event_Trigger, false);
} else {
window.clearInterval(Timeout_Timer);
}
}
function Save_VIP_List() {
VIP_Working_List = [];
var i = 0;
var name_obj = $('VIP_toggle_name_' + i);
while (name_obj ) {
if (name_obj.className == 'VIP_enabled_text') {
VIP_Working_List.push(name_obj.textContent);
}
i++;
name_obj = $('VIP_toggle_name_' + i);
}
Add_List = [];
Write_VIP_List();
Background_Show();
Refresh_VIP_Display(true);
// $('VIP_table').scrollIntoView();
Start_Update_Thread();
}
function Cancel_VIP_Edit() {
Background_Show();
Refresh_VIP_Display(true);
// $('VIP_table').scrollIntoView();
Start_Update_Thread();
}
function Edit_VIP_List() {
Stop_Update_Thread();
Next_Row_Class(true);
Read_VIP_List();
VIP_Working_List.sort(Case_Insensitive_Sort);
Add_List = [];
// Add names to table body
var ULbody = newElement('ul', { id : 'VIP_list' });
for (var i=0; i < VIP_Working_List.length; i++) {
ULbody.appendChild(Edit_VIP_List_New_Row(VIP_Working_List[i], i, Next_Row_Class()));
}
var header = newElement('h3', { 'class' : 'WidgetHeader' },
newElement('img', { src : Icon.GroupEdit }),
newElement(' Edit VIP List')
);
var footer = newElement('p', { style : 'text-align:left; padding-top:0.4em;',
'class' : 'NoSpacing ' + Next_Row_Class()
},
newElement('button', { id : 'add_VIP',
type : 'button',
title : Tooltip.AddLink,
nextRow : i,
onclick : Add_VIP_during_Edit
},
newElement('Add')
),
newElement(' \xA0 \xA0 \xA0'),
newElement('button', { id : 'save_VIP_list',
type : 'button',
onclick : Save_VIP_List
},
newElement('Save')
),
newElement(' '),
newElement('button', { id : 'cancel_VIP_edit',
type : 'button',
onclick : Cancel_VIP_Edit
},
newElement('Cancel')
)
);
var mainDiv = newElement('div', {}, header, newElement('div', { 'class' : 'WidgetBody' }, ULbody, footer));
Display_VIP_Table('Edit', mainDiv);
// call one more time so when we add lines they come out right.
Next_Row_Class();
}
function Save_VIP_Prefs() {
Working_Prefs = {
ShowBadges: $('VIP_show_badges_checkbox').checked,
ShowHelp: $('VIP_show_help_checkbox').checked,
ShowVIPs: $('VIP_show_VIPs_checkbox').checked,
ShowMine: $('VIP_show_mine_checkbox').checked,
ShowMineAlways: $('VIP_show_mine_always_checkbox').checked,
ShowOwner: $('VIP_show_owner_checkbox').checked,
ShowOwnerAlways: $('VIP_show_owner_always_checkbox').checked,
ShowMulti: $('VIP_show_multi_checkbox').checked,
ShowMultiAlways: $('VIP_show_multi_always_checkbox').checked,
ShowImages: $('VIP_show_images_checkbox').checked,
ShowImagesAlways: $('VIP_show_images_always_checkbox').checked,
AlwaysLoadAllLogs: $('VIP_always_load_all_logs_checkbox').checked,
Position: $('VIP_position').value - 0,
DateTab: $('VIP_date_tab').checked,
DateFormatList: $('VIP_date_format_list').value,
DateFormatLogs: $('VIP_date_format_logs').value,
DateFormatHide: $('VIP_date_format_hidden').value
};
if (!Working_Prefs.DateFormatList.trim()) { Working_Prefs.DateFormatList = Default_Prefs.DateFormatList; }
if (!Working_Prefs.DateFormatLogs.trim()) { Working_Prefs.DateFormatLogs = Default_Prefs.DateFormatLogs; }
if (!Working_Prefs.DateFormatHide.trim()) { Working_Prefs.DateFormatHide = Default_Prefs.DateFormatHide; }
Write_VIP_Prefs();
// if already showing all logs, function will do nothing.
if (Working_Prefs.AlwaysLoadAllLogs) {
Reload_Cache_Page_With_All_Logs();
}
Background_Show();
Refresh_VIP_Display(true);
// $('VIP_table').scrollIntoView();
Start_Update_Thread();
}
function Show_Sample_Date(str) {
var thisID, thisObj, secs;
if (typeof(str) == 'string') {
thisID = str;
thisObj = $(str);
} else {
thisID = this.id;
thisObj = this;
}
if (thisID.match(/_list$/) && Log_List[0]) {
secs = Log_List[0].split('\t')[0] - 0;
}
if (!secs && thisID.match(/_logs$/) && $('VIP_first_log')) {
secs = $('VIP_first_log').getAttribute('value') - 0;
}
if (!secs) {
secs = $('VIP_formatted_DateHidden').getAttribute('value') - 0;
}
var dateString = new Date(secs).format(thisObj.value);
$(thisID + '_sample').innerHTML = dateString;
}
function Edit_VIP_Prefs_Line( checkboxID, rowClass,
chek, dis, labelTitle,
checkboxClick, label) {
return newElement('li', { 'class' : rowClass },
newElement('input', { type : 'checkbox',
id : checkboxID,
checked : chek,
disabled : dis,
onclick : checkboxClick
}),
newElement(' '),
newElement('label', { 'for' : checkboxID,
title : labelTitle,
innerHTML : label
})
);
}
function Edit_VIP_Prefs() {
Stop_Update_Thread();
Read_VIP_Prefs();
// create the header
var header = newElement('h3', { 'class' : 'WidgetHeader' },
newElement('img', { src : Icon.GroupEdit }),
newElement(' VIP Options')
);
// create the display options tab
Next_Row_Class(true);
var ULbody1 = newElement('ul', {});
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_VIPs_checkbox', Next_Row_Class(),
Working_Prefs.ShowVIPs, false, Tooltip.ShowVIPs,
null, 'Include <span class="VIP_log">VIP logs</span> in list.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_mine_checkbox', Next_Row_Class(),
Working_Prefs.ShowMine, false, Tooltip.ShowMine,
function(){document.getElementById('VIP_show_mine_always_checkbox').disabled=!this.checked;},
'<span class="logged_in_user">Highlight</span> your own logs.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_mine_always_checkbox',
'subordinate ' + Next_Row_Class(false),
Working_Prefs.ShowMineAlways, !Working_Prefs.ShowMine, Tooltip.ShowMineAlways,
null, 'Include in list even if not a VIP.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_owner_checkbox', Next_Row_Class(),
Working_Prefs.ShowOwner, false, Tooltip.ShowOwner,
function(){document.getElementById('VIP_show_owner_always_checkbox').disabled=!this.checked;},
'<span class="cache_owner_log">Highlight</span> the cache owner’s logs.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_owner_always_checkbox',
'subordinate ' + Next_Row_Class(false),
Working_Prefs.ShowOwnerAlways, !Working_Prefs.ShowOwner, Tooltip.ShowOwnerAlways,
null, 'Include in list even if not a VIP.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_multi_checkbox', Next_Row_Class(),
Working_Prefs.ShowMulti, false, Tooltip.ShowMulti,
function(){document.getElementById('VIP_show_multi_always_checkbox').disabled=!this.checked;},
'<span class="multiple_logs">Highlight</span> multiple “found” logs by the same person.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_multi_always_checkbox',
'subordinate ' + Next_Row_Class(false),
Working_Prefs.ShowMultiAlways, !Working_Prefs.ShowMulti, Tooltip.ShowMultiAlways,
null, 'Include in list even if not a VIP.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_images_checkbox', Next_Row_Class(),
Working_Prefs.ShowImages, false, Tooltip.ShowImages,
function(){document.getElementById('VIP_show_images_always_checkbox').disabled=!this.checked;},
'Indicate logs that have images. ' +
'<img src="../images/silk/photo.png" style="vertical-align:text-bottom">'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_images_always_checkbox',
'subordinate ' + Next_Row_Class(false),
Working_Prefs.ShowImagesAlways, !Working_Prefs.ShowImages, Tooltip.ShowImagesAlways,
null, 'Include in list even if not a VIP.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_help_checkbox', Next_Row_Class(),
Working_Prefs.ShowHelp, false, Tooltip.ShowHelp,
null, 'Show instructions if there are no VIP logs.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_show_badges_checkbox', Next_Row_Class(),
Working_Prefs.ShowBadges, false, Tooltip.ShowBadges,
null, 'Show VIP badges.'));
ULbody1.appendChild(Edit_VIP_Prefs_Line('VIP_always_load_all_logs_checkbox', Next_Row_Class(),
Working_Prefs.AlwaysLoadAllLogs, false, Tooltip.AlwaysLoadAllLogs,
null, 'Always load all logs.'));
// create the date formats tab
Next_Row_Class(true);
var ULbody2 = newElement('ul', {});
ULbody2.appendChild(newElement('li', { 'class' : Next_Row_Class(),
style : 'padding-top:0.4em;' },
newElement('label', { 'for' : 'VIP_date_format_list',
title : Tooltip.DateFormatList },
newElement('VIP logs date format: ')),
newElement('input', { type : 'text',
id : 'VIP_date_format_list',
value : Working_Prefs.DateFormatList,
onchange: Show_Sample_Date,
onkeyup : Show_Sample_Date
}),
newElement('br', {}),
newElement('div', { style : 'min-height:3em;',
id : 'VIP_date_format_list_sample',
title : Tooltip.DateFormatSample },
newElement(' '))
));
ULbody2.appendChild(newElement('li', { 'class' : Next_Row_Class(),
style : 'padding-top:0.4em;' },
newElement('label', { 'for' : 'VIP_date_format_logs',
title : Tooltip.DateFormatLogs },
newElement('Cache logs date format: ')),
newElement('input', { type : 'text',
id : 'VIP_date_format_logs',
value : Working_Prefs.DateFormatLogs,
onchange: Show_Sample_Date,
onkeyup : Show_Sample_Date
}),
newElement('br', {}),
newElement('div', { style : 'min-height:3em;',
id : 'VIP_date_format_logs_sample',
title : Tooltip.DateFormatSample },
newElement(' '))
));
ULbody2.appendChild(newElement('li', { 'class' : Next_Row_Class(),
style : 'padding-top:0.4em;' },
newElement('label', { 'for' : 'VIP_date_format_hidden',
title : Tooltip.DateFormatHide },
newElement('Cache hide date format: ')),
newElement('input', { type : 'text',
id : 'VIP_date_format_hidden',
value : Working_Prefs.DateFormatHide,
onchange: Show_Sample_Date,
onkeyup : Show_Sample_Date
}),
newElement('br', {}),
newElement('div', { style : 'min-height:3em;',
id : 'VIP_date_format_hidden_sample',
title : Tooltip.DateFormatSample },
newElement(' '))
));
ULbody2.appendChild(newElement('li', { 'class' : Next_Row_Class(),
style : 'padding-top:1em; padding-bottom:1em;' },
newElement('span', { id : 'VIP_tooltip' },
newElement('img', { src : Icon.Help }),
newElement('span', { id : 'VIP_date_format_help',
innerHTML : Tooltip.DateFormatHelp })),
newElement('span', { style : 'font-size:smaller' },
newElement(' Help with date formats.'))
));
var sel = newElement('select', { id : 'VIP_position' });
var levels = ['Top', 'After Navigation', 'After Map', 'After Attributes', 'After Inventory', 'Bottom'];
for (var i=0; i<levels.length; i++) {
sel.appendChild(newElement('option', { value : i,
selected : (Working_Prefs.Position == i) },
newElement(levels[i])));
}
ULbody2.appendChild(newElement('li', { 'class' : Next_Row_Class(),
style : 'text-align:center; padding-top:1em;' },
newElement('label', { 'for' : 'VIP_position',
title : Tooltip.Position },
newElement('Position: ')),
sel));
// put the two tabs together into the body
var body = newElement('div', { 'class' : 'WidgetBody' },
newElement('div', { id : 'VIP_options' },
newElement('input', { type : 'radio',
id : 'VIP_display_tab',
name : 'VIP_tab',
checked : 'checked'
}),
newElement('label', { 'for' : 'VIP_display_tab' },
newElement('Display')),
newElement('div', { id : 'VIP_display_options',
'class' : 'VIP_tab' },
ULbody1),
newElement('input', { type : 'radio',
id : 'VIP_date_tab',
name : 'VIP_tab'
}),
newElement('label', { 'for' : 'VIP_date_tab' },
newElement('Dates')),
newElement('div', { id : 'VIP_date_options',
'class' : 'VIP_tab' },
ULbody2)
)
);
// add the footer
var footer = newElement('p', { style : 'text-align:center;',
'class' : 'NoSpacing ' },
newElement('button', { id : 'save_VIP_prefs',
type : 'button',
onclick : Save_VIP_Prefs },
newElement('Save')),
newElement(' '),
newElement('button', { id : 'cancel_VIP_edit',
type : 'button',
onclick : Cancel_VIP_Edit },
newElement('Cancel'))
);
body.appendChild(footer);
var mainDiv = newElement('div', {}, header, body);
Display_VIP_Table('Edit', mainDiv);
$('VIP_date_options').style.height = $('VIP_display_options').firstChild.offsetHeight + 'px';
$('VIP_date_tab').checked = Working_Prefs.DateTab;
Show_Sample_Date('VIP_date_format_list');
Show_Sample_Date('VIP_date_format_logs');
Show_Sample_Date('VIP_date_format_hidden');
// $('VIP_table').scrollIntoView();
}
function Build_VIP_Log_List_for_Display() {
// create list of VIP's logs
Next_Row_Class(true);
var ULbody = newElement('ul', {}), headerLink, headerText, showHelpIcon, newLI, newImg;
if (Log_List.length) {
// Add title indicating total number of logs.
var s = (Log_List.length == 1) ? '' : 's';
headerText = Log_List.length + ' VIP Log' + s;
showHelpIcon = true;
// Sort users logs in reverse entry order.
Log_List.sort().reverse();
for (var i=0; i < Log_List.length; i++) {
// Extract data fields for each user's log.
var logFlds = Log_List[i].split('\t');
var logSecs = logFlds[0] - 0; // log date in seconds since 1970
var logID = logFlds[1] - 0;
var typeID = logFlds[2] - 0;
var logOwner = logFlds[3];
var logHasImages= logFlds[4] - 0;
var hiliteclass = logFlds[5];
var logHref = '#' + logID;
if (i === 0) {
headerLink = logHref;
}
// Add data to table.
var ttip = Tooltip.ClickToScroll.replace(/%s/, Img_Desc[typeID]);
var dateString = new Date(logSecs).format(Working_Prefs.DateFormatList);
var newAnchor = newElement('a', { href : logHref,
title : ttip,
'class' : 'lnk' + (hiliteclass ? ' ' + hiliteclass : ''),
onclick : Show_and_Navigate
},
newElement('img', { src : '../images/icons/' + Img_Files[typeID],
style : 'width:16px; height:16px;'
}),
newElement(' '),
newElement('span', {}, newElement(dateString + ' ' + logOwner))
);
newLI = newElement('li', { 'class' : Next_Row_Class() }, newAnchor);
if (logHasImages > 0) {
s = (logHasImages == 1) ? '' : 's';
newImg = newElement('img', {src : '../images/silk/photo' + s + '.png',
'class' : 'link',
style : 'vertical-align:text-bottom;',
title : Tooltip.PictureFrame.replace(/%s/, logHasImages)
.replace(/%s/, s),
onclick : Simulate_Click
});
newLI.appendChild(newElement(' '));
newLI.appendChild(newImg);
}
ULbody.appendChild(newLI);
}
} else {
headerText = 'No VIP Logs';
headerLink = '';
showHelpIcon = false;
newLI = newElement('li', { 'class' : Next_Row_Class() });
if (All_Logs_Shown && Working_Prefs.ShowBadges && Working_Prefs.ShowHelp) {
newLI.innerHTML = Tooltip.HowToAdd;
newLI.style.paddingLeft = 0;
newLI.style.textIndent = 0;
} else {
newLI.style.height = '3px';
}
ULbody.appendChild(newLI);
}
// if all logs are not shown, add a warning to the end of the list.
if (!All_Logs_Shown) {
newLI = newElement('li', { 'class' : 'VIP_warning_row'
},
newElement('img', { src : Icon.Warning,
title : 'Warning'
}),
newElement(' This list is not complete. '),
newElement('a', { 'class' : 'lnk',
href : More_Logs_URL,
style : 'white-space:nowrap;'
},
newElement('span', {}, newElement('Load more logs'))
)
);
ULbody.appendChild(newLI);
}
// if we aborted because we were taking too long, add a warning to the list.
if (Count_Logs_Aborted) {
newLI = newElement('li', { 'class' : 'VIP_warning_row'
},
newElement('img', { src : Icon.Warning,
title : 'Warning'
}),
newElement(' Too many logs.'),
newElement('br', {}),
newElement('VIP List truncated.')
);
ULbody.appendChild(newLI);
}
// build the header
var header = newElement('h3', { 'class' : 'WidgetHeader' });
if (showHelpIcon) {
header.appendChild( newElement('div', { id : 'VIP_tooltip',
style : 'float:right;' },
newElement('img', { src : Icon.Help }),
newElement('span', { innerHTML : Tooltip.Legend })
));
}
// use an icon that is appropriate for the mode
newImg = newElement('img', { src : ((Log_List.length == 1) ? Icon.Single : Icon.Group) });
// if there's a link, wrap it around the icon
if (headerLink) {
header.appendChild(newElement('a', { id : 'VIP_header_link',
logtype : -1,
href : headerLink,
title : Tooltip.HeaderIcon,
onclick : Show_and_Navigate
},
newImg
));
} else {
header.appendChild(newImg);
}
header.appendChild(newElement(' ' + headerText));
// build the footer
var footer = newElement('p', { style : 'text-align:right; font-size:90%;',
'class' : 'NoSpacing'
},
newElement('span', {id : 'edit_VIP_list',
'class' : 'link',
title : Tooltip.EditListLink,
onclick : Edit_VIP_List
},
newElement('img', { src : Icon.Pencil }),
newElement('Edit List')
),
newElement(' '),
newElement('span', {id : 'edit_VIP_prefs',
'class' : 'link',
title : Tooltip.OptionsLink,
onclick : Edit_VIP_Prefs
},
newElement('img', { src : Icon.Wrench }),
newElement('Options')
)
);
return newElement('div', {}, header, newElement('div', { 'class' : 'WidgetBody' }, ULbody), footer);
}
function Refresh_VIP_Display(redraw, force) {
// if VIP list or prefs changed, recompute and display
// else if redraw==true then redraw old display
var changed = force || false, VIPdiv;
if (Read_VIP_List(true)) {
if (DEBUG) { Login_Name_Link.style.backgroundColor = 'lightpink'; }
changed = true;
} else if (Read_VIP_Prefs(true)) {
if (DEBUG) { Login_Name_Link.style.backgroundColor = 'yellow'; }
changed = true;
} else if (redraw) {
if (DEBUG) { Login_Name_Link.style.backgroundColor = 'lightgrey'; }
}
switch (Page_Name) {
case 'cache' : if (changed) {
Add_Badge_to_Logged_In_User();
Add_Badge_to_Cache_Owner();
Change_Hidden_Date_Format();
Count_Logs();
VIPdiv = Build_VIP_Log_List_for_Display();
Display_VIP_Table('VIP', VIPdiv);
VIP_Displayed_List = VIP_Working_List;
Displayed_Prefs = Working_Prefs;
Set_Display_Update_Time();
} else if (redraw) {
VIPdiv = Build_VIP_Log_List_for_Display();
Display_VIP_Table('VIP', VIPdiv);
}
break;
case 'profile': Add_Badge_to_Logged_In_User();
Add_Badge_to_Profile_Page();
VIP_Displayed_List = VIP_Working_List;
Displayed_Prefs = Working_Prefs;
Set_Display_Update_Time();
break;
case 'friends': Add_Badge_to_Logged_In_User();
Add_Badges_to_Friends_List();
VIP_Displayed_List = VIP_Working_List;
Displayed_Prefs = Working_Prefs;
Set_Display_Update_Time();
break;
case 'favoritesList':
case 'favoriteCache': Add_Badge_to_Logged_In_User();
Add_Badges_to_Favorite_List();
VIP_Displayed_List = VIP_Working_List;
Displayed_Prefs = Working_Prefs;
Set_Display_Update_Time();
}
if (DEBUG) {
window.setTimeout(function(){
Login_Name_Link.style.backgroundColor = '';
}, 300);
}
}
function Determine_Cache_Owner() {
// get real name of cache owner
var hiddenByThisUserLink = $('ctl00_ContentBody_uxFindLinksHiddenByThisUser');
if (hiddenByThisUserLink) {
Cache_Owner = decodeName(Get_URL_Parameter('u', hiddenByThisUserLink.href));
Debug_Log(Cache_Owner);
Add_Owner_Indicator(Cache_Owner);
Add_Badge_to_Cache_Owner();
LD_addStyle('#VIP_cache_logs_table_body > tr[logowner="' + Cache_Owner + '"] { display:table-row; }',
'VIP_show_CO_logs');
}
}
function Find_More_Logs_Object() {
// We don't have much to go on to find this link.
// All we know is it should be within a <p> and have "log=y" within it's href.
// Problem is someone could include a similar link in the description or a log.
// Fortunately one of those would be within a table while the one we want is not.
var objs = xPath('.//p[a[contains(@href, "log=y")]]', $('Content'), XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE);
// loop in reverse because the one we want /should/ be near the end of the page.
for (var i=objs.snapshotLength-1; i>=0; i--) {
if (Get_Parent(objs.snapshotItem(i), 'table') === null) {
return objs.snapshotItem(i);
}
}
// if we got here it means the link doesn't exist - already showing all logs.
return null;
}
function Process_Cache_Page() {
var findCounts_obj = $('ctl00_ContentBody_lblFindCounts'); // (note)55 (find)23 (DNF)2 ...
var logWarning_obj = nextElementSibling(findCounts_obj); // Warning. Spoilers may be included ...
var numVisits_obj = previousElementSibling(findCounts_obj); // xx Logged Visits
var moreLogs_obj = Find_More_Logs_Object(); // There are more logs. View them all...
numVisits_obj.id = 'NumVisits'; // for a prettier url #hash
Determine_Cache_Owner();
// See if 'MoreLogs' link is present.
if (moreLogs_obj) {
var moreLogsURL_obj = moreLogs_obj.getElementsByTagName('a')[0];
// save URL without # for use in VIP table
More_Logs_URL = moreLogsURL_obj.href;
// Add anchor tag to link, to scroll page at start of logs.
moreLogsURL_obj.href += '#NumVisits';
// Copy 'more logs' link above the logs.
var dupMoreLogs_obj = moreLogs_obj.cloneNode(true);
logWarning_obj.parentNode.insertBefore(dupMoreLogs_obj, logWarning_obj.nextSibling);
}
// Get count of each image type. Build display string.
Add_Collapse_Button_to_Cache_Logs_Table();
Change_Hidden_Date_Format();
Prepare_Logs();
Count_Logs();
// Format the list into a table.
All_Logs_Shown = !moreLogs_obj;
var mainDiv = Build_VIP_Log_List_for_Display();
if (!moreLogs_obj) {
Display_Log_Totals();
}
Add_Found_Indicator();
Display_VIP_Table('VIP', mainDiv);
VIP_Displayed_List = VIP_Working_List;
Displayed_Prefs = Working_Prefs;
Set_Display_Update_Time();
// create thread to watch for list or pref changes from other windows or tabs
Start_Update_Thread();
// Scroll to log anchor.
if (Page_URL.match(/#NumVisits$/)) {
document.location = document.location; // FireFox doesn't need this but Opera does
}
}
function Check_for_Update(scriptName, scriptVersion) {
try {
var checkURL = 'http://www.lildevil.org/greasemonkey/current-versions.txt';
if (window.opera) {
// Opera doesn't support cross-domain xmlhttpRequests so use a URL on geocaching.com
checkURL = 'http://www.geocaching.com/seek/log.aspx?LUID=606117a5-b2d0-4450-8fa1-f7faae43e4be';
}
// show version number on http://www.lildevil.org/greasemonkey/versions
var versObj = document.getElementById(scriptName);
if (versObj) {
versObj.innerHTML = scriptVersion;
}
// avoid a flood of dialogs e.g. when opening a browser with multiple tabs open
var now = new Date().getTime();
var DOSpreventionTime = 2 * 60 * 1000; // two minutes
var lastStart = GM_getValue('Update_Start', null);
GM_setValue('Update_Start', now.toString());
if (lastStart && (now - lastStart) < DOSpreventionTime) { return; }
// time to check yet?
var oneDay = 24 * 60 * 60 * 1000;
var lastChecked = GM_getValue('Update_Last', null);
var checkDays = GM_getValue('Update_Days', 1);
if (lastChecked && (now - lastChecked) < (oneDay * checkDays)) { return; }
GM_xmlhttpRequest({
method: 'GET',
url: checkURL,
headers: { 'User-Agent' : scriptName + ' v' + scriptVersion + ' auto updater' },
onload: function(result) {
var re = new RegExp('[\\s\\>]' + scriptName + '\\s+v([\\d\\.]+)\\s+(\\d+)\\s+(.+?)[\\<\\s]', 'i');
if (!result.responseText.match(re)) {
GM_log(scriptName + ': Updater: response unrecognized');
return;
}
var theOtherVersion = RegExp.$1;
GM_setValue('Update_Days', +RegExp.$2);
var theOtherURL = RegExp.$3;
if (theOtherVersion.replace(/\./g, '') <= scriptVersion.replace(/\./g, '')) { return; } // no updates or older version
if (theOtherURL.indexOf('http') !== 0) { theOtherURL = 'http://' + theOtherURL; }
if (window.confirm( 'Version ' + theOtherVersion +
' of the "' + scriptName +
'" greasemonkey script is available.\n' +
'You are currently using version ' + scriptVersion +
'.\n\nClick OK for instructions on how to upgrade.\n')) {
GM_openInTab(theOtherURL);
}
}
});
GM_setValue('Update_Last', new Date().getTime().toString());
}
catch (err) { }
}
function Main() {
Add_Styles();
Next_Row_Class(true);
Read_VIP_List();
Read_VIP_Prefs();
Determine_Logged_In_User();
Add_Badge_to_Logged_In_User();
if (Page_URL.match(/\/cache_details\.aspx/i)) { // CACHE PAGE
Page_Name = 'cache';
Process_Cache_Page();
}
else if (Page_URL.match(/\/myfriends\.aspx/i) || // MY FRIENDS PAGE
Page_URL.match(/\/account\/default\.aspx/i) || // MY PROFILE PAGE
Page_URL.match(/\/account\/ManageFriends\.aspx/i) ) { // MANAGE FRIENDS PAGE
Page_Name = 'friends';
Add_Badges_to_Friends_List();
VIP_Displayed_List = VIP_Working_List;
Displayed_Prefs = Working_Prefs;
Set_Display_Update_Time();
Start_Update_Thread();
}
else if (Page_URL.match(/\/profile/i)) { // USER PROFILE PAGE
Page_Name = 'profile';
Add_Badge_to_Profile_Page();
VIP_Displayed_List = VIP_Working_List;
Displayed_Prefs = Working_Prefs;
Set_Display_Update_Time();
Start_Update_Thread();
}
else if (Page_URL.match(/\/my\/favorites\.aspx/i)) { // MY FAVORITE LIST
Page_Name = 'favoritesList';
Add_Badges_to_Favorite_List();
VIP_Displayed_List = VIP_Working_List;
Displayed_Prefs = Working_Prefs;
Set_Display_Update_Time();
Start_Update_Thread();
}
else if (Page_URL.match(/\/cache_favorited\.aspx/i)) { // USERS WHO FAVORITED THIS CACHE
Page_Name = 'favoriteCache';
Add_Badges_to_Favorite_List();
VIP_Displayed_List = VIP_Working_List;
Displayed_Prefs = Working_Prefs;
Set_Display_Update_Time();
Start_Update_Thread();
}
else {
Debug_Log('No page match for ' + Page_URL);
}
Debug_Log('script run time: ' + (new Date().getTime() - SCRIPT_START_TIME.getTime()));
}
})();