How would I pass data to an external script loaded with $.getScript()? - javascript

So I'm trying to load a javascript remotely using jquery's $.getScript, but I'm puzzled on how I can pass data to the external script.
I've tried setting variables before the call but they aren't available in the script that gets loaded, and when I try to send/retrieve them using the query string, the remote script tries to read the querystring of the base file that it gets called from, not itself. Is there any other way to do this? Or is it possible to have a javascript file read its own querystring rather than the file it's called from (that's loaded in the browser)?
// editor ini
var editor_ini = { page: current_page, action: 'edit' };
var foo = 'bar';
// load the editor
$.getScript('assets/desktop/desklets/'+launcher.config.editor+'/execute.js', function(){});
In the execute.js file, the editor_ini and foo are both unavailable, I get the same result with:
// load the editor
$.getScript('assets/desktop/desklets/'+launcher.config.editor+'/execute.js', { page: current_page, action: 'edit', foo: 'bar' }, function(){});
because the remote script seems to be getting the query string from the original document rather than the one used when calling the file.
If it matters, I was trying to use the query object plugin for jquery for reading the query string.

global variable declared in inline javascript is accessible in external javascript page loaded using $.getScript().

I bet that your var foo='bar' is inside a function, so not visible in global scope. Try:
window.foo = 'bar'

Truly global variables will be accessible to your script. So, if they aren't, then it's probably because your variables that you think are global actually aren't. You can either move them to the top level scope or set them on the window object like Alexei suggested.
There are other ways to share data.
1) You can put an id on the <script> tag that loads the code and then have the code get the .src value from that tag and get the query string off the script's actual URL. I like this option, but I don't know if you can do it using jQuery.getScript() since I don't think it exposes that as an option.
2) You can have the loading script call a function that you provide and return an object with the desired data from that function.
3) Once the new script is loaded, you can call a setXXX() function in that script to set the state that it needs.
4) You can set information into a cookie that the other script can read.
5) You can encode data into a URL hash value that the other script can read.

Related

Using Ruby Variables in JavaScript

I'm new to Ruby so I had a question in regards to using some variables throughout my codebase. I have a variable declared in my Ruby file as follows:
#pages = 350
Now, I know that in HAML, I can simply do:
-if #pages = 350, and in HAML with inline javascript, I can do something like:
:javascript
console.log("#{#pages}");
However, I am linking an external JavaScript file in my HAML document, and I was wondering if it would be possible to use my Ruby variables in my external JS document? I need some variables in order to build what I am trying to build. Thanks!
Update as per one of the answers:
In my HAML file, I have the following:
:javascript
printPages(3);
In my external JS file, I have:
$(function() {
window.printPages = function(pages) {
console.log(pages);
}
});
I you are loading static javascript files I really would not recommend trying to insert variables into that code.
Instead, think about how you would provide that to your javascript code.
You could send it to that code as an argument.
<script type="text/javascript" src="./my-external-script.js"></script>
:javascript
runMyExternalFunction(#{#pages})
Or you could add the variable as a data attribute on your page, and your javascript could look for that when it loads.
Haml:
%body data-pages=#pages
JS:
console.log(document.body.dataset.pages) // value of #pages
Update about your javascript:
Using jquery's on page ready event $() for declaring the function is a bad idea. That means that it waits for everything on the page to be compeletely loaded, and then declares the function your page needs.
What you should be doing is setting up all the function that will be needed right away, and then calling those functions when the page is loaded.
They way you have it, the page loads, printPages() is executed (which doesn't exist yet), and then after all that printPages is created and put into the global scope.
So remove the $() from your external script and add it to your HAML instead.
In fact, if your aren't doing anything super fancy with transpiling or bundling, then you can simply declare the function in your external JS file, and it will be available globally. This doesn't work with your code because they way you've declared the function, it would only be available to code within that $() callback.
// js file
function printPages(pages) {
console.log(pages);
}
HAML:
$(() => {
printPages({#pages})
})

How can I import an external .js to my Java test with Selenium in Eclipse?

I want to import my function of JavaScript to my Java project in Eclipse and using it with Selenium, but I can't find the form to do this.
I try making .js file like this to Selenium could recognise this code:
Selenium.prototype.doProve = function() {
$("#proveDiv > div > div").each(function(i, obj)
{
$(i).click(function(){});
});
};
Well, as you can see I have 3 divs and what I want to do it's to access to the third div in which I have 2 divs more (this is the clue of the loop). In each div of the loop I want to make a click.
I tried to use this function in my Java project but I can't get any result so I tried to execute this function as a String and then executing the script like this:
String script = "$(\"#proveDiv > div > div" +
"\").each(function(i, obj){ " +
"$(i).click(function(){});})";
//Executing script
if (driver instanceof JavascriptExecutor) {
((JavascriptExecutor) driver).executeScript(script);
}
It works, but it's not very useful, because I want to make an external .js which contains all the JavaScript functions and call them from there, not in a String.
Any help would be appreciated. I saw some questions here, but any of them worked for me.
Thank you very much!
It works, but it's not very useful, because I want to make an external
.js which contains all the JavaScript functions and call them from
there, not in a String.
You can achieve this only by loading your external js file into the DOM
var addscript=window.document.createElement('script');addscript.type='text/javascript';addscript.src='http://localhost/somescript.js';document.getElementsByTagName('body')[0].appendChild(addscript);
Note : Most browsers do not allow you to load local resources so put your external js file in local webserver and then access it like http://localhost/somescript.js
After loading the js file into DOM now you can call the javascript functions in the external js file
Example
Lets say we have a external js file named somescript.js which contains the below function
//simple function which sets the value "test" to the search box
window.somefunc = function () {document.getElementsByName("s")[0].value='test';}
Webdriver code :
driver.get("http://www.jquery.com");
//Load the External js file into DOM
((JavascriptExecutor) driver)
.executeScript("var addscript=window.document.createElement('script');addscript.type='text/javascript';addscript.src='http://localhost/somescript.js';document.getElementsByTagName('body')[0].appendChild(addscript);");
//wait for the js to be loaded to the DOM
((JavascriptExecutor) driver)
.executeScript("return typeof(somefunc)").toString().equals("function");
//Now you call the JavaScript functions in the JS file
((JavascriptExecutor) driver)
.executeScript("somefunc();");
Note : Behind the scenes Selenium wraps your JavaScript code in an anonymous function. So your somefunc function is local to this anonymous function.And due to JavaScript's scoping rules, somefunc doesn't exist outside of that anonymous function. so we have made it a global function by assigning it to window.
EDIT :
And I don't really understand why you use the window statement. And I
was searching something like ((JavascriptExecutor)
driver).executeScript("here the .js"); But I don't know if it is
possible
This is how executeScript method executes the provided javascript
The script fragment provided will be executed as the body of an
anonymous function.
Example if we used the below code
((JavascriptExecutor) driver)
.executeScript("somefunc = function () {document.getElementsByName("s")[0].value='test';}");
((JavascriptExecutor) driver)
.executeScript("somefunc();");
(function() {
somefunc = function () {document.getElementsByName("s")[0].value='test';}
})();
(function() {
somefunc();
});
What do you mean where you say that you want to put the external .js
into the DOM?
By DOM i mean Document object model of the page constructed as a tree of Objects (in short your webpage).We use javascript to load the external js to the webpage and then call the functions in the js file and execute them(like in the above example).
In the code that you put in your edit. Both functions are the same?
I just gave an example by that what i meant was each script provided in execute script will be executed in the body of an anonymous function.In our case we haven't used executescript to create the somefunc function rather used it from the external js file in dom we only called it using the executescript method so you can do it with or without the window object
//simple function which sets the value "test" to the search box
somefunc = function () {document.getElementsByName("s")[0].value='test';}//this will also work
Hope this helps you.Kindly get back if you have any queries.
You could store the javascript in a file like a properties or xml file.
Sample File:
clickOnLoginButton=function bclick(){....};bclick();
Sample Code:
FileInputStream file;
Properties properties = new Properties();
// load the file handle for properties file
file = new FileInputStream(filename);
// load all the properties from this file
properties.load(file);
// we have loaded the properties, so close the file handle
file.close();
String mainExecutor = properties.getProperty(parameter);
WebDriver dr = initalizeWebDriver();
JavascriptExecutor js = (JavascriptExecutor) dr;
js.executeScript(mainExecutor);

How to include javascript file only once

I want to give clients an HTML block they can include in their site, and this HTML will contain some table and image, plus a javascript that will make manipulations over the HTML block.
so I give them the HTML :
<a data-theme="1" data-srv="http://localhost:50987/" class="block1" href="http://myserver/payment/Details">outer information</a><script type="text/javascript" src="http://myserver/Scripts/checkout.js"></script>
in checkout.js I have included JQuery if no Jquery exists in document and do manipulation over the element $('a.block1') ... the problem is when someone puts this block of HTML more then once over the same page, I want that the client will not call "checkout.js" more then once,
I've tried declaring global var inside "checkout.js" and check if it's exists, it works good to stop doing the same manipulation more then once but I want to stop the call to JS al together .
Javascript runs after it loads, you can't stop the JS running, if it is referenced multiple times. It won't be loaded multiple times, so the overhead of it running again is basically nil.
To stop the behavior of the javascript happening again, just put the check at the top level of the file, put the rest of the file in the conditional, and write to a global variable to make sure you don't run again.
if (window._your_unique_id === undefined) {
window._your_unique_id = true;
// the rest of your javascript
}
that will mean nothing in the script runs. You can still define whatever you like in that if statement, though if you define functions and variables in there, you may have to explicitly put them on the window object, because they'll otherwise be local (but then, it is bad practice to have anything implicitly defined global anyway, so it shouldn't make any difference if your code is well structured).
Just deploy your code as a module.
Ie.
(function(window){
if(window.CheckoutModule) return;
// now you're certain there's no global module loaded
var CheckoutModule = window.CheckoutModule = {};
// you can, ie, add a jQuery check here.
if('undefined' != typeof jQuery) {
// do your jQuery thing here.
}
return ;
})(window, jQuery);

javascript eval intrinsic restrictions?

I have a situation in which I have to use eval in Javascript. Yes, I know it is evil, but in this case it is required, because two requisites:
The Javascript code is big.
It has to be evaluated (and downloaded) only in a few situations, so I don't want the script to be downloaded always, but on demand.
With these requisites, I have written an XMLHttpRequest to request the code (600+K), and I want to eval that code to take place immediately. As I'll show later, the script contains just data to be inserted in two variables. The problem is that evaluating this javascript fails always with syntax error. If I put the code verbatim (without eval), the code executes fine. This is the minimal example. I have a search.js file like this:
// search.js for functional mind. Generated statically
// from the set of posts.
posts = { 'postlist' : ['YYY', 'other link...' ] };
posts_for_word = { 'word1' : [0,1], 'word2' : [Z,K] };
The last variable, posts_for_word includes indexes of posts containing that word. The problem comes when I evaluate that Javascript inside eval:
// global environment
var posts = {}; // Initial value, empty
var posts_for_word = {}; // same
function() {
var request = // create XMLHTTPREQUEST request
var response = // obtain response (the javascript)
eval( response ); // <- syntax error
// access posts or posts_for_word
posts.postlist[ posts_for_word['word1'][0] ]
....
}
The problems:
When I evaluate the javascript shown above with eval, firefox tells me that it is bad formed in the first line.
I then removed the comments. I supposed that eval would evaluate it as if it was a normal Javascript program, but it doesn't seem to accept comments (why?).
After removing the comments, the code works, but still the Javascript console of Firefox tells me that there is a syntax error in the first line (that defining the JSON first variable). Why?
You shouldn't use AJAX and eval() to make a script happen on your website, instead, create a <script> element with a link to the file and append it to the body:
(function() {
var jsCode = document.createElement('script');
jsCode.setAttribute('src', 'http://localhost/tests/doStuff.js');
document.body.appendChild(jsCode);
}());
(This code is actually taken directly from a bookmarklet of mine, and it does the trick nicely.)
As for the variable scope, if you declare them as var variable in your inner file, it would override the file scope and become global.
However, should you require a synchronous load of a script, you will have to (despite the fact it is considered bad practice) to use a synchronous AJAX call. How to do that was already written before me, Dynamically loading JavaScript synchronously

Executing injected Javascript code in a page when developing a Firefox extension

I'm developing a Firefox extension which places a button in the status bar. When the button is clicked, the extension injects some Javascript into the current page. This Javascript has a function that I would like to invoke with some parameters. I've managed injecting the code, I've inspected the page through Firebug and verified that the JS has been injected. How can I call a Javascript function in the page from my extension?
--More information
Here's the code that I'm using to inject my Javascript:
var doc = window.content.document;
//Add the script
var visibilityJS = doc.createElement("script");
visibilityJS.setAttribute("type", "text/javascript");
visibilityJS.setAttribute("charset", "UTF-8");
visibilityJS.setAttribute("src", "chrome://visibility/content/scripts/visibility.js");
head.appendChild(visibilityJS);
//Call the function
alert("Executing testfunction");
window.content.document.defaultView.testFunction();
..and the code inside my JS file that i'm going to inject. i.e. visibility.js
window.testFunction = function() {
alert("Message");
}
Thanks.
This worked. I don't know the technicalities. I got part of the solution from Felix and part of it from here.
window.content.document.defaultView.wrappedJSObject.testFunction();
If you declare a global variable in your injected code (or explicitly set a property of the window object), then one way do get a reference to this element from your extension, is via the gBrowser object:
gBrowser.contentDocument.defaultView.yourObject
^-- HTML document ^
object |-- window object
Be careful though, when you use window and document inside your code. Depending on the context it might refer to the Firefox window or the website window object.

Categories

Resources