Spell Check

It's important that my web page be able to utilize a Spell Checker of some sort.

I tried creating a web service that uses MS Word's Spell Checking DLL --  but it ALWAYS returns "TRUE".  Even if the word is "ASDFSDF" which is obviously not a valid word.

What other options do I have?  MS Word really is not designed to be run on a web server, anyway, so it probably would have been a poor choice even if I'd gotten it to work right.

Can I programmatically detect which browser I am running in, and then programmatically call and use its spell checking functionality?  All browsers have spell checking built-in, right?

HTML5 can indicate misspelled words -- visually with a red squiggly underline, but it can't tell you which words were mispelled, can it?  Can you navigate the DOM to discover which words have a red-squiggly underline?  Or is that all hidden away?
LVL 5
Tom KnowltonWeb developerAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

skijCommented:
What web server and programming language are you using?

For example, are you using ASP.NET / IIS or Apache / PHP?
Tom KnowltonWeb developerAuthor Commented:
The webserver is IIS.

The languages involved are HTML, JavaScript (the call to ajax uses $.ajax(...) to call the webservice).

The webservice is written in C# / ASP.NET.

I got the MS Word spellcheck working.  The trick was I needed to pass in the words as all lowercase, because all uppercase words are just accepted as ACRONYMS.

But my question remains:  How can I do spellchecking other than using the MS Word DLL on the server side?

Here is my current code:

<!DOCTYPE html>
<html>
<head>
    <title>Word Ninja</title>
    <script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
 
    <script src="include.js"></script>
 
 
    <script type="text/javascript">

        var _globalwordlist;
        var _wordArray;
        var mouse_x;
        var mouse_y;



        $(function () {

            var callcount = 1;
            //CONSTANTS
            var MIN_Y = 60;
            var MAX_Y = 450;
            var STARTING_X_MIN = 700;
            var STARTING_X_MAX = 1500;
            var MIN_STEP = 3;
            var MAX_STEP = 4;

            var canvas = document.getElementById("myCanvas");
            var context = canvas.getContext("2d");

            var i = 0;

            var data = "";

            letArray = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
            'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

            function genRandomLetter() {
                return letArray[genRandomNumber(0, 25)];
            }


            function genRandomNumber(start, end) {
                return Math.floor((Math.random() * end) + start);
            }

            var one = {
                visible: true,
                x: genRandomNumber(STARTING_X_MIN, STARTING_X_MAX),
                origX: genRandomNumber(STARTING_X_MIN, STARTING_X_MAX),
                step: genRandomNumber(MIN_STEP, MAX_STEP),
                y: genRandomNumber(MIN_Y, MAX_Y),
                color: '#3B653D',
                useletter: genRandomLetter(),
                tag: "one"
            };

            var two = {
                visible: true,
                x: 1200,
                origX: genRandomNumber(STARTING_X_MIN, STARTING_X_MAX),
                step: genRandomNumber(MIN_STEP, MAX_STEP),
                y: genRandomNumber(MIN_Y, MAX_Y),
                color: '#3B653D',
                useletter: genRandomLetter(),
                tag: "two"
            };

            var three = {
                visible: true,
                x: genRandomNumber(STARTING_X_MIN, STARTING_X_MAX),
                origX: genRandomNumber(STARTING_X_MIN, STARTING_X_MAX),
                step: genRandomNumber(MIN_STEP, MAX_STEP),
                y: genRandomNumber(MIN_Y, MAX_Y),
                color: '#3B653D',
                useletter: genRandomLetter(),
                tag: "three"
            };

            var four = {
                visible: true,
                x: genRandomNumber(STARTING_X_MIN, STARTING_X_MAX),
                origX: genRandomNumber(STARTING_X_MIN, STARTING_X_MAX),
                step: genRandomNumber(MIN_STEP, MAX_STEP),
                y: genRandomNumber(MIN_Y, MAX_Y),
                color: '#3B653D',
                useletter: genRandomLetter(),
                tag: "four"
            };

            _myCircleArray = [one, two, three, four];

            window.requestAnimFrame = (function (callback) {
                return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 1000 / 60);
        };
            })();

            function randomizeCircle(tempCircle) {
                tempCircle.x = genRandomNumber(STARTING_X_MIN, STARTING_X_MAX);
                tempCircle.origX = genRandomNumber(STARTING_X_MIN, STARTING_X_MAX);
                tempCircle.step = genRandomNumber(MIN_STEP, MAX_STEP);
                tempCircle.y = genRandomNumber(MIN_Y, MAX_Y);
                tempCircle.useletter = genRandomLetter();
                return tempCircle;
            }

            function drawTextBubble(myCircle, context, cx, cy) {

                //the circle
                //  context.beginPath();
                context.arc(myCircle.x, myCircle.y, 50, 0, Math.PI * 2, false);

                if (context.isPointInPath(cx, cy)) {

                    $('#status').append("xy0 (" + myCircle.x + ", " + myCircle.y + ")<br/>");
                    $('#status').append("xy0 ===POINT IN PATH=== <br/><br/>");


                    $('#status').append(myCircle.tag + "<br/><br/>");


                    context.fillStyle = '#3B653D';
                    context.fill();
                    context.strokeStyle = '#3B653D';
                    context.stroke();

                    //the letter inside the circle
                    context.beginPath();
                    context.fillStyle = '#3B653D';
                    context.fill();
                    context.font = "40px Grunge Handwriting";
                    context.fillText(myCircle.useletter, myCircle.x - 10, myCircle.y + 10);
                    context.strokeStyle = '#3B653D';
                    context.stroke();

                    $('#fxplayer')[0].play();
                    $('#word').val($('#word').val() + myCircle.useletter);
                    myCircle = randomizeCircle(myCircle);
                }
                else {

                    //   $('#status').append("xy0 (" + myCircle.x + ", " + myCircle.y + ")<br/>");
                    //  $('#status').append("xy0 ==NOT==== <br/><br/>");

                    context.fillStyle = '#3B653D';
                    context.fill();
                    context.strokeStyle = '#FFF';
                    context.stroke();

                    //the letter inside the circle
                    context.beginPath();
                    context.fillStyle = '#FFF';
                    context.fill();
                    context.font = "40px Grunge Handwriting";
                    context.fillText(myCircle.useletter, myCircle.x - 10, myCircle.y + 10);
                    context.strokeStyle = '#000';
                    context.stroke();


                }
            }

            function animate(canvas, context, startTime) {
                var time = (new Date()).getTime() - startTime;

                var myCircle;

                context.clearRect(0, 0, canvas.width, canvas.height); // only clear once

                for (var a = 0; a < _myCircleArray.length; a++) {
                    myCircle = _myCircleArray[a];
                    if (myCircle.visible) {
                        myCircle.x = myCircle.x - myCircle.step;

                        if (myCircle.x < -50) {
                            myCircle = randomizeCircle(myCircle);
                        }

                        drawTextBubble(myCircle, context, mouse_x, mouse_y);
                    }
                }

                mouse_x = 0;
                mouse_y = 0;

                requestAnimFrame(function () {
                    animate(canvas, context, startTime);
                });
            }

            // wait one second before starting animation
            setTimeout(function () {
                var startTime = (new Date()).getTime();

                canvas.onmousedown = function (e) {
                    e.preventDefault(e); // Optional
                    mouseDownOrTouchStart(windowToCanvas(e.clientX, e.clientY));
                };

                canvas.ontouchstart = function (e) {
                    e.preventDefault(e); // Optional
                    mouseDownOrTouchStart(windowToCanvas(e.touches[0].pageX, e.touches[0].pageY));

                    for (var i = 0; i < e.touches.length; ++i) {
                        //  console.log('Touch at: ' + e.touches[i].pageX + ', ' + e.touches[i].pageY);
                        $('#status').append('Touch at: ' + e.touches[i].pageX + ', ' + e.touches[i].pageY);
                    }
                };

                $('#addword').on("click", listhandler);
                $('#togglebg').on("click", bgmusichandler);
                $('#clearstatuslog').on("click", clearstatusloghandler);
                animate(canvas, context, startTime);
            }, 1000);

            function doSpellCheck(word) {
                var wordtocheck = word;                
                $.ajax({
                    type: "POST",
                    url: "http://localhost:21971/game/SpellCheck.asmx/SpellCheck",
                    //" + word,
                    data: "strCheck=" + wordtocheck, // the data in form-encoded format, ie as it would appear on a querystring
                    //contentType: "application/x-www-form-urlencoded; charset=UTF-8", // if you are using form encoding, this is default so you don't need to supply it
                    dataType: "text", // the data type we want back, so text.  The data will come wrapped in xml
                    success: function (data) {

                        console.log(data);
                        console.log("word checked was:  " + wordtocheck);
                        var loc = data.indexOf("SPTRUE");
                        if (loc >= 0) {
                            $('#wordlist').append(wordtocheck + '<br/>');
                        }
                        else {
                            $('#wordlist').append(wordtocheck + ' INVALID<br/>' );
                        }
                    }
                });
            }          


            function clearstatusloghandler() {
                $('#status').html("");
            }


            function listhandler() {
                var send = $('#word').val();
                //$('#word').html("");
                doSpellCheck(send);

            }


            ///////////////// SOUND //////////////////////
            function bgmusichandler() {

                var running = $('#bgplayer')[0].paused;

                if (!running) {
                    $('#bgplayer')[0].pause();
                }
                else {
                    $('#bgplayer')[0].play();
                }
            }





            function windowToCanvas(x, y) {
                var bbox = canvas.getBoundingClientRect();

                var tempx = x - bbox.left * (canvas.width / bbox.width);
                var tempy = y - bbox.top * (canvas.height / bbox.height);

                return { x: tempx,
                    y: tempy
                };
            }

            function mouseDownOrTouchStart(e) {

                $('#status').append('mouse down or touchstart<br/>');
                $('#status').append("mouse coord (" + e.x + ", " + e.y + ")<br/>");

                mouse_x = e.x;
                mouse_y = e.y;
            };
        });
        
    </script>
 
    <style type="text/css">
        #myCanvas
        {
            background-color: rgb(59, 101, 61);
        }
    </style>
 
</head>
<body>
    <audio id="bgplayer" autoplay style="display: none;">      
<source src="bg.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
    <audio id="fxplayer" autoplay style="display: none;">      
<source src="fx2.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
    <canvas id="myCanvas" width="750" height="600">no canvas support</canvas>
    <br />
    <input style="width: 700px;" id="word">  <span id='message1' style='color:red'>* Spelling</span>
      
      <br />
    
    <br />
    <input type="button" id="addword" name="addw" value="add word" /><br />
    <input type="button" id="togglebg" name="toggle bg music" value="toggle background music" /><br />    
    <input type="button" id="clearstatuslog" name="clearsl" value="clear status log" /><br /><br />
 
    <p style="position:absolute; left:800px; top:20px; border: 1px solid black; height: auto; width: 400px;" id="status">
    </p>
    
 
    <p style="border: 1px solid black; background-color:Gray; color:White; height: 500px; width: 200px;" id="wordlist">
    </p>
</body>
</html>
 

Open in new window

skijCommented:
What result is returned by the webservice for both correctly and incorrectly spelled words?
http://localhost:21971/game/SpellCheck.asmx/SpellCheck
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

skijCommented:
If you wish to use IIS for this you may consider using the MSDN Library's SpellCheck Class for this:
https://msdn.microsoft.com/en-us/library/system.windows.controls.spellcheck(v=vs.110).aspx

A free third-party alternative is Anthony Terra's ASP.MVC-Jquery-Spellchecker:
https://github.com/AnthonyTerra/ASP.MVC-Jquery-Spellchecker

However, this can be done without any server-side assistance using only client-side JavaScript.  
Here is an example: (the code is attached)
https://jsfiddle.net/d964n0or/
spellcheck.zip
Tom KnowltonWeb developerAuthor Commented:
However, this can be done without any server-side assistance using only client-side JavaScript.  
Here is an example: (the code is attached)
https://jsfiddle.net/d964n0or/

What is the licensing for this BJSpell javascript file and where can I find the file on the web?
skijCommented:
Information about bjspell can be found here:
http://code.google.com/p/bjspell/

It is released under the LGPL licence.  

The source code can be downloaded here:
http://code.google.com/p/bjspell/downloads/list

Here is the official demonstration page, including spelling suggestions when you hover over a misspelled word::
http://www.3site.eu/examples/BJSpell/

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Tom KnowltonWeb developerAuthor Commented:
skij:

You did an excellent job answering this question.  Thank you!

I don't **quite** understand how to just make a call to the BJSpell spellchecker based upon a button click.

So, I want to:

1)  Click on a button
2)  Call the BJSpell check on a word
3)  Determine if the word was spelled correctly (a true / false boolean result)

Could you help me with that?

The points are yours, regardless.

Tom
skijCommented:
Thanks for the question and the points.  I recommend that you post a clearly defined question as a new question and then once it has been posted, place a link here for reference.  That will provide your question greater exposure to more experts.
Tom KnowltonWeb developerAuthor Commented:
I'll do that...thanks!
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Word

From novice to tech pro — start learning today.