HTML checker form

Hi guys

I’m looking to adapt a code (see below) that I found on the web. The script basically validates whether html tags have been closed within the code that has been inputted in the a textarea. It works brilliantly but for the one thing I need it to do.

Run the script and then add your HTML code to the textarea. Click on the “Submit” button and the script will display a message telling you whether there are any unclosed tags.

However, what I need is the form to actually submit the data IF there are no tags found OR all tags have a closing tags. If there are found that do not have a closing then not only should the error message appear but the form should not submit the data.

Is this possible? If so how is it done? Any help would be fully appreciated

Best regards

Rod from the UK

<form method="post" action="">
<textarea id="unclosed-tag-finder-input" style="width:100%;height:300px">
</textarea>
<div><input type="button" id="unclosed-tag-finder-button" value="Submit" ></input></div>
<br />
<h3>Results</h3>
<pre id="unclosed-tag-finder-results">
</pre>
</form>



<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

<script type="text/javascript">
//<![CDATA[
function isSelfClosingTag(tagName) {
    return tagName.match(/area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr|script/i);
}

$('#unclosed-tag-finder-button').click(function () {
    var input = $('#unclosed-tag-finder-input').val();
    var tags = [];
    $.each(input.split('\n'), function (i, line) {
        $.each(line.match(/<[^>]*[^/]>/g) || [], function (j, tag) {
            var matches = tag.match(/<\/?([a-z0-9]+)/i);
            if (matches) {
                tags.push({tag: tag, name: matches[1], line: i+1, closing: tag[1] == '/'});
            }
        });
    });
    if (tags.length == 0) {
        $('#unclosed-tag-finder-results').text('No tags found.');
        return;
    }
    var openTags = [];
    var error = false;
    var indent = 0;
    for (var i = 0; i < tags.length; i++) {
        var tag = tags[i];
        if (tag.closing) {
            var closingTag = tag;
            if (isSelfClosingTag(closingTag.name)) {
                continue;
            }
            if (openTags.length == 0) {
                $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not have corresponding open tag.');
                return;
            }
            var openTag = openTags[openTags.length - 1];
            if (closingTag.name != openTag.name) {
                $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not match open tag ' + openTag.tag + ' on line ' + openTag.line + '.');
                return;
            } else {
                openTags.pop();
            }
        } else {
            var openTag = tag;
            if (isSelfClosingTag(openTag.name)) {
                continue;
            }
            openTags.push(openTag);
        }
    }
    if (openTags.length > 0) {
        var openTag = openTags[openTags.length - 1];
        $('#unclosed-tag-finder-results').text('Open tag ' + openTag.tag + ' on line ' + openTag.line + ' does not have a corresponding closing tag.');
        return;
    }
    $('#unclosed-tag-finder-results').text('Success: No unclosed tags found.');
});
//]]>
</script>

Ok, to submit you’ll need an action attribute on the form with the path where you want to submit the form to.

Change

<input type="button" id="unclosed-tag-finder-button" value="Submit" ></input>

to

<input type="submit" />

Change

$('#unclosed-tag-finder-button').click(function () {

to

$('form').submit(function (event) {

then you should be able to use event.preventDefault() if you want to prevent the form from submitting, if you don’t do that it will submit the path in the forms action attribute.

Hi Mark

Thank you so much for your help - it’s really appreciated.

Unfortunately, I’m still having problems. My updated code can be seen below. However, when I run it the form just submits each time I click on the submit button no matter what text I place in the textarea. You mentioned using event.preventDefault() but I have no idea what this is or how to use it.

I’m not great at scripting I’m afraid. Any help you can provide would be great.

I look forward to hearing from you

regards

Rod from the UK

<form method="post" action="secondpage.asp">
<textarea id="unclosed-tag-finder-input" style="width:100%;height:300px" rows="1" cols="20">
</textarea>
<div><input type="submit" /></div>
<br />
<h3>Results</h3>
<pre id="unclosed-tag-finder-results">
</pre>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

<script type="text/javascript">
//<![CDATA[
function isSelfClosingTag(tagName) {
    return tagName.match(/area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr|script/i);
}

$('form').submit(function (event) {
    var input = $('#unclosed-tag-finder-input').val();
    var tags = [];
    $.each(input.split('\n'), function (i, line) {
        $.each(line.match(/<[^>]*[^/]>/g) || [], function (j, tag) {
            var matches = tag.match(/<\/?([a-z0-9]+)/i);
            if (matches) {
                tags.push({tag: tag, name: matches[1], line: i+1, closing: tag[1] == '/'});
            }
        });
    });
    if (tags.length == 0) {
        $('#unclosed-tag-finder-results').text('No tags found.');
        return;
    }
    var openTags = [];
    var error = false;
    var indent = 0;
    for (var i = 0; i < tags.length; i++) {
        var tag = tags[i];
        if (tag.closing) {
            var closingTag = tag;
            if (isSelfClosingTag(closingTag.name)) {
                continue;
            }
            if (openTags.length == 0) {
                $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not have corresponding open tag.');
                return;
            }
            var openTag = openTags[openTags.length - 1];
            if (closingTag.name != openTag.name) {
                $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not match open tag ' + openTag.tag + ' on line ' + openTag.line + '.');
                return;
            } else {
                openTags.pop();
            }
        } else {
            var openTag = tag;
            if (isSelfClosingTag(openTag.name)) {
                continue;
            }
            openTags.push(openTag);
        }
    }
    if (openTags.length > 0) {
        var openTag = openTags[openTags.length - 1];
        $('#unclosed-tag-finder-results').text('Open tag ' + openTag.tag + ' on line ' + openTag.line + ' does not have a corresponding closing tag.');
        return;
    }
    $('#unclosed-tag-finder-results').text('Success: No unclosed tags found.');
});
//]]>
</script>

If the check fails you have to return false from the submit-handler (rather than just return). This prevents the form from getting submitted.

1 Like

Yes, return false or event.preventDefault() do the same thing in a jquery event handler.

e.g. If you want to prevent the submit in this condition:

if (tags.length == 0) {
  $('#unclosed-tag-finder-results').text('No tags found.');
  event.preventDefault();
}

I prefer event.preventDefault() as it’s the proper standard method to use. return false; is a jQuery thing only.

2 Likes

[quote=“markbrown4, post:5, topic:222203, full:true”]I prefer event.preventDefault() as it’s the proper standard method to use. return false; is a jQuery thing only.
[/quote]

You’ll find that return false is a thing outside of jQuery too.

The trouble with return false is that it not only prevents the default action fro occurring, it also prevents the event from bubbling up to parent elements, where you might want to also catch the event as well.

Because return false can result in some hard to troubleshoot bugs, and event.preventDefault() achieves the desired result without any other problems, one if these is preferable to use than the other.

2 Likes

Not in event listeners.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <form action="test.html">
      <input type="submit">
    </form>
    <script type="text/javascript">
      var form = document.querySelector('form');
      form.addEventListener('submit', function(event) {
        return false;
      })
    </script>
  </body>
</html>

The trouble with return false is that it not only prevents the default action fro occurring, it also prevents the event from bubbling up to parent elements, where you might want to also catch the event as well.

Yep, that’s why I prefer to event.preventDefault(); and event.stopPropagation();

1 Like

Hi guys

Thanks for your posts. However, I am more confused as before. My script now looks like this (see below) but it is still submitting the data no matter what is entered into the textarea. Ideally, the form would only submit if the tags are closed.

Like I say, I have no clue how to adapt this script as I have next to zero knowledge of javascript or jQuery.

It goes without saying, any help would be fully appreciated

Regards

Rod from the UK

> <form method="post" action="secondpage.asp">
> <textarea id="unclosed-tag-finder-input" style="width:100%;height:300px" rows="1" cols="20">
> </textarea>
> <div><input type="submit" /></div>
> <br />
> <h3>Results</h3>
> <pre id="unclosed-tag-finder-results">
> </pre>
> </form>

>     <script type="text/javascript">
>       var form = document.querySelector('form');
>       form.addEventListener('submit', function(event) {
>         return false;
>       })
>     </script>

> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

> <script type="text/javascript">
> //<![CDATA[
> function isSelfClosingTag(tagName) {
>     return tagName.match(/area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr|script/i);
> }

> $('form').submit(function (event) {
>     var input = $('#unclosed-tag-finder-input').val();
>     var tags = [];
>     $.each(input.split('\n'), function (i, line) {
>         $.each(line.match(/<[^>]*[^/]>/g) || [], function (j, tag) {
>             var matches = tag.match(/<\/?([a-z0-9]+)/i);
>             if (matches) {
>                 tags.push({tag: tag, name: matches[1], line: i+1, closing: tag[1] == '/'});
>             }
>         });
>     });
>     if (tags.length == 0) {
>         $('#unclosed-tag-finder-results').text('No tags found.');
>         return;
>     }
>     var openTags = [];
>     var error = false;
>     var indent = 0;
>     for (var i = 0; i < tags.length; i++) {
>         var tag = tags[i];
>         if (tag.closing) {
>             var closingTag = tag;
>             if (isSelfClosingTag(closingTag.name)) {
>                 continue;
>             }
>             if (openTags.length == 0) {
>                 $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not have corresponding open tag.');
>                 return;
>             }
>             var openTag = openTags[openTags.length - 1];
>             if (closingTag.name != openTag.name) {
>                 $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not match open tag ' + openTag.tag + ' on line ' + openTag.line + '.');
>                 return;
>             } else {
>                 openTags.pop();
>             }
>         } else {
>             var openTag = tag;
>             if (isSelfClosingTag(openTag.name)) {
>                 continue;
>             }
>             openTags.push(openTag);
>         }
>     }
>     if (openTags.length > 0) {
>         var openTag = openTags[openTags.length - 1];
>         $('#unclosed-tag-finder-results').text('Open tag ' + openTag.tag + ' on line ' + openTag.line + ' does not have a corresponding closing tag.');
>         return;
>     }
>     $('#unclosed-tag-finder-results').text('Success: No unclosed tags found.');
> });
> //]]>
> </script>

I was responding to Paul in post #7, Post #5 included what you needed.
Whenever you want to prevent the submit from occurring you need to run event.preventDefault();

<form method="post" action="secondpage.asp">
  <textarea id="unclosed-tag-finder-input" style="width:100%;height:300px" rows="1" cols="20">
  </textarea>
  <div><input type="submit" /></div>
  <br />
  <h3>Results</h3>
  <pre id="unclosed-tag-finder-results">
  </pre>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">

function isSelfClosingTag(tagName) {
  return tagName.match(/area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr|script/i);
}
$('form').submit(function (event) {
  var input = $('#unclosed-tag-finder-input').val();
  var tags = [];
  $.each(input.split('\n'), function (i, line) {
    $.each(line.match(/<[^>]*[^/]>/g) || [], function (j, tag) {
      var matches = tag.match(/<\/?([a-z0-9]+)/i);
      if (matches) {
        tags.push({tag: tag, name: matches[1], line: i+1, closing: tag[1] == '/'});
      }
    });
  });
  if (tags.length == 0) {
    $('#unclosed-tag-finder-results').text('No tags found.');
    event.preventDefault();
    return;
  }
  var openTags = [];
  var error = false;
  var indent = 0;
  for (var i = 0; i < tags.length; i++) {
    var tag = tags[i];
    if (tag.closing) {
      var closingTag = tag;
      if (isSelfClosingTag(closingTag.name)) {
        continue;
      }
      if (openTags.length == 0) {
        $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not have corresponding open tag.');
        event.preventDefault();
        return;
      }
      var openTag = openTags[openTags.length - 1];
      if (closingTag.name != openTag.name) {
        $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not match open tag ' + openTag.tag + ' on line ' + openTag.line + '.');
        event.preventDefault();
        return;
      } else {
        openTags.pop();
      }
    } else {
      var openTag = tag;
      if (isSelfClosingTag(openTag.name)) {
        continue;
      }
      openTags.push(openTag);
    }
  }
  if (openTags.length > 0) {
    var openTag = openTags[openTags.length - 1];
    $('#unclosed-tag-finder-results').text('Open tag ' + openTag.tag + ' on line ' + openTag.line + ' does not have a corresponding closing tag.');
    event.preventDefault();
    return;
  }
  $('#unclosed-tag-finder-results').text('Success: No unclosed tags found.');
});
</script>

Hi Mark

Thanks enormously for this - it does exactly what I need it to which is great. However, my master plan seems to have failed in that the script does not work with another script I have on my page.

I’m currently using a tool called Nicedit (see script below which I have at the top of my page) which allows users to enter html tags directly into the textarea or format their text. However, when I use this in conjunction with your script it’s just won’t work correctly.

I fear that there’s no way around this. Is it at all possible to get this working?

Any help would be fully appreciated

Best regards

Rod from the UK

<script type="text/javascript" src="http://js.nicedit.com/nicEdit-latest.js"></script> <script type="text/javascript">

//<![CDATA[

  bkLib.onDomLoaded(function() {

        new nicEditor({buttonList : ['bold','italic','underline','left','center','right','justify','ol','ul','indent','outdent','hr','forecolor','fontSize','fontFamily','fontformat','xhtml']}).panelInstance('eventdescription');

        new nicEditor({maxHeight : 100}).panelInstance('eventdescription');

  });

  //]]>

  </script>

if you do it with php it shouldn’t affect your JS. I’d submit the form and run this http://milianw.de/code-snippets/close-html-tags to clean the html then perhaps do a quick count of the < >'s to be sure and submit or throw the submission back to the form.

I just did a quick test with the function and it easily caught

<strong>this is some text with no end

and added on the missing </strong>

hth

Hi Nth

Thanks so much for your post. Unfortunately, my page are in classic asp

Any ideas?

Regards

Rod from the UK

No problem. We’d need to see a link to the full page to help diagnose, it’s not clear why those scripts would clash. What do you mean by “it just won’t work correctly”?

H Mark

Thanks for you reply.

I have pasted the entire code below. Basically if I enter “asd” into the text area and hit the submit query" button the results state “No tags found” when I would expect it to say that there is a missing tag on line 1.

If I then add the closing tag to my text and click on the “Submit query” button nothing happens. The message still says “No tags found”.

If I then clear the text altogether and then enter “asd” alone nothing happens. Again, I get the “No tags found” message. In this instance I would have expected to proceed to the “secondpage.asp” page.

I look forward to hearing from you.

Regards

Rod from the UK

<script type="text/javascript" src="http://js.nicedit.com/nicEdit-latest.js"></script> <script type="text/javascript">

//<![CDATA[

  bkLib.onDomLoaded(function() {

        new nicEditor({buttonList : ['bold','italic','underline','left','center','right','justify','ol','ul','indent','outdent','hr','forecolor','fontSize','fontFamily','fontformat','xhtml']}).panelInstance('eventdescription');

        new nicEditor({maxHeight : 100}).panelInstance('eventdescription');

  });

  //]]>

  </script>


<form method="post" action="secondpage.asp">
  <textarea id="eventdescription" style="width:100%;height:300px" rows="1" cols="20">
  </textarea>
  <div><input type="submit" /></div>
  <br />
  <h3>Results</h3>
  <pre id="unclosed-tag-finder-results">
  </pre>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">

function isSelfClosingTag(tagName) {
  return tagName.match(/area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr|script/i);
}
$('form').submit(function (event) {
  var input = $('#eventdescription').val();
  var tags = [];
  $.each(input.split('\n'), function (i, line) {
    $.each(line.match(/<[^>]*[^/]>/g) || [], function (j, tag) {
      var matches = tag.match(/<\/?([a-z0-9]+)/i);
      if (matches) {
        tags.push({tag: tag, name: matches[1], line: i+1, closing: tag[1] == '/'});
      }
    });
  });
  if (tags.length == 0) {
    $('#unclosed-tag-finder-results').text('No tags found.');
    event.preventDefault();
    return;
  }
  var openTags = [];
  var error = false;
  var indent = 0;
  for (var i = 0; i < tags.length; i++) {
    var tag = tags[i];
    if (tag.closing) {
      var closingTag = tag;
      if (isSelfClosingTag(closingTag.name)) {
        continue;
      }
      if (openTags.length == 0) {
        $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not have corresponding open tag.');
        event.preventDefault();
        return;
      }
      var openTag = openTags[openTags.length - 1];
      if (closingTag.name != openTag.name) {
        $('#unclosed-tag-finder-results').text('Closing tag ' + closingTag.tag + ' on line ' + closingTag.line + ' does not match open tag ' + openTag.tag + ' on line ' + openTag.line + '.');
        event.preventDefault();
        return;
      } else {
        openTags.pop();
      }
    } else {
      var openTag = tag;
      if (isSelfClosingTag(openTag.name)) {
        continue;
      }
      openTags.push(openTag);
    }
  }
  if (openTags.length > 0) {
    var openTag = openTags[openTags.length - 1];
    $('#unclosed-tag-finder-results').text('Open tag ' + openTag.tag + ' on line ' + openTag.line + ' does not have a corresponding closing tag.');
    event.preventDefault();
    return;
  }
  $('#unclosed-tag-finder-results').text('Success: No unclosed tags found.');
});
</script>

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.