2

I'm having trouble getting the match to bind to the oninput property of my text input. Basically I want my submit button to be enabled only when the regular expression is matched. If the regex isn't matched, a message should be displayed when the cursor is over the submit button. As it stands, typing abc doesn't enable the submit button as I want it to. Can anyone tell me what I'm doing wrong? Thank you.

    <div id="message">
    </div>

<form method="POST">
  <input type="text" id="txt" oninput="match()" />
  <input type="submit" id="enter" value="enter" disabled />
</form>

  <script>

    var txt = $("#txt").value();

    var PATTERN = /abc/;
    var REQUIREMENTS = "valid entries must contain the string 'abc'";

    // disable buttons with custom jquery function

    jQuery.fn.extend({
    disable: function(state) {
        return this.each(function() {
            this.disabled = state;
        });
      }
    });

    $('input[type="submit"]).disable(true);

    var match = function(){

      if (txt.match(PATTERN)){
        $("#enter").disable(false)
      }

      else if ($("#enter").hover()){
        function(){
          $("#message").text(REQUIREMENTS);
        }
      }

  </script>  
arcyqwerty
  • 10,325
  • 4
  • 47
  • 84
David J.
  • 1,753
  • 13
  • 47
  • 96

3 Answers3

2

Your code would be rewrite using plain/vanille JavaScript.

So your code is more clean and better performance:

  <div id="message"></div>
  <form method="POST">
     <input type="text" id="txt" oninput="match()" />
     <input type="submit" id="enter" value="enter" disabled />
  </form>

         <script>
            var txt;
            var enter = document.getElementById('enter');
            var message = document.getElementById('message');
            var PATTERN = /abc/;
            var REQUIREMENTS = "valid entries must contain the string 'abc'";

            function match() {
                txt = document.getElementById('txt').value;
                if (PATTERN.test(txt)) {
                    enter.disabled = false;
                } else if (isHover(enter)) {
                    enter.disabled = true;
                    message.innerHTML = REQUIREMENTS;
                } else {
                    enter.disabled = true;
                }
            }
            function isHover(e) {
                return (e.parentElement.querySelector(':hover') === e);
            }
        </script>

If you wanted to say that you want handle the events in different moments, your code should be the following.

Note: the buttons when are disabled doesn't fired events so, the solution is wrapper in a div element which fired the events. Your code JavaScript is more simple, although the code HTML is a bit more dirty.

<form method="POST">
   <input type="text" id="txt" oninput="match()" />
   <div style="display: inline-block; position: relative">
     <input type="submit" id="enter" value="enter" disabled  />
     <div id="buttonMouseCatcher" onmouseover="showText(true)" onmouseout="showText(false)" style="position:absolute; z-index: 1;
              top: 0px; bottom: 0px; left: 0px; right: 0px;">
     </div>
  </div>

        <script>
            var txt;
            var enter = document.getElementById('enter');
            var message = document.getElementById('message');
            var PATTERN = /abc/;
            var REQUIREMENTS = "valid entries must contain the string 'abc'";

            function match() {
                txt = document.getElementById('txt').value;
                if (PATTERN.test(txt)) {
                    enter.disabled = '';
                } else {
                    enter.disabled = true;
                }
            }
            function showText(option) {
                message.innerHTML = option ? REQUIREMENTS : "";
            }
        </script>
caballerog
  • 2,679
  • 1
  • 19
  • 32
  • Thanks, the button does indeed work, but for some reason the div text doesn't update for me when hovering over the button.. – David J. Dec 16 '15 at 00:00
  • The div text is updated when you are writing (match function) in the input (oninput event) and the cursor is over the button. Do you want only show the text when the cursor is over the button? – caballerog Dec 16 '15 at 00:02
  • Yes, I wanted the text to show only when the cursor is over the button, I didn't make that clear – David J. Dec 16 '15 at 00:04
1

Two problems here:

  1. The variable txt is defined once outside the function match, so the value is fixed to whatever the input with id txt has when the script/page is loaded.

    You should move var txt = $("#txt").val(); into the match function.

  2. Notice I changed the function value() to val().

Zakaria Acharki
  • 66,747
  • 15
  • 75
  • 101
Will
  • 66
  • 1
  • Thanks, that makes sense. I fixed the two issues, however, and the function still isn't working. :/ – David J. Dec 15 '15 at 23:52
1

Problems identified:

  • jQuery events don't happen on disabled inputs: see Event on a disabled input
    • I can't fix jQuery, but I can simulate a disabled button without it actually being disabled. There's other hacks you could do to get around this as well, for example, by overlaying a transparent element which actually captures the hover event while the button is disabled.
  • Various syntactical errors: format your code and read the console messages
    • .hover()){ function() { ... } } is invalid. It should be .hover(function() { ... })
    • else doesn't need to be followed by an if if there's no condition
    • .hover( handlerIn, handlerOut ) actually takes 2 arguments, each of type Function
    • $('input[type="submit"]) is missing a close '
  • Problems identified by @Will
    • The jQuery function to get the value of selected input elements is val()
    • val() should be called each time since you want the latest updated value, not the value when the page first loaded
  • Design issues
    • You don't revalidate once you enable input. If I enter "abc" and then delete the "c", the submit button stays enabled
    • You never hide the help message after you're done hovering. It just stays there since you set the text but never remove it.

https://jsfiddle.net/Lh4r1qhv/12/

<div id="message" style="visibility: hidden;">valid entries must contain the string 'abc'</div>

<form method="POST">
  <input type="text" id="txt" />
  <input type="submit" id="enter" value="enter" style="color: grey;" />
</form>

<script>

  var PATTERN = /abc/;

  $("#enter").hover(
    function() {
      $("#message").css('visibility', $("#txt").val().match(PATTERN) ? 'hidden' : 'visible');
    },
    $.prototype.css.bind($("#message"), 'visibility', 'hidden')
  );

  $('form').submit(function() {
    return !!$("#txt").val().match(PATTERN);
  });

  $('#txt').on('input', function() {
    $("#enter").css('color', $("#txt").val().match(PATTERN) ? 'black' : 'grey');
  });

</script>  
Community
  • 1
  • 1
arcyqwerty
  • 10,325
  • 4
  • 47
  • 84
  • Your help on the design issues is especially appreciated, thank you. The only problem here is that the message is displayed even when 'abc' is entered. – David J. Dec 18 '15 at 16:24
  • I am using your example and I don't quite understand the $('form').submit clause. I would like to evaluate a function upon submission like this: $('form').submit(function() { return !!txt.match(PATTERN); var before = $("#txt").val().slice(0,1); var after = $("#txt").val().slice(2)); alert("before is".concat(before) ); }); }} But I do not get an alert when I submit. Is the return messing me up? thanks – David J. Dec 22 '15 at 19:28
  • 1
    The `return` keyword exits the function such that any statements after the `return` will not be executed. – arcyqwerty Dec 22 '15 at 19:45
  • 1
    If you need to return a value that is computed early on, save the value to a variable and return that variable after you've completed everything else. – arcyqwerty Dec 22 '15 at 19:45