diff --git a/atoms/index.html b/atoms/index.html index aac387a..a4a2cc6 100644 --- a/atoms/index.html +++ b/atoms/index.html @@ -95,9 +95,10 @@ }; - - + + + + - - + \ No newline at end of file diff --git a/atoms/js/atom.js b/atoms/js/atom.js new file mode 100644 index 0000000..d14f15a --- /dev/null +++ b/atoms/js/atom.js @@ -0,0 +1,216 @@ +function tableDesc() { + var p = ["element","atomRadi","moleWeig","ioniEner","elecAffi","elecNega","phase","density","melting","boiling", + "oxidStat","elecConf"]; + var unit = [""," pm"," g/mol", " kJ/mol"," kJ/mol", " eV", "", " g/mL", "",""]; + var prefix = ["Element Name: ", "Atomic Radius: ", "Molecular Mass: ", "Ionization Energy: ", "Electron Affinity: ", + "Electronegativity: ", "Phase/State: ", "Density: ", "Melting Point: ", "Boiling Point: ", + "Oxidation State(s): ", "Electron Configuration: "]; + var states = {"g":"Gas","l":"Liquid","s":"Solid","Unknown":"Unknown"}; + + // Setting up divs for organization + var infoBox = document.createElement("div"); + infoBox.className = "infoBox"; + + get("elements").appendChild(infoBox); + var div = document.createElement("div"); + div.className = "info1"; + get("infoBox").appendChild(div); + var div2 = document.createElement("div"); + div2.className = "info2"; + get("infoBox").appendChild(div2); + + for(var i = 0;i < p.length; i++) { // For all possible data types + elem = document.createElement("p"); + elem.className = "eDesc " + p[i]; + if(i <= 5) { + get("info1").appendChild(elem); + } else { + get("info2").appendChild(elem); + } + } + get("info2").appendChild(document.createElement("br")); + + box = document.createElement("div"); + box.className = "preview"; + get("infoBox").appendChild(box); + + var trans1 = get("periodictable")[92]; + var trans2 = get("periodictable")[110]; + + trans1.style.backgroundColor = "#41484D"; + trans2.style.backgroundColor = "#41484D"; + trans1.appendChild(document.createTextNode("57 - 71")); + trans2.appendChild(document.createTextNode("89 - 103")); + trans1.style.fontSize = "90%"; + trans2.style.fontSize = "90%"; + + // Creates 'reactivity' for each cell + for(var i = 0;i < elementCount;i++) { + var cell = get("td")[info["location"][i]]; // Gets location of each atom in order + + cell.onclick = function() { + lastElement = this; + var index = parseInt(this.childNodes[0].childNodes[0].nodeValue-1); + for(var i = 0;i < p.length; i++) { // Loop through all data types to be displayed + if(i == 8 || i == 9) { // If data type is melting or boiling + if(info[p[i]][settings["unit"]][index] !== null) { + // Get prefix ex. Melting: + actual value + unit + changeText(p[i],prefix[i] + info[p[i]][settings["unit"]][index] + " " + settings["unit"]); + } else { // If null + changeText(p[i],prefix[i] + "Unknown"); // Make unknown + } + } else { + if(info[p[i]][index] != null) { // If data type value isn't null + if(i == 6) { // If data type is phase/state + // Get prefix + value reference ex. 'g' -> 'Gas' + unit + changeText(p[i],prefix[i] + states[info[p[i]][index]] + unit[i]); + } else if(i == 10) { // If data type is oxidation states + var para = get("oxidStat"); + + // Remove all childs in oxidation state div + while (para.firstChild) { + para.removeChild(para.firstChild); + } + + var allStates = info[p[i]][index]; + var para1 = document.createElement("span"); + para1.appendChild(document.createTextNode(prefix[i])); + para.appendChild(para1); + + for(var j = 0;j < allStates.length; j++) { // For all states in array + oxidStat = allStates[j]; + if(j == 6) { // Add new line to prevent overflow + para.appendChild(document.createElement("br")) + } + if(allStates[j].includes("b")) { // If value has b, make value different + oxidStat = allStates[j].substring(1); + var par = document.createElement("p"); + par.appendChild(document.createTextNode(oxidStat)); + par.className = "oxid common"; + para.appendChild(par); + var par = document.createElement("span"); // Spans use inline block + par.className = "comma" + par.appendChild(document.createTextNode(", ")) + para.appendChild(par); + } else { + var pa = document.createElement("p"); + pa.appendChild(document.createTextNode(oxidStat)); + pa.className = "oxid"; + para.appendChild(pa); + pa = document.createElement("span"); // Spans use inline block + pa.className = "comma" + pa.appendChild(document.createTextNode(", ")) + para.appendChild(pa); + } + } + para.removeChild(para.lastChild); // Remove last comma + } else if(i == 11) { // If data type is electron configuration + var para = get("elecConf"); + + // Remove all childs in electron configuration div + while (para.firstChild) { + para.removeChild(para.firstChild); + } + + var elecConf = info[p[i]][index].split("."); // Ex. ["1s", "2", "2s", "2"] + para.appendChild(document.createTextNode(prefix[i])); + + if(settings["elecConf"] == "abr") { + // Add 2 to get to next non superscript and subtract one to prevent undefined + for(var j = 0;j < elecConf.length-1; j+=2) { + para.appendChild(document.createTextNode(elecConf[j])); // Append electron level + // Append value for level in superscript + var sup = document.createElement("sup"); + sup.appendChild(document.createTextNode(elecConf[j+1])); + para.appendChild(sup); + } + + } else if(settings["elecConf"] == "norm") { + while(elecConf[0].includes("[")) { // Ex: [Xe]5s2 + // Get ex. [Xe] configuration + otherConf = info[p[i]][info["shorthand"].indexOf(elecConf[0].substring(1,3))].split("."); + elecConf[0] = elecConf[0].substring(4); // [Xe]5s2 = 5s2 + for(var j = otherConf.length-1; j >= 0; j--) { + // Put configuration of abbreviation in front of last configuration + elecConf.unshift(otherConf[j]); + } + } + + // Add 2 to get to next non superscript and subtract one to prevent undefined + for(var j = 0;j < elecConf.length-1; j+=2) { + if(j == 20) { // Add new line to prevent overflow + para.appendChild(document.createElement("br")) + } + para.appendChild(document.createTextNode(elecConf[j])); // Append electron level + var sup = document.createElement("sup"); + // Append value for level in superscript + sup.appendChild(document.createTextNode(elecConf[j+1])); + para.appendChild(sup); + } + } + } else { // If not special data type + changeText(p[i],prefix[i] + info[p[i]][index] + unit[i]); + } + + } else { // If null + changeText(p[i],prefix[i] + "Unknown"); + } + } + } // Remove all childs in preview, then get new atom div + try { + get("preview").removeChild(get("preview").firstChild); + } catch(err){} + get("preview").appendChild(getAtomDOM(index,window.innerHeight/3.8)); + + } + } +} + +function changeText(dom,text) { + var dom = get(dom); + // Remove all childs in div + while (dom.firstChild) { + dom.removeChild(dom.firstChild); + } + + dom.appendChild(document.createTextNode(" ")); + dom.childNodes[0].nodeValue = text; +} + +function getAtomDOM(atomNum, size) { + var holder = document.createElement("div"); + holder.style.position = "relative"; + holder.style.height = size; + holder.style.width = size; + + var atom = document.createElement("img"); + atom.src = "./resources/reactive/Ring" + info["valeElec"][atomNum] + ".gif"; + atom.style.height = size; + atom.style.width = size; + atom.style.position = "absolute"; + atom.style.top = "0"; + atom.style.left = "0"; + + var circle = document.createElement("div"); + circle.style.borderRadius = "50%"; // Creates circle + circle.style.height = size*0.8; + circle.style.width = size*0.8; + circle.style.margin = "0 auto"; + circle.style.position = "absolute"; + circle.style.top = size*0.1; + circle.style.left = size*0.1; + + var bgColor = getColor(settings["displayTheme"],atomNum); + circle.style.backgroundColor = bgColor; + circle.style.boxShadow = "inset 0 0 0 15px " + changeColor(bgColor,20) + ", inset 0 0 10px 30px " + changeColor(bgColor,-20); + var sh = document.createElement("p"); + sh.appendChild(document.createTextNode(info["shorthand"][atomNum])); + sh.className = "sh"; + + circle.appendChild(sh); + + holder.appendChild(circle) + holder.appendChild(atom); + + return holder; +} diff --git a/atoms/js/main.js b/atoms/js/main.js index b4801db..c6f5d40 100644 --- a/atoms/js/main.js +++ b/atoms/js/main.js @@ -26,26 +26,6 @@ function update() { legendChange(dispTheme); } -function get(name) { - // Condensed format for document.getX - var elements = []; - if(document.getElementsByClassName(name).length > 0) { - elements = document.getElementsByClassName(name); - } - else if(document.getElementsByTagName(name).length > 0) { - for(var a = 0; a < document.getElementsByTagName(name).length; a++) { - elements.push(document.getElementsByTagName(name)[a]); - } - } - else if(document.getElementById(name) != null) { - elements.push(document.getElementById(name)); - } - - if(elements.length == 1) { - return elements[0]; - } else { return elements; } -} - var reader = new FileReader(); var xhr = new XMLHttpRequest(); diff --git a/atoms/js/onload.js b/atoms/js/onload.js new file mode 100644 index 0000000..974fb6f --- /dev/null +++ b/atoms/js/onload.js @@ -0,0 +1,191 @@ +function createTable() { + var tbl = document.createElement('table'); + tbl.style.border = "1px hidden"; + tbl.className = "normal"; + + // Creates table width j, height i + for(var i = 0; i < 7; i++) { + var tr = tbl.insertRow(); + for(var j = 0; j < 18; j++) { + td = tr.insertCell(); + td.className = "periodictable"; + } + } + get("sidebar")[0].appendChild(tbl); + + // Repeat of process above for Lanthanides and Actinides + tbl = document.createElement('table'); + tbl.className = "extension"; + for(var i = 0; i < 2; i++) { + var tr = tbl.insertRow(); + for(var j = 0; j < 15; j++) { + var td = tr.insertCell(); + td.className = "periodictable"; + } + } + get("sidebar")[0].appendChild(tbl); + + // Creates text for the periodic table + cells = get("td"); + for(var i = 0;i < elementCount;i++) { + ele = document.createElement("p"); + text = document.createTextNode(i+1); // i+1 to offset 0 + ele.appendChild(text); + cells[info["location"][i]].appendChild(ele); + text = document.createTextNode(info["shorthand"][i]); + cells[info["location"][i]].appendChild(text); + cells[info["location"][i]].className = cells[info["location"][i]].className +" atom"; // Adds class to prevent hover animation on blank cells + } +} + +/* function keyLegend(theme) { + // Create Table + var tbl = document.createElement('table'); + // Class for CSS + tbl.className = "key"; + // Get theme + var theme = settings["displayTheme"]; +}*/ + +function createGradientLegend() { + + var units = [""," pm"," g/mol", " kJ/mol"," kJ/mol", " eV", "", " g/mL", "",""]; + + // Create Table element + var tbl = document.createElement('table'); + + // Adds Class for styling + tbl.className = "legend"; + + // Gets theme then makes vars for hexes so that repeated table access not necessary + var theme = settings["displayTheme"]; + var index = choices[1].indexOf(theme); + var unit = settings["unit"]; + + // Filter out non-gradient layouts + if (colorChart[theme].length === 2) { + var color1 = colorChart[theme][0]; + var color2 = colorChart[theme][1]; + } + + + // Creates a gradient of 101 values wide (j) for good transition + var tr = tbl.insertRow(); + for(var j = 0; j <= 1; j += 0.01) { + var td = tr.insertCell(); + td.className = "legendcell"; + if (colorChart[theme].length === 2) { + td.style.backgroundColor = gradientColor(color1, color2 , j); + } + } + + // Adds table to key area + get("legendholder").appendChild(tbl); + + // Create Key + + var min = document.createElement("p"); + min.className = "legendrangeval minlegend"; + var max = document.createElement("p"); + max.className = "legendrangeval maxlegend" + + if (colorChart[theme].length != 2) { + var minval = document.createTextNode(""); + var maxval = document.createTextNode(""); + + } else if (theme === "melting" || theme === "boiling") { + if (unit === "K") { + var extra = " " + unit; + } else { + var extra = " °" + unit; + } + var minval = document.createTextNode(ranges[theme][unit][0] + extra); + var maxval = document.createTextNode(ranges[theme][unit][1] + extra); + + + } else { + var minval = document.createTextNode(ranges[theme][0] + " " + units[index]); + var maxval = document.createTextNode(ranges[theme][1] + " " + units[index]); + + } + min.appendChild(minval); + max.appendChild(maxval); + + get("legendholder").appendChild(min); + get("legendholder").appendChild(max); + + // Create Title + + var title = document.createElement("h1"); + title.className = "tabletitle"; + title.innerHTML = choicesDisplay[1][index] + " (" + units[index] + ")"; + get("titleholder").appendChild(title); + +} + +function makeSettings() { + for(var i = 0; i < options.length;i++) { + var parent = get("option")[i]; + var text = document.createElement("p"); + // Create text of current settings choice for this option + text.appendChild(document.createTextNode(choicesDisplay[i][choices[i].indexOf(settings[parent.id])])) + text.className = "selection"; + + parent.appendChild(text); + var holder = document.createElement("div"); //Dropdown choice holder div + holder.className = "dropdown"; + parent.appendChild(holder); + + // On mouse functions + parent.onclick = function() { + // Make visible + var k = this; + this.childNodes[1].style.display = "inline"; + // Needs delay in between to execute transition properly, do not remove. + setTimeout(function(){k.childNodes[1].style.opacity = "1";},1); + } + parent.onmouseleave = function() { + // Make invisible + var k = this; + this.childNodes[1].style.opacity = "0"; + setTimeout(function(){k.childNodes[1].display = "none";},300); //Time for opacity change + } + holder.onmouseleave = function() { + // Make invisible + var k = this; + this.style.opacity = "0"; + setTimeout(function(){k.style.display = "none";},300); //Time for opacity change + } + + for(var j = 0;j < choices[i].length;j++) { // For all choices, append div for choice selection + var p = document.createElement("p"); + p.className = i.toString() + j.toString(); + p.appendChild(document.createTextNode(choicesDisplay[i][j])) + holder.appendChild(p); + + p.onclick = function(event) { + event.stopPropagation(); // Parent onclick doesn't occur when child gets clicked + var value = this.innerHTML; + var k = this; + var setting = this.parentNode.parentNode.id; + var textDiv = this.parentNode.parentNode.childNodes[0].childNodes[0]; + // Only if different value + if(value !== textDiv.nodeValue) { + this.parentNode.style.opacity = "0"; + setTimeout(function(){k.parentNode.style.display = "none";},300); + // Text transition: opacity 0 + textDiv.parentNode.style.color = themeChart["font"][settings["theme"]].replace(")",",0)").replace("b","ba"); + // Update settings through cookie + deleteCookie(setting); + document.cookie = setting+"="+choices[parseInt(this.className[0])][parseInt(this.className[1])]; + update(); + // Text transition: opacity 1 + setTimeout(function() { + textDiv.nodeValue = value; + textDiv.parentNode.style.color = themeChart["font"][settings["theme"]].replace(")",",1)").replace("b","ba"); + }, 650) + } + } + } + } +} \ No newline at end of file diff --git a/atoms/js/tools.js b/atoms/js/tools.js new file mode 100644 index 0000000..1597b66 --- /dev/null +++ b/atoms/js/tools.js @@ -0,0 +1,134 @@ +function getColor(theme, atomNum) { + if(theme == "category") { + var color = colorChart[theme][info[theme][atomNum]]; + } else if(theme == "melting" || theme == "boiling") { + if(info[theme]["K"][atomNum] == null) { // if value is null + color = "#41484D"; + } else { + // Value - Min(all values) / Max(all values) - Min(all values) + var ratio = (info[theme]["K"][atomNum] - ranges[theme]["K"][0]) / ranges[theme]["K"][2]; + var color = gradientColor(colorChart[theme][0],colorChart[theme][1], ratio); // high, low, ratio + } + } else { + if(info[theme][atomNum] == null) { // if value is null + color = "#41484D"; + } else { + // Value - Min(all values) / Max(all values) - Min(all values) + var ratio = (info[theme][atomNum] - ranges[theme][0]) / ranges[theme][2]; + var color = gradientColor(colorChart[theme][0],colorChart[theme][1], ratio); + } + } + + return color; +} + +function changeColor(hex, amt) { + + hex = hex.slice(1); + var num = parseInt(hex,16); + var r = (num >> 16) + amt; + + if (r > 255) r = 255; + else if (r < 0) r = 0; + + var b = ((num >> 8) & 0x00FF) + amt; + + if (b > 255) b = 255; + else if (b < 0) b = 0; + + var g = (num & 0x0000FF) + amt; + + if (g > 255) g = 255; + else if (g < 0) g = 0; + + var final = (g | (b << 8) | (r << 16)).toString(16); + + // Adds preceeding zeros + while (final.length < 6) {final = "0" + final}; + return "#" + final; +} + +function gradientColor(hex1, hex2, ratio) { + + // Splits hex1 into 3 pieces (2 char each) + var hex1 = hex1.replace("#", "").match(/.{1,2}/g); + // Converts each one into int + + for (var i = 0; i <= 2; i++) { + hex1[i] = parseInt(hex1[i], 16); + } + + // Does above process for hex2 + var hex2 = hex2.replace("#", "").match(/.{1,2}/g); + for (var i = 0; i <= 2; i++) { + hex2[i] = parseInt(hex2[i], 16); + } + + // Creates end table for finished hex parts + var donetable = []; + // Averages each of the three parts between hex1 and hex2 + for (var i = 0; i <= 2; i++) { + // Weighted average to get exact gradient necessary and not average + // Round to prevent weird hex decimal shenanigans + var val = Math.round((ratio) * hex1[i] + (1 - ratio) * hex2[i]); + val = val.toString(16); + + // Adds 0 to solve math automatically removing preceeding zeroes + if (val.length === 1) { + val = "0" + val; + } + donetable[i] = val; + } + + // Rejoins hex and adds # + done = "#" + donetable.join(""); + + return done; +} + +function get(name) { + // Condensed format for document.getX + var elements = []; + if(document.getElementsByClassName(name).length > 0) { + elements = document.getElementsByClassName(name); + } + else if(document.getElementsByTagName(name).length > 0) { + for(var a = 0; a < document.getElementsByTagName(name).length; a++) { + elements.push(document.getElementsByTagName(name)[a]); + } + } + else if(document.getElementById(name) != null) { + elements.push(document.getElementById(name)); + } + + if(elements.length == 1) { + return elements[0]; + } else { return elements; } +} + +function deleteCookie(setting) { + // Sets expiration date to past date, deleting cookie automatically + document.cookie = setting+"=; expires=Thu, 01 Jan 2000 00:00:00 GMT"; +} + +function getRanges() { + // Format of ranges is [Min, Max, Range] + for(var i = 1; i < choices[1].length; i++) { // Possible data types are options except for category + var option = choices[1][i]; + if(i == 7 || i == 8) { + ranges[option] = {}; + for(var j = 0; j < 3; j++) { // Units for temperatures + var unit = choices[3][j]; + var min = Math.min.apply(null,info[option][unit]); + var max = Math.max.apply(null,info[option][unit]); + var range = max - min; + ranges[option][unit] = [min,max,range]; + } + } else { + var min = Math.min.apply(null,info[option]); + var max = Math.max.apply(null,info[option]); + var range = max - min; + ranges[option] = [min,max,range]; + } + } +} \ No newline at end of file diff --git a/atoms/js/update.js b/atoms/js/update.js new file mode 100644 index 0000000..e76b1e8 --- /dev/null +++ b/atoms/js/update.js @@ -0,0 +1,73 @@ +function changeTheme(type) { + // Changes background image + get("body").style.backgroundImage = "url('./resources/static/" + type +".png')"; + + // Changes interface element colors + for(var i = 0; i < get("pulltab").length; i++) { + get("pulltab")[i].style.backgroundColor = themeChart["pulltab"][type]; + get("pulltab")[i].style.color = themeChart["font"][settings["theme"]].replace(")",",0)"); + get("pulltab")[i].onmouseover = function() { + this.style.color = themeChart["font"][settings["theme"]].replace(")",",1)").replace("b","ba"); + } + get("pulltab")[i].onmouseleave = function() { + this.style.color = themeChart["font"][settings["theme"]].replace(")",",0)").replace("b","ba"); + } + get("sidebar")[i].style.backgroundColor = themeChart["sidebar"][type]; + get("body").style.color = themeChart["font"][type]; + } +} + +function tableTheme(theme) { + for(var i = 0;i < elementCount;i++) { + // Changes background color of each cell + if (document.getElementsByClassName("periodictable").length != 0) { + document.getElementsByClassName("periodictable")[info["location"][i]].style.backgroundColor = getColor(theme, i); + } + } + try {lastElement.click();} catch(err){} +} + +function legendChange(theme) { + var units = [""," pm"," g/mol", " kJ/mol"," kJ/mol", " eV", "", " g/mL", "",""]; + + // Title + if (document.getElementsByClassName("tabletitle").length != 0) { + var index = choices[1].indexOf(theme); + document.getElementsByClassName("tabletitle")[0].innerHTML = choicesDisplay[1][index] + " (" + units[index] + ")"; + } + + if (colorChart[theme].length != 2) { + document.getElementsByClassName("legendholder")[0].style.display = "none"; + } else { + document.getElementsByClassName("legendholder")[0].style.display = ""; + var color1 = colorChart[theme][0]; + var color2 = colorChart[theme][1]; + + if (theme === "melting" && "boiling") { + var unit = settings["unit"]; + var newmin = ranges[theme][unit][0]; + var newmax = ranges[theme][unit][1]; + + if (unit != "K") { + unit = "°" + unit; + } + newmin = newmin + " " + unit; + newmax = newmax + " " + unit; + + + } else { + var newmin = ranges[theme][0] + " " + units[index]; + var newmax = ranges[theme][1] + " " + units[index]; + } + + if (document.getElementsByClassName("legend").length != 0) { + + for(var j = 0; j <= 99; j ++) { + document.getElementsByClassName("legendcell")[j].style.backgroundColor = gradientColor(color1, color2 , j/100); + } + + document.getElementsByClassName("minlegend")[0].innerHTML = newmin; + document.getElementsByClassName("maxlegend")[0].innerHTML = newmax; + } + } +} \ No newline at end of file