I am trying to figure out a way to easily disable/enable buttons within dat.gui.
I have dat.gui set up to control an animation. When the animation reaches its end, I want the "Play" button to become disabled. I have tried adding a "disabled" attribute to the DOM elements of the button, but I am still seeing the corresponding function fire when the button is clicked after this attribute is set.
My current method is the following:
li
element that corresponds to the button in the dat.gui interfaceli
element to gray out the contents of the button.This is a hack, and I would love to know if there was some method for disabling a button built right into dat.gui, or some better method that I am not aware of.
In dat.GUI the FunctionController
class is responsible for buttons. If you look at its source code, there is no conditional logic in there. The controller will listen to click
events on the button and it will always call the function on click. This means that you won't get any help from the library here - you need to check in the handler whether the button is disabled. Something along these lines:
// Find the GUI controller listening to given property on given object
function getController(gui, object, property)
{
for (var i = 0; i < gui.__controllers.length; i++)
{
var controller = gui.__controllers[i];
if (controller.object == object && controller.property == property)
return controller;
}
return null;
}
...
object.button = function()
{
// Don't do anything if the button is disabled
if (getController(gui, this, "button").domElement.hasAttribute("disabled"))
return;
alert("Button clicked");
};
gui.add(object, "button");
...
// Disable button
getController(gui, object, "button").domElement.setAttribute("disabled", "");
Note that there is no special styling for disabled elements in dom.GUI, you would have to add you own styles for that. Given that what you see in case of a button is the property label rather than the actual button this isn't going to be quite trivial - I think you will have to place the disabled
attribute on controller.domElement.parentNode
rather than controller.domElement
. Then you should be able to use the selector [disabled] > .property-name
for your styles.
Edit: You can actually do this in a more generic way by extending FunctionController
:
function blockEvent(event)
{
event.stopPropagation();
}
Object.defineProperty(dat.controllers.FunctionController.prototype, "disabled", {
get: function()
{
return this.domElement.hasAttribute("disabled");
},
set: function(value)
{
if (value)
{
this.domElement.setAttribute("disabled", "disabled");
this.domElement.addEventListener("click", blockEvent, true);
}
else
{
this.domElement.removeAttribute("disabled");
this.domElement.removeEventListener("click", blockEvent, true);
}
},
enumerable: true
});
This will add a property disabled
to the controller that will catch click
events so that the button handler isn't triggered. Disabling the button gets simpler then:
getController(gui, object, "button").disabled = true;
And the button handler can stay unchanged, it simply won't be triggered for disabled buttons.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With