tags:

views:

175

answers:

3

I have the following code to count and trigger some functions using jQuery:

        jQuery('#input_guideName').keyup(function(e)
        {               
            if(this.value.length == 5)
            {
                jQuery("#guide_btnCreateGuide").css({'background-position':'top', 'cursor':'pointer'});
                jQuery("#guide_btnCreateGuide").bind('click', function() {
                    createNewGuide(); 
                });
            }
            else if(this.value.length < 5)
            {
                jQuery("#guide_btnCreateGuide").css({'background-position':'bottom', 'cursor':'default'});
                jQuery("#guide_btnCreateGuide").unbind('click');
            }
        });   

Here are some issues I have encountered:

  1. Using CTRL + V is counted as 2 keyup, and the code will run twice, executing the createNewGuide() twice. How can I avoid this?

  2. Pasting code using right mouse button is not detected. How can I detect this? Bu putting a listener on RightMouseButton?

  3. If I paste text > 5 characters, none of my functions are triggered. I cannot add a control on if(this.value.length > 5), because then createNewGuide(); will fire for each keyup.

Any ideas how I can overcome these issues?

EDIT
My "operational objective" is to create a new guide in DB and the guide name must be at least 5 characters long. The button for the 'create guide' will not be clickable unless name is at least 5 characters long.

A: 

Instead of handling only KeyUp event, which is specific to keyboard events only you should consider binding to Change event also, that captures everything changed in the control?

Remember Chnage is a post event, so you must bind both

  $('#input_guideName').bind("change keyup", function() {
       //your code
  });
stackunderflow
That will still not detect pasting code using right mousebutton
Steven
+1  A: 

I don't really get what all your code is good for and how it works exactly, but I think you need this:

var thereIsAGuid = false;
jQuery('#input_guideName').bind('keyup mouseup', function(e){
    if(this.value.length >= 5 && thereIsAGuid == false){
        jQuery("#guide_btnCreateGuide").css({'background-position':'top', 'cursor':'pointer'});
        jQuery("#guide_btnCreateGuide").bind('click', function() {
            createNewGuide();
            thereIsAGuid = true;
        });
    } else {
        jQuery("#guide_btnCreateGuide").css({'background-position':'bottom', 'cursor':'default'});
        jQuery("#guide_btnCreateGuide").unbind('click');
        thereIsAGuid = false;
    }
}); 

keyup and mouseup events are enough I think.

Harmen
your code works. But I still have the problem that there is registered two keyup when I click CTRL + V, thus firing `createNewGuide();` twice.
Steven
+1  A: 

Handling Ctrl + V isn't as bad as you might think but handling paste in general is. There's no onpaste event (at least not cross browser) and the middle/right click paste actually happens AFTER the mouseup event so if you just did .bind('change keyup mouseup', func... you'd miss it. Given all that, I think a timeout is the best way to do this:

$(function() {
setTimeout(function() {
    var val = jQuery('#input_guideName').val();

    if (val.length > 5) {
        jQuery("#guide_btnCreateGuide")
          .css({'background-position':'top', 'cursor':'pointer'})
          .unbind('click')  // prevents duplicate click events
          .bind('click', function() {
                createNewGuide(); 
          });
    } else {
        jQuery("#guide_btnCreateGuide")
          .css({'background-position':'bottom', 'cursor':'default'})
          .unbind('click');
    }

}, 300);
});

Even in your original code, createNewGuide() wasn't being called on each keyup with this.value > 5 but rather you were registering a new event on each keyup that call createNewGuide, so then on click, it would get called multiple times.

By doing unbind before bind prevents duplicate functions getting registered onclick, so you won't ever call createNewGuide() twice, even on ctrl + v;

You can tune the delay if you're worried about your users hitting the button quickly after shorting the input.

Rob Van Dam
You're spot on. But when will you call `setTimeout()`?
Steven
`jQuery('#input_guideName').SetTimeout()`doesn't work..
Steven
Depends a little on your use case, but I'd say just wrap it in `$(function() { // code here })` so it starts as soon as the elements on the page have loaded. Can't do it earlier than that, but if you had other requirements, you could start in on some other event trigger.
Rob Van Dam
Oh no, the setTimeout is a builtin javascript function, not jquery. It's actually window.setTimeout.
Rob Van Dam
Ah, ok. But I only get an error: "SetTimeout is not defined"
Steven
Bah... I give up. I'll just have the button enabled and to all the checking there. Not as sexy, but at least it'll work... :)
Steven
You just have a typo, its `setTimeout`, lower case `s`.
Rob Van Dam
ok, thanks. Will try that :)
Steven