The definitive guide of Symfony 1.1

11.1. Basic JavaScript Helpers

JavaScript has long been considered as having little real use in professional web applications due to the lack of cross-browser compatibility. Today, the compatibility issues are (mostly) solved, and some robust libraries allow you to program complex interactions in JavaScript without the need for countless lines of code and lost hours of debugging. The most popular advance is called Ajax, which is discussed in the "Ajax Helpers" section later in this chapter.

Paradoxically, you will see very little JavaScript code in this chapter. This is because symfony has an original approach to client-side scripting: It packages and abstracts JavaScript behaviors into helpers, so your templates end up showing no JavaScript code at all. For the developer, adding a behavior to an element in the page takes one line of PHP, but this helper call does output JavaScript code, and inspecting the generated responses will reveal all the encapsulated complexity. The helpers deal with browser consistency, complex limit cases, extensibility, and so on, so the amount of JavaScript code they contain can be quite important. Therefore, this chapter will teach you how not to use JavaScript to achieve effects that you use to build with JavaScript.

All of the helpers described here are available in templates, provided that you declare the use of the Javascript helper group.

<?php use_helper('Javascript') ?>

As you'll soon learn, some of these helpers output HTML code, and some of them output JavaScript code.

11.1.1. JavaScript in Templates

In XHTML, JavaScript code blocks must be enclosed within CDATA declarations. But pages requiring multiple JavaScript code blocks can soon become tedious to write. That's why symfony provides a javascript_tag() helper, which transforms a string into an XHTML-compliant <script> tag. Listing 11-1 demonstrates using this helper.

Listing 11-1 - Inserting JavaScript with the javascript_tag() Helper

<?php echo javascript_tag("
  function foobar()
  {
  ...
  }
") ?>
 => <script type="text/javascript">
    //<![CDATA[
      function foobar()
      {
        ...
      }
    //]]>
    </script>

But the most common use of JavaScript, more than code blocks, is in a hyperlink that triggers a particular script. The link_to_function() helper does exactly that, as shown in Listing 11-2.

Listing 11-2 - Triggering JavaScript by a Link with the link_to_function() Helper

<?php echo link_to_function('Click me!', "alert('foobar')") ?>
 => <a href="#" onClick="alert('foobar'); return none;">Click me!</a>

As with the link_to() helper, you can add options to the <a> tag in the third argument.

Note Just as the link_to() helper has a button_to() brother, you can trigger JavaScript from a button (<input type="button">) by calling the button_to_function() helper. And if you prefer a clickable image, just call link_to_function(image_tag('myimage'), "alert('foobar')").

11.1.2. Updating a DOM Element

One common task in dynamic interfaces is the update of an element in the page. This is something that you usually write as shown in Listing 11-3.

Listing 11-3 - Updating an Element in JavaScript

<div id="indicator">Data processing beginning</div>
<?php echo javascript_tag("
  document.getElementById("indicator").innerHTML =
    "<strong>Data processing complete</strong>";
") ?>

Symfony provides a helper that produces JavaScript, not HTML, for this purpose, and it's called update_element_function(). Listing 11-4 shows its use.

Listing 11-4 - Updating an Element in JavaScript with the update_element_function() Helper

<div id="indicator">Data processing beginning</div>
<?php echo javascript_tag(
  update_element_function('indicator', array(
    'content'  => "<strong>Data processing complete</strong>",
  ))
) ?>

You might be wondering why this helper is particularly useful, since it's at least as long as the actual JavaScript code. It's really a matter of readability. For instance, you might want to insert content before or after an element, remove an element instead of just updating it, or even do nothing according to a certain condition. In such cases, the JavaScript code becomes somewhat messier, but the update_element_function() keeps the template very readable, as you can see in Listing 11-5.

Listing 11-5 - Options of the update_element_function() Helper

// Insert content just after the 'indicator' element
update_element_function('indicator', array(
  'position' => 'after',
  'content'  => "<strong>Data processing complete</strong>",
));

// Remove the element before the 'indicator', and only if $condition is true
update_element_function('indicator', array(
  'action'   => $condition ? 'remove' : 'empty',
  'position' => 'before',
))

The helper makes your templates easier to understand than any JavaScript code, and you have a single syntax for similar behaviors. That's also why the helper name is so long: It makes the code self-sufficient, without the need of extra comments.

11.1.3. Graceful Degradation

The <noscript> tag allows you to specify some HTML code that is displayed only by browsers that do not have JavaScript support. Symfony complements this with a helper that works the other way around: It qualifies some code so that only browsers that actually support JavaScript execute it. The if_javascript() and end_if_javascript() helpers facilitate the creation of applications that degrade gracefully, as demonstrated in Listing 11-6.

Listing 11-6 - Using the if_javascript() Helper to Allow Graceful Degradation

<?php if_javascript(); ?>
  <p>You have JavaScript enabled.</p>
<?php end_if_javascript(); ?>

<noscript>
  <p>You don't have JavaScript enabled.</p>
</noscript>

Note You don't need to include echo when calling the if_javascript() and end_if_javascript() helpers.