I have create a JQuery script that works in the browser console, but it is not working in the selenium3 automation. The exception I'm receiving is unknown error: $ is not defined. I read that the problem is the second argument in the selector. I have tried to escape the $ character but it is not working.
This is the excript I have executed in the browser console:
$('input[type=file]', $('#fonto').contents()).css('display','block')
But when I executed during my test case, is not working. This is the line of code:
((JavascriptExecutor) getDriver()).executeScript("$('input[type=file]',
$('#fonto').contents()).css('display','block')");
I need the second argument because the input is inside an iframe.
This problem occurs in firefox and chrome browsers.
Which is the proper way to execute this script?
EDIT
The JQuery is not loaded. I need to know how to enable the JQuery before execute my script.
Firstly you should switch to iframe.
Than include jquery like this:
browser.SwitchTo().Frame("your_iframe");
var jqueryLoad = "if (typeof(jQuery) == 'undefined')";
jqueryLoad += "{";
jqueryLoad += "var iframeBody = document.getElementsByTagName('body')[0];";
jqueryLoad += "var jQuery = function(selector) { return parent.jQuery(selector, iframeBody); };";
jqueryLoad += "var $ = jQuery;";
jqueryLoad += "}";
IJavaScriptExecutor jsExe = browser as IJavaScriptExecutor;
jsExe.ExecuteScript(jqueryLoad);
jsExe.ExecuteScript("Your jquery code here !");
You can execute your jquery code now. If you have nested iframes you should configure code again.
Finally I have solve the problem, but I have two different approaches:
Follow the point 2 in this link. That means add a new file into your project and it has a very useful example about how to check is it is enable or not. In this case the script should remove the iframe part, because we are already into the iframe. Something like this $('input[type=file]').css('display','block')
The problem was that the iframe hasn't the JQuery active, but the main content, the default frame, has the JQuery active. Then I can change my current frame to the default one, execute the full script with the iframe selector ($('input[type=file]', $('#fonto').contents()).css('display','block')). And after that return to the iframe.
My choice, because I have many projects that execute scripts, I will follow the second one.
Related
I'm building a Squarespace page, and I want to have an outgoing link on the page whose query parameters are set according to query parameters on the page itself. Since Squarespace embeds YUI3 in every site automatically, I'm trying to use that (even though I have more experience with jquery).
Example: The page is loaded as http://example.com/page/?email=foo#bar.com. I have a link on the page that goes to http://another.example.com/page which should be modified to go to http://another.example.com/page?address=foo#bar.com.
The following code does exactly what I need when I paste it in the browser console:
var MyButton = Y.all('a[href="http://another.example.com/page"]');
var QueryString = Y.QueryString.parse(window.location.search.substring(1));
MyButton.setAttribute('href','http://another.example.com/page?address=' + QueryString.email);
However, when I put that code in the page source, then when the page loads, the following error appears in the console: Uncaught TypeError: Y.QueryString.parse is not a function
My current theory is that YUI3 loads asynchronously in pieces, and this code runs at a point when Y.all is available but Y.QueryString.parse is not... is that right? What would be the best solution to this?
Yui3 is indeed built around asychonous modules loading, in this case you miss the querystring module.
You need to wrap your code with a Y.use call:
Y.use('querystring', function(Y) {
var MyButton = Y.all('a[href="http://another.example.com/page"]');
var QueryString = Y.QueryString.parse(window.location.search.substring(1));
MyButton.setAttribute('href', 'http://another.example.com/page?address=' + QueryString.email);
});
So I have a problem where I need to get the entirety of a script's source code as a string (whether it's an inline script or a script that uses the src attribute) from within the script itself, but without knowing beforehand exactly what script it is. I can't just do an XHR for that reason. Several scripts on the page will listen for events, and when they handle them they will also run code that identifies the script's own source code. How should I do this?
function identifySelf() {
// Some code here
return mysource; // should return the source code of the script in which this function is defined
}
You will need to identify each script tag with an id. Then
var script=document.getElementById("my_id");
var content=script.innerHTML || "";
if(content==null || content==""){
var src=script.src;
// ajax in the script, I'm not going to write the code because I'm on mobile
// I'm assuming you can write it yourself
}
EDIT: sorry, I didn't read your question fully. If you need to return the content right away, you will need to ajax in scripts' content on page load, and the return cached content. There is no way to just get the innerHTML like that.
When I load a particular webpage, I'd like to call a Javascript function that exists within their page. I could use a bookmarklet with javascript:TheFunction();, but I'd like to know if there's an easier way to do it, either with a Chrome extension or otherwise.
With chrome, you can either install a grease monkey script directly or get the Blank Canvas script handler plugin (the latter of which I use).
Chrome extensions run in a sandbox so you cannot call a function directly from the webpage code how you want. you either have to use javascript:fuction(); and set document.location, or you can create script elements on the page with a callback to your own extension. check out how this guy did it:
https://convore.com/kynetx/kbx-writing-durable-code/
i am refering to this post, and the one above and below it specifically
var anewscript = document.createElement("script");
anewscript.type = 'text/javascript';
anewscript.innerHTML=' callback_tmp= function (mydata){ ' +
' document.getElementById("someElement").onclick(mydata);' +
'}';
document.getElementsByTagName("head")[0].appendChild(anewscript);
An alternative option is to modify the javascript function to make it globally accessible from the [Chrome] debug console.
Change the function from for example
function foo(data)
to
foo = function(data)
then using the debug console, call the method with the attributes required
data = {my: "data"}
foo(data)
The following scenario is a problem I am having. I came to the conclusion that jQuery must not be ready when Javascript is executing by observing this scenario.
Scenario:
I have a Java application which injects Javascript script tags into the currently loaded DOM page. The following Java code runs inline Javascript which inserts jquery.js and myCode.js. myCode.js holds my Javascript codes.
browser.executeJavaScript("var head= document.getElementsByTagName('head')[0];" +
"var script= document.createElement('script');script.type= 'text/javascript';script.src= 'jquery.js';head.appendChild(script);" +
"var script4= document.createElement('script');script4.type= 'text/javascript';script4.src= 'http://myCode.js';head.appendChild(script4);");
In this Java application, I also have a buttonListener that fires a function in myCode.js in ActionPerformed();
executedJS = browser.executeJavaScript("replaceAllLinks()");
The problem that is encountered is nullPointerException at the above line when button is clicked. Accomodating for null case results in endless loop without any changes.
while(executedJS == null) browser.executeJavaScript("replaceAllLinks()");
The cause of the problem was pinpointed down to when jQuery functions, methods are present inside replaceAllLinks(); javascript function. when jQuery, methods were absent, no problems could be observed. There was not one instance of nullPointerException raised.
The only possible underlying issue would be that somehow jQuery library is not fully loaded while replaceAllLinks(); is being executed. If jQuery methods and functions were not in use, it doesn't matter and everything runs okay.
My question is then, how can I make sure that jQuery is fully loaded and available for use?
Every script relying on jQuery should be contained inside a DOM ready function. Such a function normally takes this form:
$(document).ready(function() {
/* code here */
});
and a shortcut to achieve the same thing would be:
$(function() {
/* code here */
});
Here's the documentation for further information on the ready method:
http://api.jquery.com/ready/
Declare some global variable at the end jquery.js, e.g.
window.jQueryIsLoaded=true;
and check this variable before using jQuery.
<edit>Forget this, see Salman A's comment below, should be the right answer.</edit>
I have a javascript function I'm writing which is being used to include an external JS file, but only once. The reason I need such a function is because it is being called when some content is loaded via AJAX and I need to run page-specific code to that content (no, just using .live won't cover it).
Here's my attempt, shortened for brevity:
$.include_once = function(filename) {
if ($("script[src='" + filename + "']").length === 0) {
var $node = $("<script></script>")
.attr({
src : filename,
type : "text/javascript"
})
;
$(document.body).append($node);
}
};
This works fine: the function is called, it loads the external file, and that file is being run when loaded. Perfect.
The problem is that it will always re-load that external file: the query I'm using to check for the presence of the script always finds nothing!
When debugging this, I added some lines:
alert($("script").length); // alerts: 4
$(document.body).append($node);
alert($("script").length); // alerts: 4
Looking in the dynamic source (the HTML tab of Firebug), I can't find the script tag at all.
I know that I could maintain an array of files that I've previously included, but I was hoping to go with a method such as this, which (if it worked), seems a bit more robust, since not all the JS files are being included in this way.
Can anyone explain the behaviour seen in this second snippet?
jQuery is a bit of a dumb-dumb in this case; it doesn't do at all what you'd expect. When you append($node) jQuery does this:
jQuery.ajax({
url: $node.src,
async: false,
dataType: "script"
})
Woops! For local files (eg on the same domain) jQuery performs a standard XMLHttpRequest for the .js file body, and proceeds to "eval" it by a whole convoluted process of creating a <script> tag (again!) and settings it's contents to your .js file body. This is to simulate eval but in the global context.
For cross-domain files, since it cannot perform the standard XMLHttpRequest due to the same-domain policy, jQuery once again creates a <script> element and inserts it into <head>.
In both the local and cross-domain cases above jQuery finally gets around to doing this:
head.removeChild(script);
And booms your .length check! Bummer.
So on to your problem, don't bother jQuery with this. Just do
document.getElementsByTagName('head')[0]
.appendChild(
document.createElement('script')
)
.src = filename;
Which will do what you'd expect, particularly wrt querying for it later.
You're trying to solve a problem that has already been solved several times over. Try LazyLoad for example. There are also similar plugins for jQuery.
Instead of setting the source attribute of the script-tag, set the "text" attribute of the script tag. This works in all modern browsers (the application where I use that in practice does not support IE6, so I do not know about this creep...).
In practice it would look like this (you HAVE TO add code to omit double inclusion on yourself - e.g. a simple array of all alread loaded scripts, though thats very application specific, and why should you anyway load code twice? try to omit double-loading code...!):
var script_source_code_string = <some dynamically loaded script source code>;
var $n = $("<script></script>");
$n.get(0).text = script_source_code_string;
$(document.body).append($n);
Or even simpler (without jquery, my code at this stage does not know jquery, it may also be loaded dynamically):
var script_source_code_string = <some dynamically loaded script source code>;
var s = document.createElement('script');
document.getElementsByTagName('head')[0].appendChild(s);
s.text = script_source_code_string;