Home > Net >  Modal Closing When Clicking It
Modal Closing When Clicking It

Time:11-21

I am trying to setup a modal and have it loading and closing correctly however found a small bug (a rather really annoying one in fact).

It seems that when the modal opens and I try to click an element within the modal; the modal itself closes.

Here is my current javascript

/* Ready Function */
$(function(){
    $('.modal-block').each(function(){
        let mb = new Modal($(this));
    });
});
const Modal = function(this$obj){
    this.$obj = this$obj;
    this.init();
}
Modal.prototype.init = function init(){
    this.modal_setup();
};

Modal.prototype.modal_setup = function modal_setup(){
    let _this = this;
    let trigger = this.$obj.find('.toggle');
    let modal = this.$obj.find('.modal');
    trigger.on('click',function(){
            modal.addClass('modal--active');
            _this.close_modal();
    });
}

Modal.prototype.close_modal = function close_modal(){
    let modal = this.$obj.find('.modal');
    $(document).mouseup(function(e)
    {
        if (!$(e.target).is(".modal, .modal-active")) {
            modal.removeClass('modal--active');        }
    });
}
.modal {
  display:none;
}
.modal--active {
  display:block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<button type="button" >
open modal
</button>
<div >
  <div >
    <span >title</span>
  </div>
</div>
</div>

How can I modify this script to close the modal when the user clicks outside the box only?

CodePudding user response:

I'd like to note that your "open modal" button does not toggle the modal. I don't know if you intend on implementing that or if you knew that, nonetheless, I thought I'd let you know.

Using CLOSEST()


So this might be a solution. I could've sworn that e.preventDefault() or e.stopPropagation() was the ideal method, but I couldn't get it to work immediately. I thought the problem had to do with event bubbling and could be solved from the like of this post, but that doesn't appear to be the case. But along the same line of thoughts, I believe you can achieve what you are looking to do with closest as opposed to is: if (!$(e.target).closest(".modal.modal--active").length > 0).

/* Ready Function */
$(function(){
    $('.modal-block').each(function(){
        let mb = new Modal($(this));
    });
});
const Modal = function(this$obj){
    this.$obj = this$obj;
    this.init();
}
Modal.prototype.init = function init(){
    this.modal_setup();
};

Modal.prototype.modal_setup = function modal_setup(){
    let _this = this;
    let trigger = this.$obj.find('.toggle');
    let modal = this.$obj.find('.modal');
    trigger.on('click',function(){
            modal.addClass('modal--active');
            _this.close_modal();
    });
}

Modal.prototype.close_modal = function close_modal(){
    let modal = this.$obj.find('.modal');
    $(document).mouseup(function(e)
    {
        if (!$(e.target).closest(".modal.modal--active").length > 0) {
        //if (!$(e.target).is(".modal.modal--active")) {
            modal.removeClass('modal--active');
        }
    });
}
.modal {
  display:none;
}
.modal--active {
  display:block;
  border: solid black 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<button type="button" >
open modal
</button>
<div >
  <div >
    <span >title
      <span>
        More content for depth test
      </span>
    </span>
  </div>
</div>
</div>

Using IS()


However, if you want to continue to just use is, the only other idea I have would be to designate a class that would be assigned to each element in the modal (maybe could be dynamically assigned through the creation of the modal to its children like in the below example with find) and checking the if statement with the is statement.

/* Ready Function */
$(function(){
    $('.modal-block').each(function(){
        let mb = new Modal($(this));
    });
});
const Modal = function(this$obj){
    this.$obj = this$obj;
    this.init();
}
Modal.prototype.init = function init(){
    this.modal_setup();
};

Modal.prototype.modal_setup = function modal_setup(){
    let _this = this;
    let trigger = this.$obj.find('.toggle');
    let modal = this.$obj.find('.modal');

    modal.addClass("stay_open");
    modal.find("*").addClass("stay_open");
    
    trigger.on('click',function(){
            modal.addClass('modal--active');
            _this.close_modal();
    });
}

Modal.prototype.close_modal = function close_modal(){
    let modal = this.$obj.find('.modal');
    $(document).mouseup(function(e)
    {
        //if (!$(e.target).closest(".modal.modal--active").length > 0) {
        if (!$(e.target).is(".stay_open")) {
            modal.removeClass('modal--active');
        }
    });
}
.modal {
  display:none;
}
.modal--active {
  display:block;
  border: solid black 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<button type="button" >
open modal
</button>
<div >
  <div >
    <span >title
      <span>
        More content for depth test
      </span>
    </span>
  </div>
</div>
</div>

CodePudding user response:

try to add event.preventDefault()

  • Related