This tutorial will explain how to add code to your theme that will pop up the player in a new window. I will use the 1pixelout player for this tutorial, but it should work with any player you have installed.

The pop-up window is created using JavaScript. Because of this, there are four issues with this technique:

  • If scripting is disabled, or the browser does not support JavaScript, the pop-up will not work
  • Pop-ups present accessibility problems
  • Search engines cannot follow links to pop-up windows
  • Many browsers prevent pop-ups from appearing by default

The standard way to get around these issues is to create a link to the page, creating a new window via the target="_blank" property of the HTML link, and have JavaScript override it.

Unfortunately, this will not work in this case, because the HTML for the popup window is being created dynamically. There's no static HTML page to link to.

To get around some of these issues, we first output the HTML for the player as it is normally, then a link that says "Open in New Window" after it. The HTML for the link is itself written in JavaScript, which means that browsers without JavaScript will not see the link at all. The JavaScript that opens the window will also put it in focus.

This helps with the first two issues. The third isn't important (since it's a dynamic page), and there's really no way to solve the fourth one.

Now, let's review the code from the Theming the Flash Player tutorial:

function phptemplate_audio_1pixelout_node_player($node, $options = array()) {
  $options = array_merge(array(
    'leftbg' => '0xFF0000',
    'rightbg' => '0x000000',
    'lefticon' => '0xFFFFFF',
    'righticon' => '0xFFFFFF',
  ));
  return theme_audio_1pixelout_node_player($node, $options);
}

We're going to expand on this code, so that the function will return an additional link to open the player in a new window. Clicking on this link will activate JavaScript that will create a small window and populate it with the player.

1. Capture the player's HTML instead of returning it

Instead of simply returning the HTML created by theme_audio_1pixelout_node_player(), we're going to capture it in a PHP variable named $object_html to use later:

function YOURTHEMENAME_audio_1pixelout_node_player($node, $options = array()) {
  $options = array_merge(array(
    'leftbg' => '0xFF0000',
    'rightbg' => '0x000000',
    'lefticon' => '0xFFFFFF',
    'righticon' => '0xFFFFFF',
  ));
  
  // Get the HTML from the default 1pixelout function
  $object_html = theme_audio_1pixelout_node_player($node, $options);
}

Note that I also changed the function name to override your theme, instead of the PHPTemplate engine itself. This is how all theme overrides should be done, due to possible function collisions with sub-themes.

2. Create the HTML for the pop-up window

Next, we need to create the HTML that will populate the pop-up window. This will include the output we captured in $object_html. Also, we will have to encode it using htmlspecialchars(), because this text will itself be inside an HTML link.

  // HTML for pop-up window
  $window_html = <<<EOT
<html>
<head>
  <title>1pixelout Player</title>
  <style type="text/css">
  <!-- 
    object {outline: none;}
  -->
  </style>
</head>
<body>
$object_html
<p><a href="javascript:self.close()">Close Window</a></p>
</body>
</html>
EOT;
  $window_html = htmlspecialchars($window_html, ENT_QUOTES);

I included the CSS for the "object" tag because some browsers automatically put an outline around embedded Flash objects, and I don't want this. You probably should include more styles; background color, text color, etc.

I also included a link that will close the window using self.close(), but you may not want this.

3. Create the window and link with JavaScript

Now we'll create a link saying "Open in New Window," which uses JavaScript to:

  1. Create a new window
  2. Populate that window with $window_html
  3. Focus that window

Opening the window is accomplished using a JavaScript function called openWindow(). In this tutorial, I actually include the JavaScript in the output of the player. I'll show you a better way later.

Here is the code:

  // Create the link with the JavaScript code
  $ouptut = <<<EOT
$object_html
<script type="text/javascript">  
<!--
function openWindow(windowHTML) {
  newWindow=window.open('','audioWindow','width=310,height=24,toolbar=No,location=No,scrollbars=No,status=No,resizable=No,fullscreen=No');
  newWindow.document.write(windowHTML);
  newWindow.focus();
}
document.write('<br /><a href="javascript:openWindow(\'$window_html\')" class="pop-up-link">' +  
   'Open in New Window</a>');  
//-->  
</script>
EOT;

Note that I put a class of pop-up-link on the link, so it can be styled using CSS.

Now, all we have to do is return $output, and our function override is complete.

Finished Theme Override Code

For those too lazy to read this tutorial, just copypasta the code below into your theme's template.php file, renaming YOURTHEMENAME with the name of your theme.

/**
 * Override the 1pixelout player skin
 * (in sites/all/modules/audio/players/1pixelout.inc)
 *
 * @param $node
 *   node object
 * @param $options
 *   array of options to pass to the player. This allows you to override the
 *   any parameter passed to the player including colors, title, etc
 * @return
 *   Use theme_audio_1pixelout_node_player() to return an HTML string
 */
function YOURTHEMENAME_audio_1pixelout_node_player($node, $options = array()) {
  $options = array_merge(array(
    'leftbg' => '0xFF0000',
    'rightbg' => '0x000000',
    'lefticon' => '0xFFFFFF',
    'righticon' => '0xFFFFFF',
  ));
  
  // Get the HTML from the default 1pixelout function
  $object_html = theme_audio_1pixelout_node_player($node, $options);
  
  // HTML for pop-up window
  $window_html = <<<EOT
<html>
<head>
  <title>1pixelout Player</title>
  <style type="text/css">
  <!-- 
    object {outline: none;}
  -->
  </style>
</head>
<body>
$object_html
<p><a href="javascript:self.close()">Close Window</a></p>
</body>
</html>
EOT;
  $window_html = htmlspecialchars($window_html, ENT_QUOTES);
  
  // Create the link with the JavaScript code
  $ouptut = <<<EOT
$object_html
<script type="text/javascript">  
<!--
function openWindow(windowHTML) {
  newWindow=window.open('','audioWindow','width=310,height=24,toolbar=No,location=No,scrollbars=No,status=No,resizable=No,fullscreen=No');
  newWindow.document.write(windowHTML);
  newWindow.focus();
}
document.write('<br /><a href="javascript:openWindow(\'$window_html\')" class="pop-up-link">' +  
   'Open in New Window</a>');  
//-->  
</script>
EOT;

  return $output;
}

A Better Way To Handle JavaScript

The above code works fine, and since you only have to paste it into your template.php file, it's easy to do. However, there is one small problem: you're creating the JavaScript openWindow function every time an audio player occurs on the page. This can be an issue if you have many players on one page (e.g. using Views).

To get around this, you would create a new file named (let's say) openWindow.js. This JavaScript file will hold the openWindow function. I've modified the function to include the header and footer HTML, so that the overridden function is more succinct. (Keep in mind that JavaScript does not have the heredoc syntax, so it looks a bit uglier.)

function openWindow(windowHTML) {
  var htmlHeader = "<html>\n<head>\n  <title>1pixelout Player</title>"
    + "\n  <style type=\"text/css\">\n  <!-- \n    object {outline: none;}\n  -->"
    + "\n  </style>\n</head>\n<body>";
  var htmlFooter = "<p><a href=\"javascript:self.close()\">Close Window</a></p>"
    + "\n</body>\n</html>";
  newWindow=window.open('','audioWindow','width=310,height=24,toolbar=No,location=No,scrollbars=No,status=No,resizable=No,fullscreen=No');
  newWindow.document.write(htmlHeader);
  newWindow.document.write(windowHTML);
  newWindow.document.write(htmlFooter);
  newWindow.focus();
}

Save this file in your template's folder. Now, open up YOURTHEMENAME.info and add this line:
scripts[] = openWindow.js

This will load the JavaScript once per page, not once per player. It does load this script on every page, which means that the function can be re-used if you need to open a pop-up window in another theme override. If you do re-use it, you probably want to modify it (e.g. pass it the window variables, HTML title, etc). This should be pretty easy if you have any JavaScript experience whatsoever.

Or, perhaps you've installed another module that uses its own JavaScript pop-up function. If that's the case, you can use that function instead.

The function override is now much simpler:

/**
 * Override the 1pixelout player skin
 * (in sites/all/modules/audio/players/1pixelout.inc)
 *
 * @param $node
 *   node object
 * @param $options
 *   array of options to pass to the player. This allows you to override the
 *   any parameter passed to the player including colors, title, etc
 * @return
 *   Use theme_audio_1pixelout_node_player() to return an HTML string
 */
function YOURTHEMENAME_audio_1pixelout_node_player($node, $options = array()) {
  $options = array_merge(array(
    'leftbg' => '0xFF0000',
    'rightbg' => '0x000000',
    'lefticon' => '0xFFFFFF',
    'righticon' => '0xFFFFFF',
  ));
  
  // Get the HTML from the default 1pixelout function
  $object_html = theme_audio_1pixelout_node_player($node, $options);
  
  // Create the link with the JavaScript code
  $ouptut = <<<EOT
$object_html
<script type="text/javascript">  
<!--
document.write('<br /><a href="javascript:openWindow(\'$object_html\')" class="pop-up-link">'  
  + 'Open in New Window</a>');  
//-->  
</script>
EOT;

  return $output;
}

Happy theming!