function shmax_menu( target, options, id )
{
    var theMenu = this;
    this.m_animating = false;
    this.m_z = 9999;
    this.m_width = typeof(options.width) != 'undefined' ? options.width : 100;
    this.m_height = typeof(options.height) != 'undefined' ? options.height : 200;
    this.m_speed = typeof(options.speed) != 'undefined' ? options.speed : 1500;
    this.m_url = typeof(options.url) != 'undefined' ? options.url: "/ajax/shmaxCategoryRest.php5";
    this.m_templatedUrl = typeof(options.templatedUrl) != 'undefined' ? options.templatedUrl: null;
    this.m_dataDepth = typeof(options.dataDepth) != 'undefined' ? options.dataDepth: "all";
    this.m_dataSource = typeof(options.dataSource) != 'undefined' ? options.dataSource: 0;
    this.m_data = typeof(options.data) == 'object' ? options.data: [];
    this.m_path = typeof(options.path) != 'undefined' ? options.path : null;
    this.m_button = typeof(options.button) != 'undefined' ? options.button : false;
    this.m_buttonWidth = typeof(options.buttonWidth) != 'undefined' ? options.buttonWidth : 100;
    this.m_curId = null;
    this.m_curItem = null;
    this.m_id = id;
    this.m_textField = null;
    this.m_depth = 0;

    if(typeof( options.textField ) == "string")
    {
        this.m_textField = $("#"+options.textField);
    }
    else if(typeof( options.textField ) == "object" )
    {
        this.m_textField = options.textField;
    }

    if(typeof( target ) == "string")
    {
        this.m_target = $("#"+target);
    }
    else if(typeof( target ) == "object" )
    {
        this.m_target = target;
    }

    var paneId = 0;

    this.initData = function(parent)
    {
        if(this.m_data != null )
        {
            theMenu.init(theMenu.m_data);
        }
        else
        {
            var data = {"_fetchMode":this.m_dataDepth,
                        "_operationType":"fetch",
                        "_dataSource":this.m_dataSource,
                        "cat_parent":"1"};
            $.ajax({
            type:       "POST",
            url:        this.m_url,
            data:       data,
            dataType:   "json",
            success:    function(rowData)
                        {
                            if(rowData.response.data)
                            {
                                theMenu.init(eval(rowData.response.data));
                            }
                        }
            });
        }
    }

    this.init = function( data )
    {
        if(this.m_path != null)
        {
            var children = this.m_data;
            this.push(this.m_data);
            this.m_curId = this.m_path[this.m_path.length-1];

            // build up the stack. We do length-1, because the top bucket
            // in the path contains the id of the currently selected node, and
            // we want to see the list of children of its parent, not the children
            // of the node itself
            for(var i = 1; i < this.m_path.length-1; i++ )
            {
                var id = this.m_path[i];
                for(var j = 0; j < children.length; j++ )
                {
                    if(children[j].i == id)
                    {
                        if(children[j].c.length==0)
                        {
                            break;
                        }

                        this.push(children[j].c);
                        children = children[j].c;
                        continue;
                    }
                }
            }
        }
        else
        {
            this.push(this.m_data);
        }

        var frame = $("<div class='shmax_menu' style='z-index:"+(this.m_z--)+"; width:"+this.m_width+"px;height:"+(this.m_height)+"px;' ></div>");

        if( this.m_button )
        {
            $(document).click(function(e)
            {
                var clicked=$(e.target);

                if( (!clicked.isChildOf(theMenu.m_button) && !clicked.isEqual(theMenu.m_button)) &&
                    (!clicked.isChildOf(theMenu.m_frame) && !clicked.isEqual(theMenu.m_frame)))
                {
                        frame.hide();
                }
            });

            var button = $( "<div id='"+this.m_id+"_button' style='width:"+this.m_buttonWidth+"px; z-index:"+(this.m_z--)+"' class='button'><div style='width:"+(this.m_buttonWidth-15)+"px'>Select</div></div>" );
            frame.hide();
            button.click(
                function(e)
                {
                    theMenu.m_frame.toggle();
                }
            );
            this.m_button = button;
            this.m_target.append(button);
        }

        this.m_frame = frame;
        this.m_target.append(frame);

        this.m_pane = this.createPane(0);
        this.m_pane.css("overflow-y","scroll");

        var margin = 3;
        this.m_back = $("<br /><div class='back' style='left:"+margin+"px; width:"+(this.m_width-(margin*7))+"px; top:"+(this.m_height-20-margin)+"px;'>Back</div>");
        this.initBack(this.m_pane);
        this.m_frame.append(this.m_back);
        this.m_back.click(
            function()
            {
                if(!theMenu.m_animating)
                {
                    theMenu.pop();
                    theMenu.shiftFrames(false);
                }
                return false;
            }
        );

        this.initBox(this.m_pane, true);
    }

    this.push = function(children)
    {
        this.m_stack[this.m_depth++] = children;
    }

    this.pop = function()
    {
        this.m_depth--;
    }

    this.initBack = function(pane)
    {
        var height = theMenu.m_height;
        if(theMenu.m_depth>1)
        {
            height -= 25;
            this.m_back.show();
        }
        else
        {
            this.m_back.hide();
        }
        pane.css("height", height);
        this.m_pane.css("height", height);
    }

    this.shiftFrames = function(forward)
    {
        var pane = theMenu.m_pane;
        pane.css("overflow-y", "hidden");

        this.m_animating = true;

        var position = this.m_width;
        var direction = -this.m_width;
        if(!forward)
        {
            position = -this.m_width;
            direction = this.m_width;
        }

        var newFrame = theMenu.createPane( position );
        this.initBack(newFrame);

        this.initBox(newFrame,true);
        newFrame.animate(
                {
                    left:0
                },
                this.m_speed,
                "linear",
                function()
                {
                    theMenu.m_pane.remove();
                    theMenu.m_pane = newFrame;
                    newFrame.css("overflow-y", "scroll");
                    theMenu.m_animating = false;
                }
            );
            pane.animate({
                left: direction
              },
              this.m_speed,
              "linear"
            );
    }

    function sortChildren(a, b){
        if(a.n < b.n)
            return -1;
        else if(a.n > b.n)
            return 1;
        return 0;
    }

    this.selectItem =  function( item )
    {
        if(this.m_curItem != null )
        {
//            this.m_curItem.css("font-weight", "normal" );
        }

//        item.css("font-weight", "bold");
        this.m_curItem = item;
    }

    this.initBox = function(pane, active)
    {
        var children = this.m_stack[this.m_depth-1];
        this.m_curItem = null;

        children.sort(sortChildren);
        for( var i = 0; i < children.length; i++)
        {
            var row = children[i];
            var menuItem = $("<div class='menu_item' ></div>");

            var labelHtml = "<div class='menu_item_label' id='"+row.i+"' name='"+i+"'>";

            if(this.m_textField == null)
            {
                var url = this.m_templatedUrl.replace( /\[id\]/,row.i );
                labelHtml += "<a href='"+url+"'>"+row.n+"</a></div>";
            }
            else
            {
                labelHtml += row.n+"</div>";
            }

            var label = $(labelHtml);
            if(row.i==this.m_curId)
            {
                if(this.m_button)
                {
                    this.m_button.html("<div style='width:"+(this.m_buttonWidth-15)+"px;'>"+row.n+"</div>");
                }
                this.selectItem(label);
            }

            menuItem.append(label);
            label.click(
                function()
                {
                    if(!theMenu.m_animating)
                    {
                        var idx = $(this).attr("name");
                        var id = $(this).attr("id");
                        theMenu.selectItem($(this));
                        theMenu.m_curId = id;
                        theMenu.m_curItem = $(this);

                        if(theMenu.m_textField != null )
                        {
                            theMenu.m_textField.val(id);
						}

                        if(theMenu.m_button)
                        {
                            theMenu.m_button.html("<div style='width:"+(theMenu.m_buttonWidth-15)+"px'>"+$(this).html()+"</div>" );
                            theMenu.m_frame.hide();
                        }
                    }

                    return true;
                }
            );

            if(row.c==-1 || row.c.length>=1)
            {
                var arrow = $("<span id='"+row.i+"' name='"+i+"' style='left:"+(this.m_width-35)+"px' class='menu_arrow'></span>");

                arrow.click(
                    function()
                    {

                        var idx = $(this).attr("name");
                        var id = $(this).attr("id");

                        var row = theMenu.m_stack[theMenu.m_depth-1][idx];
                        if(row.c==-1)
                        {
                            var data = {"_fetchMode":theMenu.m_dataDepth,
                                        "_operationType":"fetch",
                                        "_dataSource":theMenu.m_dataSource,
                                        "cat_parent":row.i};
                            $.ajax({
                            type:       "POST",
                            url:        theMenu.m_url,
                            data:       data,
                            dataType:   "json",
                            success:    function(rowData)
                                        {
                                            if(rowData.response.data)
                                            {
                                                theMenu.push(rowData.response.data);
                                                theMenu.shiftFrames(true);
                                            }
                                        }
                            });
                        }
                        else if(row.c.length)
                        {
                            theMenu.push(row.c);
                            theMenu.shiftFrames(true);
                        }
                        return false;
                    }
                );

                menuItem.append(arrow);
            }
            pane.append(menuItem);
            var element = $("#"+row.i);

        }
    }

    this.createPane = function(left)
    {
        var pane = $("<div style='left:"+(left+2)+"px; top:0px; width:" + this.m_width + "px; height:" + (this.m_height - 25 ) + "px;' class='pane'></div>" );
        pane.css("overflow-y","hidden");
        this.m_frame.append(pane);
        return pane;
    }

    this.m_stack = [];
    this.initData();
}