/* Data structure to capture item-specific configuration options, such as the
   URL for item context lookups (e.g. document contexts) and references
   to JS functions to be called when a specific menu item is selected. When
   an action_function is not defined for a menu item, the menu item's href
   link will be followed as usual.
*/
var item_info = {
  "DEFAULT": {
      "context_url": "/apps/org/workgroup/portal/ajax/action_menu.php",
      "action_functions" : {
          "markprojectcomplete": _projectComplete,
          "activateproject": _activateProject,
          "activity_mark_complete": _activityComplete
      }
  },
  "kdoc": {
      "context_url": "/apps/org/workgroup/portal/lookup_document_context.php",
      "action_functions" : {
          "lock": _documentLockModalDialog,
          "unlock": _documentUnlock
      }
  },
  "kfolder": {
      "context_url": "/apps/org/workgroup/portal/lookup_folder_context.php",
      "action_functions" : {
          "archivefolder": _folderArchive,
          "unarchivefolder": _folderUnarchive,
          "movefolder": _folderMoveGroup
      }
  }
};

////////////////////////////////////////////////////////////////////////////
// Item-specific functions: these apply to one particular item type only. //
////////////////////////////////////////////////////////////////////////////

function _activityComplete(kmenu_container, item_type, item_id, item_href) {
    // send a request to the server to actually update the project
    var params = {
        'format': 'json',
        'activity_id': item_id
    };
    jQuery.ajax({
        type: "POST",
        url: item_href,
        data: params,
        dataType: "json",
        success: function(post_results, textStatus) {
            if(!post_results.success) {
                initModal();
                displayModal(true, "Error", "<p>" + post_results.message + "</p>");
            } else {
                // update display for this project
                var completed = $("tbody#kActivity_" + item_id
                                  + " tr.primary td.completed");
                completed.text("Yes");

                var name = $("tbody#kActivity_" + item_id
                             + " tr.primary td.name a.itemlink").text();

                var note = name + " has been completed";

                // Initialize the modal window and add the notifications form
                initModal();

                var modalHeading = note
                var modalBody =
                    "<h3>Email Notifications</h3>" +
                    "<form action='' method='post' name='notifications' " +
                    "id='notifications'>" +
                        "<div>" +
                            "<input type='hidden' name='object_id' " +
                                " id='object_id' value='" + item_id + "'>" +
                            "<input type='hidden' name='action' id='action' " +
                                "value='complete'>" +
                            "<input type='hidden' name='type' id='type'" +
                                "value='activity'>" +
                            post_results.notification_html +
                        "</div>" +
                        "<div class='submit'>" +
                            "<input type='submit' value='Send'" +
                                " name='notificationssubmit'" +
                                " id='notificationssubmit'> " +
                            "<input type='submit' value=\"Don\'t Send\"" +
                                " onclick='killModal()'>"
                        "</div>" +
                    "</form>";
                displayModal(false, modalHeading, modalBody, true);

                // Event handler for submit of notifications form .
                $("div.modal div.body form#notifications").submit(
                    sendNotifications);
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            initModal();
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });

    return false;  // Prevent a page reload after the form's submit
}

function _projectComplete(kmenu_container, item_type, item_id, item_href) {
    // send a request to the server to actually update the project
    var params = {
        'format': 'json',
        'project_id': item_id
    };
    jQuery.ajax({
        type: "POST",
        url: item_href,
        data: params,
        dataType: "json",
        success: function(post_results, textStatus) {
            // update display for this project, may happen from either
            // the All Projects page or the Project Overview page,
            // update both jic.
            var percent_complete_all = $("tbody#kproject_" + item_id
                                     + " tr.primary div.percent_container");
            percent_complete_all.html("<span class='val'>100%</span>"
                                  + "<span class='graph complete'"
                                  + " style='width:100%'></span>");
            var percent_complete_val_over =
                $("div#pjct_overview_summary div.right"
                  + " div.percent_container span.val");
            percent_complete_val_over.replaceWith(
                "<span class='val'>100% Complete</span>");
            var percent_complete_graph_over =
                $("div#pjct_overview_summary div.right"
                  + " div.percent_container span.graph");
            percent_complete_graph_over.replaceWith(
                "<span class='graph complete' style='width: 100%;' />");
            var today = new Date();
            var completion_date = $("tbody#kproject_" + item_id
                                    + " tr.primary td.completion_date");
            var completion_month = today.getMonth()+1+"";
            if (completion_month.length == 1) {
                completion_month = "0" + completion_month;
            }
            var completion_day = today.getDate()+"";
            if (completion_day.length == 1) {
                completion_day = "0" + completion_day;
            }
            completion_date.text(today.getFullYear() + "-"
                                 + completion_month + "-"
                                 + completion_day);

            var name = $("tbody#kproject_" + item_id
                         + " tr td span.project-name").text();
            var note = name + " has been marked complete";

            // Initialize the modal window and add the notifications form
            initModal();

            var modalHeading = note
            var oldPercent = post_results.old_percent
            var modalBody =
                "<h3>Email Notifications</h3>"
                + "<form action='' method='post' name='notifications' "
                + "id='notifications'>"
                + "<div>"
                + "<input type='hidden' name='object_id' id='object_id' "
                + "value='" + item_id + "'>"
                + "<input type='hidden' name='action' id='action'"
                + "value='complete'>"
                + "<input type='hidden' name='type' id='type'"
                + "value='project'>"
                + "<input type='hidden' name='old_percent' id='old_percent'"
                + "value='" + oldPercent + "'>"
                + post_results.notification_html
                + "</div>"
                + "<div class='submit'>"
                + "<input type='submit' value='Send' name='notificationssubmit'"
                + " id='notificationssubmit'> "
                + "<input type='submit' value=\"Don\'t Send\""
                + " onclick='killModal()'>"
                + "</div>"
                + "</form>";
            displayModal(false, modalHeading, modalBody, true);

            // Event handler for submit of notifications form .
            $("div.modal div.body form#notifications").submit(
                sendNotifications);

        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            initModal();
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });

    return false;  // Prevent a page reload after the form's submit
}

function _activateProject(kmenu_container, item_type, item_id, item_href) {
    // send a request to the server to actually update the project
    var params = {
        'format': 'json',
        'project_id': item_id
    };
    jQuery.ajax({
        type: "POST",
        url: item_href,
        data: params,
        dataType: "json",
        success: function(post_results, textStatus) {
            // update display for this project
            var name = $("#kproject_" + item_id + " span.project-name").text();
            if (post_results.status) {
                $("#kproject_" + item_id + " span.inactive-status").hide();
                action = 'activated';
            } else {
                $("#kproject_" + item_id + " span.inactive-status").show();
                action = 'deactivated';
            }

            note = name + " has been " + action;

            // Initialize the modal window and add the notifications form
            initModal();

            var modalHeading = note
            var modalBody =
                "<h3>Email Notifications</h3>"
                + "<form action='' method='post' name='notifications' "
                + "id='notifications'>"
                + "<div>"
                + "<input type='hidden' name='object_id' id='object_id' "
                + "value='" + item_id + "'>"
                + "<input type='hidden' name='action' id='action'"
                + "value='" + action + "'>"
                + "<input type='hidden' name='type' id='type'"
                + "value='project'>"
                + post_results.notification_html
                + "</div>"
                + "<div class='submit'>"
                + "<input type='submit' value='Send' name='notificationssubmit'"
                + " id='notificationssubmit'> "
                + "<input type='submit' value=\"Don\'t Send\""
                + " onclick='killModal()'>"
                + "</div>"
                + "</form>";
            displayModal(false, modalHeading, modalBody, true);

            // Event handler for submit of notifications form .
            $("div.modal div.body form#notifications").submit(
                sendNotifications);

        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            initModal();
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });

    return false;  // Prevent a page reload after the form's submit
}

function sendNotifications() {
    // Submit notifications POST request upon form submit
    var send_proj_contact =
        $("div#notification_checkboxes input#notify_project_contact",
          $(this)).attr('checked');
    var send_assigned = $("div#notification_checkboxes input#notify_assigned",
                          $(this)).attr('checked');
    var type = $("div input#type", $(this)).val();
    var item_id = $("div input#object_id", $(this)).val();
    var action = $("div input#action", $(this)).val();
    var note = $("div#notification_submitter_note textarea", $(this)).val();
    var cc_addresses = $("div#notification_cc textarea", $(this)).val();
    var old_percent_hidden = $("div input#old_percent", $(this));
    var old_percent = '';
    if (old_percent_hidden) {
        var old_percent = old_percent_hidden.val();
    }
    var params = {
        'format': 'json',
        'send_proj_contact': send_proj_contact,
        'send_owners': send_assigned,
        'type': type,
        'item_id': item_id,
        'action': action,
        'old_percent': old_percent,
        'cc': cc_addresses,
        'submitter_note': note
    };
    jQuery.ajax({
        type: "POST",
        url: '/apps/org/workgroup/portal/ajax/send_project_notifications.php',
        data: params,
        dataType: "json",
        success: function(post_results, textStatus) {
            initModal();
            if (post_results.success) {
                displayModal(true, "Email Notifications",
                             "<p>Email has been sent</p>");
            }
            else {
                displayModal(true, "Email Notifications", post_results.message);
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });
    killModal();
    return false;  // Prevent a page reload after the form's submit
}

function _toggleDocumentLockInfo(document_id, is_locked, lock_note) {
    var doc_icon_imgs = $("[id='kdoc_" + document_id + "'] img.kdocicon",
                          "div#content div#main");
    doc_icon_imgs.each(function() {
        var img_src = $(this).attr('src');

        if (is_locked) {
            // Add "_locked" suffix to file name *before* extension
            img_src = img_src.replace(/(.*)(\..*)/, "$1_locked$2");

            // Add lock details to the details flyout, after removing any
            // existing lock info
            $("tbody#kdoc_" + document_id
              + " tr.docdetails ul.meta li.lock").remove();
            $("tbody#kdoc_" + document_id + " tr.docdetails ul.meta").append(
                "<li class='lock'>Just locked by you with note \"" + lock_note
                + "\"</li>");
        } else {
            // Removed "_locked" suffix from file name
            img_src = img_src.replace(/(.*)(_locked)(\..*)/, "$1$3");

            // Remove lock info from details flyout
            $("tbody#kdoc_" + document_id
              + " tr.docdetails ul.meta li.lock").remove();
        }

        $(this).attr('src', img_src);
    });
}

function _documentLockModalDialog(kmenu_container, item_type, item_id,
                                  item_href) {
    // Initialize the modal window and add the lock form
    initModal();

    var doc_name = $("a[class^='kdoc_']", kmenu_container).text();
    var modalHeading = "You are locking " + doc_name;
    var modalBody =
        "<form action='' method='post' name='lock' id='lock'>" +
            "<div>" +
                "<input type='hidden' name='document_id' id='document_id' " +
                    "value='" + item_id + "'>" +
                "<label for='note'>" +
                "Enter a message that describes why you are locking this file" +
                "</label>" +
                "<textarea name='note' id='note'></textarea>" +
            "</div>" +
            "<div class='submit'>" +
                "<input type='submit' value='Lock' name='locksubmit'" +
                    " id='locksubmit'>" +
                "<a href='#' class='cancel'>Cancel</a>" +
            "</div>" +
        "</form>";
    displayModal(false, modalHeading, modalBody);

    // Set the focus on the textarea message field
    $("textarea#note", "div.modal div.body").focus();

    // Event handler for submit of lock form .
    $("div.modal div.body form#lock").submit(function() {
        // Submit lock POST request upon form submit
       var lock_note = $("textarea#note", $(this)).val();
        var params = {
            'format': 'json',
            'document_id': item_id,
            'lock': 1,
            'lock_note': lock_note
        };
        jQuery.ajax({
            type: "POST",
            url: item_href,
            data: params,
            dataType: "json",
            success: function(post_results, textStatus) {
                if (post_results.success) {
                    _toggleDocumentLockInfo(item_id, post_results.locked,
                                            lock_note);
                }
                initModal();
                displayModal(true, "Lock", "<p>" + post_results.message
                             + "</p>");
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                displayModal(true, "Error", "<p>" + textStatus + "</p>");
            }
        });
        killModal();
        return false;  // Prevent a page reload after the form's submit
    });
}

function _documentUnlock(kmenu_container, item_type, item_id, item_href,
                         ondone_f) {
    initModal();
    var params = {
        'format': 'json',
        'document_id': item_id,
        'unlock': 1
    };
    jQuery.ajax({
        type: "POST",
        url: item_href,
        data: params,
        dataType: "json",
        success: function(post_results, textStatus) {
            if (post_results.success) {
                _toggleDocumentLockInfo(item_id, post_results.locked, "");
            }
            displayModal(true, "Unlock", "<p>" + post_results.message + "</p>");
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });
}

function _folderArchiveToggle(kmenu_container, item_type, item_id, item_href,
                              ondone_f, action) {
    initModal();
    var params = {
        'format': 'json',
        'folder_id': item_id,
        'action': action
    };
    jQuery.ajax({
        type: "POST",
        url: item_href,
        data: params,
        dataType: "json",
        success: function(post_results, textStatus) {
           displayModal(true, "Folder " + action + "d",
               "<p>" + post_results.message + "</p>");
           if (post_results.success) {
              var folder_archived_span = $(
                "[id^='kfolder_" + item_id + "'] h3 span",
                "div#content div#main");
              if (action == 'archive') {
                 folder_archived_span.show();
                 folder_archived_span.parents(".folder").addClass('archived');
              } else {
                 folder_archived_span.hide();
                 folder_archived_span.parents(".folder").removeClass('archived');
              }
           }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });
}

function _folderArchive(kmenu_container, item_type, item_id, item_href,
                        ondone_f) {
    _folderArchiveToggle(kmenu_container, item_type, item_id, item_href,
                         ondone_f, 'archive');
}

function _folderUnarchive(kmenu_container, item_type, item_id, item_href,
                          ondone_f) {
    _folderArchiveToggle(kmenu_container, item_type, item_id, item_href,
                         ondone_f, 'unarchive');
}

function _folderMoveGroup(kmenu_container, item_type, item_id, item_href) {
    var params = {
        'folder_id': item_id,
        'step': 1
    };
    jQuery.ajax({
        type: "GET",
        url: item_href,
        data: params,
        success: function(post_results, textStatus) {
           initModal();
           displayModal(false, "Move Folder", post_results);
           $("#destination_group_id_sel").change(function () {
                var wg_id = $("option:selected", $(this)).attr('value');
                _populateParentFolderDropDown(wg_id,
                                              $("#destination_parent_folder_sel"),
                                              folder_flat_hierarchy_by_wg_id);
               });
           $("#destination_parent_folder_sel").change(function () {
                var folder_id = $("option:selected", $(this)).attr('value');
                var wg_id = $("option:selected", "#destination_group_id_sel").attr('value');
                _populateFolderOrderDropDown(wg_id,
                                             folder_id,
                                             $("#destination_order_sel"),
                                             folders_in_order_by_parent_id);
               });
           $("#submit", ".modal .body").click(function() {
                var group_selected = $("option:selected", "#destination_group_id_sel").val();
                return _submitModalViaAjax(item_href, params);
                });

           // Force refresh of select fields on initial load
           $("#destination_group_id_sel").change();
           $("#destination_parent_folder_sel").change();
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });
}

function _submitModalViaAjax(item_href, params) {
    // Copy all form inputs into AJAX parameters
    var inputs = $(".modal .body :input").each(function() {
        params[$(this).attr('name')] = $(this).val();
    });
    var progress_elem = $(".modal .body .progress_indicator");
    return _ajaxReplaceModalContent(item_href, params, progress_elem);
}

function _ajaxReplaceModalContent(item_href, params, progress_elem) {
    if (progress_elem.length) {
        $(".modal .header a.cancel").hide();
        $(".modal .body").html(progress_elem);
        progress_elem.show();
    }
    jQuery.ajax({
        type: "POST",
        url: item_href,
        data: params,
        success: function(result, textStatus) {
            $(".modal .header a.cancel").show();
            $(".modal .body").html(result);
            var redir_close_url = $(".modal .body .redir_close_url");
            if (redir_close_url.attr("href")) {
                $("div.modal .header .cancel").attr("href", redir_close_url.attr("href"));
                $("div.modal .header .cancel").unbind('click');
                $("div.modal .header .cancel").click(function () {
                    return true;
                });
            }
            $("#submit", ".modal .body").click(function() {
                return _submitModalViaAjax(item_href, params);
            });
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });
    return false;
}

function _populateParentFolderDropDown(wg_id, parent_select, folder_hier, include_top_level) {
    if(typeof include_top_level === 'undefined') {
        include_top_level = true;   // optional arg :P
    }
    
    var folders = [];
    if (folder_hier[wg_id]) {
        folders = folder_hier[wg_id];
    }
    var options_str = '';
    for (var folder_index in folders) {
        var folder_id = folders[folder_index]['id'];
        var folder_label = folders[folder_index]['description'];
        var is_current = folders[folder_index]['is_current'];
        if(folder_id == 0 && !include_top_level) {
            continue;
        }
        options_str += '<option value="' + folder_id + '"' +
                       (is_current ? ' selected="selected"' : '') +
                       '>' + folder_label + '</option>';
    }
    if (folders.length > 0) {
        parent_select.html(options_str);
        parent_select.change();
        parent_select.removeAttr('disabled');
    } else {
        parent_select.attr('disabled', 'disabled');
    }
}
function _populateFolderOrderDropDown(wg_id, folder_id, order_select, subfolder_list) {
    var folders = [];
    if (subfolder_list[wg_id] && subfolder_list[wg_id][folder_id]) {
        folders = subfolder_list[wg_id][folder_id];
    }
    var options_str = '';
    var first = true;
    var startedOptgroup = false;
    var selected_str = 'selected="selected"';
    for (var folder_index in folders) {
        var folder_id = folders[folder_index]['display_order'];
        var folder_label = folders[folder_index]['name'];
        options_str += '<option value="' + folder_id + '" ' + selected_str + '>' +
                       '' + folder_label +
                       '</option>';
        // Add optgroup after first option
        if (first && folders.length > 1) {
            options_str += '<optgroup label="Place After">';
            first = false;
            startedOptgroup = true;
            selected_str = '';
        }
    }
    // Add optgroup end tag
    if (startedOptgroup) {
        options_str += '</optgroup>';
    }
    if (folders.length > 0) {
        order_select.html(options_str);
        order_select.removeAttr('disabled');
    } else {
        order_select.attr('disabled', 'disabled');
    }
}

////////////////////////////////////////////////////////
// Generic action menu functions: apply to all menus. //
////////////////////////////////////////////////////////

function initModal(){
    // Initialize the modal window container
    $("div#main", "div#content").append("<div class='modal'>" +
        "<div class='header'>" +
        "<a href='#' class='cancel'>Close</a>" +
        "<h4>Modal Window</h4>" +
        "</div>" +
        "<div class='body'>" +
        "</div>" +
        "</div>" +
        "<div class='mask'></div>"
    );
    // Position the modal window
    modalWindow = $("div.modal", "div#main");
    xPos = ($(window).width() * 0.5) - (modalWindow.width() * 0.5);
    yPos = (($(window).scrollTop() + ($(window).height() * 0.5))
            - (modalWindow.width() * 0.5));
    modalWindow.css("left", xPos);
    modalWindow.css("top", yPos);

    // Resize the background mask
    $("div.mask").css("height", $(document).height());
    $("div.mask").css("width", $(window).width());

    // On window resize, resize the background mask and resposition the modal
    // window
    $(window).bind('resize', function() {
        $("div.mask").css("height", $(document).height());
        $("div.mask").css("width", $(window).width());
        xPos = ($(window).width() * 0.5) - (modalWindow.width() * 0.5);
        yPos = (($(window).scrollTop() + ($(window).height() * 0.5))
                - (modalWindow.width() * 0.5));
        modalWindow.css("left", xPos);
        modalWindow.css("top", yPos);
    });
}

function displayModal(addOkButton, heading, body, hideCancelLink) {
    // Add meaningful header and body content to the modal window
    $("div.header h4", "div.modal").text(heading);
    if (addOkButton) {
        body += "<div class='submit'>"
              + "<input class='cancel' type='submit' value='OK' name='OK'"
              + " id=''>"
              + "</div>";
    }
    if (hideCancelLink) {
        $("a.cancel", "div.modal").hide().css("visibility", "hidden");
    } else {
        $("a.cancel", "div.modal").show().css("visibility", "visible");
    }
    $("div.body", "div.modal").append(body);

    // Display the modal window
    $("div.modal", "div#main").fadeIn();
    $("div.mask", "div#main").fadeIn();

    // Put focus on any submit input type in modal dialog
    $("div.modal :input[type='submit']", "div#main").focus();

    attachCancelModalWindowHandler();
}

// Hide the modal window and remove the elements from the DOM
function killModal(){
    $("div.modal", "div#main").fadeOut();
    $("div.mask", "div#main").fadeOut();
    $("div.modal", "div#main").remove();
    $("div.mask", "div#main").remove();
}

function displayNotification(message) {
    var message_container = $("#notification-message");
    if (message_container.size() && message) {
        message_container.text(message).show();
    }
}

// Cancels a modal window upon ESC, or click of cancel link / close button
function attachCancelModalWindowHandler() {
    // Attach window cancel handler to modal dialog
    $("div.modal .cancel").click(function(){
        killModal();
    });

    // ESC button pressed while modal window was active
    $(document).keyup(function(event){
        if (event.keyCode == 27) {
            killModal();
        }
    });
}

// Parses the type string and numeric ID portion of a menuable item's 'id'
// attribute, based on the assumption that this attribute contains a
// string in the format "type_numericid", for example 'kdoc_123'
function parseItemTypeAndId(id_string) {
    if (!id_string || id_string.search('_') < 0) {
        return false;
    }
    return id_string.split('_');
}

// Returns any context information associated with this item.
function getItemContext(item_type, item_id) {
    var itemElem =
        $("[id='" + item_type + "_" + item_id + "']", "div#content div#main");
    var spanElems = itemElem.find("span.itemcontext:first");
    return spanElems.text();
}

// Toggle visiblity of action menu
// Note that $.browser is deprecated as of jquery 1.3
function hideShowContextualMenuHandler(ul_container) {
    if (ul_container.hasClass("expand")) {
        // Contract menu
        ul_container.removeClass("expand");
    }
    else {
        // Un-expand any other menus that may have been clicked previously
        $("ul.nav-actions li ul").removeClass("expand");
        if (isIE6 || isIE7) {
            $("ul.forceIndex")
                .removeClass("forceIndex");
        }

        // Expand menu
        ul_container.addClass("expand");
        ul_right_side_pos = ul_container.offset().left + ul_container.width();
        if ($(window).width() < ul_right_side_pos) {
            ul_container.css("left", '');
            ul_container.css("right", 0);
        }
        if (isIE6 || isIE7) {
            ul_container.parents("ul")
                .addClass("forceIndex");
            ul_container.parents(".nav-actions")
                .attr("style", "z-index:215; zoom:1;");
            ul_container.parents(".action")
                .attr("style", "z-index:0; position:static;");
            ul_container.parents(".toggleactions a")
                .attr("style",
                      "background-image: "
                      + "url(/kicons/dotorg/images/arrow_down_wht.gif);");
        }

    }
}

// Handle a selection from an item's menu.
function menuActionClickHandler() {

    var kmenu_container = $(this).parents(".kmenuable")[0]

    hideShowContextualMenuHandler($(this).parents("ul"));

    // Find the item's type and ID
    var id_string = $(this).parents(".kmenuable").attr("id");
    var typeAndId = parseItemTypeAndId(id_string);
    var item_type = typeAndId[0];
    var item_id = typeAndId[1];

    if (item_info[item_type]) {
        var action_functions = item_info[item_type].action_functions;
    } else {
        var action_functions = item_info['DEFAULT'].action_functions;
    }

    // Lookup item-specific action function, if any special ones defined (in
    // array at top of file).
    var action_type = $(this).attr("class");
    var action_function = action_functions[action_type];
    if (action_function) {
        // Invoke item-specific action function.
        action_function(kmenu_container, item_type, item_id,
                        $(this).attr("href"));
        return false; // Do not follow this item's link.
    } else {
        // No item-specific action function, follow menu item's link as normal.
        return true;
    }
}

// Populate the contents of the Javascript action menu for a given
// kmenu_container using information in the given array of action objects.
// Each action object must be a dictionary containing 'label', 'type' and
// 'action_url' keyed values.
function populateActionMenu(ul_container, actions) {
    ul_container.parent().find(">a").removeClass("fetch");

    // Build LI item to represent each action) entry.
    var html_str = "";
    for (actionref in actions) {
        var action = actions[actionref];
        html_str += "<li><a class='" + action.type + "' ";
        html_str += "href='" + action.action_url + "' ";
        html_str += ">" + action.label + "</a></li>";
    }

    // Insert action items' LI representation into menu.
    ul_container.append(html_str);

    // Attach handler for menu actions
    $("li a", ul_container).click(menuActionClickHandler);
}

// Lookup context information for one or more items of a given type, then
// populate the corresponding menu in the DOM.
function lookup_context_and_refresh_menu(item_type, item_id, item_context,
                                         ul_container) {
    // Clear out any existing action menu contents.
    ul_container.empty();

    // Determine the contex lookup URL for this item
    if (!item_info[item_type] && !item_info['DEFAULT']) {
        ul_container.append("<li><a>You have no actions to " +
                            "perform on this item</a></li>");
        ul_container.parent().find(">a").removeClass("fetch");
        return;
    }

    if (item_info[item_type]) {
        var context_url = item_info[item_type].context_url;
    } else {
        var context_url = item_info['DEFAULT'].context_url;
    }

    data_arr = {};
    data_arr['item_ids'] = item_id;
    data_arr['context']  = item_context
    // Lookup the item's context
    jQuery.ajax({
        type: "GET",
        url: context_url,
        data: data_arr,
        dataType: "json",
        success: function(context_result, textStatus) {
            if (context_result.success) {
                for (var myid in context_result.items) {
                    if (!context_result.items[myid].actions.length) {
                        ul_container.append("<li><a>You have no actions to " +
                                            "perform on this item</a></li>");
                        ul_container.parent().find(">a").removeClass("fetch");
                    } else {
                        var actions = new Array();
                        for (var myaction
                                 in context_result.items[myid].actions) {
                            var item_action =
                                context_result.items[myid].actions[myaction];
                            actions.push(item_action);
                        }
                        // build and fill in these actions in the items action
                        // menu
                        populateActionMenu(ul_container, actions);
                    }
                }
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            hideShowContextualMenuHandler(ul_container);
            initModal();
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
            ul_container.parent().find(">a").removeClass("fetch");
        }
    });
}

// On click:
// Parse the item info from its id
// Dispatch to lookup_context_and_refresh_menu which will make the ajax
// call to get the menu items and fill them in the markup
function actionMenuOnClickHandler(evt) {
    var evt = jQuery.event.fix(evt);
    var clickee = $(evt.target);
    var parent_ul = clickee.parents("ul.nav-actions");
    var ul_container = $("+ ul", clickee);

    if (!ul_container.hasClass("expand")) {
        // Display a spinner to indicate the AJAX call is in progress
        clickee.addClass("fetch");
        hideShowContextualMenuHandler(ul_container);

        var id_string = clickee.parents(".kmenuable").attr("id");
        var typeIdContext = parseItemTypeAndId(id_string);
        var item_type = typeIdContext[0];
        var item_id = typeIdContext[1];
        var item_context = getItemContext(item_type, item_id);
        lookup_context_and_refresh_menu(item_type, item_id,
                                        item_context, ul_container);
    }
    else {
        hideShowContextualMenuHandler(ul_container);
    }
    // Forcibly stop event propagation
    evt.stopPropagation();
    return false;
}

// Add an 'active' class to every ul with the 'nav-actions' class inside the
// given root element, and replace any existing content with the menu
// representation.
function initActionMenuContent(root_element) {
    root_element.find("ul.nav-actions")
      .addClass("active")
      .html("<li class='toggleactions'><a href='#'>Actions</a><ul></ul></li>");
}

// Attach an onClick event handler to every ul with the 'nav-actions' class
// inside the given root element
function initActionMenuHandler(root_element) {
    root_element.find("ul.nav-actions li.toggleactions > a")
        .click(function(e) {
            return actionMenuOnClickHandler(e);
        });
}

/*
==============================================================================
To initialize action menus on a page you can use one of the following methods.

(1)
Seed your HTML page with action menu stubs friendly to non-JS browsers:

<ul class='nav-actions active'>
  <li><a href="1">Plain links to display in place of...</a></li>
  <li><a href="2">... action menus for non-JS browsers</a></li>
</ul>

Then invoke the action menu initialization functions on page load, like so:

$(document).ready(function() {
    // Replace non-JS links with dynamic action menu
    initActionMenuContent($("div#main"));

    // Bind onClick handler to action menu
    initActionMenuHandler($("div#main"));
});

(2)
Alternately, if you are sure that the browser supports Javascript you can
create pre-rendered action menus directly in HTML like so:

<ul class='nav-actions active'>
  <li class='toggleactions'>
    <a href='#' onclick='actionMenuOnClickHandler(event)'>Actions</a>
    <ul></ul>
  </li>
</ul>

==============================================================================
*/
