Automatically eval a local script on a specific URI in Firefox - javascript

I want to improve an existing website (I have no access to) by using my own javascript.
This means I have to add an < script > to the < head >. I am currently doing this by clicking on a bookmark which has something like this as its target:
javascript: if(document.createElement){
void(head=document.getElementsByTagName('head').item(0));
void(script=document.createElement('script'));
void(script.src='http://local/script.js');
void(script.type='text/javascript');
void(head.appendChild(script));
} // i added some spacer to make it readable
This works fine, but since i've got a lot of different scripts it gets complicated to organize them.
I am now looking for a way to automatically insert a defined script-uri if the top.location.href matches a given string.
Is there a way firefox can do something like this - maybe with the help of an add-on?

Userscripts are what you're looking for. Use Greasemonkey for Firefox to run your own script on specific sites.

https://addons.mozilla.org/en-US/developers/docs/sdk/1.12/modules/sdk/page-mod.html uses the add-on sdk, and provides precisely what you're looking for (i.e. an easy way to attach a script to a webpage if it matches a given domain). That gives you the option of making your addon a standalone one easily; moreover, if you were to extend its functionality significantly, the addon sdk would certainly be the way to go!

Related

jQuery on MTurk, why does Chrome report "Unsafe JavaScript attempt to access frame with URL"?

I'm doing a couple of things with jQuery in an MTurk HIT, and I'm guessing one of these is the culprit. I have no need to access the surrounding document from the iframe, so if I am, I'd like to know where that's happening and how to stop it!
Otherwise, MTurk may be doing something incorrect (they use the 5-character token & to separate URL arguments in the iframe URL, for example, so they DEFINITELY do incorrect things).
Here are the snippets that might be causing the problem. All of this is from within an iframe that's embedded in the MTurk HIT** (and related) page(s):
I'm embedding my JS in a $(window).load(). As I understand it, I need to use this instead of $(document).ready() because the latter won't wait for my iframe to load. Please correct me if I'm wrong.
I'm also running a RegExp.exec on window.location.href to extract the workerId.
I apologize in advance if this is a duplicate. Indeed - after writing this, SO seems to have a made a good guess at this: Debugging "unsafe javascript attempt to access frame with URL ... ". I'll answer this question if I figure it out before you do.
It'd be great to get a good high-level reference on where to learn about this kind of thing. It doesn't fit naturally into any topic that I know - maybe learn about cross-site scripting so I can avoid it?
** If you don't know, an MTurk HIT is the unit of work for folks doing tasks on MTurk. You can see what they look like pretty quick if you navigate to http://mturk.com and view a HIT.
I've traced the code to the following chunk run within jquery from the inject.js file:
try {
isHiddenIFrame = !isTopWindow && window.frameElement && window.frameElement.style.display === "none";
} catch(e) {}
I had a similar issue running jQuery in MechanicalTurk through Chrome.
The solution for me was to download the jQuery JS files I wanted, then upload them to the secure amazon S3 service.
Then, in my HIT, I called the .js files at their new home at https://s3.amazonaws.com.
Tips on how to make code 'secure' by chrome's standards are here:
http://developer.chrome.com/extensions/contentSecurityPolicy.html
This isn't a direct answer to your question, but our lab has been successful at circumventing (read hack) this problem by asking workers click on a button inside the iframe that opens a separate pop-up window. Within the pop-up window, you're free to use jQuery and any other standard JS resources you want without triggering any of AMT's security alarms. This method has the added benefit of allowing workers to view your task in a full-sized browser window instead of AMT's tiny embedded iframes.

Is there a name for this browser technique?

Is there a name for this technique that consists in exploring a page open in the browser to find specific content and modify it?
Some examples:
Skype finds phone numbers on a page, and attaches a call menu
a script finds percentages in a page and replaces them with a small pie
an advertising engine finds keywords in the page and converts them into hyperlinks
add an icon next to all the hyperlinks on the page that point to another domain
etc.
I understand that it is a kind of progressive enhancement. But I am specifically interested in the first step, the content discovery process. I'd be interested in articles that offer best practices, or explain the shortcomings of this technique.
Edit: I added an example to show that this technique is not just for text nodes, but can apply to any kind of html content.
For example, execute this code for this web-page (from the console), and all numbers on the page will be replaced with "X":
function walkTheDOM( node, func ) {
func( node );
node = node.firstChild;
while ( node ) {
walkTheDOM( node, func );
node = node.nextSibling;
}
}
walkTheDOM( document.body, function ( node ) {
if ( node.nodeType === 3 ) {
node.data = node.data.replace( /\d/g, 'X' );
}
});
This is functionality is called Add-ons and the technic used by these is DOM traversing
The cases you describe is not something specific to one site, but appear on every site you visit, so there must be some extra functionality added to your browser. This often happen when checking on install toolbars etc when installing a new software like Skype
The technic can be called recognition (as in PNR, Skype Phone Number Recognition), and what they are doing is traversing your site DOM .
This add ons describe above probably runs only on page load, so content added later on with ajax will not be affected.
If its your own add-on there is a way to access it with javascript ad described here: how to call a function in Firefox extension from a html button.
Take also a look at GreaseMonkey and jQuery traversing.
So the conclusion for now is that there doesn't seem to be a name or established practices for this technique.
Thanks to those who have mentioned search engines, it makes sense to see it as a local search, with an effort to interpret the content and structure.
As it is already said it is call summarization but you can find about it more searching therm "web crawling bot/technique/robot". Here some starting document you might find useful:
Crawling the Web
Summarization
It is the technique used in all the web crawlers. Please have a look at open source well documented web crawler/search engine Yioop!

alternative when an older browser does not accept jquery

I have just been altered to the fact that a user of my website is using a very old browser which does not run jquery (in this case Safari 1.x) and as a result can not access the login panel which uses jquery's slideToggle function.
Can anyone think of a fix which detects whether a browser is able to use jquery - and if not make that link go to a different page rather than showing the login panel?
You could a little conditional check like
if(!'jQuery' in window) {
// jQuery is not available
}
or, if Safari 1.x doesn't know about the IN operator (I'm not sure) use
if(!window.jQuery) {
}
I think there are alternative answers to this, but for me, I would have to weigh up the time it will take you to support his obsolete browser (I'm sure there may be other things inside the site), versus the payback to you...
In the plain HTML source code for the the href= of the login link, set that to a plain HTML login page.
Using jQuery, attach the click handler to the link, if this part fails, thats ok, the browser will just follow the href in the link to the plain login page, allowing your old-browser-user to login still.
$(document).ready(function(){
$('#login_link_id').click(function(){
// Your code here
});
});
If you use javascript/jQuery you should ALWAYS ensure your site works perfectly without it. In this case if you have a login popup box; you probably assign a click event assigned after the DOM has loaded.
What you should do is ensure that if jQuery isn't present the link loads a "normal" login webpage as opposed to the popupbox. I use something similar to this:
Log in
<script>
if(!'jQuery' in window) {
$(document).ready(function(){
//assign on click event to loginlink
});
}
</script>
If jQuery doesn't exist then login.html will be opened normally.
Wow, seriously?! Safari 1.x?? Anyhow, try this...
var isJQSupported = false;
$(function() { //shorthand for document.ready
isJQSupported = true;
//your usual code
});
if (!isJQSupported) {
window.location = "http://www.apple.com/safari/download/";
}
To me it sounds like safari 1.X has problems with jQuery internally. Which means simple checks like whether $ exists in the global space or whether $(function) does anything are not going to help.
The most likely root cause will be that javascript throws an error in loading of jQuery itself which will then stop the rest of your javascript code from execution.
There are four viable options here.
Either make the website work with noscript. Replace your login control with pure HTML and postbacks and ask the user to turn javascript off. This option is useful since you won't be fixing the issue for safari 1.x problems specifically.
You can make javascript check for safari 1.X and other non-supported browsers and only load jQuery through script tag injection or ajax if your user is using a supported browser. If the user is using a browser not compatible with jQuery then you can instead use plain javascript.
Get a copy of safari 1.x and see why jQuery breaks. Then fix it and ask for it to pulled into the release of jQuery 1.5. This relies on the fix being something that does can be done without hacking and that the jQuery team agrees is worth adding in.
Ask the user to use a compliant browser.
There might be some more options. I would personally lean towards asking the user to use a compliant browser because supporting Safari 1.x is ridiculous.
This seems like a case where progressive enhancement is needed.
You have to do multiple checks
see if $ exists
see if $.fn exists
[not sure if needed] check if $.support is a function
check for feature support as needed with $.support() http://api.jquery.com/jQuery.support/
At the end of the check, when jQuery reports that features you need are present - the rest of the script can run.
If you're not sure which features mentioned in the support you use, then this might need a single test on Safari 1.x to see what are the values returned by $.support(), but that is what your nasty old-browser-user can do for you (if you prepare code and publish) and report the resulting text. Then you compare the list with other [old] browsers that are accessible and determine features that are required.
The easy way would be to require everything and cancel all scripts if suport for any feature is missing. This will also rule out IE6 and IE7 and opera below 9.something and firefox below 2.0 or including - I'm not sure.
Use a server side language to detect if it's the old safari based on user-agent and load a different javascript file

How to help the debugger see my javascript, or how to best refactor my script to help make it debugger-friendly?

I have an ASP.NET MVC project that uses some simple AJAX functionality through jQuery's $.get method like so:
$.get(myUrl, null, function(result) {
$('#myselector').html(result);
});
The amount of content is relatively low here -- usually a single div with a short blurb of text. Sometimes, however, I am also injecting some javascript into the page. At some point when I dynamically include script into content that was itself dynamically added to the page, the script still runs, but it ceases to be available to the debugger. In VS2008, any breakpoints are ignored, and when I use the "debugger" statement, I get a messagebox saying that "no source code is available at this location." This fails both for the VS2008 debugger and the Firebug debugger in Firefox. I have tried both including the script inline in my dynamic content and also referencing a separate js file from this dynamic content -- both ways seemed to result in script that's unavailable to the debugger.
So, my question is twofold:
Is there any way to help the debugger recognize the existence of this script?
If not, what's the best way to include scripts that are used infrequently and in dynamically generated content in a way that is accessible to the debuggers?
I can not comment yet, but I can maybe help answer. As qwerty said, firefox console can be the way to go. I'd recommend going full bar and getting firebug. It hasn't ever missed code in my 3 years using it.
You could also change the way the injected javascript is added and see if that effects the debugger you're using. (I take it you're using Microsoft's IDE?).
In any case, I find the best way to inject javascript for IE is to put it as an appendChild in the head. In the case that isn't viable, the eval function (I hate using it as much as you do) can be used. Here is my AJAX IE fixer code I use. I use it for safari too since it has similar behavior. If you need that too just change the browser condition check (document.all for IE, Safari is navigator.userAgent.toLowerCase() == 'safari';).
function execajaxscripts(obj){
if(document.all){
var scripts = obj.getElementsByTagName('script');
for(var i=0; i<scripts.length; i++){
eval(scripts[i].innerHTML);
}
}
}
I've never used jquery, I preferred prototype then dojo but... I take it that it would look something like this:
$.get(myUrl, null, function(result) {
$('#myselector').html(result);
execajaxscripts(result);
});
The one problem is, eval debug errors may not be caught since it creates another instance of the interpreter. But it is worth trying.. and otherwise. Use a different debugger :D
This might be a long shot, but I don't have access to IE right now to test.
Try naming the anonymous function, e.g.:
$.get(myUrl, null, function anon_temp1(result) {
$('#myselector').html(result);
});
I'm surprised firebug is not catching the 'debugger' statement. I've never had any problems no matter how complicated the JS including method was
If this is javascript embedded within dynmically generated HTML, I can see where that might be a problem since the debugger would not see it in the initial load. I am surprised that you could put it into a seperate .js file and the debugger still failed to see the function.
It seems you could define a function in a seperate static file, nominally "get_and_show" (or whatever, possibly nested in a namespace of sorts) with a parameter of myUrl, and then call the function from the HTML. Why won't that trip the breakpoint (did you try something like this -- the question is unclear as to whether the reference to the .js in the dynamic HTML was just a func call, or the actual script/load reference as well)? Be sure to first load the external script file from a "hard coded" reference in the HTML file? (view source on roboprogs.com/index.html -- loads .js files, then runs a text insertion func)
We use firebug for debug javascript, profile requests, throw logs, etc.
You can download from http://getfirebug.com/
If firebug don't show your javascript source, post some url to test your example case.
I hope I've been of any help!
If you add // # sourceURL=foo.js to the end of the script that you're injecting then it should show up in the list of scripts in firebug and webkit inspector.
jQuery could be patched to do this automatically, but the ticket was rejected.
Here's a related question: Is possible to debug dynamic loading JavaScript by some debugger like WebKit, FireBug or IE8 Developer Tool?

Add a bookmark that is only javascript, not a URL

I'm thinking that the reason I can't do this is because it might be a huge security hole, but here goes...
I want to have a bookmark on my browser (FF3, preferably) that is only a snippet of javascript code. It would merely construct a URL based on the current date and then do a window.location = on that URL.
I know that I could make a page and keep it on my local machine and just refer to it that way, but I was just wondering if you could bypass that step and actually have the "location" of the bookmark really just be javascript. I could have sworn that this was possible years ago, but I can't find anything that tells me either way now.
What you want is a bookmarklet they are easy to create and should work in most major browsers.
Edit: Stack overflow seems not to allow creating bookmarklets in the context of the site, basically you can create a new bookmark and type the following in the location field
javascript:window.location='http://www.google.com/search?q='+Date()
to get a bookmarklet that searches google for the current date.
It is worthy of note that you can put that in a function wrapper as well. imranamajeed nicely illustrated that for us... but apparently I'm too new to the site to up his post. :P
so for clarity:
javascript:(function(){
location.href = location.href + "#";
})();
(the carriage returns did not affect performance in chrome and IE)
One minor catch. IE can only handle a 508 character URL in this format. If you save it in IE with a url longer than this, it will truncate without warning and thus fail.
If you need a really complex script, you'll need to use a "hosted" bookmarklet, where you have a short bookmark that injects a script tag into the page, to "call" your hosted bookmarklet.
It isn't as nice/portable, but its the only workaround.
Google Bookmark
javascript:(function(){var%20a=window,b=document,c=encodeURIComponent,d=a.open("http://www.google.com/bookmarks/mark?op=edit&output=popup&bkmk="+c(b.location)+"&title="+c(b.title),"bkmk_popup","left="+((a.screenX||a.screenLeft)+10)+",top="+((a.screenY||a.screenTop)+10)+",height=420px,width=550px,resizable=1,alwaysRaised=1");a.setTimeout(function(){d.focus()},300)})();
Well, I just created a bookmark in FF3, went back and updated it and added the following test:
javascript:alert('Wacky%20test%20yo');
Low and behold, after I saved and loaded, I was able to get my alert.
I'm sure you can work up something similar for your needs.

Categories