How to alter/remove this inline javascript with Greasemonkey? - javascript

I found this script in the head of a website:
<script type="text/javascript" >
function Ext_Detect_NotInstalled(ExtName,ExtID) {
}
function Ext_Detect_Installed(ExtName,ExtID) {
alert("We have found unwanted extension. Please contact support")
window.location = "logout.php"
}
var Ext_Detect = function(ExtName,ExtID) {
var s = document.createElement('script');
s.onload = function(){Ext_Detect_Installed(ExtName,ExtID);};
s.onerror = function(){Ext_Detect_NotInstalled(ExtName,ExtID);};
s.src = 'chrome-extension://' + ExtID + '/captured.js';
document.body.appendChild(s);
}
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
function displayErrorAndLogout() {
alert("Please use chrome browser to view the content");
window.location = "logout.php"
}
if (is_chrome==true)
{
window.onload = function() { Ext_Detect('Chrome','ngpampappnmepgilojfohadhhmbhlaek');};
} else {
is_chrome = navigator.userAgent.toLowerCase().indexOf('crios') > -1;
if (is_chrome == false){
if (detectIE()){
displayErrorAndLogout()
}
if (navigator.userAgent.indexOf('UCBrowser') > -1) {
displayErrorAndLogout()
}
This script check internet download manager extension and popup a logout message.
Is this possible to remove or alter this inline java script using Greasemonkey?

If you want to disable the check for the Chrome addon, it's easy: the script assigns a function to onload, so if you simply assign something else to onload, Ext_Detect will never run, and your extension will not be detected:
window.onload = () => null;
Unfortunately, the other part that checks for crios and UCBrowser and runs detectIE runs synchronously, presumably at the beginning of page load, and userscripts cannot reliably run at the very beginning of page load, so that behavior may not be possible to alter, though you could try it with #run-at document-start: displayErrorAndLogout calls alert before assigning to window.location, so if you make it so that alert throws an error, the location will not change:
#run-at document-start
// ==/UserScript==
window.alert = function() {
throw new Error();
};

Related

Execute Script tag using JS instead of PHP

I have a case in php, where I execute <script> tag of Adsense, if the userAgent is not BOT, but for some good reason I want to execute it using JS.
Helper Function:
function detectBottypes() {
$userAgent = strtolower($_SERVER['HTTP_USER_AGENT']);
if(!empty($userAgent) and preg_match('~(bot|crawl|google|lighthouse|spider|feedparser|crawler|pinterest)~i', $userAgent)) {
return true;
}
return false;
}
in View:
#if( Request::is('photo/*') && detectBottypes()==false )
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" crossorigin="anonymous">
</script>
#endif
Above, if request is photo/* and not bot then it is rendered in view, but I want it to be rendered in either of cases but only executed for the specific case.
I have the case of JS
window.onload = function () {
var agent = navigator.userAgent.toLowerCase();
if (agent.indexOf('bot') != -1) {
// ******* Execute here ********
}
else {
}
}
Reason why I want: I cache the view file to skip the load on server, so if the page is first crawled by Bot(Google) it is cached without the above case of Adsense Script ( Ad is not loaded to Bot) but since it is cached if later it is viewed by real user, the cached version without Ads is shown which I do not want, so preferred to be with JS
You can dynamically load a script with something like:
window.onload = function () {
var agent = navigator.userAgent.toLowerCase();
if (agent.indexOf('bot') != -1) {
var scriptTag = document.createElement('script');
scriptTag.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
scriptTag.async = true;
scriptTag.type = 'text/javascript';
scriptTag.crossorigin = 'anonymous';
document.head.prepend(scriptTag);
} else {
}
}
This should cause the browser to download and run the script. However there's a broader question on your use of caching. It may be simpler if you cache two versions of the content and serve each one based on the UA, if that is an option.

load inserted script, making sure that libraries load first [duplicate]

I'm creating a jquery plugin and I want to verify an external script is loaded. This is for an internal web app and I can keep the script name/location consistent(mysscript.js). This is also an ajaxy plugin that can be called on many times on the page.
If I can verify the script is not loaded I'll load it using:
jQuery.getScript()
How can I verify the script is loaded because I don't want the same script loaded on the page more than once? Is this something that I shouldn't need to worry about due to caching of the script?
Update:
I may not have control over who uses this plugin in our organization and may not be able to enforce that the script is not already on the page with or without a specific ID, but the script name will always be in the same place with the same name. I'm hoping I can use the name of the script to verify it's actually loaded.
If the script creates any variables or functions in the global space you can check for their existance:
External JS (in global scope) --
var myCustomFlag = true;
And to check if this has run:
if (typeof window.myCustomFlag == 'undefined') {
//the flag was not found, so the code has not run
$.getScript('<external JS>');
}
Update
You can check for the existence of the <script> tag in question by selecting all of the <script> elements and checking their src attributes:
//get the number of `<script>` elements that have the correct `src` attribute
var len = $('script').filter(function () {
return ($(this).attr('src') == '<external JS>');
}).length;
//if there are no scripts that match, the load it
if (len === 0) {
$.getScript('<external JS>');
}
Or you can just bake this .filter() functionality right into the selector:
var len = $('script[src="<external JS>"]').length;
Few too many answers on this one, but I feel it's worth adding this solution. It combines a few different answers.
Key points for me were
add an #id tag, so it's easy to find, and not duplicate
Use .onload() to wait until the script has finished loading before using it
mounted() {
// First check if the script already exists on the dom
// by searching for an id
let id = 'googleMaps'
if(document.getElementById(id) === null) {
let script = document.createElement('script')
script.setAttribute('src', 'https://maps.googleapis.com/maps/api/js?key=' + apiKey)
script.setAttribute('id', id)
document.body.appendChild(script)
// now wait for it to load...
script.onload = () => {
// script has loaded, you can now use it safely
alert('thank me later')
// ... do something with the newly loaded script
}
}
}
#jasper's answer is totally correct but with modern browsers, a standard Javascript solution could be:
function isScriptLoaded(src)
{
return Boolean(document.querySelector('script[src="' + src + '"]'));
}
UPDATE July 2021:
The accepted solutions above have changed & improved much over time. The scope of my previous answer above was only to detect if the script was inserted in the document to load (and not whether the script has actually finished loading).
To detect if the script has already loaded, I use the following method (in general):
Create a common library function to dynamically load all scripts.
Before loading, it uses the isScriptLoaded(src) function above to check whether the script has already been added (say, by another module).
I use something like the following loadScript() function to load the script that uses callback functions to inform the calling modules if the script finished loading successfully.
I also use additional logic to retry when script loading fails (in case of temporary network issues).
Retry is done by removing the <script> tag from the body and adding it again.
If it still fails to load after configured number of retries, the <script> tag is removed from the body.
I have removed that logic from the following code for simplicity. It should be easy to add.
/**
* Mark/store the script as fully loaded in a global variable.
* #param src URL of the script
*/
function markScriptFullyLoaded(src) {
window.scriptLoadMap[src] = true;
}
/**
* Returns true if the script has been added to the page
* #param src URL of the script
*/
function isScriptAdded(src) {
return Boolean(document.querySelector('script[src="' + src + '"]'));
}
/**
* Returns true if the script has been fully loaded
* #param src URL of the script
*/
function isScriptFullyLoaded(src) {
return src in window.scriptLoadMap && window.scriptLoadMap[src];
}
/**
* Load a script.
* #param src URL of the script
* #param onLoadCallback Callback function when the script is fully loaded
* #param onLoadErrorCallback Callback function when the script fails to load
* #param retryCount How many times retry laoding the script? (Not implimented here. Logic goes into js.onerror function)
*/
function loadScript(src, onLoadCallback, onLoadErrorCallback, retryCount) {
if (!src) return;
// Check if the script is already loaded
if ( isScriptAdded(src) )
{
// If script already loaded successfully, trigger the callback function
if (isScriptFullyLoaded(src)) onLoadCallback();
console.warn("Script already loaded. Skipping: ", src);
return;
}
// Loading the script...
const js = document.createElement('script');
js.setAttribute("async", "");
js.src = src;
js.onload = () => {
markScriptFullyLoaded(src)
// Optional callback on script load
if (onLoadCallback) onLoadCallback();
};
js.onerror = () => {
// Remove the script node (to be able to try again later)
const js2 = document.querySelector('script[src="' + src +'"]');
js2.parentNode.removeChild(js2);
// Optional callback on script load failure
if (onLoadErrorCallback) onLoadErrorCallback();
};
document.head.appendChild(js);
}
This was very simple now that I realize how to do it, thanks to all the answers for leading me to the solution. I had to abandon $.getScript() in order to specify the source of the script...sometimes doing things manually is best.
Solution
//great suggestion #Jasper
var len = $('script[src*="Javascript/MyScript.js"]').length;
if (len === 0) {
alert('script not loaded');
loadScript('Javascript/MyScript.js');
if ($('script[src*="Javascript/MyScript.js"]').length === 0) {
alert('still not loaded');
}
else {
alert('loaded now');
}
}
else {
alert('script loaded');
}
function loadScript(scriptLocationAndName) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = scriptLocationAndName;
head.appendChild(script);
}
Create the script tag with a specific ID and then check if that ID exists?
Alternatively, loop through script tags checking for the script 'src' and make sure those are not already loaded with the same value as the one you want to avoid ?
Edit: following feedback that a code example would be useful:
(function(){
var desiredSource = 'https://sitename.com/js/script.js';
var scripts = document.getElementsByTagName('script');
var alreadyLoaded = false;
if(scripts.length){
for(var scriptIndex in scripts) {
if(!alreadyLoaded && desiredSource === scripts[scriptIndex].src) {
alreadyLoaded = true;
}
}
}
if(!alreadyLoaded){
// Run your code in this block?
}
})();
As mentioned in the comments (https://stackoverflow.com/users/1358777/alwin-kesler), this may be an alternative (not benchmarked):
(function(){
var desiredSource = 'https://sitename.com/js/script.js';
var scripts = document.getElementsByTagName('script');
var alreadyLoaded = false;
for(var scriptIndex in document.scripts) {
if(!alreadyLoaded && desiredSource === scripts[scriptIndex].src) {
alreadyLoaded = true;
}
}
if(!alreadyLoaded){
// Run your code in this block?
}
})();
Simply check if the global variable is available, if not check again. In order to prevent the maximum callstack being exceeded set a 100ms timeout on the check:
function check_script_loaded(glob_var) {
if(typeof(glob_var) !== 'undefined') {
// do your thing
} else {
setTimeout(function() {
check_script_loaded(glob_var)
}, 100)
}
}
Another way to check an external script is loaded or not, you can use data function of jquery and store a validation flag. Example as :
if(!$("body").data("google-map"))
{
console.log("no js");
$.getScript("https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&callback=initilize",function(){
$("body").data("google-map",true);
},function(){
alert("error while loading script");
});
}
}
else
{
console.log("js already loaded");
}
I think it's better to use window.addEventListener('error') to capture the script load error and try to load it again.
It's useful when we load scripts from a CDN server. If we can't load script from the CDN, we can load it from our server.
window.addEventListener('error', function(e) {
if (e.target.nodeName === 'SCRIPT') {
var scriptTag = document.createElement('script');
scriptTag.src = e.target.src.replace('https://static.cdn.com/', '/our-server/static/');
document.head.appendChild(scriptTag);
}
}, true);
Merging several answers from above into an easy to use function
function GetScriptIfNotLoaded(scriptLocationAndName)
{
var len = $('script[src*="' + scriptLocationAndName +'"]').length;
//script already loaded!
if (len > 0)
return;
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = scriptLocationAndName;
head.appendChild(script);
}
My idead is to listen the error log if there is an error on script loading.
const checkSegmentBlocked = (e) => {
if (e.target.nodeName === 'SCRIPT' && e.target.src.includes('analytics.min.js')) {
window.isSegmentBlocked = true;
e.target.removeEventListener(e.type, checkSegmentBlocked);
}
};
window.addEventListener('error', checkSegmentBlocked, true);
Some answers on this page are wrong. They check for the existence of the <script> tag - but that is not enough. That tells you that the tag was inserted into the DOM, not that the script is finished loading.
I assume from the question that there are two parts: the code that inserts the script, and the code that checks whether the script has loaded.
The code that dynamically inserts the script:
let tag = document.createElement('script');
tag.type = 'text/javascript';
tag.id = 'foo';
tag.src = 'https://cdn.example.com/foo.min.js';
tag.onload = () => tag.setAttribute('data-loaded', true); // magic sauce
document.body.appendChild(tag);
Some other code, that checks whether the script has loaded:
let script = document.getElementById('foo');
let isLoaded = script && script.getAttribute('data-loaded') === 'true';
console.log(isLoaded); // true
If the both of those things (inserting and checking) are in the same code block, then you could simplify the above:
tag.onload = () => console.log('loaded');
I found a quick tip before you start diving into code that might save a bit of time. Check devtools on the webpage and click on the network tab. The js scripts are shown if they are loaded as a 200 response from the server.

pop up to open pdf does not work on Internet explorer

i use a little java script to open pdf documents in a smaller tab:
// JavaScript Document
function openHeyPopup(objectLink) {
window.open(objectLink, "Externer Link", "width=700,height=600,scrollbars=yes");
}
function initHeyPopup()
{
if (!document.getElementsByTagName){ return; }
var anchors = document.getElementsByTagName("a");
// loop through all anchor tags
for (var i=0; i<anchors.length; i++){
var anchor = anchors[i];
if (anchor.getAttribute("href") && (anchor.getAttribute("rel") == "heypopup")){
anchor.onclick = function () {openHeyPopup(this); return false;}
}
}
}
function addLoadEvent(func)
{
var oldonload = window.onload;
if (typeof window.onload != 'function'){
window.onload = func;
} else {
window.onload = function(){
oldonload();
func();
}
}
}
addLoadEvent(initHeyPopup); // run initLightbox onLoad
This works fine for chrome and firefox. But in Internet explorer i get a empty browser window.
http://www.interieursalon.com/wp/wp-content/uploads/2016/08/web-interieursalon-portfolio.pdf
Anybody no how can i fix this for IE?
Best regards
In IE due to security reasons, opening new tabs with insecure content is blocked. we can try out this below code which helps us in downloading the file.
//window.navigator checks for IE version if yes, it gets executed and in place of data give your blob.
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
return window.navigator.msSaveOrOpenBlob(data, "data.pdf");
}

Browser Update Script

Browser-Update.org provides a nice piece of javascript which alerts users of out-of-date browsers to update them. Unfortunately (a) IE7 is not included in the default list of out-of-date browsers, and (b) the script doesn't work over SSL.
The script they suggest is
<script type="text/javascript">
var $buoop = {}
$buoop.ol = window.onload;
window.onload=function(){
try {if ($buoop.ol) $buoop.ol();}catch (e) {}
var e = document.createElement("script");
e.setAttribute("type", "text/javascript");
e.setAttribute("src", "http://browser-update.org/update.js");
document.body.appendChild(e);
}
</script>
Instead, I'm using external javascript as follows:
app.onload(function() {
if ('https:' === document.location.protocol) return; // Browser Update script is not currently available over SSL.
var $buoop = {vs:{i:7,f:2,o:10.5,s:2,n:9}};
var e = document.createElement('script');
e.setAttribute('type', 'text/javascript');
e.setAttribute('src', 'http://browser-update.org/update.js');
document.body.appendChild(e);
});
To be clear: app.onload() is a nice function which adds functions to the window.onload handler.
This seems to work, but there's an unfortunate side-effect. If the alert is dismissed, it shouldn't show again in that browsing session. With the script above, that doesn't seem to work. On IE7, the alert happens on each page load. Is there a way around that?
var _shown = false;
app.onload(function() {
if(!_shown) {
if ('https:' === document.location.protocol) return; // Browser Update script is not currently available over SSL.
var $buoop = {vs:{i:7,f:2,o:10.5,s:2,n:9}};
var e = document.createElement('script');
e.setAttribute('type', 'text/javascript');
e.setAttribute('src', 'http://browser-update.org/update.js');
document.body.appendChild(e);
_shown = true;
}
});
and if the page is reloading between navigation store it in a cookie or as a session variable.
you could save a cookie when the alert is shown and check every time if that cookie exists before showing the alert.

Bookmarklet wait until Javascript is loaded

I've got a bookmarklet which loads jQuery and some other js libraries.
How do I:
Wait until the javascript library I'm using is available/loaded. If I try to use the script before it has finished loading, like using the $ function with jQuery before it's loaded, an undefined exception is thrown.
Insure that the bookmarklet I load won't be cached (without using a server header, or obviously, being that this is a javascript file: a metatag)
Is anyone aware if onload for dynamically added javascript works in IE? (to contradict this post)
What's the simplest solution, cleanest resolution to these issues?
It depends on how you are actually loading jQuery. If you are appending a script element to the page, you can use the same technique that jQuery uses to dynamically load a script.
EDIT: I did my homework and actually extracted a loadScript function from the jQuery code to use in your bookmarklet. It might actually be useful to many (including me).
function loadScript(url, callback)
{
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = url;
// Attach handlers for all browsers
var done = false;
script.onload = script.onreadystatechange = function()
{
if( !done && ( !this.readyState
|| this.readyState == "loaded"
|| this.readyState == "complete") )
{
done = true;
// Continue your code
callback();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
head.removeChild( script );
}
};
head.appendChild(script);
}
// Usage:
// This code loads jQuery and executes some code when jQuery is loaded
loadScript("https://code.jquery.com/jquery-latest.js", function()
{
$('my_element').hide();
});
To answer your first question: Javascript is interpreted sequentially, so any following bookmarklet code will not execute until the library is loaded (assuming the library was interpreted successfully - no syntax errors).
To prevent the files from being cached, you can append a meaningless query string...
url = 'jquery.js?x=' + new Date().getTime();
I've paid an attention that in Chrome the order of scripts that are loaded is undetermined, when using #Vincent Robert's technique. In this case a little modification helps:
(function() {
var callback = function() {
// Do you work
};
// check for our library existence
if (typeof (MyLib) == 'undefined') {
var sources = [
'http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js',
'https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js',
'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js',
'http://myhost.com/javascripts/mylib.min.js'];
var loadNextScript = function() {
if (sources.length > 0) {
var script = document.createElement('script');
script.src = sources.shift();
document.body.appendChild(script);
var done = false;
script.onload = script.onreadystatechange = function() {
if (!done
&& (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) {
done = true;
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
loadNextScript();
}
}
} else {
callback();
}
}
loadNextScript();
} else {
callback();
}
})();
I got a little closer with this, but not completely. It would be nice to have a discrete, example of a bookmarklet that demonstrated how to avoided caching.

Categories

Resources