ngplayground
ngplayground

Reputation: 21627

jQuery click to run a function, click again to run another

I'm trying to run a small piece of jQuery - when it's clicked it runs a function and when clicked again it runs another.

I have tried the following but this doesn't even run the first.

$('body').on('click', '.card--small', function() {
    console.log('clicked');
    $(this).addClass('card--expanded');
    if (topCheck() == 'chrome') {
        $('.card--expanded .card--small__container').css({
            'top': '51px'
        });
    }
}, function() {
    console.log('clicked again');
    $(this).removeClass('card--expanded');
    if (topCheck() == 'chrome') {
        $('.card--expanded .card--small__container').css({
            'top': '0'
        });
    }
});

function topCheck() {
    var ua = navigator.userAgent.toLowerCase();
    if (ua.indexOf('safari') != -1) {
        if (ua.indexOf('chrome') > -1) {
            console.log('Chrome');
        } else {
            return 'safari';
            console.log('Safari');
        }
    }
}

Upvotes: 1

Views: 1156

Answers (6)

guest271314
guest271314

Reputation: 1

Try

css

.card--small__container {
    top:0px;
    display:block;
    position:relative;
}

js

$("body")
.on("click", ".card--small", function () {    
    if (topCheck() == "Chrome" 
       && !$(this).data("clicked") 
       && !$(this).hasClass("card--expanded")) {
        $(this).data("clicked", true)
            .addClass("card--expanded")
            .css("top", "51px");
    } else if ( !! $(this).data("clicked") 
              && $(this).hasClass("card--expanded")) {
        $(".card--small")
        .css("top", "0")
        .removeClass("card--expanded");
    }
});

function topCheck() {
    var ua = navigator.userAgent.toLowerCase();
    return ua.indexOf("chrome") !== -1 ? "Chrome" : "Safari"
};

http://jsfiddle.net/o4ebav8t/

Upvotes: 0

Giedrius D
Giedrius D

Reputation: 1263

To answer your original question on how to toggle function called on click, your code should look something like this:

function click1() {
  // ...
  $(this).off('click', click1).on('click', click2)
}

function click2() {
  // ...
  $(this).off('click', click2).on('click', click1)
}

$('#link').on('click', click1)

Live demo

But from your code snippet it seems that it would be simpler to implement toggling in single function:

$('body').on('click', '.card--small', function() {
    if (!$(this).hasClass('card--expanded') {
        $(this).addClass('card--expanded');
        if (topCheck() == 'chrome') {
            $('.card--expanded .card--small__container').css({
                'top': '51px'
            });
        }
    } else {
        $(this).removeClass('card--expanded');
        if (topCheck() == 'chrome') {
            $('.card--expanded .card--small__container').css({
                'top': '0'
            });
        }
    }
});

Upvotes: 0

pete
pete

Reputation: 25081

Just use the card--expanded class as a flag to determine which click you need and design your function accordingly.

$('body').on('click', '.card--small', function (e) {
    var self = $(this),
        isExpanded = self.hasClass('card--expanded'),
        isChrome = topCheck() === 'chrome'; // will always be false as topCheck never returns 'chrome' (it returns either 'safari' or undefined).
    self.toggleClass('card--expanded', !isExpanded);
    if (!isExpanded) {
        console.log('clicked');
        if (isChrome) { // will never execute as isChrome will always be false
            $('.card--expanded .card--small__container').css({
                'top': '51px'
            });
        }
    } else {
        console.log('clicked again');
        if (isChrome) { // will never execute as isChrome will always be false
            $('.card--expanded .card--small__container').css({
                'top': '0'
            });
        }
    }
});

The point is to use some external condition as a flag to keep track of the click state. This could be a global variable, or a local variable above your handler in the scope chain (or a CSS class, or a HTML5 data attribute, etc.). There are a number of ways to do this. Using a CSS class seems like a natural fit in your case.

Also, the topCheck function would be better written if there were a chance it could return 'chrome':

function topCheck() {
    var ua = navigator.userAgent.toLowerCase();
    if (ua.indexOf('safari') > -1) {
        if (ua.indexOf('chrome') > -1) {
            return 'chrome';
            console.log('Chrome');
        } else {
            return 'safari';
            console.log('Safari');
        }
    }
}

or

function topCheck() {
    var ua = navigator.userAgent.toLowerCase(),
        browser = 'unknown';
    if (ua.indexOf('safari') > -1) {
        if (ua.indexOf('chrome') > -1) {
            browser = 'chrome';
            console.log('Chrome');
        } else {
            browser = 'safari';
            console.log('Safari');
        }
    }
    return browser;
}

Personally, I dislike multiple return statements per function so I would use the second form.

Upvotes: 2

lupz
lupz

Reputation: 3638

A simple approach without jQuery. Just keep some kind of state around to determine what to do.

<html>
  <head>
    <style>
      div {
        background-color: #ff0;
      }
    </style>
    <script>
      var state = 0;

      function runIt() {
        if (state > 0) {
          doSomethingDifferent();
          state = 0;
          return;
        }
        doSomething();
        state = 1;
      }

      function doSomething() {
        alert("something");
      }

      function doSomethingDifferent() {
        alert("something different");
      }
    </script>
  </head>
  <body>
    <div onClick="runIt()">Click me</div>
  </body>
</html>

Another approach would be to rebind the click event to another function.

Upvotes: 1

Michelangelo
Michelangelo

Reputation: 5948

In your function topCheck nothing is returned when you detect Chrome. You only log it. Your click event calls the function topCheck but does not get anything back from the function when Chrome is detected. So your if statement probably gets an undefined value.

Upvotes: 0

britter
britter

Reputation: 137

$('.card--small').click( function(){
   // run function 1
   function_1();
   $(this).unbind('click').click( function(){
      // run function 2
      function_2();
   });
});

Inside function 2 you would have to rebind $('.card--small') to run function 1 on click, if you want to run function 1 again.

Upvotes: 1

Related Questions