In this tutorial, I will guide you how to create a random song lyrics generator. We will use HTML5, CSS3, and JavaScript to write this software.
You can easily copy/paste or download the complete source code of our random song lyrics generator.
Folder Structure of Random Song Lyrics Generator
- data
- dictionary_ENG.js
- syntax_ENG.dsl
- bg.jpg
- config.js
- generator.js
- index.html
- styles.css
- utils.js
data/dictionary_ENG.js
var adjectives={any:["different","used","important","every","large","available","popular","able","basic","known","various","difficult","several","united","historical","hot","useful","mental","scared","additional","emotional","old","political","similar","healthy","financial","medical","traditional","federal","entire","strong","actual","significant","successful","electrical","expensive","pregnant","intelligent","interesting","poor","happy","responsible","cute","helpful","recent","willing","nice","wonderful","impossible","serious","huge","rare","technical","typical","competitive","critical","electronic","immediate","aware","educational","environmental","global","legal","relevant","accurate","capable","dangerous","dramatic","efficient","powerful","foreign","hungry","practical","psychological","severe","suitable","numerous","sufficient","unusual","consistent","cultural","existing","famous","pure","afraid","obvious","careful","latter","obviously","unhappy","acceptable","aggressive","boring","distinct","eastern","logical","reasonable","strict","successfully","administrative","automatic","civil","former","massive","southern","unfair","visible","alive","angry","desperate","exciting","friendly","lucky","realistic","sorry","ugly","unlikely","anxious","comprehensive","curious","impressive","informal","inner","pleasant","sexual","sudden","terrible","unable","weak","wooden","asleep","confident","conscious","decent","embarrassed","guilty","lonely","mad","nervous","odd","remarkable","substantial","suspicious","tall","tiny"]}
var modal_verbs={any:["might","can","must","could","may","shall","should","will","would"]}
var modal_verbs_to={any:["want","like","love","need","try"]}
var nouns={any:["people","history","way","art","world","information","map","two","family","government","health","system","computer","meat","year","thanks","music","person","reading","method","data","food","understanding","theory","law","bird","literature","problem","software","control","knowledge","power","ability","economics","love","internet","television","science","library","nature","fact","product","idea","temperature","investment","area","society","activity","story","industry","media","thing","oven","community","definition","safety","quality","development","language","management","player","variety","video","week","security","country","exam","movie","organization","equipment","physics","analysis","policy","series","thought","basis","boyfriend","direction","strategy","technology","army","camera","freedom","paper","environment","child","instance","month","truth","marketing","university","writing","article","department","difference","goal","news","audience","fishing","growth","income","marriage","user","combination","failure","meaning","medicine","philosophy","teacher","communication","night","chemistry","disease","disk","energy","nation","road","role","soup","advertising","location","success","addition","apartment","education","math","moment","painting","politics","attention","decision","event","property","shopping","student","wood","competition","distribution","entertainment","office","population","president","unit","category","cigarette","context","introduction","opportunity","performance","driver","flight","length","magazine","newspaper","relationship","teaching","cell","dealer","finding","lake","member","message","phone","scene","appearance","association","concept","customer","death","discussion","housing","inflation","insurance","mood","woman","advice","blood","effort","expression","importance","opinion","payment","reality","responsibility","situation","skill","statement","wealth","application","city","county","depth","estate","foundation","grandmother","heart","perspective","photo","recipe","studio","topic","collection","depression","imagination","passion","percentage","resource","setting","ad","agency","college","connection","criticism","debt","description","memory","patience","secretary","solution","administration","aspect","attitude","director","personality","psychology","recommendation","response","selection","storage","version","alcohol","argument","complaint","contract","emphasis","highway","loss","membership","possession","preparation","steak","union","agreement","cancer","currency","employment","engineering","entry","interaction","mixture","preference","region","republic","tradition","virus","actor","classroom","delivery","device","difficulty","drama","election","engine","football","guidance","hotel","owner","priority","protection","suggestion","tension","variation","anxiety","atmosphere","awareness","bath","bread","candidate","climate","comparison","confusion","construction","elevator","emotion","employee","employer","guest","height","leadership","mall","manager","operation","recording","sample","transportation","charity","cousin","disaster","editor","efficiency","excitement","extent","feedback","guitar","homework","leader","mom","outcome","permission","presentation","promotion","reflection","refrigerator","resolution","revenue","session","singer","tennis","basket","bonus","cabinet","childhood","church","clothes","coffee","dinner","drawing","hair","hearing","initiative","judgment","lab","measurement","mode","mud","orange","poetry","police","possibility","procedure","queen","ratio","relation","restaurant","satisfaction","sector","signature","significance","song","tooth","town","vehicle","volume","wife","accident","airport","appointment","arrival","assumption","baseball","chapter","committee","conversation","database","enthusiasm","error","explanation","farmer","gate","girl","hall","historian","hospital","injury","instruction","maintenance","manufacturer","meal","perception","pie","poem","presence","proposal","reception","replacement","revolution","river","son","speech","tea","village","warning","winner","worker","writer","assistance","breath","buyer","chest","chocolate","conclusion","contribution","cookie","courage","dad","desk","drawer","establishment","examination","garbage","grocery","honey","impression","improvement","independence","insect","inspection","inspector","king","ladder","menu","penalty","piano","potato","profession","professor","quantity","reaction","requirement","salad","sister","supermarket","tongue","weakness","wedding","affair","ambition","analyst","apple","assignment","assistant","bathroom","bedroom","beer","birthday","celebration","championship","cheek","client","consequence","departure","diamond","dirt","ear","fortune","friendship","funeral","gene","girlfriend","hat","indication","intention","lady","midnight","negotiation","obligation","passenger","pizza","platform","poet","pollution","recognition","reputation","shirt","sir","speaker","stranger","surgery","sympathy","tale","throat","trainer","uncle","youth"]}
var verbs={any:["be","have","do","say","get","make","go","see","know","take","think","come","give","look","use","find","want","tell","put","mean","become","leave","work","need","feel","seem","ask","show","try","call","keep","provide","hold","turn","follow","begin","bring","like","going","help","start","run","write","set","move","play","pay","hear","include","believe","allow","meet","lead","live","stand","happen","carry","talk","appear","produce","sit","offer","consider","expect","suggest","let","read","require","continue","lose","add","change","fall","remain","remember","buy","speak","stop","send","receive","decide","win","understand","describe","develop","agree","open","reach","build","involve","spend","return","draw","die","hope","create","walk","sell","wait","cause","pass","lie","accept","watch","raise","base","apply","break","explain","learn","increase","cover","grow","claim","report","support","cut","form","stay","contain","reduce","establish","join","wish","achieve","seek","choose","deal","face","fail","serve","end","kill","occur","drive","represent","rise","discuss","love","pick","place","argue","prove","wear","catch","enjoy","eat","introduce","enter","present","arrive","ensure","point","plan","pull","refer","act","relate","affect","close","identify","manage","thank","compare","announce","obtain","note","forget","indicate","wonder","maintain","publish","suffer","avoid","express","suppose","finish","determine","design","listen","save","tend","treat","control","share","remove","throw","visit","exist","encourage","force","reflect","admit","assume","smile","prepare","replace","fill","improve","mention","fight","intend","miss","discover","drop","hit","push","prevent","refuse","regard","lay","reveal","teach","answer","operate","state","depend","enable","record","check","complete","cost","sound","laugh","realise","extend","arise","notice","define","examine","fit","study","bear","hang","recognise","shake","sign","attend","fly","gain","perform","result","travel","adopt","confirm","protect","demand","stare","imagine","attempt","beat","born","associate","care","marry","collect","voice","employ","issue","release","emerge","mind","aim","deny","mark","shoot","appoint","order","supply","drink","observe","reply","ignore","link","propose","ring","settle","strike","press","respond","arrange","survive","concentrate","lift","approach","cross","test","charge","experience","touch","acquire","commit","demonstrate","grant","prefer","repeat","sleep","threaten","feed","insist","launch","limit","promote","deliver","measure","own","retain","assess","attract","belong","consist","contribute","hide","promise","reject","cry","impose","invite","sing","vary","warn","address","declare","destroy","worry","divide","head","name","stick","nod","recognize","train","attack","clear","combine","handle","influence","realize","recommend","shout","spread","undertake","account","select","climb","contact","recall","secure","step","transfer","welcome","conclude","disappear","display","dress","illustrate","imply","organise","direct","escape","generate","investigate","remind","advise","afford","earn","hand","inform","rely","succeed","approve","burn","fear","vote","conduct","cope","derive","elect","gather","jump","last","match","matter","persuade","ride","shut","blow","estimate","recover","score","slip","count","hate","attach","exercise","house","lean","roll","wash","accompany","accuse","bind","explore","judge","rest","steal","comment","exclude","focus","hurt","stretch","withdraw","back","fix","justify","knock","pursue","switch","appreciate","benefit","lack","list","occupy","permit","surround","abandon","blame","complain","connect","construct","dominate","engage","paint","quote","view","acknowledge","dismiss","incorporate","interpret","proceed","search","separate","stress","alter","analyse","arrest","bother","defend","expand","implement","possess","review","suit","tie","assist","calculate","glance","mix","question","resolve","rule","suspect","wake","appeal","challenge","clean","damage","guess","reckon","restore","restrict","specify","constitute","convert","distinguish","submit","trust","urge","feature","land","locate","predict","preserve","solve","sort","struggle","cast","cook","dance","invest","lock","owe","pour","shift","kick","kiss","light","purchase","race","retire","bend","breathe","celebrate","date","fire","monitor","print","register","resist","behave","comprise","decline","detect","finance","organize","overcome","range","swing","differ","drag","guarantee","oppose","pack","pause","relax","resign","rush","store","waste","compete","expose","found","install","mount","negotiate","sink","split","whisper","assure","award","borrow","bury","capture","deserve","distribute","doubt","enhance","phone","sweep","tackle","advance","cease","concern","emphasise","exceed","qualify","slide","strengthen","transform","favour","grab","lend","participate","perceive","pose","practise","satisfy","scream","smoke","sustain","tear","adapt","adjust","ban","consult","dig","dry","highlight","outline","reinforce","shrug","snap","absorb","amount","block","confine","delay","encounter","entitle","plant","pretend","request","rid","sail","trace","trade","wave","cite","dream","flow","fulfil","lower","process","react","seize","allocate","burst","communicate","defeat","double","exploit","fund","govern","hurry","injure","pray","protest","sigh","smell","stir","swim","undergo","wander","anticipate","collapse","compose","confront","ease","eliminate","evaluate","grin","interview","remark","suspend","weigh","wipe","wrap","attribute","balance","bet","bound","cancel","condemn","convince","correspond","dare","devise","free","gaze","guide","inspire","modify","murder","prompt","reverse","rub","slow","spot","swear","telephone","wind","admire","bite","crash","disturb","greet","hesitate","induce","integrate","knit","line","load","murmur","render","shine","swallow","tap","translate","yield","accommodate","age","assert","await","book","brush","chase","comply","copy","criticise","devote","evolve","flee","forgive","initiate","interrupt","leap","mutter","overlook","risk","shape","spell","squeeze","trap","undermine","witness","beg","drift","echo","emphasize","enforce","exchange","fade","float","freeze","hire","in","object","pop","provoke","recruit","research","sense","situate","stimulate","abolish","administer","allege","command","consume","convey","correct","educate","equip","execute","fetch","frown","invent","march","park","progress","reserve","respect","twist","unite","value","assign","cater","concede","conceive","disclose","envisage","exhibit","export","extract","fancy","inherit","insert","instruct","interfere","isolate","opt","peer","persist","plead","price","regret","regulate","repair","resemble","resume","speed","spin","spring","update","advocate","assemble","boost","breed","cling","commission","conceal","contemplate","criticize","decorate","descend","drain","edit","embrace","excuse","explode","facilitate","flash","fold","function","grasp","incur","intervene","label","please","rescue","strip","tip","upset","advertise","aid","centre","classify","coincide","confess","contract","crack","creep","decrease","deem","dispose","dissolve","dump","endorse","formulate","import","impress","market","reproduce","scatter","schedule","ship","shop","spare","sponsor","stage","suck","sue","tempt","vanish","access","commence","contrast","depict","discharge","draft","enclose","enquire","erect","file","halt","hunt","inspect","omit","originate","praise","precede","relieve","reward","round","seal","signal","smash","spoil","subject","target","taste","tighten","top","tremble","tuck","warm","activate","amend","arouse","bang","bid","bow","campaign","characterise","circulate","clarify","compensate","compile","cool","couple","depart","deprive","desire","diminish","drown","embark","entail","entertain","figure","fling","guard","manufacture","melt","neglect","plunge","project","rain","reassure","rent","revive","sentence","shed","slam","spill","stem","sum","summon","supplement","suppress","surprise","tax","thrust","tour","transmit","transport","weaken","widen","bounce","calm","characterize","chat","clutch","confer","conform","confuse","convict","counter","debate","dedicate","dictate","disagree","effect","flood","forbid","grip","heat","long","manipulate","merge","part","pin","position","prescribe","proclaim","punish","rebuild","regain","sack","strain","stroke","substitute","supervise","term","time","toss","underline","abuse","accumulate","alert","arm","attain","boast","boil","carve","cheer","colour","compel","crawl","crush","curl","deposit","differentiate","dip","dislike","divert","embody","exert","exhaust","fine","frighten","fuck","gasp","honour","inhibit","motivate","multiply","narrow","obey","penetrate","picture","presume","prevail","pronounce","rate","renew","revise","rip","scan","scratch","shiver"]}
var article={singular:{any:["a","the"]},plural:{any:["the"]}}
var personal_pronouns_subject={singular:{first:["I"],second:["you"],third:["he","she","it"]},plural:{first:["we"],second:["you"],third:["they"]}}
var personal_pronouns_object={singular:{first:["me"],second:["you"],third:["him","her","it"]},plural:{first:["us"],second:["you"],third:["them"]}}
var possessive_pronouns={singular:{first:["my"],second:["your"],third:["his","her","its"]},plural:{first:["our"],second:["your"],third:["their"]}}
var indefinite_pronouns={singular:{any:["anybody","anyone","anything","nobody","noone","everybody","everyone","everything"]}}
var demonstrative_pronouns={singular:{any:["this","that"],},plural:{any:["these","those"]}}
var persons=["first","second","third"]
var number=["singular","plural"]
var tenses=["present","future","futureperfect","past","presentperfect","imperfect","conditional","pastconditional","pastperfect","presentprogressive","futureprogressive"]
var genders=["masculine","feminine","neuter"]
var wordTypes={ART: article,NOU: nouns,VRB: verbs,ADJ: adjectives,PPS: personal_pronouns_subject,PPO: personal_pronouns_object,PSP: possessive_pronouns,MVB: modal_verbs,MVT: modal_verbs_to,IDP: indefinite_pronouns,DEP: demonstrative_pronouns}data/syntax_ENG.dsl
# ---- Syntax documentation----
# each non-comment line in this file represents a sentence structure
# every literal (e.g. XYZ) must have a corresponding field in the generator's wordTypes array, like wordTypes.XYZ, which holds all the applicable words of that type
#
# ---- Special characters ----
# # line comment
# (blank space) and (high precedence)
# | xor (low precedence)
# ? optional
# : apply function
# "xyz": xyz as an absolute string (will not be modified)
#
# ============ EXAMPLE ============
#
# ((A|B) C:x D? E F".")
#
# yields an array with 4 sentences
#
# A x(C) D E F.
# A x(C) E F.
# B x(C) D E F.
# B x(C) E F.
(((ART|DEP|PSP) ADJ? NOU)|PPS|IDP) (VRB:conjugate|MVB:conjugate|(MVT:conjugate VRB)) ((((ART|DEP|PSP) ADJ? NOU)|PPO) ADJ?:adverb)?("."|"!"|"...")
ART ADJ NOU VRB:conjugatebg.jpg
You can click here to download this image file.

config.js
Here we will use Ultralingua API and Datamuse API to get multilingual translation dictionary and word-finding query engine functionality respectively.
var config = {
conjugationApiUrl: "http://api.ultralingua.com/api/2.0/conjugations/eng/",
semanticsApiUrl: "http://api.datamuse.com/words",
defaultSettings: {
language: "ENG"
}
}generator.js
function generator(initSettings) {
var settings
var sentenceStructures
var initGenerator = function() {
setSettings(initSettings)
getDslFile("data/syntax_" + settings.language + ".dsl")
}
var addSentenceStructure = function(newSentenceStructure) {
if(newSentenceStructure instanceof SentenceStructure) {
sentenceStructures.concat(newSentenceStructure)
}
}
var getSettings = function() {
return settings
}
var setSettings = function(newSettings) {
if(newSettings && newSettings instanceof GeneratorSettings) {
settings = newSettings
} else {
settings = new GeneratorSettings(config.defaultSettings.language)
}
}
var createSentence = function() {
return getRandomSentence()
}
function conjugate() {
function getConjugationResult(result) {
var conjugation = result[0]["conjugations"].filter(function(c) {
var tenseMatches = c["partofspeech"]["tense"] == sentence.tense
var personMatches = !c["partofspeech"]["person"] || c["partofspeech"]["person"].indexOf(sentence.person) >= 0
var numberMatches = !c["partofspeech"]["number"] || c["partofspeech"]["number"].indexOf(sentence.number) >= 0
return tenseMatches && personMatches && numberMatches
})
document.getElementById("lyrics").textContent = conjugation[0]["surfaceform"]
}
utils.conjugationApiCall(verb, sentence, getConjugationResult)
}
var getRandomWord = function (type, sentence, modifyFunction) {
if (!type || !wordTypes[type]) {
var typeKeys = Object.keys(wordTypes)
type = typeKeys[Math.floor(Math.random() * typeKeys.length)]
}
var words = getWordArrayForSentence(wordTypes[type], sentence)
return words[Math.floor(Math.random() * words.length)]
}
function getRandomSentence() {
var person = persons[Math.floor(Math.random() * persons.length)]
var personNumber = number[Math.floor(Math.random() * number.length)]
var tense = tenses[Math.floor(Math.random() * tenses.length)]
var gender = person == "third" && number == "singular" ? genders[Math.floor(Math.random()*genders.length)] : undefined
var language = settings.language
return new Sentence(
"",
person,
personNumber,
tense,
gender,
null,
language
)
}
function getDslFile(url) {
var request = new XMLHttpRequest();
request.open("GET", url, true)
request.onreadystatechange = function (){
if(request.readyState === 4) {
if(request.status === 200 || request.status == 0) {
parseDsl(request.responseText);
}
}
}
request.send(null);
}
function validateDslLine(line) {
// #1 parenthesis and quotation
var parenthesisCount = 0
if(line.match(/\"/g) && line.match(/\"/g).length % 2 != 0) {
console.error("DSL validation failed: bad quotation")
return false
}
for(var c in line) {
if(!line.hasOwnProperty(c)) continue
if(!line[c].match(/[\w|$|\(|\)|:|\?| |\||\"]/)) {
var quotationsBefore = line.substring(0, c).match(/\"/g) ? line.substring(0, c).match(/\"/g).length : []
var quotationsAfter = line.substring(parseInt(c)+1).match(/\"/g) ? line.substring(parseInt(c)+1).match(/\"/g).length : []
if(quotationsBefore % 2 != 1 || quotationsAfter % 2 != 1) {
var blanks = ""
var n = 0
while(n < c) {
blanks += " "
n++
}
console.error("DSL validation failed: unexpected character - '" + line[c] + "'\n" + line + "\n" + blanks + "^")
return false
}
}
if(line[c] == "(") {
parenthesisCount += 1
} else if(line[c] == ")") {
parenthesisCount -= 1
if(parenthesisCount < 0) {
console.error("DSL validation failed: bad parenthesis")
return false
}
}
}
if(parenthesisCount != 0) {
console.error("DSL validation failed: bad parenthesis")
return false
}
return true
}
function createSentenceStructureFromDslLine(dslLine) {
var sentenceStructure = new SentenceStructure()
function resolve(str, subParts) {
var parenthesisIndex = str.indexOf("(")
var blankIndex = str.indexOf(" ")
var pipeIndex = str.indexOf("|")
if(parenthesisIndex >= 0 && parenthesisIndex < blankIndex) {
var innerPartClose = str.indexOf(")")
var innerPartOpen = str.lastIndexOf("(")
var innerPart = str.substring(innerPartOpen, innerPartClose)
} else if(blankIndex >= 0 && parenthesisIndex > blankIndex) {
// var part =
} else if(pipeIndex >= 0) {
}
}
var rawParts = resolve(dslLine, [])
// for(var rawPart of rawParts) {
// var part = new SentenceStructurePart(type, modifyFunction)
// sentenceStructure.addPart(part)
// }
addSentenceStructure(sentenceStructure)
}
function parseDsl(dslContent) {
var lines = dslContent.split(/\r?\n/)
lines = lines.filter(function(line) {
return line && line.indexOf("#") != 0
})
for(var line of lines) {
if(validateDslLine(line)) {
var sentenceStructure = createSentenceStructureFromDslLine(line)
addSentenceStructure(sentenceStructure)
}
}
}
function getWordArrayForSentence(array, sentence) {
if(array && sentence) {
if(array.any) return array.any
if(array[sentence.number]) {
if(array[sentence.number].any) return array[sentence.number].any
else if(array[sentence.number][sentence.person]) return array[sentence.number][sentence.person]
}
}
return null
}
initGenerator()
return {
getSettings: getSettings,
setSettings: setSettings,
createSentence: createSentence,
addSentenceStructure: addSentenceStructure
}
}
class Sentence {
constructor(text, person, number, tense, gender, structure, language) {
this.text = text
this.person = person
this.number = number
this.tense = tense
this.gender = gender
this.structure = structure
this.language = language
}
}
class SentenceStructure {
constructor(parts) {
this.parts = parts
}
addPart(part) {
part.added = true
if(this.parts) {
this.parts = this.parts.concat(part)
} else {
this.parts = [part]
}
}
}
class SentenceStructurePart {
constructor(type, modifyFunction) {
this.type = type
this.modifyFunction = modifyFunction
this.added = false
}
}
class GeneratorSettings {
constructor(language) {
this.language = language
}
}index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="config.js"></script>
<script src="data/dictionary_ENG.js"></script>
<script src="utils.js"></script>
<script src="generator.js"></script>
<link rel="stylesheet" href="styles.css">
<link href="https://fonts.googleapis.com/css?family=Thasadith" rel="stylesheet">
</head>
<body>
<div id="background-image"></div>
<button onClick="generator.createSentence()">Create</button>
<br>
<div id="lyrics"></div>
</body>
<script>
var generator;
(function() {
generator = generator()
})()
</script>
</html>styles.css
body {
color: #92caff;
}
* {
font-family: 'Thasadith', sans-serif;
font-size: 20px;
}
button {
background-color: rgba(146, 202, 255, 0.33);
border: 1px solid rgba(146, 202, 255, 0.5);
color: #92caff;
transition: all .2s ease;
text-shadow: 0 0 10px white;
box-shadow: 0 0 0 0 rgba(146, 202, 255, 0.5);
}
button:hover,
button:active {
background-color: rgba(146, 202, 255, 0.5);
color: white;
cursor: pointer;
box-shadow: 0 0 5px 0 rgba(146, 202, 255, 0.5);
}
#background-image {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: url(bg.jpg);
background-size: cover;
z-index: -999;
}
#lyrics {
display: inline-block;
max-width: calc(100% - 20px);
text-overflow: ellipsis;
margin: 10px;
padding: 10px;
border: 1px solid rgba(255,255,255,.2);
background-color: rgba(0,0,0,.5);
}utils.js
var utils = {
conjugationApiCall: function(verb, sentence, callback) {
var xmlhttp = new XMLHttpRequest()
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
callback(JSON.parse(xmlhttp.response))
}
}
}
var url = config.conjugationApiUrl + verb + "?tense=" + sentence.tense + "&person=" + sentence.person
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
}
Object.prototype.getAt = function(index) {
return this[Object.keys(this)[index]]
}
Object.prototype.getKeyAt = function(index) {
return Object.keys(this)[index]
}