Code snippets for symfony 1.x

Navigation

Snippets by user scott meves

Inspired by this snippet (http://www.symfony-project.com/snippets/snippet/83) here is a version I created that inherits from sfPager. I had a collection of objects (not propel objects) that I needed to iterate through and this did the trick. Note that this is not really optimal because the full array has to be populated with whatever data you are looking at during each request, whereas something like sfPropelPager is smart enough to only fetch/hydrate the objects you are going to need for that particular view.

If you want to have a quick drop down (select) menu that automatically takes users to a specific page on your site, this method works well and results in clean URLS. This snippet is for content / urls stored in a database.

That way we can have urls like "content/about" or "content/news". (Note you will want to make sure your content titles are URL friendly themselves, perhaps using a stripped_title field instead of the title field that is parsed to replace spaces and punctuation.)

In the peer class of the "content" table we want to create a method we can use to populate our jump menu:

Remembering AJAX State

If you are updating your interface with ajax actions, typically users have no way to bookmark or return to the page with those updates already in place. This is seen as a fundamental problem with ajax: the URL shown at the top of the browser no longer constitutes a complete specification of the information shown in the window.

This snippet explains how you can track and recreate the current view even when using ajax to update your page. Now if users reload the page or send this link to a friend, the current state will remain intact. (You can view an example of this technique on http://www.ask.com/)

The trick relies on two parts:

Updating the window.location.hash (the part of the url after the "#", also called an anchor) on a page.

Using it to reconstruct the state of the interface. In other words, when users click on your ajax links, you will update the URL with a new hash string, and when the page is loaded you can you look for this hash string and update the interface accordingly.

Part One: Tracking State

First, you must allow the links created using the helpers link_to_remote and link_to_function to NOT have a 'return false;' appended to the end of the onclick attribute of the tag that is generated. There is no way to change this by way of the default helper, but it's easy to override with our own.

A 'return false' statement means the browser won't try to navigate to the url in the 'href' attribute of your link. Usually you don't want your browser window to navigate to the default "href" link--you are just creating the link as means to make the ajax call. Typically href attributes, if any, are present in case the user does not have javascript enabled.

However, we do not want "return false" appended to the onclick attribute. Ideally our helper function would allow us to do something like this:

Now for my ajax links I use my new helper and make sure to pass an href attribute as well as the 'return' attributte. This determines if clicking on the link will return true (update the url) or false (don't update it). Here is a real example of how I use it to keep track of what message is currently viewed in a message component within my interface.

Notice that the href attribute has a string that mirrors the URL attribute. We could probably take the my_link_to_remote helper a step further and automatically generate the HREF attribute based on the URL, but I decided to keep some flexibility there. Now, if a user clicks the link, the url will get a string like "#message:viewInline|id:3|view:inbox" appended to it.

In my experience, both IE 6 and FF did NOT scroll to the top of the window nor did the page reload. In fact I believe the W3 DOM specs state that links to a hash address never reload the document. Instead, I get a nice new attribute in the URL of the page. Now, if my user wants to bookmark the page, or perhaps reload it, the current ajax state can be recalled using the information in the anchor tag.

Part Two: Using the Hash to Reconstruct State

Although you cannot retrieve the value after the hash from within PHP, you can retrieve it client-side by way of the 'location.hash' function and then set a cookie, update the page, or do whatever you like based on those attributes. I am using it to reload a message from a users inbox into the inline viewer. Let's see how it works.

First, we need a way to load in the hash string and turn it into something we can use. Here is the function I use and included in my main.js file that is used throughout my site.

Next, whenever my page is loaded I should check to see if the hash contains attributes I set within my ajax actions. If there are, I call the same client-side update from remote function as I do when a user clicks on the ajax link in the interface. Here is the top of my indexSuccess.php file for my home page action. I do not include this within the main.js file because I want to use the PHP helpers like remote_function provided by symfony. Compare this to the use of my_link_to_remote in the code above.

This time, instead of calling the "remote_function" helper with parameters within PHP, I rely on javascript to send the correct parameters using the "with" parameter. That way, I can include values from javascript that aren't available until the page is loaded.

That's all there is to it (phew!). Now that this is all set up, I can easily convert my inline ajax links to javascript functions that are automatically called when the necessary attributes exist within the URL hash.

Often times in my navigation I want to change the style of the "current" tab, link, menu item, etc. to reflect that the user is in fact on that page. In order to do this I created a super simple helper called link_to_styled. I added this code to app/lib/helper/StyleHelper.php: