I'm doing some code that requires actions on multiple sites (get some data switch to another site etc.) in a loop.
I'm trying to do this using setInterval().
Simplified, the task looks like this when launched in a console:
function checkit() {
window.location='http://www.google.pl';
}
var nre = setInterval(checkit,5000);
I have tried launching this script (in more complicated forms through different measures, from bookmarklet, from server side script etc, the interval runs OK in my original code, even does everything what I require in a loop until another page is called (through window.open or window.location). than the loop just seizes to execute.
I'm pretty new to JS (2 days experience) so I'm probbably doing something uterly stupid. Any Advice on how to get this thing going (is this even possible)?
Best regards
The problem you're going to have is that JS doesn't stay from page to page, so once the page changes, that loop goes away. You'll need to have the JS on each page you're wanting to visit to continue flow and even then, the variables are nuked when you change pages.
The only way to circumvent this issue is by storing a serialized object (or JSON string) within the window.name value which is remember across pages and domains within that tab.
Related
I have a website that loads mostly using AJAX calls. The javascript and CSS files are only loaded once when the page first loads.
My issue is that the javascript/CSS can get out of sync with the HTML and server-side code. The page can be using an old versions of the javascript file (from when the page first loaded) while the server-side code and ajax-loaded HTML files always use the latest code and files.
What are some strategies for dealing with this?
I have considered polling the server at set intervals and asking if there is a newer version of the JS. Then, if there is, reloading the page. But, it seems that this can get ugly, with the page suddenly reloading at awkward moments instead of, for example, as the result of a user-initiated call.
Also, there are some changes to the javascript that do not necessarily require that a page be reloaded. For example, the changes might affect a different page/module than the one that the user is on.
Re-loading the javascript with every Ajax call is not viable
I can imagine ugly solutions to this, but thought I'd ask first.
EDIT (in response to comments and suggested answers)
The only way to get the JS back into sync is to reload the page, which then loads the new JS. Adding new JS to an old page won't work as it doesn't get rid of any old functions, listeners, etc. I'm not asking how to reload a page or how to load javascript. I'm asking for a strategy of knowing WHEN to do it, especially in a way that does not seem awkward to the user. Do people incorporate polling to ask if there is a new JS version? Do they then suddenly (from the user's point of view) reload the page? Do they poll even when the tab is hidden? Is this a problem for the server? Where do they keep track of the latest required JS version? Or, do they ask with every AJAX request - hey, should I reload? Did they write a special function for that? Do they keep all new html/server code backwards compatible with the js?
Someone who has dealt with this, how do you do it?
Two possible solutions include
calling $.getScript() to retrieve, update variables at document from at server-side to match variables at document before calling $.ajax(/* settings */) ;
alternatively could use web workers to update original document variables to match server-side variables at beforeSend of $.ajax(/* settings */)
At result of first step of either approach, abort $.ajax() call, call error handlers, notify user, send message to server about error.
var head = document.getElementsByTagName("head")[0],
scripts = {};
function load_script(name){
var myscript = document.createElement('script');
myscript.setAttribute("type","text/javascript");
myscript.setAttribute("src", name);
if (scripts[name]) head.replaceChild(myscript, scripts[name]);
else head.appendChild(myscript);
scripts[name] = myscript;
}
// the first call to load the script code
// and then call if you decide to upgrade a newer version
load_script('js1.js');
load_script('js2.js');
I want to automatically grab some content from a page.
I wonder if it is possible:
Run my own written JavaScript on the page after the page is loaded (I use FireFox. I don't have the ability to change content of the page. I just want to run JS on my browser.). The script will use getelementbyid or similar method to get the link to the next page
Run a JavaScript to collect my interested content (some URLs) on that page and store those URLs in a local file
Go to next page (the next page will get really loaded with my browser, but I do not need to intervene at all) and repeat step 1 and step 2, until there is no next page.
The classic way to do this is to write a Perl script using LWP or PHP script using CURL, etc. But that is all server side. I wonder if I can do it client side.
I do something rather similar, actually.
By using GreaseMonkey, you can write a user-script that will interact with the pages however you need. You can get the next page link and scroll things as you like.
You can also store any data locally, within Firefox though some new functions called GM_getValue and GM_setValue.
I take the lazy way out. I just generate a long list of the URLs that I find when navigating the pages. I do a crude "document.write" method and I dump out my list of URLs as a batch file that rules on wget.
At that point I copy-and-paste the batch file then run it.
If you need to run this often enough that it should be automated, there used to be a way to turn GreaseMonkey scripts into Firefox extensions, that have access to more power.
Another option is currently AFAIK, Chrome only. You can collect whatever information you need and build a large file from it, then use the download attribute of a link and come up with a single-click to save things.
Update
I was going to share the full code for that I was doing, but it was so tied to a particular website that it wouldn't have really helped -- so I'll go for a more "general" solution.
Warning, this code typed on the fly and may not be actually correct.
// Define the container
// If you are crawling multiple pages, you'd want to load this from
// localStorage.
var savedLinks = [];
// Walk through the document and build the links.
for (var i = 0; i < document.links.length; i++) {
var link = document.links[i];
var data = {
url: link.url,
desc = getText(link)
};
savedLinks.push(data);
}
// Here you'd want to save your data via localStorage.
// If not on the last page, find the 'next' button and load the next page
// [load next page here]
// If we *are* on the last page, use document.write to output our list.
//
// Note: document.write totally destroys the current document. It really is quite
// an ugly way to do it, but in this case it works.
document.write(JSON.stringify(savedLinks, null, 2));
Selenium/webdriver will let you write a simple java/ruby/php app that will launch Firefox, use its JavaScript engine to interact with the page in the browse.
Or, if the web page does not require JavaScript to make the content you see interested in available, you could use a html parser in your favourite language and leave the browser out of it.
If you want to do it in JavaScript in Firefox you could probably do it in a greasemonkey script
Assuming a JavaScript-based single-page application is returned by the server on the initial request. Besides some initialization code, which is common for every application, just the portion of the application needed to show the requested page (e.g. index page) is returned by the server on the initial request (then cached and rendered).
As the user clicks through the application, other portions of the application should be asynchronously loaded ('fetched', 'requested' or however you wanna call it) from the server. By "portions" a mean javascript code, images, css, etc. required to render the page. Let's focus on the javascript code part in this discussion.
It's important to notice that the javascript code to be returned to the browser is not contained in separate (static) files (which would be easy then and might be the case in the future due to e.g. performance reasons), but rather in one file, so it's not a 1:1 assiociation (request : file).
E.g. we could have a single app defined like this:
var LayoutPresenter = App.Presenter.extend('LayoutPresenter', {
__view: '<div>{{link "Author" "/author"}} - {{link "Book" "/book"}}</div>'
});
var AuthorPresenter = App.Presenter.extend('AuthorPresenter', {
__view: '<div><h1>{{name}}</h1></div>',
__parent: LayoutPresenter,
__context: { name: "Steve" }
});
var BookPresenter = App.Presenter.extend('BookPresenter', {
__view: '<div><h1>{{title}}</h1></div>',
__parent: LayoutPresenter,
__context: { title: "Advanced JavaScript" }
});
App.Presenter is part of the library I am writing and is available in the browser (or on any other client).
So assuming the user is browsing to the Book page which hasn't be loaded before (neither initially nor cached in the browser), the BookPresenter code, which is a function, should be returned by the server (assuming the LayoutPresenter code is already available in the browser and App.Presenter is available anyway because it's part of the library). I am running node.js on the server side.
How would you recommend to address this problem?
There is the eval function, so one could send javascript as a string and bring it back to live using eval(), but such an approach seems to be bad practice.
Never use eval - it's evil. The better option would be use jQuery ajax and set the dataType as script. This will evaluate your js, and also provide you with a call back once the script is loaded.
Refer to Ajax dataTypes and jQuery getScript shorthand. This is of course assuming that you can separate your code into logical modules
You might also consider it worth your time to check this question (How can I share code between Node.js and the browser?)
dNode is an option that is described in the question above and it looks quite exciting in terms of possibilities. You could create a list of function required for the Book page, then call them right off the server itself. That would eliminate the need to maintain separate js modules for each section of your page. Kudos to #Caolan for suggesting it.
As interesting as it is, take care to properly scope your functions; you don't want random users playing around on your server.
Scenario:
A web site with x number of pages is being served with a single, concatenated JavaScript file. Some of the individual JavaScript files pertain to a page, others to plugins/extensions etc.
When a page is served, the entire set of JavaScript is executed (as execution is performed when loaded). Unfortunately, only a sub-section of the JavaScript pertains directly to the page. The rest is relevant to other pages on the site, and may have potential side-effects on the current page if written poorly.
Question:
What is the best strategy to only execute JavaScript that relates directly to the page, while maintaining a single concatenated file?
Current solution that doesn't feel right:
JavaScript related to a specific page is wrapped in a "namespaced" init function for that page. Each page is rendered with an inline script calling the init function for that page. It works hunky-dory, but I would rather not have any inline scripts.
Does anyone have any clever suggestions? Should I just use an inline script and be done with it? I'm surprised this isn't more of an issue for most developers out there.
Just use an inline script. If it's one or two lines to initialize the JavaScript you need that's fine. It's actually a good design practice because then it allows re-use of your JavaScript across multiple pages.
The advantages of a single (or at least few) concatenated js files are clear (less connections in the page mean lower loading time, you can minify it all at once, ...).
We use such a solution, but: we allow different pages to get different set of concatenated files - though I'm sure there exists different patterns.
In our case we have split javascript files in a few groups by functionality; each page can specify which ones they need. The framework will then deliver the concatenated file with consistent naming and versioning, so that caching works very well on the browser level.
We use django and a home-baked solution - but that's just because we started already a few years ago, when only django-compress was available, and django compress isn't available any more. The django-pipeline successor seems good, but you can find alternatives on djangopackages/asset-managers.
On different frameworks of course you'll find some equivalent packages. Without a framework, this solution is probably unachievable ;-)
By the way, using these patterns you can also compress your js files (statically, or even dynamically if you have a good caching policy)
I don't think your solution is that bad although it is a good thing that you distrust inline scripts. But you have to find out on what page you are somehow so calling the appropriate init function on each page makes sense. You can also call the init function based on some other factors:
The page URL
The page title
A class set in the document body
A parameter appended to your script URL and parsed by the global document ready function.
I simply call a bunch of init functions when the document is ready. Each checks to see if it's needed on the page, if not, simply RETURN.
You could do something as simple as:
var locationPath = window.location.pathname;
var locationPage = locationPath.substring(locationPath.lastIndexOf('/') + 1);
switch(locationPage) {
case 'index.html':
// do stuff
break;
case 'contact.html':
// do stuff
break;
}
I'm really confused exactly why it doesn't feel right to call javascript from the page? There is a connection between the page and the javascript, and making that explicit should make your code easier to understand, debug, and more organized. I'm sure you could try and use some auto wiring convention but I don't think it really would help you solve the problem. Just call the name spaced function from your page and be done with it..
My question is, how to to use Same function in Two different tabs at same time. Simply Like browser, multiple Tabs loading simultaneously. How to do like this in JavaSript or jQuery.
You would typically just include that function in the javascript for both of those pages.
If the two pages are from the same origin (e.g. same domain), then they can technically communicate with one another and one page could tell the other to execute a function on it's behalf, but if you are just trying to share code, then it's way easier to just include a copy of the code in both pages.
If you're including the same xxxxx.js file in both pages, it will likely be cached in the browser and will load quickly from cache after it's first load.
If you're controlling when the tab is opened, you can make a variable for this tab and target that:
var newWindow = window.open(this.getAttribute('href'), 'name');
newWindow.function();
But it's hard to tell what you're asking.