0

Let me start by saying, sorry for the confusing wording of the title, I wasn't sure how to state my issue.

I am using the jQuery ".on" function to handle three events for a specific element/selector (.custom-video-image), like so:

$('.custom-video-image').on({
        'click': function() {
            video = '<iframe src="'+ $(this).attr('data-video') +'"></iframe>';
            $(this).siblings('.custom-play').css('display', 'none');
            $(this).parent().toggleClass("image-wrapper video-wrapper");
            $(this).replaceWith(video);
        },
        'mouseover': function() {
            $(this).siblings('.custom-play').attr("src","images/youtube-play-color.png");
        },
        'mouseout': function() {
            $(this).siblings('.custom-play').attr("src","images/youtube-play-dark-trans.png");
        }
    });

As you can see ".custom-video-image" has three events. However, I want to add multiple elements/selectors to this function but not globally. For example, I am not looking to attach the three events to the additional elements/selectors, which would be achieved like so:

$('.custom-video-image, .selector-2, .selector-3').on({
        'click': function() {
            video = '<iframe src="'+ $(this).attr('data-video') +'"></iframe>';
            $(this).siblings('.custom-play').css('display', 'none');
            $(this).parent().toggleClass("image-wrapper video-wrapper");
            $(this).replaceWith(video);
        },
        'mouseover': function() {
            $(this).siblings('.custom-play').attr("src","images/youtube-play-color.png");
        },
        'mouseout': function() {
            $(this).siblings('.custom-play').attr("src","images/youtube-play-dark-trans.png");
        }
    });

What I am looking to achieve is apply the two additional elements/selectors to the "mouseover" and "mouseout" events. The following code is simply for illustrative purposes - this is what I am trying to achieve:

$('.custom-video-image').on({
        'click': function() {
            video = '<iframe src="'+ $(this).attr('data-video') +'"></iframe>';
            $(this).siblings('.custom-play').css('display', 'none');
            $(this).parent().toggleClass("image-wrapper video-wrapper");
            $(this).replaceWith(video);
        },
$('.custom-video-image, .selector-2, .selector-3').on({
        'mouseover': function() {
            $(this).siblings('.custom-play').attr("src","images/youtube-play-color.png");
        },
$('.custom-video-image, .selector-2, .selector-3').on({
        'mouseout': function() {
            $(this).siblings('.custom-play').attr("src","images/youtube-play-dark-trans.png");
        }
    });

Again, I know that last code sample isn't functional, I just wanted to illustrate what I am trying to achieve in one ".on" function - if that is even possible.

Finally, I know I can achieve this by creating multiple ".on" function calls or various other approaches but I wanted to see if it was possible using this method to specify additional elements/selectors for specific events in an ".on" function.

Any help is greatly appreciated, if there is an alternative solution to reducing the required lines of code to achieve the same effect, I am all ears! Simply trying to learn more effective and efficient ways.

Thank you.

Edit 1: If no alternative solution presents itself, I will be resorting to the following solution (I am open to any suggestions which better the following code):

$('.custom-video-image').on({
        'click': function () {
            video = '<iframe src="' + $(this).attr('data-video') + '"></iframe>';
            $(this).siblings('.custom-play').css('display', 'none');
            $(this).parent().toggleClass("image-wrapper video-wrapper");
            $(this).replaceWith(video);
        }
    });

$('.custom-video-image, .custom-play, .banner-overlay__copy').on({
        'mouseover': function() {
            $(this).siblings('.custom-play').attr("src","images/youtube-play-color.png");
        },
        'mouseout': function() {
            $(this).siblings('.custom-play').attr("src","images/youtube-play-dark-trans.png");
        }
    });
3
  • What is your reason against using two separate .on() calls? What various other approaches are not desirable and why? Maybe chaining jQuery's add() would be helpful, but I'm not sure what benefits it offers. Commented Dec 21, 2015 at 21:12
  • Well, it will sound idiotic but mostly for code simplicity but I also figured the performance would benefit from this because it would just run the function once to determine what to trigger, rather than executing a few lines deeper. Ultimately, the desire for an answer is a lot of curiosity - for future projects it would be nice to know if I could "chain" multiple selectors to various events defined in an ".on" array. Like I said, I don't know if its possible or even worth it but I wanted to find out. Feel free to just answer, "No, that's dumb, just code the extra lines" :p Commented Dec 21, 2015 at 21:16
  • I believe I could achieve the desired outcome by including some "if($(this).is('.item a')){" code into the events. Will test and report results. Commented Dec 21, 2015 at 21:39

2 Answers 2

1

It is possible to use a single event handler and perform conditional actions based on the event type and target. Notice that on() passes your handler an Event object, from which you can determine the event's type and target.

In my example below, I'm using a switch statement to define actions for various conditions.

I could see this being useful for handlers with complex logic or dynamic functionality. Those benefits aside, separate calls to on() are arguably more readable and simpler to maintain.

$('.s1,.s2,.s3').on('click mouseover mouseout', function(e) {
  
  var $eventTarget = $(e.target),
      eventType = e.type;

  switch (true) {

    case $eventTarget.hasClass('s1') && eventType == 'click':
      $eventTarget.toggleClass('red');
      break;
      
    case $eventTarget.hasClass('s2') && $.inArray(eventType,['mouseover','mouseout'])>=0:
      $eventTarget.toggleClass('green');
      break;
      
    case $eventTarget.hasClass('s3') && $.inArray(eventType,['mouseover','mouseout'])>=0:
      $eventTarget.toggleClass('blue');
      break;
      
    default:
      
  }

});
.red { background-color: red;}
.green { background-color: lightgreen;}
.blue { background-color: lightblue;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="s1">ELEMENT 1</div>
<div class="s2">ELEMENT 2</div>
<div class="s3">ELEMENT 3</div>

Sign up to request clarification or add additional context in comments.

2 Comments

Awesome answer! I don't have much practice with Switch Statements so this is very useful. I am going to leave the question open a bit longer to see what others have to say, before selecting your answer as the accepted answer.
showdev: check out my solution below; not sure how much you know about performance but I'm interested in finding out what the best solution would be - between the switch statement, my solution or two ".on" functions - based on performance and code clarity.
0

As mentioned in one of my comments, I was going to test the ability to have $('.selector-1, .selector-2, .selector-3).on({... and determine which events fired based on the element. I devised a solution, however, I am unsure if it would benefit performance or really anything, when compared to both switch statements or two separate ".on" events.

Here is the solution I came up with:

$('.custom-video-image, .custom-play, .banner-overlay__copy').on({
        'click': function() {
            if($(this).is('.custom-play, .custom-video-image')) {
                video = '<iframe src="'+ $(this).attr('data-video') +'"></iframe>';
                $(this).siblings('.custom-play').css('display', 'none');
                $(this).parent().toggleClass("image-wrapper video-wrapper");
                $(this).replaceWith(video);
            }
        },
        'mouseover': function() {
            if($(this).is('.custom-play')) {
                $(this).attr("src","images/youtube-play-color.png");
            } else {
                $(this).siblings('.custom-play').attr("src","images/youtube-play-color.png");
            }
        },
        'mouseout': function() {
            if($(this).is('.custom-play')) {
                $(this).attr("src","images/youtube-play-dark-trans.png");
            } else {
                $(this).siblings('.custom-play').attr("src","images/youtube-play-dark-trans.png");
            }
        }
    });

All I am doing, is running a check that says "if selector-'x'" for all three events.

This has been tested and works fine, but would like any available input as to which solution would be the best for performance/code clarity. Thanks.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.