Bind first parameter always will be the function you are trying to bind "this" object, being the following values assigned to the parameters your function have. If you check the your Fiddle, once the button is clicked you have the following values:
this: "mycatid",
categoryId: "my cat text"
subheadingText: Event
event: MouseEvent
so, in order to make the code work as exepected:
var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';
faqCategoryButtons.addEventListener('click', categoryNavigation.bind(null, categoryId, subheadingText, event));
function categoryNavigation(categoryId, subheadingText, event){
if (event && event.preventDefault) {
event.preventDefault();
} else if (event) {
event.returnValue = false;
}
}
In this case I have added an extra "null" to make it work because I understand you are not using the "this", however, you can add any value and it will become the "this" of the function.
Edit: reply to the comment's question
It looks like even though when I
bind the parameters to the function it needs to be in this order
categoryNavigation.bind(null, categoryId, subheadingText, event) But
when I define the function, the parameters need to be in this order
categoryNavigation(categoryId, subheadingText, context, event){} Is
that expected behaviour that the arguments get rearranged when the
function is called?
As I mentioned in my answer, the first parameter when you do the binding is the "this", what I would call the context, and that is the real "rearrangement" that the function does. Beside that, the order of the parameters is the same. however, something to take in account is that the "bind" returns a function with the those parameters already "binded" to the old function, and it should be called again.
In your case, you binded null, categoryId, subheadingText, event. However in the shown code, only categoryId and subheadingText were defined, but event was not. That means that the event you binded there, technically should be 'undefined' - but might be a random event value the code had at this point -. In the other hand, click does return its own "event" value as a paramter, so in the end, in your code you have a click event that will call a function that you binded beforehand "null, cathegoryId, subheadingText, ", and that, when the event arises, is called and an the click's event is placed there (but there is not space to place that event, because all the parameters were defined already)
In other words, your code (after the this binded fix)
var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';
faqCategoryButtons.addEventListener('click', categoryNavigation.bind(null, categoryId, subheadingText, event));
function categoryNavigation(categoryId, subheadingText, event){
if (event && event.preventDefault) {
event.preventDefault();
} else if (event) {
event.returnValue = false;
}
}
is equivalent to:
var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';
function categoryNavigationBinded(eventForTheclick){
const categoryNavigationThis = cagegoryNavigation.bind(null); // in the fixed code, categoryNavigation has its "this = null"
categoryNavigationThis(categoryId, subheadingText, event) // note that event is not defined, and for what I know is "undefined"
}
faqCategoryButtons.addEventListener('click', categoryNavigationBinded);
function categoryNavigation(categoryId, subheadingText, event){
if (event && event.preventDefault) {
event.preventDefault();
} else if (event) {
event.returnValue = false;
}
}
For the code, I presume you want to do something like this:
var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';
function categoryNavigationBinded(eventForTheclick){
const categoryNavigationThis = cagegoryNavigation.bind(null); // in the fixed code, categoryNavigation has its "this = null"
categoryNavigationThis(categoryId, subheadingText, eventForTheclick) // here I am placing the click's event into the 3rd categoryNavigation parameter
}
faqCategoryButtons.addEventListener('click', categoryNavigationBinded);
function categoryNavigation(categoryId, subheadingText, event){
if (event && event.preventDefault) {
event.preventDefault();
} else if (event) {
event.returnValue = false;
}
}
That would be the "extended" version, so I can explain what will happen, and the "short version" using the bind in the same way you did in your code would be:
var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';
faqCategoryButtons.addEventListener('click', categoryNavigation.bind(null, categoryId, subheadingText)); // the last parameter, "event", will be the parameter the click will place its own event
function categoryNavigation(categoryId, subheadingText, event){
if (event && event.preventDefault) {
event.preventDefault();
} else if (event) {
event.returnValue = false;
}
}
TLDR: the parameters doesn't really reorganize in the bind except for the first "this", however in your code, you defined the "event" parameter before you really had the real event value, so it was "lost" (and send as a "5th" parameter when clicking)