Prevent people from being able to click icon inside of a button

Viewed 631

I am making a quick throw-together website that requires users to be able to interact with a button to execute a delete action.

I have my button (code is shown below) where I have a basic bootstrap button paired with an icon (provided by their library) in which the user clicks to delete an "Infraction"

<button
  referencedInfraction="<%= i.infractionID %>"
  targetUserID="<%= i.userID %>"
  class="deleteButton btn btn-danger"
>
  <i class="bi bi-trash-fill"></i>
</button>

The infraction that the user wants to delete is passed through an attribute to the code below.

$(".deleteButton").click((event) => {
  $("#confirmDeleteSingleInfractionModal").modal("toggle");

  let data = {
    infractionID: $(event.target).attr("referencedInfraction"),
    targetUserID: $(event.target).attr("targetUserID"),
  };

  console.log(data);

  $("#confirmDeleteSingleInfractionModal").on("hide.bs.modal", function () {
    console.log("deleting");

    $.ajax({
      type: "delete",
      url: `${window.location.origin}/dataLink/infraction`,
      data,
      success: () => {
        console.log("done");
      },
      error: () => {
        showInfractionDeleteError();
      },
    });
  });
});

However, I've run into a bit of an issue. I notice that the only way for the user to actually click the button is if they click around the edges where the <I> element is not present.

Is there any way to prevent this from showing in event.target()?

All I want is the custom attribute from the button clicked, not the image.

Any help would be appreciated.

3 Answers

You can check if the element which is been clicked is i tag or button and depending on this change your selector to get required data.

Demo Code :

$('.deleteButton').click((event) => {
  console.log(event.target.tagName.toLowerCase())
  //get tag which is clicked change selector if needed
  var target = event.target.tagName.toLowerCase() === 'button' ? $(event.target) : $(event.target).parent()

  //$('#confirmDeleteSingleInfractionModal').modal('toggle');
  let data = {
    infractionID: target.attr('referencedInfraction'),
    targetUserID: target.attr('targetUserID')
  }


  console.log(data);
  //other codes..
});
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.1.0/css/v4-shims.min.css">

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button referencedInfraction="1" targetUserID="12" class="deleteButton btn btn-danger"> <i class="fas fa-heart"></i> </button>
<button referencedInfraction="2" targetUserID="13" class="deleteButton btn btn-danger"><i class="fas fa-heart"></i> </button>

If you set pointer-events: none on the element with the icon that should prevent the click event from firing on it and instead use the button, allowing you to get the data attributes. Example:

.bi-trash-fill {
    pointer-events: none
}

Or whatever element/class makes sense for your application. This allows the user to click anywhere on the button (including on the icon) and the event will fire getting the attributes from the button.

The best way to work around this is to add a function to the icon <i></i> that is called once it is clicked and inside this function you can call the same function called by clicking on the button <button></button> itself. Also you can pass the same data from the icon element <i></i> to its function to be used in the button function.

note: you don't want to prevent clicking on the icon because it will be a bad UX (user experience) but actually you want to use it for the right purpose.

Related