Archived

This topic is now archived and is closed to further replies.

kentyman

uTorrent Bookmarklet, or "Add new torrents from your iPhone"

Recommended Posts

Update: I have since made a webpage that generates these bookmarklets for you. You can find it at http://btbookmarklet.sourceforge.net/.

After discovering the power of the uTorrent WebUI, I naturally wanted to be able to use it from my iPhone. Though the WebUI doesn't currently support Safari out-of-the-box, one can currently manage their torrents remotely by using the iPhone-optimized web interface found here: http://www.davidraso.com/utorrent-iphone/. This interface does allow adding new torrents, as long as you don't mind remembering and hand-typing their entire URL or Mininova ID. Powerful, but cumbersome.

What I wanted was the ability to click a torrent link and have it automatically start downloading at home. To accomplish this, I've written a bookmarklet that transforms all links on your current page into links that redirect to the uTorrent WebUI.

The code of the bookmarklet is as follows:

javascript:(function() { var host = "http://<HOST>/gui/"; for (var i = 0; i < document.links.length; i++) { document.links[i].href = "javascript:(function() { var img = document.createElement('img'); img.setAttribute('src', '"+ host + "?action=add-url&s=" + encodeURIComponent(document.links[i].href) + "'); img.setAttribute('style', 'visibility:hidden'); document.body.appendChild(img); setTimeout('window.open(\"" + host + (navigator.userAgent.match(/iP(hone|od)/i) ? "iphone/i.html" : "") + "\", \"_self\");', 4000); })();"; } })();

To use it, just make a new bookmark named "uTorrent Bookmarklet" and put the above code in as its URL. You'll need to edit the code by changing <HOST> to your host and port (e.g. "mydomain.dyndns.org:8080"). If you don't want to login each time, you can even add your login information (e.g. "username:password@mydomain.dyndns.org:8080").

Additionally, for those that don't want to edit the code, I've made a host-generic version that queries for your host and port each time you run it:

javascript:(function() { var host = "http://" + prompt('Enter "<host>:<port>":', "") + "/gui/"; for (var i = 0; i < document.links.length; i++) { document.links[i].href = "javascript:(function() { var img = document.createElement('img'); img.setAttribute('src', '"+ host + "?action=add-url&s=" + encodeURIComponent(document.links[i].href) + "'); img.setAttribute('style', 'visibility:hidden'); document.body.appendChild(img); setTimeout('window.open(\"" + host + (navigator.userAgent.match(/iP(hone|od)/i) ? "iphone/i.html" : "") + "\", \"_self\");', 4000); })();"; } })();

I've since found a similar solution that someone made for use with Transmission: http://www.macosxhints.com/article.php?story=20071215111252241. The nice part about using uTorrent with its WebUI instead was that I didn't need to do any server-side development.

Keep in mind that you don't need an iPhone or iPod Touch to make use of this bookmarklet; use it anytime you want to easily add new torrents from afar!

Update: I updated the bookmarklets so that you get forwarded on to the WebUI 4 seconds after clicking a link (presumably this is enough time for the torrent to be added). On iPhones/iPods, you get forwarded to the iPhone-optimized WebUI I mentioned above. Many thanks to those that helped me get this working!

Share this post


Link to post
Share on other sites

I wanted to make it so that it would first send the add-url, and then go to the WebUI (or in the iPhone case, the iPhone WebUI), but I was having trouble with the Javascript.

I tried making the links do "javascript:location.href = <add-url>; location.href = <webui>;". This seemed to work on my computer, but didn't work on my iPhone. I was wondering if that was because the second location.href assignment was happening before the first GET was finished sending?

Anyone know the right way to accomplish this? If so, I can update the bookmarklets above.

Share this post


Link to post
Share on other sites

I actually tried setTimeout before and couldn't get it to work.

So I made a bookmarklet to do two alerts, and it works fine:

javascript:(function() { alert('Yo!'); setTimeout("alert('Yo, again!');", 4000); })();

Then I made one that changes location.href and then alerts later, and it doesn't work:

javascript:(function() { location.href = 'http://google.com/'; setTimeout("alert('Yo!');", 4000); })();

It seems the timer gets lost when the location changes.

I don't actually need to go to the add-url location, I just need to make sure the GET is accomplished, and then I need to go to the WebUI. Is there a way to do a GET in the background and wait till it's done, so I can change location.href afterward?

Thanks for your help.

Share this post


Link to post
Share on other sites

Perhaps you can "cheat" by doing something like:

javascript:(function() { var host = 'http://<HOST>/gui/'; document.writeln('<img style="visibility:hidden" src="' + host + '?action=add-url&s=' + <URL> + '">'); setTimeout('location.href="' + host + '";', 4000); })();

Ugly, but from what I can tell, it seems to work in sending the request in...

Question: Why wrap the whole thing inside a dummy function?

Share this post


Link to post
Share on other sites

First, about the "(function(){})();" stuff:

I started using this anonymous function syntax because I used these bookmarklets as examples to base my bookmarklet off of. I'm a software engineer by trade, but have zero experience with Javascript, so examples have so far been my only learning tool. I have since found certain code where not using this syntax leads to strange errors. For example, this bookmarklet works fine in Firefox and IE:

javascript:(function() { setTimeout("alert('Yo!');", 1000); })();

This one, however, does not alert at all in either browser, and instead brings me to a page with a random integer on it:

javascript:setTimeout("alert('Yo!');", 1000);

In Firefox, it consistently return 2, and in IE it returns 2374054, and increments each time I click the bookmarklet.

Because of this, I'm taking for granted that I need the anonymous function. If someone could explain the reason I need it, that'd be very much appreciated.

As for the <img/> hack:

Wow, that is quite the hack. :) But your right, it seems to work all right, at least in Firefox and IE. Unfortunately, I could not get it to work on my iPhone. My uTorrent at home is currently closed so I can't do further testing right now, so I'm gonna have to go off my memory of what I tried last night...

Here's what I tried first:

javascript:(function() { var host = "http://<HOST>/gui/"; var links = document.links; for (var i = 0; i < links.length; i++) { links[i].href = "javascript:document.writeln(\"<img style='visibility:hidden' src='" + host + "?action=add-url&s=" + encodeURIComponent(links[i].href) + "' />\"); setTimeout(\"location.href='" + host + (navigator.userAgent.match(/iP(hone|od)/i) ? "iphone/i.html" : "") + "';\", 4000);"; } })();

Notice that it changes the href to some Javascript without the anonymous function. If I remember correctly, this works in Firefox but not IE. So then I tried it with the anonymous function:

javascript:(function() { var host = "http://<HOST>/gui/"; var links = document.links; for (var i = 0; i < links.length; i++) { links[i].href = "javascript:(function() { document.writeln(\"<img style='visibility:hidden' src='" + host + "?action=add-url&s=" + encodeURIComponent(links[i].href) + "' />\"); setTimeout(\"location.href='" + host + (navigator.userAgent.match(/iP(hone|od)/i) ? "iphone/i.html" : "") + "';\", 4000); })();"; } })();

I believe this worked well in both Firefox and IE, but not Mobile Safari. I'll have to try again.

I wonder if it has something to do with the fact I'm putting Javascript in the href? Should I be changing .onclick instead of .href?

Share this post


Link to post
Share on other sites

Heh, I've never used void(0) to stop an anchor from working. Ever since I could remember, I've always used "return false" :P

That said, I doubt using onclick would make a difference, as the problem lies with the location.href changing, not how it is changing :/

Share this post


Link to post
Share on other sites

Very cool little bookmarklet there! However whenever I click on a torrent and the file begins the download, shortly after uTorrent gives me the error Access is Denied. Any ideas?

Share this post


Link to post
Share on other sites

Zaza, I'm not sure what would be causing that, but if the file begins to download, I'm assuming it's some other problem not related to the bookmarklet. Maybe someone else has an idea?

Share this post


Link to post
Share on other sites

Thanks for the responses! The odd thing is if I download a torrent normally from my web browser, I don't have the problem. If anyone doesn't have anymore ideas then I guess I'll get the troubleshooting forum a shot.

Share this post


Link to post
Share on other sites

Welp, I can't seem to get the <img/> hack to work on the iPhone. Any other ideas on how I can get it to go to the WebUI after doing an add-url call?

Share this post


Link to post
Share on other sites

Not tested, but uh...

- try creating the img element using DOM instead of document.writeln()?

- clear the page, then create two iframes -- (1) invisible, and pointing to the add-url, (2) "fullscreen" and pointing to the webui?

Share this post


Link to post
Share on other sites

DOM element manipulation works much better. I've updated the first post with the new code.

Thanks for all the help, guys!

Edit: Heh, new problem.

On the iPhone, the change of location.href doesn't seem to work properly with the Back/Next history. So I can't add a torrent (which eventually goes to the WebUI), click Back, and then add another torrent.

Because of this, I find it better to take out the setTimeout part:

javascript:(function() { var host = "http://<HOST>/gui/"; for (var i = 0; i < document.links.length; i++) { document.links[i].href = "javascript:(function() { var img = document.createElement('img'); img.setAttribute('src', '"+ host + "?action=add-url&s=" + encodeURIComponent(document.links[i].href) + "'); img.setAttribute('style', 'visibility:hidden'); document.body.appendChild(img); })();"; } })();

Anyone know a better way to go to a page that might work better with the Back/Next stack in Mobile Safari?

Share this post


Link to post
Share on other sites

That seems to work perfectly, Ultima. I've updated the original post with the new code. Thank you again for your "random ideas"! :)

I've tested on Mobile Safari, Firefox, and Internet Explorer, and it seems to work well on all of them. On Mobile Safari and Internet Explorer, you have to use the bookmarklet again each time you press Back. On Firefox, you can click Back and then another torrent without using the bookmarklet again.

I've even tested the case where you take well over 4 seconds to enter your username/password on Mobile Safari, and it seems to work well (the setTimeout must be paused while the login dialog is up)!

Share this post


Link to post
Share on other sites

Excellent :)

Yeah, alert() and prompt() are blocking functions, meaning all scripts stop executing while they're displayed.

Regarding the anonymous functions... I think I finally understood why they're needed :P The reason you saw the integer when using setTimeout() is because it returns something. In fact, anything that returns something will get that something displayed on the browser after that something is executed, and that's where the anonymous functions come into play. Since the anonymous function doesn't return anything, the browser doesn't try to display anything, which means any changes to the browser contents will stay (rather than get overwritten by the returned data).

Share this post


Link to post
Share on other sites

Ah, that makes a lot of sense. Glad I understand it now, too.

Now that I finally got this thing working the way I want it, do y'all think it's useful enough for non iPhone/iPod Touch users that it should be mentioned in the "everyting about WebUI" post as a standalone gadget, instead of just a nice addition to the iPhone interface? I find it to be very useful to use from from my browser at work, for example. Actually, does anyone else even use it? :)

Share this post


Link to post
Share on other sites

Honestly, I don't use the WebUI much, and any torrenting I do is local to my µTorrent, so I can't really say I'd use it. I certainly looks useful, especially for Mobile Safari users (where it might not be as easy to copy/paste URLs to webui manually).

I've added the bookmarklet to the sticky, by the way.

Share this post


Link to post
Share on other sites

Just a quick usage note:

I've noticed that after clicking a link on the iPhone/iPod, and then clicking Back to go back to your tracker, you have to take note of whether or not Mobile Safari reloads the page. If it reloads the page, you'll have to use the uTorrent Bookmarklet again before clicking another link. If it does not reload the page, you'll want to make sure to not use the uTorrent Bookmarklet again before clicking the link.

Share this post


Link to post
Share on other sites