Javascript, jQuery, Web Development

Summarise.js – Make Bootstrap Alerts More… Responsive

I would like to introduce something which has made my life easier when using Bootstrap in dynamic event based situations, especially for XHR forms. I call it: summarise.js. It, essentially, allows you to make Bootstrap alerts which can be controlled entirely in JavaScript. This means you can make them work around XHR calls and other dynamic events.

You can find more at the project’s GitHub repository: https://github.com/Sammaye/summarise

Advertisements
Javascript, jQuery

Amazon like Product Gallery with Prodigal

I recently had a need to create a product gallery like on Amazon capable of using images and videos and having a filter for showing one or the other, or both. So I went off, procrastinated about it for about 3 days then made it in about 1.

I have called it: prodigal.

You can find the GitHub repository to fork, love etc here: https://github.com/Sammaye/prodigal.

The browsers I have tested this on as working are:

  • Firefox (latest)
  • IE (7 and above)
  • Safari 5.1 and above
  • Opera 12 and above
  • and Chrome (latest)

All you need to do to get started is to look at the example.html page within the repository and you can use it, for example:

$('.some-thumbs').prodigal({ //options });

With .some-thumbs being a class that is on all the thumbnails you wish to enter prodigal.

jQuery

Facebook Dropdown Menu Using jdropdown

Get jdropdown at its GitHub home: https://github.com/Sammaye/jdropdown.

Note: this plugin requires jQuery 1.7.x or higher.

I have made a plugin that can handle dropdown menus from a single anchor. I made this plugin since there was, frankly, no real decent plugins for it. There are plugins for navigation bars, select boxes, option boxes, and many more but none for making a simple menu from a random anchor on your page.

The plugin is called jdropdown, and you can call it on any element (literally) like:

$('.someel').jdropdown({ 'container': 'somecontainer' })

The constructor can take up to 3 parameters:

  • container – This is the jQuery selector (minus the $() around the selector since that’s not actually part of the selector) for the item which the menu items will be put in.
  • orientation – This param tells the script whether to align the menu to the left or right of its anchor and it takes either “left” or “right”.
  • items – This parameter is optional and it is to tell the widget what items will be in the menu. The value is an array of object arrays (i.e. [{//item one}, {//item two}]) and any data can be put into these items but there must be at least a “label” field if your not using your own renderItem function in which case, anything is possible!

The plugin currently has two functions you can override:

  • renderMenu – This basically gives off some HTML for the items to go into the ul
  • renderItem – This works a lot like jQuery UI plugins and it just appends each item to the menu container

Note: If you override the renderMenu function with complex html you may be required to also override the renderItem to append/prepend to the correct element within that menu.

The plugin also has a number of API functions which you can hook into:

  • open – is triggered when the menu opens. This has a $(this) of the anchor which holds all data in the data() function about the menu
  • selectItem – is triggered when an item in the menu is selected. It has a $(this) of the menu item, its parent element holds all information in its data() function about the item
  • close – This is triggered upon close the menu and because of its global scope, has no $(this)

Now, for an example of how to use one of these events:

$(document).on('jdropdown.selectItem', '#fb_menu a', function(e){
    e.preventDefault();
    alert('You selected: '+$(this).parent().data('jdropdown.item').label);

    // Do some crazy AJAXy weirdy stuff here to make your app awesome
});

This function binds to document that when a item in the #fb_menu container is clicked it will run that function.

Final thoughts:

  • As I said, items is optional in the plugin definition. This is because you can actually attach items to the anchors themselves allowing you to have the same styled menu with different options without having to have duplicated code. The simple way of doing this is to add a data-items attribute to your anchor’s HTML and make the value a (valid to: parseJSON Doc) JSON string.
  • Also note the item itself can take ANY data and the jdropdown plugin will just attach that data to the data() of the li for that item allowing you to access it when it is selected. So for example you can place “id” in there or “woop” with values of 3 and access it like: $(this).parent().data('jdropdown.item').id.
  • You must put the container into the HTML page first, best place is at the end of the doc just before the end body tag.
  • You can call this on almost any element so long as you have provided items in some manner.

Have fun! Any questions or if you need clarification just post a comment.

jQuery

Create a Sometimes position:fixed Top Menu jQuery

After reading Ben Nadel’s post (www.bennadel.com/blog/1810-Creating-A-Sometimes-Fixed-Position-Element-With-jQuery.htm) I decided that I wanted to implement his first example into my site. Only problem is, I didn’t want to write it out every time I wanted to call a new “sometimes-fixed-position-element” so I decided to make a jQuery plugin called “stickytoolbar” (Yup!).

/**
 * @author Some guy in the back alley
 * @licence WTF? Like I care
 *
 * This plugin is basically designed to allow some one to widgetise the handling of sticky toolbars from the example on
 * http://www.bennadel.com/blog/1810-Creating-A-Sometimes-Fixed-Position-Element-With-jQuery.htm
 *
 * This plugin is very basic and does nothing special tbh.
 *
 */
(function($){
    $.fn.stickytoolbar = function (options) {

        $(this).addClass(options.onStaticClass).data('options', $.extend({
            'onStaticClass': '',
            'onFixedClass': ''
        }, options));

        $(window).bind(
            'scroll resize', function () {
                $('.stickytoolbar-placeholder').each(function () {

                    var options = $(this).data().options,

                        // Get the current offset of the placeholder.
                        // Since the message might be in fixed
                        // position, it is the plcaeholder that will
                        // give us reliable offsets.
                        placeholderTop = $(this).offset().top,

                        // Gets the message element so it can be used
                        bar = $(this).find('.stickytoolbar-bar'),

                        // Get the current scroll of the window.
                        viewTop = $(window).scrollTop();

                    // Check to see if the view had scroll down
                    // past the top of the placeholder AND that
                    // the message is not yet fixed.
                    if ((viewTop > placeholderTop) && !bar.hasClass('stickytoolbar-fixed')) {

                        // The message needs to be fixed. Before
                        // we change its positon, we need to re-
                        // adjust the placeholder height to keep
                        // the same space as the message.
                        //
                        // NOTE: All we're doing here is going
                        // from auto height to explicit height.
                        $(this).height($(this).height());

                        // Make the message fixed.
                        bar.addClass('stickytoolbar-fixed')
                            .css({
                                left: $(this).offset().left + 'px',
                                top: '0px',
                                position: 'fixed',
                                width: $(this).width() + 'px'
                            })
                            .removeClass(options.onStaticClass)
                            .addClass(options.onFixedClass);

                        // Check to see if the view has scroll back up
                        // above the message AND that the message is
                        // currently fixed.
                    } else if ((viewTop <= placeholderTop) && bar.hasClass('stickytoolbar-fixed')) {

                        // Make the placeholder height auto again.
                        $(this).css({'height': 'auto', 'width': 'auto'});

                        // Remove the fixed position class on the
                        // message. This will pop it back into its
                        // static position.
                        bar.removeClass('stickytoolbar-fixed')
                            .css({left: 'auto', top: 'auto', position: 'static', width: 'auto'})
                            .removeClass(options.onFixedClass)
                            .addClass(options.onStaticClass);

                    }
                });
            }
        );
    };
})(jQuery);

You can use this plugin like so (as an example I have also placed in a setting param):

<script>
    $('.toolbar').stickytoolbar({ onStaticClass: 'sticktoolbar-static' });
</script>

<div class="stickytoolbar-placeholder toolbar">
    <div class="stickytoolbar-bar"></div>
</div>
jQuery

jQuery Rotating Banner/Slider with Fade In/Fade Out Effects

I made a plugin for JQuery that allows for me to make a fade in/out jQuery banner slider from a JSON source file. It is on GitHub: https://github.com/Sammaye/jslider (Yes I named it jslider; I know, I’m a pikey).

This plugin is real simple all you need to make is a JSON data source like so:

[{"image":"slide_01.jpg"},{"image":"slide_02.jpg"},{"image":"slide_03.jpg"}]

This JSON file will be the source for all your slides. As you can see I have just specified 3 slides and 3 images, one image for each slide. After you have your source data you just need the page:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jslider</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript" src="/js/j-slider.js" ></script>
    <script type="text/javascript">$(document).ready(function(){ $(".j-slider_outer").j_slider(); });</script>

    <style>
        .j-slider_outer {
        }

        .j-slider_inner {
            display: block;
            position: relative;
        }

        .j-slider_row {
            position: absolute;
        }

        .j_slider-slide_outer {
            position: absolute;
        }

        .j_slider-slide_active {
            display: block;
            z-index: 45 !important;
        }

        .j_slider-slide {
            display: block;
        }

        .j_slider-next, .j_slider-previous {
            overflow: hidden;
            font-size: 15px;
            font-weight: bold;
            color: #ffffff;
        }

        .j_slider-next {
            display: block;
            position: absolute;
            right: 0;
            z-index: 45;
        }

        .j_slider-previous {
            display: block;
            position: absolute;
            left: 0;
            z-index: 45;
        }

        .j_slider-controls_outer {
            display: block;
            position: absolute;
            right: 3px;
            bottom: 5px;
            z-index: 45;
        }

        .j_slider-controls_inner {
            float: left;
            height: 16px;
            width: 16px;
            font-size: 12px;
            color: #ffffff;
            margin: 0 3px;
            cursor: pointer;
            background: url("ibutton.png");
        }

        .j_slider-controls_active {
            background: url("button.png");
        }
    </style>
</head>
<body>
    <div class="j-slider_outer"><div class="j-slider_inner"></div></div>
</body>
</html>
Javascript, jQuery, PHP, Web Development

PHP Multiple Upload Progress Bar With Advanced Upload Control

Note: this article is DEPRECATED. Please use one the many great scripts on the internet, like blueimp’s jQuery file upload plugin.

tl;dr: this is on GitHub: https://github.com/Sammaye/multifile_ajax_uploader

First thing you need to do is install the uploadprogress extension for PHP:

apt-get install php5-pear
apt-get install php5-dev
pecl install uploadprogress

Afterwards open up your php.ini and add:

extension=uploadprogress.so

And, finally, restart (don’t reload) your server:

sudo /etc/init.d/apache2 restart
sudo servicee nginx restart
# etc

Believe it or not, but you now have PHP upload progress identification installed. Now you just need to make a script that will upload a file and display its progress. Shall we move on?

The JavaScript

var upload_timer;
var timeout = 5000;
var u_ids = [];

$(document).ready(function () {

    // Add a new upload form
    add_upload();

    // When the "Add new upload" link is clicked add a new upload form
    $('#add_upload_form').click(function () {
        add_upload();
        return false;
    });

});

/**
 * Stops an upload
 *
 * @param id
 */
function stop_upload(id) {

    var answer = confirm("Are you sure you wish to remove this upload?"), p_id = "#up_prog" + id;

    // Only remove the upload if it has not completed.
    if (answer && ($(p_id + " .uploadProgInner").css("width") != "100%") && ($("#container_outer" + id).length > 0)) {

        // Form ids and write the cancelling message
        var message_id = "#up_message_prog" + id;
        $(message_id).html("<b style='color:red;'>Cancelling...</b>");

        // Make the upload go away peacefully showing the user it has been cancelled.
        setTimeout(function () {
            $("#container_outer" + id).remove();
            u_ids.splice(u_ids.indexOf(id), 1);
        }, "2000");
    } else {
        if (($(id + " .uploadProgInner").css("width") == "100%") || ($("#container_outer" + id).length == 0)) {
            $("#general_error").show();
            $("#general_error span").html("<h2>File Upload Could Not Be Removed</h2><p>The file upload could not be removed. This is most likely due to the file having had already been completed or already removed by some other means.</p>");
        }
    }
}

/**
 * This function runs when a upload is submitted. It checks the
 * file field as best it can for a valid file. TBH there are some things
 * we just have to do AFTER the file has been uploaded to /temp
 *
 * @param id
 * @returns {Boolean}
 */
function check_upload(id) {
    var file = $("#" + id).val(), end = file.length, start = end - 5;

    var ext = file.substring(start, end);

    // Is the file a divx extension?
    if (ext == ".divx") {
        $("#uploadForm-outer" + id).hide();
        $("#up_prog" + id).show();
    } else {
        $("#general_error").show();
        $("#general_error span").html("<h2>Wrong File Type</h2><p>You attempted to upload a file type that is not supported by this uploader. Pleae try again soon, we hope to have support for mkv, avi and other formats in their raw form.</p>");
        return false;
    }
}

/**
 * This adds a new upload form to the screen
 */
function add_upload() {

    var ts, count;

    // We make a ts as a cache buster for shit browsers cough-Opera-cough
    ts = Math.round(new Date().getTime() / 1000);

    // How many forms already exist?
    count = $(".uploadFormContainer").length;

    // So long as limit has not been reached (10)
    if (count < 10) {

        // Generate the form
        $.get("/upload/add", {ts: ts}, function (data) {

            // Add to the page
            $("#uploadForm_container-outer").append(data);

            // If this is the first form then add the updater iframe
            if (count == 0 && $('#uInfo_ifr').length == 0) {
                $("#u_iframe_container").html("<a href=" / upload / getInfo
                ">/upload/getInfo</a>"
            )
                ;
            }

            // Add the upload id to the list of IDs
            var e = $(".uploadFormContainer").last().find("input[name=UPLOAD_IDENTIFIER]").val();
            count_ids = u_ids.length;
            u_ids[count_ids] = e;
        });

    } else {

        // Show upload limit error
        $("#general_error").show();
        $("#general_error span").html("<h2>Upload Limit Reached</h2><p>This form has been limited to 10 uploads to protected internet connections. If you are sure you understand what your ISP allows you to upload you can open a new window and continue uploading there.</p>");
    }
}

/**
 * This gets the updated status of the uploads
 *
 * @param info
 */
function update_progress(info) {

    // Scrolls through the IDs assigning the information.
    for (i = 0; i < info.length; i++) {

        // Sometimes uploadprogress can return null for a upload
        if (info[i] != null) {

            // Calculate how much has been uploaded
            var done = Math.floor(100 * parseInt(info[i].uploaded) / parseInt(info[i].total));

            // Ascertain the IDs for the elements needing change
            var id = "#up_prog" + info[i].id;
            var message_id = "#up_message_prog" + info[i].id;

            // Change the width of the progress bar to match done and set a message for the upload status
            $(id + " .uploadProgInner").css("width", done + "%");
            $(message_id + " span").html(done + "% Completed of " + info[i].file + " - Estimated Time Left: " + info[i].left + " at " + info[i].speed + "ps");
        }
    }

}

The Upload Form

Now we have the JavaScript we need the upload form itself. This form will be rendered every time add_upload() is called within the JavaScript whilst the user is under the upload limit:

<?php
global $session;
$u_id = strval(new MongoId());
?>
<div class="uploadFormContainer" id="container_outer<?php echo $u_id ?>">
    <div class="uploadForm" id="uploadForm-outer<?php echo $u_id ?>">

        <h2>Please select a file to upload</h2>

        <form 
            onsubmit='check_upload("<?php echo $u_id ?>")' 
            action="/upload/to_server" 
            target="u_ifr<?php echo $u_id ?>" 
            method="post" 
            enctype="multipart/form-data"
        >
            <input type="hidden" name="UPLOAD_IDENTIFIER" value="<?php echo $u_id ?>"/>
            <input type="file" name="<?php echo $u_id ?>" id="<?php echo $u_id ?>"/>

            <input type="submit" value="Upload" class="uploadFormSubmit"/>
        </form>


    </div>

    <div class="uploadBar" id="up_prog<?php echo $u_id ?>">
        <div class="uploadProgOuter">
            <div class="uploadProgInner">&nbsp;</div>
        </div>
        <div class="up_message_prog" id="up_message_prog<?php echo $u_id ?>">
            <span>Connecting to server...</span>
            <a href="javascript:;" class="cancel_uploadForm" onclick='stop_upload("<?php echo $u_id ?>")'>
                <b>Cancel</b>
            </a>
        </div>
        <div id="up_err<?php echo $u_id ?>"></div>
    </div>
</div>

The Progress Update Page

Now we have a form up and running (I will let you decipher the form :P) we just need the progress update page:

<?php
// A nice little hack for telling IE we wont abuse iframe permissions
header('P3P: CP="CAO PSA OUR"');
global $session;
?>
<html>
    <head>
        <title>Upload Info Page</title>
    
        <script type="text/javascript">
    
            // Get the u_ids from the parent window
            var u_ids = parent.u_ids, id_url = "";
    
            // Run the initial function
            refreshiframe();
    
            function refreshiframe() {
    
                // Get the url formatted version of u_ids (upload IDs)
                if (u_ids != null && u_ids.length > 0) {
                    for (i = 0; i<u_ids.length; i++) {
                        // return an url of the current id
                        if (i == 0) {
                            id_url = id_url + "ids[]="+u_ids[i];
                        } else {
                            id_url = id_url + "&ids[]="+u_ids[i];
                        }
                    }
                } else {
                    id_url = "ids[]=0";
                }
    
                // if php detects the set $_GET then delay the refresh else do it now
                <?php if (empty($_GET['ids']) && !isset($_GET['ids'])) { ?>
                    redirect();
                <?php }else{ ?>
                    setTimeout("redirect()",5000);
                <?php } ?>
            }
    
            function redirect() {
                // redirect with full url encoded u_ids
                parent.uInfo_ifr.location.href="/upload/getInfo?"+id_url;
            }
        </script>
    
    </head>
    
    <body>
        <script type="text/javascript">
        
            var info = [];
        
            <?php for ($i = 0; $i<count($_GET['ids']); $i++) {
        
                $upload_id = $_GET['ids'][$i];
        
                // This is our magic function. It gets our upload information
                $info = uploadprogress_get_info($upload_id);
        
                // We format the data to be printed into JS JSON arrays and echo it to screen
                if (!empty($info) && $info) { ?>
                    info[<?php echo $i ?>] = {'id':'<?php echo $upload_id ?>', 'file':'<?php echo $info['filename'] ?>', 'uploaded':<?php echo $info['bytes_uploaded'] ?>, 'total':<?php echo $info['bytes_total'] ?>, 'left':'<?php echo gmdate("H:i:s", $info['est_sec']) ?>', 'speed':'<?php echo convert_size_human($info['speed_average']) ?>'};
                <?php } else { ?>
                    info[<?php echo $i ?>] = null;
                <?php } ?>
        
            <?php } ?>
        
            // Now lets update the upload progress
            parent.update_progress(info);
        
        </script>
    </body>
</html>

The Page

Now we need the other page this all goes into:

<div class="UIMessage error UIMessageConstrained UIUploadErrorMessage" id="general_error">
    <span></span>
</div>

<div class="upload_container">

    <div id="uploadForm_container-outer"></div>

    <div id="u_iframe_container" class="u_iframe_container"></div>

    <a href="" id="add_upload_form">Add new upload</a>

</div>

Believe it or not, but that is it! You now know how to make a progress bar in PHP. Remember, this isn’t flash and nor is it HTML 5, it will work on any browser with almost any settings so long as they don’t have JavaScript turned off :P. All you need to do now is style it. Here is my style sheet to get you started:

.upload_container {
    width: 600px;
    margin: auto;
}

.uploadFormContainer {
    padding: 10px;
    border: 1px solid #C9D7F1;
    margin-bottom: 10px;
}

.uploadForm {
    border: 1px solid #E1ECFE;
    background: none repeat scroll 0 0 #F0F6FF;
    padding: 10px;
}

.uploadForm h2 {
    margin-bottom: 10px;
}

.uploadFormSubmit {
    float: right;
    font-weight: bold;
}

.uploadBar {
    display: none;
}

.uploadProgOuter {
    background: white;
    height: 40px;
    padding: 2px;
    border: 1px solid #73A6FF;
}

.uploadProgInner {
    background: #73A6FF;
    width: 10%;
    height: 40px;
}

.up_message_prog {
    margin-top: 7px;
}

.u_iframe_container {
    display: none;
}

.UIUploadErrorMessage {
    display: none;
    margin: 15px auto;
}

This style produces this result (or close anyway):

Any questions? If so, just write a comment, otherwise; enjoy :).

CSS, Javascript, jQuery

Facebook Top Bar/Bottom Bar Sticky Navigation Bar

This snippet shows you how to make a Facebook bottom bar like they used to have before the latest redesign.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Facebook Navigation Example</title>

    <script>
        // This is the JavaScript that controls the menu
        var SubMenutimer;
        var last_o;

        $(".mainbar").ready(function () {
            $(".staticMenu dt a").click(function () {

                $(".staticMenu dd ul").not($(this).parents(".staticMenu").find("ul")).hide();
                $(".staticMenu dt a").not($(this)).removeClass("selected");
                $(this).parents(".staticMenu").find("ul").toggle();

                if ($(this).parents(".staticMenu").find("ul").css("display") == "none") {
                    $(this).removeClass("selected");
                } else {
                    $(this).addClass("selected");
                }

            });

            $(".staticMenu dd ul li a").click(function () {
                var text = $(this).html();
                $(".staticMenu dt a span").html(text);
                $(".staticMenu dd ul").hide();
            });

            $(document).bind('click', function (e) {
                var $clicked = $(e.target);
                if (!$clicked.parents().hasClass("staticMenu")) {
                    $(".staticMenu dd ul").hide();
                    $(".staticMenu dt a").removeClass("selected");
                }

            });
        });

        function openSubMenu(o) {
            cancelSubMenuClose();

            if (last_o) $(last_o).parent().find("div").hide();

            last_o = o;
            $(o).parent().find("div").show();
        }

        function closeSubMenu() {
            SubMenutimer = setTimeout("close()", 500);
        }

        function cancelSubMenuClose() {
            clearTimeout(SubMenutimer);
        }

        function close() {
            $(last_o).parent().find("div").hide();
        }
    </script>

    <style>
        div.mainbar {
            top: 0;
            z-index: 99;
            padding: 0;
            position: fixed;
            width: 100%;
        }

        div.mainbarInner {
            background: url(/images/pre_top.png);
            border: 1px solid #bcb6aa;
            border-top: 0;
            border-bottom: 0;
            margin: 0 15px;
        }

        ul.mainMenu {
            list-style: none;

        }

        ul.mainMenu li {
            float: left;
            border-right: 1px solid #bcb6aa;
        }

        .mainMenu li a {
            padding: 5px 4px 5px 4px;
            margin-bottom: 1px;
            display: block;
            font-weight: bold;
            color: #444444;
            line-height: 15px;
            text-decoration: none;
        }

        .mainMenu li a:hover {
            background: white;
            text-decoration: none;
        }

        .staticMenu dl {
        }

        .staticMenu dd {
            position: relative;
        }

        /* DT styles for sliding doors */
        .staticMenu dt a {
            padding: 5px 4px 5px 4px;
            margin-bottom: 1px;
            display: block;
            font-weight: bold;
            color: #444444;
            line-height: 15px;
            text-decoration: none;
        }

        .staticMenu dt a.selected {
            background: white;
            position: relative;
            z-index: 99;
            padding-bottom: 6px;
        }

        /* UL styles */
        .staticMenu dd ul {
            display: none;
            list-style: none;
            position: absolute;
            cursor: pointer;
        }

        ul.mainMenuSub {
            position: absolute;
            top: -2px;
            left: -1px;
            padding: 2px;
            border: 1px solid #b4a291;
            background: white;
        }

        ul.mainMenuSub li {
            border: 0;
            width: 223px;
        }

        ul.mainMenuSub li.seperator {
            width: 223px;
            height: 2px;
            display: block;
            background: url(/images/mainmenusep.png) repeat-x;
            margin-bottom: 6px;
            margin-top: 4px;
            overflow: visible;
        }

        ul.mainMenuSub li a:link {
            display: block;
            font-weight: bold;
            text-align: left;
            overflow: hidden;
            padding: 2px 4px 3px 19px;
            color: #444444;
            text-decoration: none;
        }

        ul.mainMenuSub li a:hover {
            background: #444444;
            color: white;
            text-decoration: none;
        }

        ul.mainMenuSub li a img {

            border: 0;
        }

        ul.mainMenuSmall li {
            width: 173px;
        }

        div.mainMenuSubTwo {
            display: none;
            left: 220px;
            position: absolute;
            top: 3px;
            z-index: 99;
            background: white;
        }

        div.mainMenuSubTwo ul {
            border: 1px solid #b4a291;
            padding: 2px;
            background: white;
        }

        a.MainSubExpandable {
            background: white url(/images/mainmenuexpandable.png) no-repeat right top;
        }

        ul.mainMenuSub li a.MainSubExpandable:hover {
            background: #444444 url(/images/mainmenuexpandable.png) no-repeat;
            background-position: right -20px;
        }
    </style>

</head>
<body>
    <div class="mainbar">
        <div class="mainbarInner" style="overflow:visible; position:relative; display:block; height:26px;">
            <ul class="mainMenu">
                <li>
                    <dl style="" class="staticMenu">
                        <dt><a href="/applications" onclick="return false;">Applications</a></dt>
                        <dd>
                            <ul class="mainMenuSub">
                                <li><a>There are no applications here</a></li>
                            </ul>
                        </dd>
                    </dl>
                </li>
                <li>
                    <dl style="" class="staticMenu">
                        <dt><a href="/places" onclick="return false;">Places</a></dt>
                        <dd>
                            <ul class="mainMenuSub">
                                <li><a href="javascript:;" onmouseover="openSubMenu(this)" class="MainSubExpandable" onmouseout="closeSubMenu(this)" style="cursor:pointer;">Library</a>

                                    <div class="mainMenuSubTwo" id="subMenuMainLib" onmouseover="cancelSubMenuClose()" onmouseout="closeSubMenu(this)">
                                        <ul>
                                            <li><a href="#">Videos</a></li>
                                            <li><a href="#">Favourites</a></li>
                                            <li><a href="#">Playlists</a></li>
                                            <li><a href="#">Subscriptions</a></li>
                                        </ul>
                                    </div>
                                </li>
                                <li class="seperator"><!-- --></li>
                                <li><a href="javascript:;" class="dropdownglobalchange" id="M" style="cursor:pointer;">Networks</a></li>
                                <li><a href="javascript:;" class="dropdownglobalchange" id="M" style="cursor:pointer;">Groups</a></li>
                                <li><a href="javascript:;" class="dropdownglobalchange" id="M" style="cursor:pointer;">Friends</a></li>
                                <li class="seperator"><!-- --></li>
                                <li><a href="javascript:;" class="dropdownglobalchange" id="M" style="cursor:pointer;">Inbox</a></li>
                                <li><a href="javascript:;" class="dropdownglobalchange" id="F" style="cursor:pointer;">Channel</a></li>
                            </ul>
                        </dd>
                    </dl>
                </li>
                <li>
                    <dl style="" class="staticMenu">
                        <dt><a href="/settings" onclick="return false;">Settings</a></dt>
                        <dd>
                            <ul class="mainMenuSub">
                                <li><a href="javascript:;" onmouseover="openSubMenu(this)" class="MainSubExpandable" onmouseout="closeSubMenu(this)" style="cursor:pointer;">Preferences</a>
                                    <div class="mainMenuSubTwo" id="subMenuMainLib" onmouseover="cancelSubMenuClose()" onmouseout="closeSubMenu(this)">
                                        <ul>
                                            <li><a href="#">About Me</a></li>
                                            <li><a href="#">Appearence</a></li>
                                            <li><a href="#">Main Menu</a></li>
                                            <li><a href="#">Privacy</a></li>
                                            <li><a href="#">Notifications</a></li>
                                            <li><a href="#">Adverts</a></li>
                                            <li><a href="#">Safe Search</a></li>
                                        </ul>
                                    </div>
                                </li>
                                <li><a href="javascript:;" onmouseover="openSubMenu(this)" class="MainSubExpandable" onmouseout="closeSubMenu(this)" style="cursor:pointer;">Administration</a>
                                    <div class="mainMenuSubTwo" id="subMenuMainLib" onmouseover="cancelSubMenuClose()" onmouseout="closeSubMenu(this)">
                                        <ul>
                                            <li><a href="#">Block List</a></li>
                                            <li><a href="#">Parental Controls</a></li>
                                            <li><a href="#">Email Options</a></li>
                                            <li><a href="#">Username</a></li>
                                            <li><a href="#">Password</a></li>
                                            <li><a href="#">Payments</a></li>
                                            <li><a href="#">Linked Accounts</a></li>
                                            <li><a href="#">Security Question</a></li>
                                            <li><a href="#">Deactivate Account</a></li>
                                        </ul>
                                    </div>
                                </li>
                                <li class="seperator"><!-- --></li>
                                <li><a href="javascript:;" class="dropdownglobalchange" id="M" style="cursor:pointer;">Help Center</a></li>
                                <li><a href="javascript:;" class="dropdownglobalchange" id="M" style="cursor:pointer;">About StageX</a></li>
                                <li class="seperator"><!-- --></li>
                                <li><a href="javascript:;" class="dropdownglobalchange" id="M" style="cursor:pointer;">Developers</a></li>
                            </ul>
                        </dd>
                    </dl>
                </li>
            </ul>
            <div style='float:right;'>
                <ul class="mainMenu" style="float:right;">
                    <li style="border-right:0;">
                        <dl class="staticMenu">
                            <dt><a href="/settings" onclick="return false;">Sam</a></dt>
                            <dd>
                                <ul class="mainMenuSub" style="right:-1px; left:auto;">
                                    <li><a href="javascript:;" class="dropdownglobalchange" id="A" style="cursor:pointer;">Available</a></li>
                                    <li><a href="javascript:;" class="dropdownglobalchange" id="F" style="cursor:pointer;">Busy</a></li>
                                    <li><a href="javascript:;" class="dropdownglobalchange" id="F" style="cursor:pointer;">Away</a></li>
                                    <li><a href="javascript:;" class="dropdownglobalchange" id="F" style="cursor:pointer;">Appear Offline</a></li>
                                    <li class="seperator"><!-- --></li>
                                    <li><a href="javascript:;" class="dropdownglobalchange" id="M" style="cursor:pointer;">Log out</a></li>
                                    <li><a href="javascript:;" class="dropdownglobalchange" id="M" style="cursor:pointer;">Switch User</a></li>
                                </ul>
                            </dd>
                        </dl>
                    </li>
                </ul>
                <div class="notificationArea" style='float:right;'>
                    Notification Icons
                </div>
            </div>
        </div>
    </div>
</body>
</html>