skip to Main Content

I have a Place Order button, that contains a click event that will run some tasks and place the order via ajax.

I would like to add another click event that will be triggered before the original event, and perform some actions and validations.

Depending on the outcome of it:

  1. I would like to prevent the other events to be triggered
  2. OR if success, just proceed and call the other click listeners.

However I’m struggling a lot to achieve that with PrototypeJS or pure JavaScript.

This would be a simple example, but of course I tried many different approaches, including overrigind Event.observe method, cloning the button, and so on.

Any idea is appreciated.

var button = $('onestepcheckout-place-order-button')

//Original event
button.observe('click', function(e) {
  console.log('Order submitted')
})

// New event (I only have access to modify from here onwards)
button.observe('click', function(event) {

  if (confirm('Are you sure?') === false) {
    console.log('The order should not be submitted')
    event.preventDefault()
    event.stopPropagation()
    return false
  }

  // The other events should be triggered (order submitted)
  button.fire('click')
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.3/prototype.js"></script>
<button id="onestepcheckout-place-order-button" type="button"><span>Place order</span></button>

2

Answers


  1. Chosen as BEST ANSWER

    It turns out that, although prototype can store the events internally, we cannot have access to it like we can in jQuery.

    My solution was to clone the original button and add an event to it and also to the form, using pure javascript.

    This way I was able to inject a clone of the original button, but without it events attached, run my function and its validation, and trigger the original button click() event if the validation passes.

    Here's what I did:

    var button = document.getElementById('onestepcheckout-place-order-button')
    var form = document.getElementById('orderForm')
    
    
    // some code will add one or more event listeners to the original button
    button.addEventListener('click', function(e) {
      console.log('Button clicked will submit form via ajax')
      //ajax (the order may be placed via ajax. replace the webhook.site url with yours if you want to see it in action there)
      new Ajax.Request('https://webhook.site/25fab621-3f15-4d9f-ad87-3a746113adf2', {
        method: 'POST',
        data: {
          name: 'John Doe',
          email: '    '
        }
      })
    }, false)
    
    // clone the button
    var newButton = button.cloneNode(true)
    
    // replace old button for the new button (with no events attached)
    button.parentNode.replaceChild(newButton, button)
    
    // just a generic function to validate and prevent default
    var validateAndPreventDefault = function(event) {
      event.preventDefault() // prevent the default behavior of the form/button
    
      if (confirm('Are you sure?') === false) {
        // add condition here
        // if some condition is not met, prevent the form from being submitted
        console.log('The order should not be submitted')
    
        return false
      }
    
      console.log('The order will bet submitted')
      button.click() // trigger the click event on the old button
      return true
      // The other events should be triggered (order submitted)
    }
    
    // add the event listener to the form and the button, preventing the default behavior in both cases
    form.addEventListener('submit', validateAndPreventDefault, false)
    newButton.addEventListener('click', validateAndPreventDefault, false)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.3/prototype.min.js"></script>
    <form id="orderForm" method="post" action="#">
      <!--    type button-->
      <button id="onestepcheckout-place-order-button" type="button"><span>Place order</span></button>
    
      <!--    type submit-->
      <button id="onestepcheckout-place-order-button-original" type="submit"><span>Submit button</span></button>
    </form>


  2. I think you are running into a protection the browser puts in place, that prevents JS from artificially triggering click events that are not part of an original click event. For example, the browser will prevent you from triggering a click event on an element, if you trigger the event from a mouse move event.

    In your scenario, because the confirm() method is triggered that interrupts the "flow" of the click event from one handler to the next.

    Here’s my suggestion, extract the order submitted handler into a separate method definition, so that method is called while passing the event to that method. The original click event listener can call that method, as well as the new one that has the "are you sure" confirm() call.

    function submitorder(event){
       //... original submit order
    }
    
    $('onestepcheckout-place-order-button').observe('click',submitorder);
    // OR 
    $('onestepcheckout-place-order-button').observe('click',function(event){
    
        if (confirm('Are you sure?') === false) {
            console.log('The order should not be submitted')
            event.preventDefault()
            event.stopPropagation()
            return false
        }
    
        submitorder(event);
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search