In the comments Mark asked for a way to open link from the module in a new window. Since others might be interested I make this a blog post, but since I’m lazy I’ll make the post about the most simple way to do this.
Well, the easiest way is to set a target for the links, and the easist way to achieve that would be, as far as the place here module is concerned, to go to the modules/mod_placehere/tmpl directory, open the template(s) in an editor and hardcode the target into the code. For the readmore link this would look like this:
<a target=”_blank” href=”<?php echo $article->readmore_link; ?>” class=”readon<?php echo $params->get( ‘pageclass_sfx’ ); ?>”>
The bit right after the anchor – target=”_blank” – forces a new window or a new tab, depending on browser and browser configuration.
This method has some drawbacks, two of which I will adress here: One, it does not work with the module for Joomla 1.0.x (which does not use templates) and b) it means you code will not validate, since target is not a valid attribute in XHTML. We will cheat a bit and hide the target attribute from the validator by setting the target with Javascript.
This could be done with a script that looks like this:
<script type=”text/javascript”>
links = document.getElementById(‘leftcolumn’).getElementsByTagName(‘a’);
for(i=0;i<links.length;i++) {
links[i].target = “_blank”;
}
</script>
which you would have to place at the bottom of your page. But what does this actually do?
To understand these few lines it helps to understand concepts like “DOM”, “chaining” and “iteration”.
DOM is the “Document Object Model”. In the olden days a HTML document used to be a long list of characters, a.k.a a string. If you wanted to find a specified segment in the document the browser had to search through the whole string (which was a mix of the HTML formatting and the content), a cumbersome and not particularly efficient process. Modern Browsers have a different way – they represent a document as a collection of parent- and child elements (where every child can be in turn a parent to other childs). This allows for more efficient methods, like getElementById() which targets an element with a unique CSS Id, or getElementsByTagName, which collects all Elements of a given type. Methods like this can be chained.
Functions (which in some contexts might be called “methods”) have usually a return value that can be assigned to a variable. If you do something like
<script type=”text/javascript”>
function test() {
return “this is a test”;
}
toast = test();
</script>
the variable toast will hold the return value of the function test (i.e. “this is a test”). This is only useful when you plan to use the return value somewhere in your function script; on the other hand assining a value to a variable takes work both from you and the browser, and you don’t want to waste the work if you do not need the variable later on. In comes the concept of chaining, which allows you to skip one (or multiple) assignments, because, instead of writing
<script type=”text/javascript”>
temp = document.getElementById(‘leftcolumn’);
links = temp.getElementsByTagName(‘a’);
</script>
you can chain these method together with the dot notation like this:
<script type=”text/javascript”>
links = document.getElementById(‘leftcolumn’).getElementsByTagName(‘a’);
</script>
This will pick the element with the CSS Id of “leftcolumn” from your HTML document and search it for all links elements with the type of “a(nchor)”. The result will be stored in the variable “links”.
“links” will now hold a list with all links in leftcolumn (also called an array). It will be a list even when there is only one link, since getElementsByTagName always returns a list. To assign a new property (like a target) to every element in this list you need to move from entry to entry, a process that’s called iteration. The easiest way to iterate through a list is a for-loop.
<script type=”text/javascript”>
for(i=0;i<links.length;i++) {
links[i].target = “_blank”;
}
</script>
First you will notice a bit with the dot notation. However this is not method chaining; “length” is a “property” of the variable links that refers to the number of entries in the list (you can tell easily tell the difference between a method call and a property, since a method call has brackets, or parenthesis or whatever the correct word is “()” ).
The list has an internal counter that start with “0″ (this is a convention, it doesn’t have to make sense, even if it seems more intuitive to most people to start a list with 1). So the first entry of the list is links[0], the second is links[1] etc.
We do not know in advance how long our list is, but we can easily find out by accessing its length property. So we have our loop:
<script type=”text/javascript”>
for(i=0;i<links.length;i++) { }
</script>
which means to the browser: starting with zero; as long as the counter is smaller as the length of the list; increment (add one to) the counter; do whatever you are told to do inside the curly brackets (the counter needs to be smaller than the list length since the list starts with 0; if the length is ten the the last list element ist links[9]).
So there we are again with our complete script:
<script type=”text/javascript”>
links = document.getElementById(‘leftcolumn’).getElementsByTagName(‘a’);
for(i=0;i<links.length;i++) {
links[i].target = “_blank”;
}
</script>
This sets the target property for every item of the list (i.e. it creates a target attribute on every link).
I said you would have to place the script at the bottom of your template. This is because the script cannot successfully execute before the element with the ID of ‘leftcolumn’ exists in the page. If you want to use in in another place, or in an external script file (best way) you can use the onload event handler.
Events are mostly responses to user interaction (click, mouseover, mouseenter etc). An event handler allows you to assign a response to an event.
A page load is also an event. It is executed when the page and the related assets (images, script files etc) are fully loaded, making sure that every element you script needs already exists. So you could place the following in the head of your template file:
<script type=”text/javascript”>
window.onload = function() {
var links = document.getElementById(‘leftcolumn’).getElementsByTagName(‘a’);
for(i=0;i<links.length;i++) {
links[i].target = “_blank”;
}
}
</script>
Onload is is a method of the window object (Document Object Model, you remember?). There are some other elements with a onload event (images for example), but mostly this is used on the window itself. For the load event we define a so called “anonymus function” (which is called anonymus because it does not have a name. Duh).
So the above script works on every Joomla template where there is an element with the ID of leftcolumn that contains one or more links. Naturally this works with other ids to.
Of course most joomla templates now include the mootools javascript library which means that you could rewrite the above as
<script type=”text/javascript”>
window.addEvent(‘load’, function() {
$$(‘#leftcolumn a’).setProperty(‘target’,'_blank’);
})
</script>
which is an altogether more reliable and elegant way of doing things, but you wouldn’t have learned anything that way.