how to change content of external javascript with javascript - javascript

im working on a userscript for youtube, so i cant change the actual file on their server, but i need a way to change one of the functions in it.
the function seems to not exist before and after it runs.
i could probably change the URL of the file in the html, for example with:
document.body.innerHTML = document.body.innerHTML.replace( /*javascript file URL before*/g, "*after*");
but im afraid the file is called from other places too, like somewhere in their obfuscated javascript i cant make out, so it would be better to not change its URL, but the code the page loads from it.
i dont know how though. is there maybe a way to listen to when a function is called from the file, and give a different code instead?

Just override the javascript function like:
yourFunction = function(a){
alert(a)
};

Related

Is it possible to debug JS when the URL keeps changing?

I'm trying to debug the JavaScript of a website which references some JS via a random URL path each pageload. This makes Chrome think that the JS is a different document, but I can see the same JS is being served up each time. However, breakpoints don't stay because the URL is different.
Is there a way I can get breakpoints to stay somehow between page loads of the same JS with different URL paths, or maybe break on function name instead of the normal way?
The only way i think is to put
debugger;
everywhere you wanted the breakpoint. As you have rightly understood that the browser considers it as a new file, and there is no way to tell the browser that it is same file when the URL is different.

Android variable to JavaScript

I am building an Android WebView which loads an url on a server of mine. However, now I want to use an identifier from the Android as parameter of a function on the JS code and I simply can't do it.
I already tried appending "javascript:myFunction(myParameter);" to the url on the loadUrl method and tried adding a JavascriptInterface. Neither of them did work, and it looked like it needed my files (html and js) to be local. However, I need to open a xml document and, as far as I know, you can't do it with local files, so I couldn't test it.
I am not used to web/android dev, so I don't even know if I'm not trying to do something dumb, but it seems to me that it should be simple to do and yet I'm stuck on it. Thanks in advance.
Add the variable to the URL, for example:
file://my/file.html?variable=someValue
You should then be able to parse the URL in JS using document.location, for example:
alert(document.location);

Call a function in one Javascript file from another Javascript file?

I need to call a function in an external ".js" file from another ".js" file, without referencing the external file in the <head> tag.
I know that it is possible to dynamically add an external ".js" file to the which allows access to that file, i can do that like so...
var AppFile = "test/testApp_1.js";
var NewScript=document.createElement('script');
var headID = document.getElementsByTagName("head")[0];
NewScript.src = AppFile;
headID.appendChild(NewScript);
However...
this is no use to me as the external files need to be stand-alone files that run start-up procedures on...
$(document).ready(function()
{...}
so adding the full file dynamically has an unwanted affect. Also, i cannot pre-reference the external file in the <head> tag as it needs to be dynamic.
So, this external file "test/testApp_1.js" contains a function that returns a string variable...
function setAppLogo(){
var LogoFile = "test/TestApp_1_Logo.png";
return LogoFile;
}
I need access to either this function, or I could store the string as a global var in the external file... either way is fine, I just need access to the value in LogoFile without loading the whole external file.
This one has had me stumped for a few hours now so any ideas would be greatly appreciated.
You might benefit from having some sort of app.js file that contains global variables/values that you will want to use from lots of places. You should include this .js file on every page (and maybe minify it/concatenate it with other js if you want to be clever and improve performance). Generally these globals should be attached to some object you create such as var APPNAME = { }; with variables/functions on it that will be used from many places.
Once you have this, then the external '.js' file that you want to load, and the one you are currently in, can both access the global APPNAME variable and all its attributes/functions and use them as desired. This may be a better approach for making your javascript more modular and separatable. Hope this helps.
You want to load the file once jQuery has loaded using ajax, and then run the related script in the successful ajax function.
See jQuery's getScript function: http://api.jquery.com/jQuery.getScript/
$(document).ready(function(){
$.getScript("http://domain.com/ajax/test.js", function(data, textStatus, jqxhr) {
console.log(data); //data returned
console.log(textStatus); //success
console.log(jqxhr.status); //200
console.log('Load was performed.');
//run your second script executable code here
});
});
It is possible to load the whole script through XHR (e.g. $.get in jQuery) and then parse it, perhaps using a regular expression, to extract the needed part:
$.get('pathtoscript.js', function(scriptBody) {
var regex = /function\s+setUpLogo\(\)\s*\{[^}]+}/g;
alert(scriptBody.match(regex)[0]); // supposed to output a function called
// 'setUpLogo' from the script, if the
// function does not have {} blocks inside
});
Nevertheless, it shall be noted that such an approach is highly likely to trigger maintenance obstacles. Regular expressions are not a best tool to parse JavaScript code; the example above, for instance, will not parse functions with nested {} blocks, which may well exist in the code in question.
It might be recommended to find a server-side solution to the problem, e.g. adding necessary script path or its part before the page is sent to browser.
I'm not sure this is a good idea but you can create an iframe and eval the file inside its 'window' object to avoid most of the undesired side effects (assuming it does not try to access its parent). Then you can access whatever function/variable you want via the iframe's window object.
Example:
function loadSomeJsInAFrame(url,cb) {
jQuery.get(url,function(res) {
iframe = jQuery('<iframe></iframe>').hide().appendTo(document.body);
iframe[0].contentWindow.eval(res);
if(cb) cb(iframe[0].contentWindow);
},'text');
}
loadSomeJsInAFrame('test/testApp_1.js',function(frameWindow) {
console.log(frameWindow.setAppLogo());
jQuery(frameWindow.frameElement).remove();
});
This will not guarantee that the sript in the file can not mess with your document, but not likely if it comes from a trusted source.
Also, don't forget to remove your iframe after you get what you need from it.
Ok, thanks everybody for all the input but i think that what I was trying to do is currently not possible, i.e. accessing a function from another file without loading that file.
I have however found a solution to my problem. I now query my server for a list of apps that are available, i then use this list to dynamically build the apps in a UI. when an app is then selected i can then call that file and the functions within. Its a bit more complex but its dynamic, has good performance and, it works. Thanks again for the brainstorming! ;)
It may be possible with the help of Web Workers. You would be able to run your script you've wanted to inject in kinda isolated environment, so it won't mess up your current page.
As you said, it is possible for setAppLogo to be global within "test/testApp_1.js", so I will rely on this statement.
In your original script you should create a worker, which references to a worker script file + listen to messages that would come from the worker:
var worker = new Worker('worker.js');
worker.onmessage = function (e) {
// ....
};
Then, in the worker (worker.js), you could use special function importScripts (docs) which allows to load external scripts in worker, the worker can also see global variables of these scripts. Also there is a function postMessage available in worker to send custom messages back to original script, which in turn is listening to these messages (worker.onmessage). Code for worker.js:
importScripts('test/testApp_1.js');
// "setAppLogo" is now available to worker as it is global in 'test/testApp_1.js'
// use Worker API to send message back to original script
postMessage(setAppLogo());
When it invokes you'll get the result of setAppLogo in you listener:
worker.onmessage = function (e) {
console.log(e.data); // "test/TestApp_1_Logo.png"
};
This example is very basic though, you should read more about Web Workers API and possible pitfalls.

Is it possible to set the source of an image using the javascript: pseudo-protocol?

Basically, I have a context where I'm only allowed to create an image, but I want to run a script before I decide on the source, so I'm wondering if this is possible:
<img src="javascript:{load a remote script and run it to figure out the source}" />
The work-around that I've come up with is:
<img src="any-old-image.gif" onload="document.write('<scr' + 'ipt src=\"http://mysite-script.js\"'></scr' + 'pt>');" />
but I'm hoping something a little cleaner is possible.
P.S. I'm aware that "javascript:" is quote-unquote evil. This is a special situation.
Create a function that gathers whatever data you need and sends it to the server (via XMLHttpRequest, or whatever method you prefer). Create a function that examines the response from the server and decides what image to use. You can then set the url to your image directly:
document.getElementById("myImage").src = myImageSrc;
Edit: Addressing comment.
If you can only muck with the img element itself, then you are right, img.onload is what you want. And if there's more than just a couple of lines of script, importing the script seems reasonable. Maybe this is a little bit cleaner than document.write:
document.body.appendChild(document.createElement("script")).src =
"http://mysite.com/myscript.js";
If what you want can be done on the server. You could just make the src attribute point your server side script and write back the image after executing whatever you want.
Not sure if that fits your issue though.

JSONP for cross-site bookmarklet guidance

I'm looking to build a cross-site bookmarklet that gets a highlighted word, passes it to a CodeIgniter method (domain.com/controller/method), and returns the definition via a dictionary API. I've got a skeleton working well on a single domain, but I'm looking to expand it to use JSONP cross-domain. But I feel unclear.
I know I need to load a script from a remote location and inject it in the current context. And I believe I'll need to get the highlighted word on a page, then call a URL that looks like domain.com/controller/method/word to get that script. Then it gets foggy.
I think I essentially have two questions:
Where do I include the necessary javascript to handle the parsing and passing of the word via XMLHTTPRequest? I think this will be the SRC of the script that I'll inject in the new context. Is this somehow within my relevant CodeIgniter method? Or does this new script come from a random location on the same server as the relevant method and simply call to it?
Answer: This is not supplementary to XMLHTTPRequest, this is in lieu of it, so that step is completely removed. The new script calls to the method, passes requisite information via query strings, and receives the JSON array in response.
Am I correct in understanding I'll eventually pass the JSON response from the method back as word(json_encode($array));?
Answer: Yes, I'll pass that back as callbackFunctionName(json_encode($array));.
Do I need to set headers, as done here?
Update
I included the answers to two of my three answers above. If someone can explain things thoroughly, of course I'll mark their answer as correct, else I'll elaborate my stumbling blocks in an answer. I still have no idea where I write the callback function and what I'll be doing with that in JS.
Thanks so much for any help you can give on this.
First set your bookmarklet with a link you can drop on the bookmark bar:
<html>
<head></head>
<body>
load
</body>
</html>
Replace the url by your script, it will be loaded and running on the host page.
However it sits now in the hosted page, and can't call your server with XMLHTTPRequest as the domains do not match.
Here comes JSONP.
In the loaded script, you can put a function eg: function srvCallback(json){...}
When you want to call your server you will inject it as a script using a similar function as in the bookmarklet above:
function jsonp(src){
var s = document.createElement('script');
old = document.getElementById('srvCall');
old && document.body.removeChild(old);
s.charset = 'UTF-8';
s.id = 'srvCall';
document.body.insertBefore(s, document.body.firstChild);
s.src = src + '?' + new Date().getTime();
}
Inject your request, eg:
jsonp('http://domain.com/controller/method/word')
The server should respond something like:
srvCallback({word:'hello'});
And finally the function srvCallback is automatically called, inside the function you get your JSON and show the result to the user.

Categories

Resources