Source: enyo-x/source/widgets/menu.js

/*jshint node:true, indent:2, curly:true, eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
regexp:true, undef:true, trailing:true, white:true */
/*global XT:true, XV:true, XM:true, Backbone:true, enyo:true, _:true */

(function () {

  /**
	@name XV.MenuItem
    @class A button styled to look like a menu item, intended for use in an onyx.Menu.<br />
    For example, see the popup menu in {@link XV.RelationWidget}.<br />
    Derived from <a href="http://enyojs.com/api/#onyx.MenuItem">onyx.MenuItem</a>.
    @extends onyx.MenuItem
   */
  enyo.kind(
    /** @lends XV.MenuItem# */{
    name: "XV.MenuItem",
    kind: "onyx.MenuItem",
    classes: "xv-menuitem",

    disabledChanged: function () {
      this.addRemoveClass("disabled", this.disabled);
    },

    tap: function (inSender) {
      if (!this.disabled) { return this.inherited(arguments); }
    }
  });

  /**
    Used by container views to handle list actions.
  */
  XV.ListMenuManagerMixin = /** @lends XV.ListMenuManagerMixin# */{
    listActionSelected: function (inSender, inEvent) {
      var list = inEvent.originator.list,
        keys = _.keys(list.getSelection().selected),
        action = inEvent.originator.action,
        method = action.method,
        callback = function () {
          list.resetActions();
          _.each(keys, function (key) {
            list.deselect(key);
            list.renderRow(key);
          });
        },
        confirmed = function () {
          var Klass,
            model = list.getModel(keys[0]);
          if (action.isViewMethod) {
            list.$.listItem.doActionSelected({
              model: model,
              action: action,
              callback: callback
            });

          // If the list item model doesn't have the function being asked for, try the editable version
          // Either way, loop through selected models and perform method
          } else if (model instanceof XM.Info && !model[method]) {
            Klass = XT.getObjectByName(model.editableModel);
            _.each(keys, function (key) {
              model = list.getModel(key);
              Klass[method](model, callback);
            });
          } else {
            _.each(keys, function (key) {
              model = list.getModel(key);
              model[method](callback);
            });
          }
        };

      if (action.notify !== false) { // default to true if not specified
        // if the action requires a user OK, ask the user
        this.doNotify({
          type: XM.Model.QUESTION,
          message: action.notifyMessage || "_confirmAction".loc(),
          callback: function (response) {
            if (response.answer) {
              confirmed();
            }
          }
        });

      } else {
        // if the action does not require a user OK, just do the event
        confirmed();
      }
      return true;
    },
    showListItemMenu: function (inSender, inEvent) {
      var menu = this.$.listItemMenu;

      // reset the menu based on the list specific to this request
      menu.destroyClientControls();

      // then add whatever actions are applicable
      _.each(inEvent.actions, function (action) {
        var name = action.name,
          actPrivs = action.privilege ? action.privilege.split(" ") : [],
          isDisabled = false,
          component = _.find(menu.$, function (value, key) {
            // see if the component has already been created
            return key === name;
          });

        if (actPrivs.length) {
          isDisabled = !_.some(actPrivs, function (privilege) {
            return XT.session.privileges.get(privilege);
          });
        }

        if (component) {
          // if it's already been created just handle state
          component.setDisabled(isDisabled);

        } else {
          // otherwise if we are allowed, make it
          if (inEvent.actionPermissions[name]) {
            menu.createComponent({
              name: name,
              kind: 'XV.MenuItem',
              content: action.label || ("_" + name).loc(),
              action: action,
              disabled: isDisabled,
              list: inEvent.list
            });
          }
        } // else if it doesn't exist and we don't have permissions, do nothing
      
      });

      // If no menu items, let the user know something about the situation
      if (!menu.getClientControls().length) {
        menu.createComponent({
          name: "noActions",
          kind: 'XV.MenuItem',
          content: "_noEligibleActions".loc(),
          disabled: true
        });
      }

      menu.render();

      // convoluted code to help us deceive the Menu into thinking
      // that it's part of a MenuDecorator which is inside the
      // list.
      if (!inEvent.originator.hasNode()) {
        inEvent.originator.node = inEvent.originator.eventNode;
      }
      inEvent.originator.generated = true;
      menu.requestMenuShow(this, {activator: inEvent.originator});
      menu.adjustPosition();
    }
  };

}());