Ask your JavaScript questions! Pay money and get answers fast! (more info)

I need a script that opens links for MP3s in a new window JavaScript

  • SOLVED

I need a Javascript script that will find every link on the page that ends with ".mp3" and ensures that, when clicked, that link opens in a new window.

We have taken an old site and rebuilt it in Symfony. The new site is suppose to go live on July 8th. The final preview push is suppose to happen on July 1st. The site contains thousands of pages, with a lot of content, including video, text, images and mp3s. One of the editors just pointed out to me what she regards as an inconsistent flaw in the old site - the videos and images tend to open in new windows, but the MP3s have direct links, that take the viewer away from the page they are looking at. The links to the MP3s look like this:

http://www.domain.com/school/files/Audio/mia_hamm.mp3


Since we are dealing with thousands of pages and thousands of links, and the site needs to get pushed to preview on July 1st, we obviously do not have time to go through the pages and hand-edit the links to the MP3s. So I thought we might handle this with Javascript.

So, I need a Javascript script that will find every link on the page that ends with ".mp3" and ensures that, when clicked, that link opens in a new window.

Answers (6)

2010-06-26

Jarret Minkler answers:

When you say images and videos open in new links is this a separate module or action in symfony?

Are you using echo link_to for all your links?

While it is a fix to use JavaScript it seems like the wrong solution. I think a better solution would be to customize the built in functions in symfony to suite your needs.

Not sure the above jquery is correct either. Needs a regex.

$(*[href$=mp3])

(Ends in mp3)


Lawrence Krubner comments:

Jarret, that would be a very clever idea if the site had originally been built with Symfony. I get what you are saying, and it is a good idea. However, this site was initially built in a different system. Also, like with WordPress, the main content of the site was a mix of HTML and text, and the HTML contained links to videos and images and mp3s. These links were not created with Symfony tags like url_for(), nor do we have time to go back through and edit the thousands of pages of content to make all the links proper Symfony links. But it is a very good idea for the future. Thanks.


Jarret Minkler comments:

Shame :( everytime I hear "thousands of pages" I die a little. Lol.

2010-06-26

Oleg Butuzov answers:

clear js, no jquery or other selector engine required, work faster than jquery css3 selector example.

function mp3_to_target_new(){
var links = document.getElementsByTagName("a");

for(var i = 0; i < links.length; i++){
if (links[i].href.indexOf('.mp3') != -1){
links[i].target = '_blank';
}
}
}

2010-06-27

Morgan Chélin answers:

The <strong>first solution</strong>, which consists in modifying every links in page at page loading is quite simple. Code below is more or less similar to those proposed earlier, except for the extension test (indexOf is a waste of time in this case, and may return false positive) and the window name (which corresponds to the name of the file).


var mp3_corrections =
{
// returns true if href relies on a mp3 file
is_mp3 : function(href)
{
var l;
l = href.length - 5;
return ((l >= 0) && (href.substr(l) === ".mp3"));
},
// returns the name of the window corresponding to the href file
get_window_name : function(href)
{
var i;
return ((i = href.lastIndexOf("/")) > 0) ? href.substr(i) : href;
},
// corrects mp3 links in the page, adding target attribute
correct : function()
{
var links, link, i, l, name_regexp;

links = document.getElementsByTagName("a");
for(i = 0, l = links.length; i < l; i++)
{
link = links[i];
if(this.is_mp3(link.href))
{
link.target = this.get_window_name(link.href);
}
}
}
}


I won't repeat what said Yaron Shapira about code place. If you use the prototype framework, just add

Element.observe(window, "load", mp3_corrections.correct);

after the mp3_correction object définition. Otherwise, add

mp3_corrections.correct();


<strong>Another solution</strong> I see, and which has the advantage to avoid delaying page loading, is to listen uncaught click events of the page. Disadvantage is that every click event which bubbles until window will be tested.

What to add to the <em>mp3_corrections</em> object if you use Prototype :


install : function()
{
Element.observe(document.body, "click", this.intercept_mp3_links.bind(this));
},
// if event come from a mp3 link, stop its propagation and opens a new window
intercept_mp3_links : function(event)
{
var el;

el = Event.element(event);
if(Element.match(el, "a") && this.is_mp3(el.href))
{
Event.stop(event);
window.open(
link.href,
this.get_window_name(link.href),
"dependent=yes,location=no,menubar=no"
);
}
}


Otherwise :


install : function()
{
var body, callback;

body = document.body;
if(body.addEventListener)
{
body.addEventListener("click", mp3_corrections.intercept_mp3_links, false);
}
else
{
if((callback = body.onClick))
{
body.onClick = "mp3_corrections.intercept_mp3_links(event); " + callback;
}
else
{
body.onClick = "return mp3_corrections.intercept_mp3_links(event);";
}
}
},
intercept_mp3_links : function(event)
{
var el;

el = event.srcElement || event.target;

if((el.tagName.toLowerCase() === "a") && this.is_mp3(el.href))
{
Event.stop(event);
window.open(
link.href,
this.get_window_name(link.href),
"dependent=yes,location=no,menubar=no"
);
if(event.preventDefault)
{
event.preventDefault();
event.stopPropagation();
}
else
{
event.cancelBubble = true;
return false;
}
}

return true;
}


And you'll have to call <em>mp3_corrections.install</em> the same way than for the <em>mp3_correction.correct</em> method.

Personally, I prefer the second solution.
I gave examples for the Prototype framework, but there's also simplest ways to proceed with JQuery or ExtJs for example ...


Lawrence Krubner comments:

Morgan, very clever code. I'm going to toy with the capture of the bubbling clicks. This could be useful for redirecting some of the URLs that need to be changed in the new environment.

2010-06-26

Andrzej answers:

Can we use jQuery?

If yes:

$(document).ready(function() {
$('a[href$=".mp3"]').attr('target', '_blank');
});


Lawrence Krubner comments:

Sorry, no jQuery. The site already uses Prototype, and we think it would be too heavy to include 2 libraries.

2010-06-27

Yaron Shapira answers:

Vanilla Javascript code below (slightly better then Oleg's suggestion). You would want to run this script as early as possible, so if you are using jQuery or similiar library, you have the ondomready type event ($(function(){}) in jQuery). If you were to use jQuery or similar, you are probably still better off leaving the code itself as vanilla javascript, because that will be fastest. You could go fancy and even "disable" all links until you've added your new target - let me know if you find this necessary. If you want to use pure javascript for the domready event, look here: http://www.javascriptkit.com/dhtmltutors/domready.shtml. Optionally you could run this code on window load, but this is a fairly late event in the life of the page... You could also simply run the code right before the closing </body> tag but that is not 100% dependable and may not be convenient anyway (depeneding on how your site is set up).

var mp3s = document.getElementsByTagName("a");
var len = mp3s.length;
for(var i=0;i<len;i++) {
if(mp3s[i].href.indexOf(".mp3") != -1){
mp3s[i].target = "_blank"; // replace with any other name if you want all mp3s to open in a single (but different) window
}
}

2010-06-27

erez213 answers:

function newWindowLinksMP3()
{
if (!document.getElementsByTagName) return;
var anchors = document.getElementsByTagName("a");
for (var i=0; i<anchors .length; i++)
{
var anchor = anchors[i];
if (anchor.getAttribute("href") && anchor.getAttribute("href").indexOf('.mp3') != -1){
anchor.target = "_blank";
}
}
}
window.onload = function() {
newWindowLinksMP3();
}


Simply put this in your document and the code will do the rest