16

I have some problems with my jQuery "compare" function. Its mission is to compare two text areas and highlight the differences.

eg. "My name is Michael" in one text area, and "My name is Michel" in another.

My function shall return both inputs and highlight the char "a" from the first input, and highlight a missing char from the second.

This is how the function looks so far, but it doesn't seem to work 100% of the time.

$(function () {

$('#btnCompare').on('click', function () {
    compare();
});

function compare() {
    $('#divColLeft').empty();
    $('#divColRight').empty();
    var textOne = $('#taOneComp').val();
    var textTwo = $('#taTwoComp').val();

    var output;
    var outputX;

    var arrTextOne = [];
    var arrTextTwo = [];

    for (var i = 0; i < textOne.length; i++) {
        output = textOne.charAt(i);
        arrTextOne.push(output);
    }
    for (var x = 0; x < textTwo.length; x++) {
        outputX = textTwo.charAt(x);
        arrTextTwo.push(outputX);
    }

    $.each(arrTextOne, function (y, e) {
        if ($.inArray(e, arrTextTwo) == -1) {
            $('#divColLeft').append(e);
            $('#divColLeft').highlight(e);
        } else {
            $('#divColLeft').append(arrTextOne[y]);
        }
    });

    $.each(arrTextTwo, function (z, f) {
        if ($.inArray(f, arrTextOne) == -1) {
            $('#divColRight').append(f);
            $('#divColRight').highlight(f);
        } else {
            $('#divColRight').append(arrTextTwo[z]);
        }
    });
}

});

Update: To be more precise and improve the original question

If some includs the char "a" before any of the two texts, this is a difference that should be highlighted. In the first text the "a" should be highlighted, in the second text i want to input an empty space that is highlighting the difference(the missing char).

4
  • 2
    You might want to take a look at code.google.com/p/google-diff-match-patch Commented Mar 29, 2013 at 16:24
  • 1
    You say that the function should: "highlight a missing char from the second". How can you highlight something that's missing? Would you insert a space character in that position and then highlight? Commented Apr 2, 2013 at 17:51
  • I had looked something very similar past few days - and found jsdiff which worked for me real well. An example showing its working is at this link. Commented Apr 2, 2013 at 19:35
  • Floremin, that is a correct anticipation. And something i should have mentioned. Commented Apr 3, 2013 at 19:36

3 Answers 3

7
+50

Your code will work only if the two strings has the exact same length and the same words arrangement, otherwise it will break down i.e. if you add an extra character at the beginning of the tested string.
after some coding i managed to come up with the code below, it compares two strings and find missing charcters/words, extra characters/words and wrong spellings:

function compare() {
    var elm1 = document.getElementById("div1"),
        elm2 = document.getElementById("txt"),
        output = document.getElementById("div2"),
        txt1 = elm1.innerHTML,          //original text
        txt2 = elm2.value,              //submitted text
        arr1 = txt1.split(" "),         //split original text to array of words
        arr2 = [];                      //miss matching words will be added here

//filter txt1 and txt2 from matching words and add miss matching to arr2///////
    for (var i in arr1) {
        var match = txt2.match(new RegExp("\\b" + arr1[i] + "\\b"));
        if (match) {
            txt2 = txt2.replace(new RegExp("\\s?" + arr1[i]), "");
            txt1 = txt1.replace(new RegExp("\\s?" + arr1[i]), "");
        } else if (!match) {
            arr2.push(arr1[i]);
        }
    }
//compare miss matching words from original and submitted text, if matching charachters is more that 50% highlight missing and extra characters
    var arr3 = txt2.split(" "), //convert filtered submitted text to words array
        right = elm1.innerHTML,
        wrong = elm2.value;
    for (var a in arr2) {
        for (var b in arr3) {
            var match2 = arr3[b].match(new RegExp("[" + arr2[a] + "]", "g")),
                t = (arr2[a].length > arr3[b].length) ? arr2[a].length : arr3[b].length;
            if (match2 && match2.length >= t * 0.5) { //check for words that look similar
                txt2 = txt2.replace(new RegExp("\\s?" + arr3[b]), "");
                txt1 = txt1.replace(new RegExp("\\s?" + arr2[a]), "");
                var str1 = "",
                    str2 = "",
                    n = 0;
                for (var c = 0; c < t; c++) {
                    if (arr2[a].charAt(c) === arr3[b].charAt(c + n)) {
                        str1 += arr3[b].charAt(c + n);
                        str2 += arr2[a].charAt(c);
                    } else if (arr2[a].charAt(c) !== arr3[b].charAt(c + n)) {
                        if(arr2[a].charAt(c + 1) == arr3[b].charAt(c + n)){
                            str2 += arr2[a].charAt(c).fontcolor("blue");
                            str1 += "_".fontcolor("red");
                            n--;
                        }else if(arr2[a].charAt(c) == arr3[b].charAt(c + n + 1)){
                            str1 += arr3[b].charAt(c + n).fontcolor("orange");
                            n++;
                            c--;
                        }else{
                            str1 += arr3[b].charAt(c + n).fontcolor("red");
                            str2 += arr2[a].charAt(c).fontcolor("green");
                        }
                    }
                }
                wrong = wrong.replace(arr3[b], str1);
                right = right.replace(arr2[a], str2);
            }
        }
    }
//check for extra words//////////////////////////////////////
    extra = txt2.split(" ");
    for(var d in extra){
        wrong = wrong.replace(extra[d], extra[d].fontcolor("grey"));
    }
//check for missing words//////////////////////////////////////
    missing = txt1.split(" ");
    for(var f in missing){
        right = right.replace(missing[f], missing[f].fontcolor("blue"));
    }
    output.innerHTML = wrong;
    elm1.innerHTML = right;
}

DEMO

How It Works:

  1. Compare original and submitted texts and find matching words and remove them
  2. Compare the remaining words from both strings
  3. If two words look similar (equal characters => 50% of total characters)
  4. check for missing/extra/misspelled characters and highlight them.
  5. Remove the misspelled words from both strings
  6. Highlight the remaining words in the original text as missing words
  7. Highlight the remaining words in the submitted text as extra words
Sign up to request clarification or add additional context in comments.

8 Comments

Great one. But I see one more thing in the question that you should add, check this comment stackoverflow.com/questions/15706827/…
Great i will test this code later today, as @KonradGadzina says. If some includs "a" before any of the two texts, this is a difference that should be highlighted. In the first text the "a" should be highlighted, in the second text i want to input an empty space that is highlighting the difference(the missing char). Also updated my original post.
done, i think it's better to add "_" to indicate the missing character instead but if you want it to be a space i can change it. see my demo
thanks, i tried out the demo and it worked as expected. Will implement it to my own solution later this week :). Thanks
@razzak The function does not match texts that includes commas or dots. Probably more special chars. Is this possible to add somehow? Like if i type a bigger sentence that includes those special chars, the function should be smart enough to handle this aswell? Thanks in advance
|
0

My code Compare first textarea words with second textare words.For Example ..first textarea text is 'How are you' and second textarea text is 'I am fine'.It will compare 'how' with 'I' and 'are' with 'am'.. Please try this code...My fiddle

  $(function () {

            $('#btnCompare').on('click', function () {
                compare();
                return false;
            });

            function compare() {
                $('#divColLeft').empty();
                $('#divColRight').empty();

                var textOne = $.trim($('#taOneComp').val());
                var textTwo = $.trim($('#taTwoComp').val());

                var TempArr1 = textOne.split(' ');
                var TempArr2 = textTwo.split(' ');
                var arr1 = [];
                for (var i = 0; i < TempArr1.length; i++) {
                    if (TempArr1[i] !== "" && TempArr1[i] !== null) {
                        arr1.push(TempArr1[i]);
                    }
                }

                var arr2 = [];
                for (var i = 0; i < TempArr2.length; i++) {
                    if (TempArr2[i] !== "" && TempArr2[i] !== null) {
                        arr2.push(TempArr2[i]);
                    }
                }
                var minArrLen = arr1.length < arr2.length ? arr1.length : arr2.length;

                for (var x = 0; x < minArrLen; x++) {

                    var maxCharLen = arr1[x].length > arr2[x].length ? arr1[x].length : arr2[x].length;
                    for (var y = 0; y < maxCharLen; y++) {
                        if (arr1[x].charAt(y) == ' ') {
                            $('#divColLeft').append('<span  class="missing">' + arr2[x].charAt(y) + '</span>');

                            $('#divColRight').append('<span class="missmatch">' + arr2[x].charAt(y)) + '</span>';
                        }
                        else if (arr2[x].charAt(y) == ' ') {
                            $('#divColLeft').append('<span class="missing">' + arr1[x].charAt(y) + '</span>');

                            $('#divColRight').append('<span class="missmatch">' + arr1[x].charAt(y)) + '</span>';
                        } else if (arr1[x].charAt(y) == arr2[x].charAt(y)) {
                            $('#divColLeft,#divColRight').append(arr1[x].charAt(y));
                        }
                        else {
                            $('#divColLeft').append('<span  class="missmatch">' + arr1[x].charAt(y) + '</span>');
                            $('#divColRight').append('<span  class="missing">' + arr2[x].charAt(y) + '</span>');
                        }
                    }
                    $('#divColLeft').append(' ');
                    $('#divColRight').append(' ');
                }

                if (minArrLen < arr1.length) {
                    for (var Len = minArrLen; Len < arr1.length; Len++) {
                        $('#divColLeft').append(arr1[Len])
                                        .append(' ');
                    }
                } else if (minArrLen < arr2.length) {
                    for (var Len = minArrLen; Len < arr2.length; Len++) {
                        $('#divColRight').append(arr2[Len])
                                        .append(' ');
                    }
                }
            }
        });

5 Comments

your code will break if you add extra word or character at the beginning of the second input. try "this is a test" and "a this is a test".
I wrote coding to compare words...Suppose if we give "this is a test" and "a this is a test"...it will compare this with a..
hmm it's not what the OP wants i guess, it's mentioned that Its mission is to compare two text areas and highlight the differences.
He not mentioned exact comparision rule and just mentioned My function shall return both inputs and highlight the char "a" from the first input, and highlight a missing char from the second.
@razzak is correct, or this is what i am after. If some includs "a" before the two texts, this is a difference that should be highlighted. In the first text the "a" should be highlighted, in the second text i want to input an empty space that is highlighting the difference(the missing char).
-1
$(document).ready(function () {

  $('#btnCompare').on('click', function () {
      compare();
  });

  function compareText(textOne, textTwo)
  {
      var len = Math.min(textOne.length, textTwo.length);
      for (var i=0;i<len; i++)
      {
          if (textOne.charAt(i) == textTwo.charAt(i)) continue;

          return i;      // this character is different
      }

      if (textOne.length == textTwo.length) return -1;    // same

      return i;
  }

  function compare() {
      $('#divColLeft').empty();
      $('#divColRight').empty();
      var textOne = $('#taOneComp').val();
      var textTwo = $('#taTwoComp').val();

      var diffIndex = compareText(textOne, textTwo);
      if (diffIndex == -1)
      {
          // TODO: tell user they are identical
          $('#divColLeft').html('Identical');

      } else {

          // if textTwo has more characters, 
          // add a dummy character for highlighting to textOne

          if (diffIndex >= (textOne.length)) textOne += '_';

          var char = textOne.charAt(diffIndex);

          // highlight differing character

          var tmpLeft = textOne.substring(0, diffIndex);
          tmpLeft += "<span style='background-color:yellow;font-weight:bold'>" + char + "</span>";
          tmpLeft += textOne.substring(diffIndex+1);

          $('#divColLeft').html(tmpLeft);
      }
  }
});

2 Comments

I Will look Into this answear this weekend. Right now on vacation. Thanks in advance
Hmm, it's not a very extensive solution. What if someone added one extra letter? Then everything after this character will fail to match, although it is a minor difference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.