There are 16 previous versions of this script.
/*
Google Date Keeper
First release: 17 Dec 2008, v0.1.0 (Greasemonkey version)
UPDATES
* * * * * *
[ 13 Nov 2009 ]
v.0.4.3 - [ * ] More complete testing of parameters when setting date selector value
v.0.4.2 - [ * ] Change regular expression for responseText.
v.0.4.1 - [ * ] Change addEventListener to target document instead of date selector itself
v.0.4.0 - [ * ] Test page with language input node instead (neccessary for certain sites). Script will run only if test pass.
v.0.3.9 - [ + ] Redirect sites with # to search?
v.0.3.8 - [ * ] Change @include from search* to *
v.0.3.7 - [ - ] Remove checking of url in script. Use only @include.
[ 30 Oct 2009 ]
v.0.3.6 - [ + ] Make adjustment to synchronize with the new internal google date options
v.0.3.5 - [ - ] Remove feature that show date info when date option is at "anytime"
v.0.3.4 - [ * ] Auto version checker feature: Fix bug that only check when date option is not set at "anytime"
*/
// ==UserScript==
// @name Google Date Keeper
// @namespace http://userscripts.org/scripts/show/38800
// @description Date dropdowns disappearing at google search? Try this persistent date selector! Works for all countries and languages + Has extended date features! Easy, intuitive and flexible.
// @include http://www.google.*/*
// @exclude
// @svc:version [0.4.3]
// ==/UserScript==
var gdk = {
dateSelectNode: null, submitNode: null, language: null, timer: null, keypressed: null,
init: function () {
gdk.redirect();
if (top != self) return;
// clean up unused GM_values
try { GM_deleteValue('showDateInfoForAllOption'); } catch (err) { }
gdk.language = document.evaluate("//input[@name='hl']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0).value;
if (!gdk.language) return;
gdk.testDateSelector();
gdk.common.init();
},
redirect: function () {
var re = /(https?:\/\/[^\/]+?\/)(#)/;
if (re.test(top.location.href)) top.location.href = top.location.href.replace(re,'$1search?').replace('fp=','');
},
refreshDateSelectNode: function () {
gdk.dateSelectNode = document.evaluate("//select[@name='as_qdr']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
},
testDateSelector: function () {
gdk.refreshDateSelectNode();
// if date selector already exist
if (gdk.dateSelectNode) {
// check page language with locally stored value
// If they don't match, retrieve and store date selector locally else do nothing
if (GM_getValue('language') != gdk.language) gdk.buildDateSelector.storeLocalValues(gdk.dateSelectNode.innerHTML);
return;
}
gdk.submitNode = document.evaluate("//input[@name='btnG']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
// check page language with locally stored value. If they match, build date selector
if (GM_getValue('language') == gdk.language && GM_getValue('dateselector') != "") {
gdk.buildDateSelector.start(GM_getValue('dateselector'));
return;
}
// build date selector from scatch
gdk.xmlHttpRequest.start();
},
xmlHttpRequest: {
start: function () {
GM_xmlhttpRequest({
method: 'GET', url: location.href.replace(/search\?/i, 'advanced_search?'),
onload: function (res) {
var responseText = gdk.xmlHttpRequest.processResponseText(res.responseText);
if (responseText != '') {
gdk.buildDateSelector.start(responseText);
gdk.buildDateSelector.storeLocalValues(responseText);
}
}
});
},
processResponseText: function (responseText) {
var re = /name=.?as_qdr.?>(.+?)<\/select>/;
if (re.test(responseText)) {
return (/name=.?as_qdr.?>(.+?)<\/select>/.exec(responseText)[1]);
} else {
return '';
}
},
},
buildDateSelector: {
start: function (htmlText) {
// CHECK IF USER'S SELECTION IS FOUND IN THE DROPDOWN
var dateValueAS;
var flag = false;
var re = /as_qdr=([a-zA-Z]+)(\d*)&|$/;
if (re.test(location.href)) {
dateValueAS = re.exec(location.href)[1];
if (re.exec(location.href)[2] == '') flag = true;
}
// ... when user's selection isn't found in the dropdown
if (flag == false) {
gdk.dateGoogle = document.evaluate("//input[@name='tbs']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
re = /qdr:(.)(\d*)$/;
if (gdk.dateGoogle && re.test(gdk.dateGoogle.value)) {
if (re.exec(gdk.dateGoogle.value)[2] == '') {
dateValueAS = re.exec(gdk.dateGoogle.value)[1];
flag = true;
} else {
var target = document.getElementById('prs');
var dateValueTB = re.exec(gdk.dateGoogle.value)[1];
var dateText = /<b>(.+)<\/b>/.exec(target.innerHTML)[1].toLowerCase();
htmlText = htmlText + '<option selected value="' + dateValueTB + '">' + dateText + '</option>';
}
} else {
dateValueAS = 'all';
flag = true;
}
}
// build date selector
var newTag = document.createElement('select');
newTag.name = "as_qdr";
newTag.setAttribute('style', 'margin-left: 3px; margin-right: 3px');
newTag.innerHTML = htmlText;
gdk.submitNode.parentNode.insertBefore(newTag, gdk.submitNode);
// refresh node
gdk.refreshDateSelectNode();
// ... when user's selection is found in the drop down
if (flag == true) if (dateValueAS) gdk.dateSelectNode.value = dateValueAS;
// remove duplicate input name=as_qdr
var node = document.evaluate("//input[@name='as_qdr']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
if (node) node.parentNode.removeChild(node);
},
storeLocalValues: function (htmlText) {
GM_setValue('language', gdk.language);
GM_setValue('dateselector', htmlText);
},
},
common: {
init: function () {
// add listeners
if (document.forms[0]) document.forms[0].addEventListener("submit", gdk.common.events.submit, true);
document.addEventListener('keydown', function (e) {
if (e.target.tagName == 'SELECT' && e.target.name == 'as_qdr') gdk.common.events.keyDownEvent(e);
}, false);
// THE "SCRIPT VERSION CHECKER"
GM_registerMenuCommand("Google Date Keeper (Check Latest Version)", SVC.versionInfo.manualChecking);
SVC.versionInfo.autoChecking();
},
events: {
submit: function () {
// when there is internal google date options
gdk.dateGoogle = document.evaluate("//input[@name='tbs']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
if (gdk.dateGoogle) {
gdk.refreshDateSelectNode();
var value = gdk.dateSelectNode.options[gdk.dateSelectNode.selectedIndex].value;
value == "all" ? gdk.dateGoogle.value = "" : gdk.dateGoogle.value = "qdr:" + value;
}
},
keyDownEvent: function (e) {
if ((e.which >=48 && e.which <=57) || (e.which >=96 && e.which <=105)) {
if (e.which >=48 && e.which <=57) // main number keys
gdk.keypressed ? gdk.keypressed = gdk.keypressed + String.fromCharCode(e.which)
: gdk.keypressed = String.fromCharCode(e.which);
if (e.which >=96 && e.which <=105) // num pad keys
gdk.keypressed ? gdk.keypressed = gdk.keypressed + String.fromCharCode(e.which-48)
: gdk.keypressed = String.fromCharCode(e.which-48);
gdk.timer = setTimeout(function () { gdk.common.timerReachedAction (e); }, 1000);
} else {
window.clearTimeout(gdk.timer);
gdk.keypressed = null;
}
},
},
timerReachedAction: function (e) {
if (e.target.value == 'all') return;
// update value in date select node
gdk.dateSelectNode.options[gdk.dateSelectNode.selectedIndex].value = e.target.value.substring(0,1) + /[1-9]\d*/.exec(gdk.keypressed);
// when there are internal google date options, update value in google date node
gdk.dateGoogle = document.evaluate("//input[@name='tbs']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
if (gdk.dateGoogle) gdk.dateGoogle.value = "qdr:" + gdk.dateSelectNode.options[gdk.dateSelectNode.selectedIndex].value
gdk.keypressed = null;
document.forms[0].submit();
},
},
};
// SCRIPT VERSION CHECKER
// VERSION 0.2.0
var SVC = {
currentVersion: "0.4.3",
scriptName: "Google Date Keeper",
scriptNum: 38800,
// GLOBAL SETTINGS
currentDate: null, userRequestCheck: null, timer: null,
init: function () {
SVC.currentDate = new Date();
var cv = parseInt(/[1-9][\d]*/.exec(SVC.currentVersion.replace(/\D/g, "")));
// INITIALIZE LOCAL VALUES (FOR FIRST-TIME USE)
if (!GM_getValue("latest")) GM_setValue("latest", cv );
if (!GM_getValue("notified")) GM_setValue("notified", false);
if (!GM_getValue("lastChecked")) GM_setValue("lastChecked", (SVC.currentDate.getTime() - 1000*60*60*25) + "");
// UPDATE LOCAL VALUES (FOR FIRST-TIME USE AFTER REINSTALL NEWER VERSION)
if (GM_getValue("latest") < cv) {
GM_setValue("latest", cv);
GM_setValue("notified", false);
GM_setValue("lastChecked", SVC.currentDate.getTime() + "");
}
},
verify: function () {
SVC.userRequestCheck = false;
var sp = SVC.currentDate.getTime() - parseInt(GM_getValue("lastChecked"));
// CHECK SOURCE IF USER HAS BEEN NOTIFIED OF AN UPDATED VERSION BEFORE AND 14 DAYS HAVE PASSED
if (GM_getValue("notified") && (sp / (1000*60*60*24) > 14)) SVC.getInfo();
// CHECK SOURCE FOR THE LATEST VERSION IF ONE DAY HAS PASSED SINCE LAST CHECKED
if (!GM_getValue("notified") && ( sp / (1000*60*60*24) > 1 )) SVC.getInfo();
},
getInfo: function () {
var uso = 'http://userscripts.org';
function retrieve(url, re, count) {
SVC.xhr.get(url, function (status, text) {
window.clearTimeout(SVC.timer);
if (status == 404 && SVC.userRequestCheck) SVC.manualErrorMsg();
if (status == 200) {
if (re.test(text)) var uv = re.exec(text)[1];
if (uv) SVC.compare(uv);
if (!uv && count == 1) {
retrieve(uso + '/scripts/show/' + SVC.scriptNum, /<h1.+>.+\s([^\s]+)<\/h1>/, 2);
} else if (!uv && SVC.userRequestCheck) {
SVC.manualErrorMsg();
}
}
});
SVC.timer = setTimeout(function () {
if (count == 1) retrieve(uso + '/scripts/show/' + SVC.scriptNum, /<h1.+>.+\s([^\s]+)<\/h1>/, 2);
if (count == 2) SVC.manualErrorMsg();
}, 2000);
};
retrieve(uso + '/scripts/source/' + SVC.scriptNum + '.meta.js', /@svc:version[\s]*\[(.+)\]/, 1);
},
xhr: {
get: function (url, process) {
GM_xmlhttpRequest({
method: 'GET',
url: url,
onload: function (res) { process(res.status, res.responseText); },
});
},
},
compare: function (version) {
var updatedVersionInt = parseInt(/[1-9][\d]*/.exec(version.replace(/\D/g, "")));
// DO NOTHING IF NO CHANGE IN VERSIONS
if (updatedVersionInt <= GM_getValue("latest")) {
if (SVC.userRequestCheck) alert('Auto-check completed!\n---------------------------\n\nYou are using the latest greasemonkey script \n\n~ ' + SVC.scriptName + ' ~ version ' + SVC.currentVersion + '.\n\n ');
return;
}
GM_setValue("notified", true);
GM_setValue("lastChecked", SVC.currentDate.getTime() + "");
// NOTIFY USER
if (SVC.userRequestCheck) {
var reply = confirm('Auto-check completed!\n---------------------------\n\nThe Greasemonkey Script ~ ' + SVC.scriptName + ' ~ has recently been updated to v.' + version + '. \n\nYou are currently using version ' + SVC.currentVersion + '.\nWould you like to visit the download page at userscript.org now?\n\n ');
if (reply) GM_openInTab("http://userscripts.org/scripts/show/" + SVC.scriptNum);
} else {
var reply = confirm('Latest news for Greasemonkey Scripts!\n-----------------------------------------------\n\nThe Greasemonkey Script ~ ' + SVC.scriptName + ' ~ has recently been updated to v.' + version + '. \n\nYour current working version is ' + SVC.currentVersion + '.\nWould you like to visit the download page at userscript.org now?\n\n ');
if (reply) GM_openInTab("http://userscripts.org/scripts/show/" + SVC.scriptNum);
}
},
versionInfo: {
autoChecking: function () {
SVC.init();
SVC.verify();
},
manualChecking: function () {
SVC.userRequestCheck = true;
SVC.getInfo();
},
},
manualErrorMsg: function () {
var reply = confirm('Alert!\n-------\n\nAuto-checking for the latest version of the Greasemonkey Script ~ ' + SVC.scriptName + ' ~ has not been successful.\n\nYou may wish to try again later or visit the download page to check manually. For your information, your current working version is ' + SVC.currentVersion + '. \n\nWould you like to visit the download page at userscript.org now?\n\n ');
if (reply) GM_openInTab("http://userscripts.org/scripts/show/" + SVC.scriptNum);
},
};
gdk.init();
