Could someone please explain the behaviour of jQuery's getScript() function?
Consider a javascript file test.js:
var tmp = 'a variable';
alert('here');
When test.js is loaded via html's <script> tag, everything works fine: tmp variable is available in the global scope and a message box appears.
I'm trying to get the similar behavior via this code:
<script>
$(document).ready(function() {
$.getScript("static/js/proto/test.js");
setTimeout(function() {
// at this point tmp should be available
// in the global scope
alert(tmp);
} , 2000); // 2 seconds timeout
}
</script>
But browser's error console reports an "Undefined variable tmp" error.
What am I doing wrong?
Thank you.
$.getScript may be asynchronous, use the callback parameter:
$.getScript("static/js/proto/test.js", function() {
// here you are sure that the script has been executed
});
See the documentation for $.getScript: http://api.jquery.com/jQuery.getScript
The real problem with the script was my lack of experience with JS in general and particulary in AJAX: I was trying to run this script on a local machine without a web server.
Guess what: AJAX expects status '200' from a web server to load a document asynchronously. As there was no web server, the status of the async call was '0'.
Thank you everyone for answering.
Related
Here is my problem, I want to call Java method like window.jsBridge which is defined in java via:
CustomChromeClient client = new CustomChromeClient(
"jsBridge", WebCallJsFunction.class);
mWebView.setWebChromeClient(client);
mWebView.loadUrl("file:///android_asset/test.html");
and in my html:
<body>
</script>
document.write(window.jsBridge.getSomething())
</script>
</body>
The page will show nothing, because window.jsBridge is undefined, but if I chage it to this:
setTimeout(() => {
document.write(window.jsBridge.getSomething())
}, 500)
the page will write the correct thing. I guess the reason is that the java method: mWebView.setWebChromeClient(client) is executing with the js in text.html at the same time, and when the js run: document.write(window.jsBridge.getSomething()) then java code has not executed completed, am I right? So how to solve this problem?
I recently updated Chrome to version 55.0.2883.75.
I am using a self developed Chrome Plugin to parse my HTML files wherein I use chrome.tabs.executescript to get data from background HTML page.
So when I execute chrome.extension.onRequest, I save the background page's parsed data to a global variable and access it in the callback function of chrome.tabs.executescript and process it.
This was working fine till I update to Version 55.0.2883.75.
How can I access the global variables in the new version ??
My Code Below :
Step 1 :
chrome.extension.onRequest.addListener(
function (request, sender, sendResponse) {
parser = new DOMParser();
htmlDoc = parser.parseFromString(request.content, "text/html");
//outputJson is a global variable which is Populated here
outputJson = parseMyPage(outputJson, htmlDoc);
});
Step 2:
chrome.tabs.getSelected(null, function (tab) {
// Now inject a script onto the page
chrome.tabs.executeScript(tab.id,{
code: "chrome.extension.sendRequest({content: document.body.innerHTML}, function(response) { console.log('success'); });"
}, function () {
//my code to access global variables
if (outputJson && null != outputJson) {
// other stuff
}
});
});
The way your code is designed, you are relying on the order in which two asynchronous blocks of code are executed: the extension.onRequest1 event and the callback for tabs.executeScript(). Your code requires that the extension.onRequest1 event fires before the tabs.executeScript() callback is executed. There is no guarantee that this will be the order in which these occur. If this is a released extension, it is quite possible that this was failing on users' machines, depending on their configuration. It is also possible that the code in Chrome, prior to Chrome 55, resulted in the event and callback always happening in the order you required.
The solution is to to rewrite this to not require any particular order for the execution of these asynchronous code blocks. Fortunately, there is a way to do that and reduce complexity at the same time.
You can transfer the information you desire from the content script to your background script directly into the callback of the tabs.executeScript(), without the need to explicitly pass a message. The value of the executed script is passed to the callback in an array containing one entry per frame in which the script was injected. This can very conveniently be used to pass data from a content script to the tabs.executeScript() callback. Obviously, you can only send back a single value per frame this way.
The following code should do what you desire. I hand edited this code from your code in this Question and my answer here. While the code in that answer is fully tested, the fact that I edited this only within this answer means that some errors may have crept in:
chrome.tabs.getSelected(null, function (tab) {
// Now inject a script onto the page
chrome.tabs.executeScript(tab.id,{
code: "document.body.innerHTML;"
}, function (results) {
parser = new DOMParser();
htmlDoc = parser.parseFromString(results[0], "text/html");
//outputJson is a global variable which is Populated here
outputJson = parseMyPage(outputJson, htmlDoc);
//my code to access global variables
if (outputJson && null != outputJson) {
// other stuff
}
});
});
extension.sendRequest() and extension.onRequest have been deprecated since Chrome 33. You should replace these anywhere you are using them with runtime.sendmessage() and runtime.onMessage.
Whats wrong with this code?
I'm trying to send a post request using jQuery ajax from PhantomJS, but it returns nothing besides "post:"
var webPage = require('webpage');
var page = webPage.create();
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js', function() {
console.log('post:');
$.post("http://httpbin.org/post", function(data) {
console.log(data);
});
});
PhantomJS has two contexts. page.includeJs() instructs the DOM context (page context) to load the given JavaScript file. The callback is called when it is done. It means jQuery will only be available in the page context and never outside of it. You get access to the page context through page.evaluate().
Example:
page.onConsoleMessage = function(msg){
console.log("remote> " + msg);
};
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js', function() {
page.evaluate(function(){
console.log('post:');
$.post("http://httbpin.org/post", function(data) {
console.log(data);
});
});
setTimeout(function(){
// don't forget to exit
phantom.exit();
}, 2000);
});
You will have to run PhantomJS with the --web-security=false commandline option, otherwise it won't be able to send the request because of cross-domain restrictions:
phantomjs --web-security=false script.js
Please note that page.evaluate() is sandboxed. Please read the documentation fully.
The problem is related to security, you're trying to access a different domain.
In chrome it is possible to disable cross domain restrictions executing the following command in console:
chromium-browser --disable-web-security
Also you can add these flags to your direct access.
I am attempting to run a script in a webpage, that should be executed in an <iframe>. Right now I can call a function that is set within the <iframe>.. I'm just having issues running a script to the <iframe>'s context.
Here's how I run a function set in the <iframe>
$('#iframe').get(0).contentWindow.performSearch();
Now instead of calling the preformSearch function, I wish to run a script - for this example, this is the script...
console.log('worked!');
My actual script is a big one, so I won't put it here - for the sake of this question.
So, is there any way to run that script through the <iframe>'s context? For example, my first guess would be/was..
$('#iframe').get(0).contentWindow.function(){
console.log('worked!');
}
I've never messed with running functions through something like an <iframe> before though, so I'm stumped.
Thanks for any help in advance!
NOTE I am using NW.js (Node-Webkit) to remove all <iframe> restrictions.
NOTE v2 The preformSearch() function was just a reforence on how I call functions in the frame.
You could try and use the messaging mechanizm
which means that on the parent frame you could send the message with
var win =$("#iframe").contentWindow;
win.postMessage({ messageType: "predefinedMessage", features: data }, '*');
and than in the iframe you could get the message
function FrameCommunicator(attachManager) {
var mfilesFrame;
function _actOnMessage(data) {
if (data.messageType === "predefinedMessage") {
//perform here what you need
}
}
window.addEventListener("message", function (e) {
var data = e.data;
mfilesFrame = e.source;
_actOnMessage(data);
}, false);
}
now the thing is that the iframe and the parent fram can have the same code if they reference to the remotely.
Another way would be just to send the content of the message as JS and run it with eval , but that is risky , bad practice and lotsa other things :)
In my MVC view I need to get razor c# code to execute a javascript function at unpredictable times, way after the page has loaded.
I have used a thread to simulate unpredictableness but ultimately instead of the thread it will be a WCF callback method that raises an event which runs the helper, but to eliminate session issues I have used the thread.
Javascript to execute:
<script type="text/javascript">
function DisplayNews(news) {
alert(news);
}
</script>
Helper that runs the javascript (because sticking this directly in the below thread didn't work)
#helper UpdateNews(string news)
{
<script>
DisplayNews(news);
</script>
}
Thread that simulates unpredictableness/post page loading or non user invoked events
#{
System.Threading.Thread T = new System.Threading.Thread(new System.Threading.ThreadStart(delegate
{
while (true)
{
System.Threading.Thread.Sleep(5000);
UpdateNews("Some cool news");
}
}));
T.Start();
}
If I stick a break point at UpdateNews("Some cool news"); I can see that it gets hit every 5 seconds as it should, but thats as far as it gets, nothing else happens. I can't stick a break point in the helper or the Javascript so I can't see where it stops working after that.
Is this going to work at all or is there another way I should be approaching this?
Any help would be greatly appreciated.
In server side code you can call an client function...
Razor executed in server side and javascript is in client side.that mean when you get server response it's created by razor code in server side and now you can just use javascript in client side
I may be misunderstanding what you are trying to do but you can have javascript that will run on page load that will be wrapped in a set timeout with a random millisecond period.
Something like this:
<script>
window.onload = function() {
setTimeout(function() {}, 1000); // this will run 1 second after page load
}
</script>
simply randomize the number being passed as the second parameter to setTimeout and your javascript will run at a random time after the page loads.