
Have you ever come across a website and saw some really interesting aspects of the user interface ? Maybe it was a site design that looks like a flash site but was not? Or maybe you came across a site that had a visually appealing menu.
Coming from mostly a backend-development background I get this feeling often. Last week it happened when I saw the Hide option on Facebook. I have seen it a hundred times before but on that day I found myself wondering, so I recreated the sample in my own way from scratch.
The following questions came to mind while looking at Facebook’s implementation:
- how to make the hide option, appear next to feed item that the mouse is hovering over.
- how to make the ‘menu’ item under the hide option appear and stay there when the Hide button is clicked
- how to remove the selected options from the list without having to refresh the whole page
- how to send the filter option to the server without posting back the whole page
I decided that I will use styling and jQuery to complete steps 1 – 3 and use a ajax call via jQuery to post the selected filter option back to the server.
Note that you will need some prior knowledge of jQuery selectors in order to follow the code sample. See the following urls for some background information on this:
- http://woorkup.com/2009/10/05/jquery-lesson-series-introduction-to-selectors/
- http://docs.jquery.com/Selectors
The following are the steps I completed to make these options work:
Create the folder structure:

- Download the latest query plug-in (jquery.js in the screenshot) from http://jquery.com/
- Create your project with necessary files. See the screen shot for my folder structure:
Import the style sheets and javascript files:
1. Place the following statements in the index.php file to reference the style sheets and javascript files
<html>
<head>
<title>How did they do that: Facebook Hide</title>
<link type="text/css" rel="stylesheet" href="styles/default.css" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery.feedfilter.js"></script>
<script type="text/javascript" src="js/hidebutton.js"></script>
</head>
<body>
Create the news feed items:
- The sample only shows one of the news feed entries for clarity sake. Repeat item-container div for each additional item you want.
- Note the following things when reviewing the snippet
- The class name for the feed item is item-container.
- Hide-button is a child element of item-container
- Hide-menu-header and hide-button-options are child elements of hide-button.
- The hide-menu-header relates to the Hide button on the screen shot and hide-button-options relate to the menu item under that.
- The custom user attribute on the span. This is the id (in our case a fictional id x) of the user’s events that must be filtered. This is the value that will be posted back to the server during the ajax call.
<body>
<center>
<div class="item-container">
<div class="left">
<div class="left">
<a class="left" href="/profile/sampleprofile">
<img class="profile-pic" src="images/avatar.png" width="55px" height="55px" />
</a>
<div style="clear:both"></div>
</div>
<div class="info">
<p>
<strong>
<a href="/profile/sampleprofile">Bruce Banner</a>
</strong> posted on twitter
</p>
<div class="detail">
<a href="#">8 hours ago</a> | <a href="#">comment</a> | <a href="#">like</a>
</div>
</div>
</div>
<div class="hide-button">
<div class="hide-menu-header">
<input type="button" value="hide"/>
</div>
<span class="hide-button-options" user="x">
<input type="button" value="Bruce Banner" />
</span>
</div>
</div>
...
<center>
<body>
Link up all the events to the appropriate elements:
Add script to hidebutton.js. The $(document).ready(…) construct is used to ensure that the initialization is only run once the full DOM is loaded. Note that $(document).ready(…) will run as soon as index page is loaded because it is imported in index.php and is not wrapped by any functions.
The script calls three methods that in turn use jQuery selectors to find the appropriate elements by class name or id and then links events to them.
- initializeFeedItemHoverEvent: adds the hover event to all elements that contain class item-container (news feed entries). There are 2 functions in this method. The first is fired when a mouse cursor is moved over the element and the second is fired when the mouse is moved away from the element
- initializeHideMenuClick: adds a click event to all hide-menu-header (hide menu button) items. It uses $(…).parent and $(…).find to find the appropriate elements relative to the current element. $(this) in this method relates to the hide menu button. It also uses removeClass and addClass to toggle the selected and unselected appearance of the hide menu button.
- initializeHideSubMenuClick: Calls the feedfilter() method (explained in the next step) on the appropriate hide button sub menu element. The feedfilter() method will use ajax to post the filter back to the server.
//file: hidebutton.js
$(document).ready(function() {
initializeFeedItemHoverEvent();
initializeHideMenuClick();
initializeHideSubMenuClick();
});
//Initialise the hover events over the newsfeed entries function initializeFeedItemHoverEvent(){
//Find all newsfeed items that have a class called item-container
$('.item-container').hover(function() {
//Show the hide button when the mouse moves onto the item
$(this).find('.hide-button').show();
},
function() {
//When the mouse cursor leaves the newsfeed item,
//hide the hide button and reset the styling to original
var hideButton = $(this).find('.hide-button');
hideButton.hide();
resetStyles(hideButton);
//Hide the submenu of the hide button
$(this).find('.hide-button-options').hide();
})
}
//Initialise the click on the hide menu item
function initializeHideMenuClick(){
//Find the hide button the user clicked and toggle (show/ hide) submenu
$('.hide-menu-header').click(function() {
//Find parent with class 'hide-button' of the current element
//from there find the child of the found element called 'hide-button-options'
var element = $(this).parent('.hide-button').find('.hide-button-options');
//Find out which class is set on the current element
//and based on that set a different class
if ($(this).attr('class') == 'hide-menu-header'){
$(this).removeClass('hide-menu-header');
$(this).addClass('hide-menu-header-selected');
element.show();
}
else {
$(this).removeClass('hide-menu-header-selected');
$(this).addClass('hide-menu-header');
element.hide();
}
})
}
//Initialise the click event on the hide sub menu
function initializeHideSubMenuClick(){
//When the user clicks on the menu option then
//call the feedfilter method in the jquery.feedfilter.js file
if ($(".hide-button-options").length > 0) {
$(".hide-button-options").feedfilter();
}
}
//Hide the menu button and its sub menus
function resetStyles(hideButton){
var menuHeader = hideButton.find(".hide-menu-header-selected");
if (menuHeader != null){
menuHeader.removeClass('hide-menu-header-selected');
menuHeader.addClass('hide-menu-header');
}
}
Complete the server post back:
The following section describes the code that fires when a user clicks on the hide button sub menu option. It first extracts the user id that is stored in the custom user attribute and posts it back to the specified page.
Note the if (response == “success”) {..} section. It finds all the news feed items with a sub element that has a user attribute with the same value as the news feed item that the user chose to hide.
//jquery.feedfilter.js
//Specifiy the feedfilter function definition
//What must happen when the user clicks the sub menu item
(function($) {
$.fn.feedfilter = function() {
this.click(function() {
//Call setFeedfilter
setFeedfilter($(this));
return false;
})
function setFeedfilter(obj) {
//Get the value of the user attribute on the current element
//as the user clicked on the hide sub menu the current element is
//the hide sub menu
var user = obj.attr("user");
var container = obj;
var originalContent = container.html();
$.ajax({
type: "POST", //post back method
url: "ajaxpostback.php", //page to post back to
dataType: "json",
data: {"userId": user}, //additional parameters
beforeSend: function(xmlhttprequest) {
//change the content of the sub menu button to appear as a
//loading animated gif
container.html('<img src="\" alt="\"loading\"" />')
},
complete: function(xmlhttprequest, textStatus) {
//add any code here that should fire once the post back
//is completed
},
success: function(response) {
//add any code that must run once the postback is completed and
//successfull
if (response == "success") {
$(".item-container .hide-button-options").each( function() {
var data = $(this).attr("user");
if (user == data)
{
$(this).parent('div').parent('.item-container').hide();
}
}
);
}
else
{
alert(response);
}
},
error: function(xmlhttprequest,status,error) {
alert("There was a problem with filtering events.");
container.html(originalContent);
}
})
}
}
})(jQuery)
What happens on the post back page?
I have not implemented the actual persisting of the filter setting but have shown how to retrieve the parameter value passed from the client side.
<?php
//Persist $_POST["userId"];
echo json_encode(array("success"));
?>
View the result
Browse to the index.php page and you should get something similar to the screenshot shown below.

What’s next?
- Styling can be refined. I used some inline styles etc that can be moved to the style sheets.
- Content is static at the moment. The news feed items would normally be generated from a data store of some sort
- Add additional error handling
- I used inline php and markup together to simplify the example. Best practice though, is to split your php code and markup. One approach would be to implement the Model View Controler (MVC) design pattern. A good option for this is to use the Zend Framework (http://framework.zend.com/). It implements the MVC pattern and has loads wrapper classes that wraps commonly used functionality to promote reuse.




