Custom button for editableList

Hi folks,

I'm looking for a way to add custom buttons to an editableList:

image

Thought first that this would be possible via the addButton function of the editableList, but that seems to be about the "Add" button...

It would be nice if the editableList would allow us to do something like this:

myEditableList.addCustomButton("myButtonLabel", function () {
   // Do my stuff
});

And that this addCustomButton function will append the button after the other buttons, similar to this how it works now:

$('<a href="#" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px;"><i class="fa fa-plus"></i> '+addLabel+'</a>')
   .appendTo(this.topContainer)
   .on("click", function(evt) {
      evt.preventDefault();
      that.addItem({});
   });

Would be nice to know whether it is ok for me to create a pull request.
And of course all tips are welcome (e.g. what would need to be the input parameters of the callback function, and so on ...).

Thanks and have a nice weekend!
Bart

3 Likes

It seems that only a small change is required in the editableList , to support custom buttons:

  • I have added a right margin of 5px to the "Add" button:
    $('<a href="#" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px; margin-right: 5px;"><i class="fa fa-plus"></i> '+addLabel+'</a>')
    
  • And a new function to create a custom button:
    addCustomButton: function(buttonLabel, callback) {
       var label = buttonLabel || "unknown";
       $('<a href="#" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px; margin-right: 5px;">'+label+'</a>')
          .appendTo(this.topContainer)
          .on("click", function(evt) {
             evt.preventDefault();
             if (callback !== undefined) {
                callback();
             }
          });
    }
    

That way I can easily add a custom button like this:

$("ol.list").editableList("addCustomButton", "<i class='fa fa-warning'></i> alert", function() {
   alert("button pressed");
})

Which results in a working custom button:

@dceejay, @knolleary: is this good enough for a pull request?

Hi Bart,

I think it would be better to do it as part of the initialisation of the list. I don't see this being something that needs to happen dynamically.

To be somewhat consist with other ui components, I'd suggest a buttons array:

$("#foo").editableList({ 
   ...
   buttons: [
       {
          label: "button Label",
          icon: "" // optional "fa fa-star",
          click: function(evt) { ...}
      }
   ]
});

addButton would still work in the same way it does today and would be an implicit first entry in the buttons array unless addButton is set to false.

Thanks Nick!
Indeed via the initialisation options will be sufficient. So I have changed it to this:

            var buttons = this.options.buttons || [];

            if (this.options.addButton !== false) {
                var addLabel;
                if (typeof this.options.addButton === 'string') {
                    addLabel = this.options.addButton
                } else {
                    if (RED && RED._) {
                        addLabel = RED._("editableList.add");
                    } else {
                        addLabel = 'add';
                    }
                }
                buttons.unshift({
                    label: addLabel,
                    icon: "fa fa-plus",
                    click: function(evt) {
                        that.addItem({});
                    }
                });
            }

            buttons.forEach(function(button) {
                var innerHtml = "";
                if (button.icon) {
                    innerHtml = '<i class="'+button.icon+'"></i> ';
                }
                if (button.label) {
                    innerHtml += button.label;
                }
                $('<a href="#" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px; margin-right: 5px;">'+innerHtml+'</a>')
                    .appendTo(that.topContainer)
                    .on("click", function(evt) {
                        evt.preventDefault();
                        if (button.click !== undefined) {
                            button.click();
                        }
                    });
            });

The addButton will insert the "Add" button to the start of the button array.

Now I can do it like you suggested:

var clickableShapesList = $("ol.list").editableList({
   addItem: function(container, i, clickableShape) {
      //...
   },
   removable: true,
   sortable: true,
   buttons: [{
      label: "with icon",
      icon: "fa fa-star",
      click: function(evt) { 
         alert("with icon");
      }
   },
   {
      label: "without icon",
      click: function(evt) { 
         alert("without icon");
      }
   }]
});

Which results in this:

image

Hope you like this...

Once the external API is agreed, it's far easier to review an implementation in a PR then in a forum post. So go ahead and we can continue the discussion there.

1 Like

Bart, please consider supporting a title property (for tooltips) while you're in there :pray:

2 Likes

I created a pull-request (inclusive the "title" property) and a second pull-request to update the editableList documentation.

1 Like