For my first use of javascript I've made an app that takes an input verb from html in Japanese and outputs it in to many conjugated (manipulated) forms.
Essentially, it defines an alphabet, some initial arrays and functions for use, a function to initially check for values and interact with the html page, an object to pass different verb values to, and then a whole slew of "self invoking functions" that essentially take the verb and pass it to the object, and then another function to interact with the page.
Right now I'm at a loss on how to rewrite it in modular JS. I have a couple libraries defined in the HTML (bootstrap, jQuery, and a Japanese IME). Although I'm using self-invoking functions and have a general idea of what modules are, I have no idea what a practical way of splitting up the code in to modules would be.
$(document).ready(function () {
//hiragana table
var hiragana = {
a: ["あ", "か", "さ", "た", "な", "は", "ま", "や", "ら", "わ", "が", "ざ", "だ", "ば", "ぱ"],
i: ["い", "き", "し", "ち", "に", "ひ", "み", " ", "り", " ", "ぎ", "じ", "ぢ", "び", "ぴ"],
u: ["う", "く", "す", "つ", "ぬ", "ふ", "む", "ゆ", "る", " ", "ぐ", "ず", "づ", "ぶ", "ぷ"],
e: ["え", "け", "せ", "て", "ね", "へ", "め", " ", "れ", " ", "げ", "ぜ", "で", "べ", "ぺ"],
o: ["お", "こ", "そ", "と", "の", "ほ", "も", "よ", "ろ", "を", "ご", "ぞ", "ど", "ぼ", "ぽ"],
teOne: ["み", "に", "び"],
teTwo: ["い", "ち", "り"],
change: function (input, initVowel, desiredVowel) {
var x = hiragana[initVowel].indexOf(input);
return hiragana[desiredVowel][x];
}
};
var groupOneExceptions = ["はいる", "はしる", "かえる", "かぎる", "きる", "しゃべる", "しる", "いる"];
var groupThree = ["くる", "する"];
var existence = [["いる", "ある"], ["です"]];
//check if in array
function isInArray(array, search) {
return array.indexOf(search) >= 0;
}
//add input to the page
function printPage(id, value) {
$("#" + id).replaceWith("<div id = " + id + ">" + value + "</span>");
}
//bind input to wanakana on page load
var input = document.getElementById("input");
wanakana.bind(input);
//check radio buttons and enact changes on enter form
$("input:radio[name=input-method]").change(function () {
if ($(this).val() === "Hiragana") {
//wanakana support
wanakana.bind(input);
$("#input").attr("placeholder", "たべる");
}
if ($(this).val() === "Romaji") {
wanakana.unbind(input);
$("#input").attr("placeholder", "taberu");
}
});
//Click the button to get the form value.
$("#submit").click(function () {
var verb = {
//put an if check here for masu? LATER
group: "",
u: $("#input").val(),
end: "",
endTwo: "",
withoutEnd: "",
i: "",
te: "",
preMasu: "",
masu: "",
ta: "",
taEnd: "",
nakatta: "",
mashita: "",
masendeshita: "",
teEnd: "",
nai: "",
naiEnd: "",
masen: "",
ou: "",
ouEnd: "",
naidarou: "",
eba: "",
ebaEnd: "",
nakereba: "",
eru: "",
eruEnd: "",
erunai: "",
seru: "",
serunai: "",
reru: "",
rerunai: ""
};
var init = (function () {
printPage("callout", "");
//clear table
for (prop in verb) {
if (typeof verb[prop] === "string") {
printPage(prop, "");
}
}
//init verb.u for hiragana processing
if (wanakana.isKana(verb.u) === false) {
verb.u = wanakana.toHiragana(verb.u);
}
//do some initial slicing
verb.end = verb.u.slice(-1);
verb.endTwo = verb.u.slice(-2, -1);
verb.withoutEnd = verb.u.slice(0, -1);
if (isInArray(hiragana.u, verb.end) === false) {
printPage("callout", "<div class=\"bs-callout bs-callout-danger\"> It doesn't look like " + verb.u + " is a valid Japanese verb in plain form. Try something that ends with an \"u\".</div>");
}
if (isInArray(existence[0], verb.u)) {
printPage("callout", "<div class=\"bs-callout bs-callout-info\"> If you were referring to the existence construct " + verb.u + " (to be), refer here.</div>");
} else if (isInArray(existence[1], verb.u)) {
printPage("callout", "<div class=\"bs-callout bs-callout-info\"> If you were referring to the existence construct " + verb.u + " (is), refer here.</div>");
}
})();
if (isInArray(hiragana.u, verb.end)) {
verb.getGroup = (function () {
if (isInArray(groupThree, verb.u)) {
verb.group = "3";
} else if (verb.end === "る" && (isInArray(hiragana.i, verb.endTwo) || isInArray(hiragana.e, verb.endTwo))) {
verb.group = "2";
} else if (isInArray(hiragana.u, verb.end)) {
verb.group = "1";
}
if (isInArray(groupOneExceptions, verb.u)) {
verb.group = "1";
}
})();
verb.getI = (function () {
if (verb.group === "1") {
verb.preMasu = hiragana.change(verb.end, "u", "i");
verb.i = verb.u.slice(0, -1) + verb.preMasu;
}
if (verb.group === "2") {
verb.i = verb.u.slice(0, -1);
}
if (verb.group === "3") {
verb.i = hiragana.change(verb.withoutEnd, "u", "i");
}
})();
verb.getTe = (function () {
if (verb.group === "3" || verb.group === "2") {
verb.te = verb.i + "て";
}
if (verb.group === "1") {
if (isInArray(hiragana.teOne, verb.preMasu)) {
verb.teEnd = "んで";
} else if (isInArray(hiragana.teTwo, verb.preMasu)) {
verb.teEnd = "って";
} else if (verb.preMasu === "き") {
verb.teEnd = "いて";
} else if (verb.preMasu === "ぎ") {
verb.teEnd = "いで";
} else if (verb.preMasu === "し") {
verb.teEnd = "して";
}
//exception
if (verb.u === "いく") {
verb.teEnd = "って";
}
verb.te = verb.withoutEnd + verb.teEnd;
}
})();
verb.getNai = (function () {
if (verb.group === "3") {
if (verb.u === "する") {
verb.nai = "しない";
}
if (verb.u === "くる") {
verb.nai = "こない";
}
}
if (verb.group === "2") {
verb.nai = verb.i + "ない";
}
if (verb.group === "1") {
if (verb.preMasu === "い") {
verb.naiEnd = "わ";
} else {
verb.naiEnd = hiragana.change(verb.preMasu, "i", "a") + "ない";
}
verb.nai = verb.withoutEnd + verb.naiEnd;
if (verb.u === "ある") {
verb.nai = "ない";
}
}
})();
verb.getMasu = (function () {
verb.masu = verb.i + "ます";
})();
verb.getMasen = (function () {
verb.masen = verb.i + "ません";
})();
verb.getTa = (function () {
if (verb.group === "3" || verb.group === "2") {
verb.ta = verb.i + "た";
}
if (verb.group === "1") {
verb.taEnd = verb.teEnd.slice(0, -1) + hiragana.change(verb.teEnd.slice(-1), "e", "a");
verb.ta = verb.withoutEnd + verb.taEnd;
}
})();
verb.getNakatta = (function () {
verb.nakatta = verb.nai.slice(0, -1) + "かった";
})();
verb.getMashita = (function () {
verb.mashita = verb.i + "ました";
})();
verb.getMasendeshita = (function () {
verb.masendeshita = verb.masen + " でした";
})();
verb.getOu = (function () {
if (verb.group === "3") {
verb.ou = verb.nai.slice(0, -2) + "よう";
}
if (verb.group === "2") {
verb.ou = verb.i + "よう";
}
if (verb.group === "1") {
verb.ouEnd = hiragana.change(verb.preMasu, "i", "o") + "う";
verb.ou = verb.withoutEnd + verb.ouEnd;
}
})();
verb.getNaidarou = (function () {
verb.naidarou = verb.nai + " だろう";
})();
verb.getEba = (function () {
if (verb.group === "3") {
verb.eba = verb.withoutEnd + "れば";
}
if (verb.group === "2") {
verb.eba = verb.i + "れば";
}
if (verb.group === "1") {
verb.ebaEnd = hiragana.change(verb.preMasu, "i", "e") + "ば";
verb.eba = verb.withoutEnd + verb.ebaEnd;
}
})();
verb.getNakereba = (function () {
verb.nakereba = verb.nai.slice(0, -1) + "ければ";
})();
verb.getEru = (function () {
if (verb.group === "3") {
if (verb.u === "する") {
verb.eru = "できる";
}
if (verb.u === "くる") {
verb.eru = "こられる";
}
}
if (verb.group === "2") {
verb.eru = verb.withoutEnd + "られる";
}
if (verb.group === "1") {
verb.eruEnd = hiragana.change(verb.preMasu, "i", "e") + "る";
verb.eru = verb.withoutEnd + verb.eruEnd;
}
})();
verb.getErunai = (function () {
verb.erunai = verb.eru.slice(0, -1) + "ない";
})();
verb.getReru = (function () {
if (verb.group === "3") {
if (verb.u === "する") {
verb.reru = "される";
}
if (verb.u === "くる") {
verb.reru = "こらせる";
}
}
if (verb.group === "2") {
verb.reru = verb.eru;
}
if (verb.group === "1") {
verb.reru = verb.nai.slice(0, -2) + "れる";
}
})();
verb.getRerunai = (function () {
verb.rerunai = verb.reru.slice(0, -1) + "ない";
})();
verb.getSeru = (function () {
if (verb.group === "3") {
if (verb.u === "する") {
verb.seru = "させる";
}
if (verb.u === "くる") {
verb.seru = "こさせる";
}
}
if (verb.group === "2") {
verb.seru = verb.withoutEnd + "させる";
}
if (verb.group === "1") {
verb.seru = verb.nai.slice(0, -2) + "せる";
}
})();
verb.getserunai = (function () {
verb.serunai = verb.seru.slice(0, -1) + "ない";
})();
verb.process = (function () {
var prop = "";
//goes through verb object, checks for romaji, prints page
for (prop in verb) {
if (typeof verb[prop] === "string") {
if (wanakana.isKana($("#input").val()) === false) {
verb[prop] = wanakana.toRomaji(verb[prop]);
}
printPage(prop, verb[prop]);
} //string
} //for in
})();
}
});
});
-
\$\begingroup\$ Don't mix business and presentation logic. \$\endgroup\$CodesInChaos– CodesInChaos2014年08月27日 13:44:40 +00:00Commented Aug 27, 2014 at 13:44
1 Answer 1
Comments such as
//check if in array
before a function calledisInArray
and//hiragana table
are completely pointless. It would be more important to describe what you are actually doing for everyone who doesn't know Japanese.$("#" + id).replaceWith("<div id = " + id + ">" + value + "</span>");
: Besides the mismatching tags, this looks like a very bad way to output something.document.getElementById("input");
: Don't hard code IDs. The next time you or someone else needs to re-use the code on a different page, they'll need to search and replace them all, also why don't you use jQuery here?wanakana
is not defined.There are far too many magic strings.
In general you seem to completely confused on the point of using self-invoking functions. You are not using them for any practical purpose nor do they return anything and yet you attempt to store their return value.
I can only suggest:
Re-write everything in a straight forward procedural manner, breaking the functionally down into functions (procedures) no longer than, say, 10 lines (arbitrary number, just for the practice).
Don't have the functions access any "global" variables - that is let them work only with their arguments. The only exception would be accessing any global constants.
Make sure you don't use any string literals, other than when defining constants.
Give all constants a name with CAPITAL_LETTERS, so they are recognizable as such.
Ignore input and output for now. For testing/development just start your program with a function call to the main function with the verb as it's argument, and output to the console. E.g.:
console.log( japaneseVerbConjugator("Some Japanese verb") );
-
\$\begingroup\$ Hi and thanks a lot! I've recoded everything and separated the "business" and "presentation" code in to different files (modules?) returning actual values using requireJS. I was wondering why HTML was so clumsy in Javascript but thanks to a quick google of "magic string" I understand what you mean. I'll change the getElementbyId method to JQuery for consistency, and stop using literals when processing output strings. However, I don't quite get what you mean with accessing arguments, right now an object is serving as a data storage object and the conjugation functions are simply accessing it. \$\endgroup\$cardboardtheory– cardboardtheory2014年09月02日 03:33:40 +00:00Commented Sep 2, 2014 at 3:33
-
\$\begingroup\$ If there's a better way of doing the same task please let me know! Otherwise, I'll really try to improve my code according to your advice. If there's more advice or any other sources for useful knowledge and standard ways of doing things, I would be infinitely grateful as my coding knowledge up to now is basically a few Codecademy courses. \$\endgroup\$cardboardtheory– cardboardtheory2014年09月02日 03:39:35 +00:00Commented Sep 2, 2014 at 3:39