Ryan Grush
Ryan Grush

Reputation: 2128

Javascript - call a function multiple times but only have one effect

I know I can easily work around this, but I'm looking for the best practice in this case. This is a simplified version http://jsbin.com/isered/3/edit. I'm trying create a function for reuse but I need it so that when the event is triggered (i.e. clicking on the anchor tag), it only appends the output area once, not for each time the function has been called.

Jquery/Javascript

$(function () {

   function foo () {
      $('a').on('click', function () {
      $('.asdf').append('poo');
    });
   }

   foo ();
   foo ();
});

HTML

<a href='#'>hello</a>
<a href='#'>world</a>

<p class='asdf'></p>

Upvotes: 0

Views: 1309

Answers (5)

kenecaswell
kenecaswell

Reputation: 7598

$(function () {
    function foo () {
        $('a').on('click', function () {
            var num = $('.asdf').text().length;
            if (num == 0) {
                $('.asdf').append('poopsicles');
            }
        });
    }

    foo();
    foo();
});

I guess this question has already been answered, but here ya go.

Upvotes: 0

Brandon J. Boone
Brandon J. Boone

Reputation: 16472

Underscore.js already has this function.

So why re-invent the wheel.

_.once(function) Creates a version of the function that can only be called one time. Repeated calls to the modified function will have no effect, returning the value from the original call. Useful for initialization functions, instead of having to set a boolean flag and then check it later.

Example:

$(function () {

  var foo = _.once(function() {
    $('a').on('click', function () {
      $('.asdf').append('poo');       
    });
  });

  foo ();
  foo ();
});

Upvotes: 0

mVChr
mVChr

Reputation: 50185

I usually encounter this when I want to make a container only once but process the rest of the function on subsequent clicks as well. In that case, I put a check for the container's existence as follows:

var foo = function(){
    $('a').on('click', function(ev){
       if (!$('.asdf .foo').length) {
           $('.asdf').append('<div class="foo">');
       }
       // do other click stuff here
    });
};

Upvotes: 1

Matt Ball
Matt Ball

Reputation: 359876

You could unbind the events before binding them:

function foo () {
  $('a').off('click').on('click', function () {
      $('.asdf').append('poo');       
  });
}

Though I don't understand why calling the function once and only once is not the best solution.

Upvotes: 2

Blender
Blender

Reputation: 298246

You can make a state variable, in this case a class:

$(function () {
  function foo() {
    $('a:not(.clicked)').on('click', function() {
      $(this).addClass('clicked');
      $('.asdf').append('poo');
    });
  }

  foo();
  foo();
});

Upvotes: 2

Related Questions