I've been playing around with Jekyll and CoffeeScript the last few days and made a Periodic Table to learn those two.
Now, to create the Periodic Table, I take an array of li
s as input which then replaces itself with a table using a custom format like so:
periodicTable = [
[1, "s:16", 2],
[3, 4, "s:10", 5, "-", 10],
[11, 12, "s:10", 13, "-", 18],
[19, "-", 36],
[37, "-", 54],
[55, 56, "*", 72, "-", 86],
[87, 88, "**", 104, "-", 118],
["s:18"],
["s:2", "*", 57, "-", 71],
["s:2", "**", 89, "-", 103]
]
s:n
means that the nexttd
should be empty with acolspan
of n"-"
is a range indicator, meaning the next and previous items are the start and end of the range respectively
To create the actual table, the following CoffeeScript file is used:
window.PeriodicTable = {}
periodicTable = [
[1, "s:16", 2],
[3, 4, "s:10", 5, "-", 10],
[11, 12, "s:10", 13, "-", 18],
[19, "-", 36],
[37, "-", 54],
[55, 56, "*", 72, "-", 86],
[87, 88, "**", 104, "-", 118],
["s:18"],
["s:2", "*", 57, "-", 71],
["s:2", "**", 89, "-", 103]
]
spacerIdentifier = "s"
rangeSymbol = "-"
# Get a list item searching by atomic number
PeriodicTable.getListItemByAtomicNumber = (list, atomicNumber) ->
i = 0
while i < list.length
item = list[i]
if !item.nodeName
continue
if +item.dataset['atomicNumber'] == atomicNumber
return item
i++
return null
# Create the periodic table
PeriodicTable.createTable = (list) ->
table = document.createElement "table"
table.className = "periodic-table"
ul = list[0].parentNode
for i of periodicTable
row = PeriodicTable.createRow list, periodicTable[i]
table.appendChild row
ul.parentNode.insertBefore table, ul
return true
# Create a table row
PeriodicTable.createRow = (list, items) ->
row = document.createElement "tr"
i = 0
skipNext = false
while i < items.length
if skipNext
skipNext = false
i++
continue
item = items[i]
# Not a number has a special meaning
if isNaN item
if item.indexOf(spacerIdentifier) != -1
# Item is a spacer
col = PeriodicTable.createCol list, "", +(item.substring(2))
else if item == rangeSymbol
# Item indicates range
col = PeriodicTable.createColSequence list, items[i - 1], items[i + 1]
skipNext = true
else
# Item has some other special meaning, just print it
col = PeriodicTable.createCol list, item
# If the next one is a range symbol, tell the script to skip this one
else if items[i + 1] == rangeSymbol
i++
continue
# Print the column
else
col = PeriodicTable.createCol list, item
if !(col instanceof Array)
col = [col]
row.appendChild c for c in col
i++
return row
# Create a column
PeriodicTable.createCol = (list, atomicNumber, offset) ->
col = document.createElement "td"
if !isNaN atomicNumber
listContent = PeriodicTable.getContentFromListItem(list, atomicNumber)
if typeof listContent == "string"
content = listContent
else
content = listContent.content
col.className = PeriodicTable.getClassName listContent.type
else
content = atomicNumber
col.innerHTML = content || " "
if offset != undefined && !isNaN offset
col.setAttribute "colspan", offset
col.className = 'spacer'
return col
# Create a range of columns
PeriodicTable.createColSequence = (list, start, end) ->
cols = []
i = start
while i <= end
col = PeriodicTable.createCol list, i
cols.push col
i++
return cols
# Get the content from the list item with said atomic number
PeriodicTable.getContentFromListItem = (list, atomicNumber) ->
li = PeriodicTable.getListItemByAtomicNumber list, atomicNumber
if li
atomicNumber = li.dataset["atomicNumber"]
symbol = li.dataset["symbol"]
element = li.innerText
elementType = li.dataset["elementType"]
href = (li.getElementsByTagName "a")[0].getAttribute("href")
return {
content: "<a href=\"" + href + "\"><p>" + element + "</p><p><span>" + atomicNumber + "</span><span>" + symbol + "</span></p></a>",
type: elementType
}
else
return ""
# Get the class name from the element type
PeriodicTable.getClassName = (type) ->
type.replace(/\s/g, "-").toLowerCase()
list = document.querySelectorAll "#elements li"
PeriodicTable.createTable list
ul = document.getElementById "elements"
ul.parentNode.removeChild ul
A list item is built up like so:
<li data-symbol="H" data-atomic-number="1" data-element-type="Other non-metal">
<a href="/element/hydrogen">Hydrogen</a>
</li>
I'm now looking to optimize the script, like some way to turn all those while
loops into for
loops (I tried for in
, but that resulted in 2 extra items being taken, the length of the array and something with function item() { [native code] }
) without using the backticks to escape JavaScript.
I created a GitHub repo for the project.
Could anyone give me a few pointers on this?
table { border-collapse: collapse; }
td { border: 1px solid black; }
<script type="text/coffeescript">
window.PeriodicTable = {}
periodicTable = [
[1, "s:16", 2],
[3, 4, "s:10", 5, "-", 10],
[11, 12, "s:10", 13, "-", 18],
[19, "-", 36],
[37, "-", 54],
[55, 56, "*", 72, "-", 86],
[87, 88, "**", 104, "-", 118],
["s:18"],
["s:2", "*", 57, "-", 71],
["s:2", "**", 89, "-", 103]
]
spacerIdentifier = "s"
rangeSymbol = "-"
# Get a list item searching by atomic number
PeriodicTable.getListItemByAtomicNumber = (list, atomicNumber) ->
i = 0
while i < list.length
item = list[i]
if !item.nodeName
continue
if +item.dataset['atomicNumber'] == atomicNumber
return item
i++
return null
# Create the periodic table
PeriodicTable.createTable = (list) ->
table = document.createElement "table"
table.className = "periodic-table"
ul = list[0].parentNode
for i of periodicTable
row = PeriodicTable.createRow list, periodicTable[i]
table.appendChild row
ul.parentNode.insertBefore table, ul
return true
# Create a table row
PeriodicTable.createRow = (list, items) ->
row = document.createElement "tr"
i = 0
skipNext = false
while i < items.length
if skipNext
skipNext = false
i++
continue
item = items[i]
# Not a number has a special meaning
if isNaN item
if item.indexOf(spacerIdentifier) != -1
# Item is a spacer
col = PeriodicTable.createCol list, "", +(item.substring(2))
else if item == rangeSymbol
# Item indicates range
col = PeriodicTable.createColSequence list, items[i - 1], items[i + 1]
skipNext = true
else
# Item has some other special meaning, just print it
col = PeriodicTable.createCol list, item
# If the next one is a range symbol, tell the script to skip this one
else if items[i + 1] == rangeSymbol
i++
continue
# Print the column
else
col = PeriodicTable.createCol list, item
if !(col instanceof Array)
col = [col]
row.appendChild c for c in col
i++
return row
# Create a column
PeriodicTable.createCol = (list, atomicNumber, offset) ->
col = document.createElement "td"
if !isNaN atomicNumber
listContent = PeriodicTable.getContentFromListItem(list, atomicNumber)
if typeof listContent == "string"
content = listContent
else
content = listContent.content
col.className = PeriodicTable.getClassName listContent.type
else
content = atomicNumber
col.innerHTML = content || " "
if offset != undefined && !isNaN offset
col.setAttribute "colspan", offset
col.className = 'spacer'
return col
# Create a range of columns
PeriodicTable.createColSequence = (list, start, end) ->
cols = []
i = start
while i <= end
col = PeriodicTable.createCol list, i
cols.push col
i++
return cols
# Get the content from the list item with said atomic number
PeriodicTable.getContentFromListItem = (list, atomicNumber) ->
li = PeriodicTable.getListItemByAtomicNumber list, atomicNumber
if li
atomicNumber = li.dataset["atomicNumber"]
symbol = li.dataset["symbol"]
element = li.innerText
elementType = li.dataset["elementType"]
href = (li.getElementsByTagName "a")[0].getAttribute("href")
return {
content: "<a href=\"" + href + "\"><p>" + element + "</p><p><span>" + atomicNumber + "</span><span>" + symbol + "</span></p></a>",
type: elementType
}
else
return ""
# Get the class name from the element type
PeriodicTable.getClassName = (type) ->
type.replace(/\s/g, "-").toLowerCase()
list = document.querySelectorAll "#elements li"
PeriodicTable.createTable list
ul = document.getElementById "elements"
ul.parentNode.removeChild ul
</script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/coffee-script/1.1.2/coffee-script.min.js"></script>
<ul id="elements">
<li data-symbol="H" data-atomic-number="1" data-element-type="Other non-metal">
<a href="/element/hydrogen">Hydrogen</a>
</li>
<li data-symbol="He" data-atomic-number="2" data-element-type="Noble gas">
<a href="/element/lithium">Helium</a>
</li>
<li data-symbol="Li" data-atomic-number="3" data-element-type="Alkali metal">
<a href="/element/lithium">Lithium</a>
</li>
<li data-symbol="Be" data-atomic-number="4" data-element-type="Alkaline earth metal">
<a href="/element/beryllium">Beryllium</a>
</li>
<li data-symbol="B" data-atomic-number="5" data-element-type="Metalloid">
<a href="/element/boron">Boron</a>
</li>
<li data-symbol="C" data-atomic-number="6" data-element-type="Other non-metal">
<a href="/element/carbon">Carbon</a>
</li>
<li data-symbol="N" data-atomic-number="7" data-element-type="Other non-metal">
<a href="/element/nitrogen">Nitrogen</a>
</li>
<li data-symbol="O" data-atomic-number="8" data-element-type="Other non-metal">
<a href="/element/oxygen">Oxygen</a>
</li>
<li data-symbol="F" data-atomic-number="9" data-element-type="Other non-metal">
<a href="/element/fluorine">Fluorine</a>
</li>
<li data-symbol="Ne" data-atomic-number="10" data-element-type="Noble gas">
<a href="/element/neon">Neon</a>
</li>
</ul>