Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm particularly concerned about where I have declared the functions, can I move them around to clean up the code without breaking anything? The "conjugate" function contains a lot of stuff that has nothing to do with actually conjugating verbs and rather handles output strings and html DOM objects. I really want to minimalize/optimize that function so it only does the essential and have the other DOM stuff handled by a more appropriate function but I'm scared to break anything lol

Also my use of multiple global variables, is there a better way to do that?

Sorry for the incredibly noobish question but I have kinda rushed through this to get my ideas down as quick as possible and it's suddenly become a bit overwhelming :/

Thanks in advance for any help!

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="./jquery.js"></script>
        <style>
            .answer {

                list-style-type: none;
                cursor: pointer;
                font-family: fontin;
            }
            #base, .answer {
                padding:10px 15px;
                background-color: #B7BECC;
                overflow: auto;
                margin: 20px 1px;
                border: 1px solid;
                font-size: 18.7pt;
                text-align: center;
                display:inline;
            }
            #base {
                border-radius: 10px;
            }
            .answers{
             margin-top:30px;
            }
            #container{
            margin: 21px auto;
            position: relative;
            width: 100%;
            max-width: 1000px;
            text-align: center;
            min-width: 600px;
            }

        </style>
        <script>
            $(function () {
                var video = $("#video").get(0);
                var baseverbs = ["작다", "놀다", "닦다"];
                var questionnum = 0;
                var correct = "";
                //set mouseover colors
                $(".answer").each(function () {
                    $(this).mouseover(function () {
                        var bg = $(this).css("background-color");
                        if (bg == "rgb(183, 190, 204)" || bg == "#b7becc") {
                            $(this).css("background-color", "#E5E8EE")
                        }
                    }).mouseout(function () {
                        var bg = $(this).css("background-color");
                        if (bg == "rgb(229, 232, 238)" || bg == "#e5e8ee") {
                            $(this).css("background-color", "#B7BECC")
                        }
                    })
                });

                function seperate(x) {
                    x = x.charCodeAt();
                    var y = {};
                    var z = {};
                    y["tail"] = (x - 44032) % 28;
                    y["vowel"] = 1 + ((x - 44032 - y["tail"]) % 588 / 28);
                    y["lead"] = 1 + (parseInt((x - 44032) / 588));
                    z["vowel"] = vowels[y["vowel"]];
                    z["tail"] = tails[y["tail"]];
                    z["lead"] = leads[y["lead"]];
                    return z;
                }
                var vowels = "0ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ".split("");
                var leads = "0ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ".split("");
                var tails = "0ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈ".split("");

                function buildhangeul(x) {
                    var tail = tails.indexOf(x["tail"]);
                    var vowel = vowels.indexOf(x["vowel"]);
                    var lead = leads.indexOf(x["lead"]);
                    var codepoint = tail + (vowel - 1) * 28 + (lead - 1) * 588 + 44032;
                    return String.fromCharCode(codepoint);
                }

                function pausehere(time) {
                    video.addEventListener('timeupdate', function (e) {
                        if (this.currentTime >= time && this.currentTime < (time + 0.3)) {
                            this.pause()
                        }
                    }, true);
                };

                function conjugate(baseverbs) {
                    var baseverb = baseverbs[questionnum];
                    $("#base").text(baseverb);
                    $(".answer").css("background-color", "#B7BECC");
                    var output = {};
                    output.incorrect = [];
                    var tstr = baseverb;
                    var each = tstr.split("");
                    if (each[each.length - 1] == "다") {
                        var stemlast = each[each.length - 2];
                        var lastjamo = seperate(stemlast);
                        //ㅂ irregular
                        if (lastjamo["tail"] == "ㅂ") {
                            lastjamo["tail"] = "0";
                            stemlast = buildhangeul(lastjamo);
                            output.correct = each.slice(0, -2).join("") + stemlast + "워";
                            output.incorrect[0] = each.slice(0, -1).join("") + buildhangeul({
                                "lead": "ㅇ",
                                "vowel": lastjamo["vowel"],
                                "tail": "0"
                            });
                            output.incorrect[1] = each.slice(0, -1).join("") + "워";
                            output.incorrect[2] = each.slice(0, -2).join("") + stemlast + "와";
                        } //ㅏ and ㅗ regular
                        else if (lastjamo["vowel"] == "ㅏ" && lastjamo["tail"] != "0" || lastjamo["vowel"] == "ㅗ" && lastjamo["tail"] != "0") {
                            output.correct = stemlast + "아";
                            output.incorrect[0] = buildhangeul({
                                "lead": lastjamo["lead"],
                                "vowel": lastjamo["vowel"],
                                "tail": "0"
                            }) + buildhangeul({
                                "lead": lastjamo["tail"],
                                "vowel": lastjamo["vowel"],
                                "tail": "0"
                            });
                            output.incorrect[1] = stemlast + "ㅏ";
                            output.incorrect[2] = stemlast;
                        }
                        //ㅓ, ㅜ, and ㅣ regular
                        else if (lastjamo["vowel"] == "ㅓ" && lastjamo["tail"] != "0" || lastjamo["vowel"] == "ㅜ" && lastjamo["tail"] != "0" || lastjamo["vowel"] == "ㅣ" && lastjamo["tail"] != "0") {
                            output.correct = stemlast + "어";
                        }
                        //ㅏ and ㅓ reductive
                        else if (lastjamo["vowel"] == "ㅏ" && lastjamo["tail"] == "0" || lastjamo["vowel"] == "ㅓ" && lastjamo["tail"] == "0") {
                            output.correct = stemlast;
                            output.incorrect[0] = stemlast + buildhangeul({
                                "lead": "ㅇ",
                                "vowel": lastjamo["vowel"],
                                "tail": "0"
                            });
                            output.incorrect[1] = buildhangeul({
                                "lead": lastjamo["lead"],
                                "vowel": "ㅐ",
                                "tail": "0"
                            });
                            output.incorrect[2] = baseverb;
                        }
                        //ㅗ and ㅜ reductive
                        else if (lastjamo["vowel"] == "ㅗ" && lastjamo["tail"] == "0") {
                            lastjamo["vowel"] = "ㅘ";
                            output.correct = buildhangeul(lastjamo);
                            output.incorrect[0] = stemlast + "와";
                            output.incorrect[1] = stemlast + "아";
                            output.incorrect[2] = buildhangeul({
                                "lead": lastjamo["lead"],
                                "vowel": "ㅝ",
                                "tail": "0"
                            });
                        } else if (lastjamo["vowel"] == "ㅜ" && lastjamo["tail"] == "0") {
                            lastjamo["vowel"] = "ㅝ";
                            output.correct = buildhangeul(lastjamo);
                            output.incorrect[0] = stemlast + buildhangeul({
                                "lead": "ㅇ",
                                "vowel": "ㅝ",
                                "tail": "0"
                            });
                            output.incorrect[1] = buildhangeul({
                                "lead": lastjamo["lead"],
                                "vowel": "ㅜ",
                                "tail": "0"
                            }) + buildhangeul({
                                "lead": "ㅇ",
                                "vowel": "ㅓ",
                                "tail": "0"
                            });
                            output.incorrect[2] = buildhangeul({
                                "lead": lastjamo["lead"],
                                "vowel": "ㅘ",
                                "tail": "0"
                            });
                        }
                        //ㅣreductive
                        else if (lastjamo["vowel"] == "ㅣ" && lastjamo["tail"] == "0") {
                            lastjamo["vowel"] = "ㅕ";
                            output.correct = each.slice(0, -2).join("") + buildhangeul(lastjamo);
                        }
                        //르 irregular
                        else if (stemlast == "르") {
                            var secondlastjamo = seperate(each[each.length - 3]);
                            secondlastjamo["tail"] = "ㄹ";
                            if (secondlastjamo["vowel"] == "ㅗ") {
                                stemlast = "라"
                            } else if (secondlastjamo["vowel"] == "ㅜ") {
                                stemlast = "러"
                            };
                            var secondlast = buildhangeul(secondlastjamo);
                            output.correct = each.slice(0, -3).join("") + secondlast + stemlast;
                        };
                    } else {
                        alert("Only Korean verbs in dictionary form please ;)")
                    }
                    $("#wrong0").text(output.incorrect[0]);
                    $("#wrong1").text(output.incorrect[1]);
                    $("#wrong2").text(output.incorrect[2]);
                    $("#correct").text(output.correct);
                    correct = output.correct;

                    random($(".answers"));
                    $(".answer").css("border-radius", "0px");
                    $('.answer').first().css('border-radius', '10px 0px 0px 10px');
                    $('.answer').last().css('border-radius', '0px 10px 10px 0px');
                }

                $('.answer').click(function () {
                    if (video.currentTime <= 160){$("#warning").text("Not yet!").fadeIn(300).delay(1400).fadeOut(300);return}
                    if ($(this).text() === correct) { //if correct
                        //skip to congratulations
                        $(this).css("background-color", "#62F05F");

                        questionnum++;
                        if (questionnum === 1) {
                            video.currentTime = 164.2;
                            video.play();
                            pausehere(166.8);
                        }else if(questionnum === 2){
                            video.currentTime = 167.1;
                            video.play();
                            pausehere(170);
                        }else if(questionnum === 3){
                            video.currentTime = 171.7;
                            video.play();
                        }


                        //if incorrect
                    } else {
                        //skip to try again msg
                        $(this).css("background-color", "red");
                        video.currentTime = 160.5;
                        video.play();
                        pausehere(164);
                    }
                    alert(questionnum);
                    if (questionnum >= 3){return;};
                    setTimeout(conjugate(baseverbs), 300);
                });

                $("#reset").click(function () {
                    video.currentTime = 0;
                    videostart()
                });

                function videostart() {
                    video.play();
                    //pause after tutorial
                    pausehere(159);
                }

                var random = function (r) {
                    r.children().sort(function (a, b) {
                        return Math.floor(Math.random() * 3) - 1;
                    }).appendTo(r);
                };

                videostart();
                conjugate(baseverbs);
            })
        </script>
    </head>
    <body>
    <div id="container">
        <div id="videowrapper">
            <video id="video" no-controls>
                <source src="conjugation tut.mp4" type="video/mp4">
                    <source src="play.ogg" type='video/ogg'>
                        <source src="play.webm" type="video/webm">Your browser does not support the video tag.</video>
            <br />
            <button id="reset">Replay</button>
        </div>
        <br />
        <div id="base"></div>
        <ul class="answers">
            <li class="answer" id="wrong0"></li>
            <li class="answer" id="wrong1"></li>
            <li class="answer" id="wrong2"></li>
            <li class="answer" id="correct"></li>
        </ul>
        <br /><br /><br>
        <div id="warning">
        </div>
    </div>
    </body>

</html>
share|improve this question
add comment

1 Answer 1

up vote 3 down vote accepted

I didn't really have a chance to really take this apart but your first foreach loop binding the mouseover events can actually be written like in this jsfiddle http://jsfiddle.net/KSzFy/

When you call a event binding function on a jquery array it will apply the event to all items in the jquery array.

As far as dealing with global functions and variables, its best to wrap all of them in a javascript object and then bind that object to the window. That way you are still keeping the potential for naming collisions to a minimum but you are also creating ad-hoc name spaces for yourself.

 window.pageSpaceName = {
      publicVariable : 'value',
      publicFunction : function(){alert('I do something')}
}

Also since all JS objects are really just hashes, jquery has a handy function called extend that will combine objects together for you allowing you to 'import' separate pieces of your js namespace together.

Assume we have a top level javascript object with functions that are required across the entire site.

(function(){
   $.extend(true, siteNameSpace, {pageSpaceName : {
       publicVariable : 'value',
       publicFunction : function(){alert('I do something')}
    }});
}).call(this);

then on your page you can access your variables and functions like so

window.siteNameSpace.pageSpaceName.publicFunction();

If you have all of your objects in self executing blocks and are using extend like in the example importing the namespaces will be as simple as including the script file on the page.

I generally create a 'global' namespace object and include it in the base page of the site so every child page will already have that base object created for it.

window.siteNameSpace = {};
share|improve this answer
    
the signature of $.extend is $.extend(isDeepCopy,target,source) –  Justen Martin Jan 28 '13 at 5:49
1  
So just to state it explicitly - the namespacing technique actually creates more global variables than the OP's function which creates zero while namespacing creates at least one. This is still very useful for code organization but it IS more globals and should be avoided if you don't need it (for example if you don't need to share code). One gotcha that I've seen people run into with this is when they have global utility functions that call other global utility functions in the same namespace - you can't rely on this I recommend writing it in module pattern style: goo.gl/5Ubyj –  George Mauer Jan 28 '13 at 15:21
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.