Skip to content

Instantly share code, notes, and snippets.

@trlkly
Last active February 18, 2018 02:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trlkly/5ec05f7953d57899ea03a5613466d114 to your computer and use it in GitHub Desktop.
Save trlkly/5ec05f7953d57899ea03a5613466d114 to your computer and use it in GitHub Desktop.
Less limited GreaseMonkey 4 drop-in shim **UNTESTED**
/*
Portions of this script are copied from https://gist.github.com/arantius/3123124
under the following license and permission:
The MIT License (MIT)
Copyright (c) 2014 Anthony Lieuallen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
NOT IMPLEMENTED:
* GM_getResourceText
* GM_registerMenuCommand
INFERIOR TO ORIGINAL
* GM_getValue
* GM_setValue
* GM_listValues
* GM_getResourceURL
*/
// Directly replaced functions that are always available:
if ('undefined' === typeof GM_info && 'undefined' !== typeof GM) { const GM_info = GM.info; }
if ('undefined' === typeof GM_log) { const GM_log = console.log; }
// Directly replaced, but require additional @grant:
if ('undefined' !== typeof GM) {
if ('undefined' === typeof GM_xmlhttpRequest) { const GM_xmlhttpRequest = GM.xmlHttpRequest; }
if ('undefined' === typeof GM_openInTab) { const GM_openInTab = GM.openInTab; }
if ('undefined' === typeof GM_setClipboard) { const GM_setClipboard = GM.setClipboard; }
}
// Shimmed functions (always available):
if ('undefined' === typeof GM_addStyle) {
const GM_addStyle = function (aCss) {
'use strict';
let head = document.head || document.documentElement;
if (head) {
let style = document.createElement('style');
style.setAttribute('type', 'text/css');
style.textContent = aCss;
head.appendChild(style);
return style;
} else { //if document isn't ready, try again when it is
var observer = new MutationObserver( () => {
GM_addStyle(aCss);
observer.disconnect();
});
observer.observe(document, { childList: true });
return null;
}
};
}
// Shimmed function that loads resource from the web, not from disk:
if ('undefined' === typeof GM_getResourceURL) {
const GM_getResourceURL = function(resource) {
'use strict';
return GM_info.script.resources[resource].url;
};
}
// Shimmed functions that rely on DOM Storage localStorage facility
// These work like always, but saved values will be domain-specific.
// This means values saved on one site will not transfer to another
// site. Bypassing this requires a more slower but more powerful shim.
const __GM_STORAGE_PREFIX = [
'', GM_info.script.namespace, GM_info.script.name, ''].join('***');
if ('undefined' === typeof GM_deleteValue) {
const GM_deleteValue = function (aKey) {
'use strict';
localStorage.removeItem(__GM_STORAGE_PREFIX + aKey);
};
}
if ('undefined' == typeof GM_getValue) {
const GM_getValue = function (aKey, aDefault) {
'use strict';
let val = localStorage.getItem(__GM_STORAGE_PREFIX + aKey);
if (null === val && 'undefined' != typeof aDefault) return aDefault;
return val;
};
}
if ('undefined' === typeof GM_listValues) {
const GM_listValues = function () {
'use strict';
let prefixLen = __GM_STORAGE_PREFIX.length;
let values = [];
let i = 0;
for (let i = 0; i < localStorage.length; i++) {
let k = localStorage.key(i);
if (k.substr(0, prefixLen) === __GM_STORAGE_PREFIX) {
values.push(k.substr(prefixLen));
}
}
return values;
};
}
if ('undefined' === typeof GM_setValue) {
const __GM_SET_VALUE_SHIMMED = true;
let GM_setValue = function (aKey, aVal) {
'use strict';
localStorage.setItem(__GM_STORAGE_PREFIX + aKey, aVal);
};
}
//require this script AFTER the first if you need storage on multiple URLs
//You must also @grant GM.setValue and GM.getValue
//For best results, change your script to @run-at document-start
//and encase it in the appropriate addEventListener instead.
//If you need to start as soon as possible, listen for the custom event
//'DOMStorageLoaded' on the main window object.
if ('undefined' !== typeof __GM_SET_VALUE_SHIMMED && 'undefined' !== typeof GM && GM.setValue && GM.getValue) {
var GM_values;
(async function() {
var GM_values = JSON.parse(await GM.getValue('values'));
Object.keys(GM_values).forEach(GM_setValue);
var finished = new Event('DOMStorageLoaded');
window.dispatchEvent(finished);
})();
GM_setValue = function (aKey, aVal) {
'use strict';
localStorage.setItem(__GM_STORAGE_PREFIX + aKey, aVal);
GM_values[aKey] = aVal;
GM.setValue('values', JSON.stringify(values));
};
}
@trlkly
Copy link
Author

trlkly commented Feb 18, 2018

Use these scripts as a quick-fix to get GM4 support. Moving to the Promise API is probably a better longterm solution.

Note that these scripts have not been tested, and will ignore the items already in storage. If you use the second script, a single object is written to storage that contains all values, because this is faster with the new API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment