0

I have a textarea that on keyup calls a function when a certain word or phrase has been entered, but also calls another function which undoes the initial function, if the word or phrase is then deleted.

var phraseList = [
    "foo foo",
    "foobar",
    "foobity foofoo foo"
];


$("#id_message").on('keyup', function(){
      for(var i=0;i<phraseList.length;i++){
        if($('#id_message').val().toLowerCase().indexOf(phraseList[i]) > -1){
            doEgg();
        }else{
            undoEgg();
        }
      }
});

However on every keyup the value of indexOf is temporarily set to -1 until it has made its way through the characters and found the offending word.

So this causes doEgg(); and undoEgg(); to be called repeatedly in quick succession, which is not what I want to happen.

Is there any way to calculate .indexOf() but only after the text area has been looked over? So it assigns a value to indexOf() only once.

From what I know onChange doesn't work for what I need as I want the functions to run as the person types rather than when the whole textarea has been completed.

Thanks

EDIT.

The functions being called are:

function doEgg(){
    // if(changeback)clearInterval(changeback);
    audioElement.play();
    // var change = setInterval(function () {
    change = setInterval(function () {
            var all = $('#wall_container').find('img').not('.easter');
            var random = Math.floor(Math.random()*all.length)
            var Rimg = $( all[random] )
            var cdown = all.length;
            var r = 1+Math.floor(Math.random()*33);

            Rimg.attr('data-oldsrc', Rimg.attr('src')).attr('src', 'http://localhost:8888/wp-content/uploads/crying/crying'+r+'.gif').addClass('easter');

            if(cdown==0){
                clearInterval(change);                    
            }

        }, 500)
}

function undoEgg(){
    // if(change)clearInterval(change);
    audioElement.pause();
    // var changeback = setInterval(function () {
    changeback = setInterval(function () {
        var all = $('#wall_container').find('img').filter('.easter');
        var random = Math.floor(Math.random()*all.length)
        var Rimg = $( all[random] )
        var cdown = all.length;

        Rimg.attr('src', Rimg.attr('data-oldsrc')).removeClass('easter');

        if(cdown==0){
            clearInterval(changeback);
        }
    }, 500)
}
rxssmcdxwell
  • 109
  • 1
  • 14

2 Answers2

1

what do you mean? something like this?

var phraseList = [
    "foo foo",
    "foobar",
    "foobity foofoo foo"
];

$(function() {
  $("#id_message").on('keyup', function() {
      $("#result").empty();
      for(var i=0;i<phraseList.length;i++) {
        if($('#id_message').val().toLowerCase().indexOf(phraseList[i]) > -1){
            $("#result").append("found<br>");
        } else {
            $("#result").append("not found<br>");
        }
      }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<input id="id_message">
<div id="result"></div>

or like this:

var phraseList = [
    "foo foo",
    "foobar",
    "foobity foofoo foo"
];

$(function() {
  $("#id_message").on('keyup', function() {
      var $result = $("#result").empty();
      var val = this.value.toLowerCase();
      var words = phraseList.filter(function(e,i){ return val.indexOf(e)> -1 });
      if(words.length) {
        $result.append("found<br>");
      } else {
        $result.append("not found<br>");
      }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<input id="id_message">
<div id="result"></div>

EDIT: you can set a delay for this with a timeout:

var phraseList = [
    "foo foo",
    "foobar",
    "foobity foofoo foo"
];

$(function() {
  var timeout = 0;
  
  $("#id_message").on('keyup', function() {
      clearTimeout(timeout);
      var $result = $("#result").empty();
      var val = this.value.toLowerCase();
      var words = phraseList.filter(function(e,i){ return val.indexOf(e)> -1 });
      timeout = setTimeout(function(){
        if(words.length) {
          $result.append("found<br>");
        } else {
          $result.append("not found<br>");
        }
      }, 500);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<input id="id_message">
<div id="result"></div>

those 500 are milliseconds, if you want it to execute more immediately set it closer to 0 and viceversa

Santiago Hernández
  • 5,438
  • 2
  • 26
  • 34
  • Thanks you @Santiago-Hernández the second code seems to work in theory. But I am struggling to implement it on my site. If I replace the $results.append... with doEgg(); and undoEgg(); the same problem arises. I have added the functions being called to my question above, if that helps. – rxssmcdxwell Jul 23 '15 at 18:42
  • So close @SantiagoHernandez! – rxssmcdxwell Jul 23 '15 at 19:01
  • thanks @SantiagoHernandez this seems to be working. but from what I can gather I need to set the interval of the function so that it is greater than the sum of the setIntervals called by either `doEgg()` or `undoEgg()`. so if there are 10 images that doEgg() replaces and the interval of doEgg() is set to `100`. Then the interval for your function must be more than 10x100, so `1000`. Which does not seem ideal... Is there a way I can stop doEgg() or stop undoEgg() if the other one is called? – rxssmcdxwell Jul 23 '15 at 20:15
  • would that work in my instance? I believe the issue now is that if `undoEgg()` is called before `doEgg()` is complete. Then the code gets all confused again and the images begin to flicker. So I need a way to instantly complete `doEgg()` or wait for `doEgg()` to complete before `undoEgg()` is called. – rxssmcdxwell Jul 23 '15 at 20:47
  • Thank you for your help btw @SantiagoHernandez, very much appreciated – rxssmcdxwell Jul 23 '15 at 20:47
  • Hi @SantiagoHernandez , [I have made a jsfiddle to show you the problem.](https://jsfiddle.net/sd8v747c/). You can see that when the setInterval of the `doEgg()` and `undoEgg()` is higher than the interval of your function. The value in the result div flickers back and forth. On my site the `doEgg()` function replaces an image on the page every `100ms` for example. If there are 10 images, then the total time for the `doEgg()` function to run is `1000ms` and so the images flicker. – rxssmcdxwell Jul 23 '15 at 21:49
  • hi, sorry im not sure if this solves your issue: [fiddle](https://jsfiddle.net/sd8v747c/1/) – Santiago Hernández Jul 23 '15 at 21:54
  • 1
    Thank you @SantiagoHernandez ! You sir are a genius, thank you so much for your help! – rxssmcdxwell Jul 23 '15 at 22:04
1

Don't use for loop. Instead of indexOf use inArray method.

Try this code snippets:

var phraseList = [
    "foo foo",
    "foobar",
    "foobity foofoo foo"
];


$("#id_message").on('keyup', function () {
    var value = $('#id_message').val();
    if ($.inArray(value, phraseList) != -1) {
        doEgg();
    } else {
        undoEgg();
    }
});
function doEgg() {
    alert("do");
}
function undoEgg() {
    alert("undo");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<input type='text' id='id_message' />

Update:

Use match method like this with RegEx.

var phraseList = [
    "foo foo",
    "foobar",
    "foobity foofoo foo"
];


$("#id_message").on('keyup', function () {
    var value = $('#id_message').val().toLowerCase(),
        flag = [];
    flag = $.map(phraseList, function (val) {
        var re = new RegExp("\\b" + val + "\\b","g");
        if (value.match(re))
            return val;
    });
    if (flag.length)
        doEgg();
    else
        undoEgg();
});
function doEgg() {
    alert("do");
}
function undoEgg() {
    alert("undo");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<input type='text' id='id_message' />

Hope this helps you!

John R
  • 2,741
  • 2
  • 13
  • 32
  • Hi @John-R, this almost works but is not quite there yet. If you run the code snippet and type "i love foo foo" you will see that the doEgg() function does not run. Also if you type "foo foo love me" then you will see that any character you type after "foo foo" will run the undoEgg() function even though the word "foo foo" exists. – rxssmcdxwell Jul 23 '15 at 18:35
  • Thanks @JohnR, sad to say that your update has made the code worse off. Now on every character the doEgg() function runs. – rxssmcdxwell Jul 23 '15 at 19:12
  • @rxssmcdxwell Hope that I have answered as per the requirement. Please check my update now and let me know your comments. – John R Jul 23 '15 at 20:00
  • OP's question is _"this causes doEgg(); and undoEgg(); to be called repeatedly in quick succession, which is not what I want to happen"_, clearly this doesn't answer. However your `for` advice is cool :) – Santiago Hernández Jul 23 '15 at 20:22
  • Thank you @JohnR both your answer and @SantiagoHernandez seem to fix my problem in the same way. But I have to keep the setInterval of `doEgg()` and `undoEgg()` very low, around `10`. I feel you have both answered my initial question. – rxssmcdxwell Jul 23 '15 at 20:39