issue-7 More docs. Throw some errors. Optimizations to save a couple CPU cycles.

This commit is contained in:
ellisgl 2020-12-18 13:31:02 -06:00
parent b1c098a1dc
commit ec84e8f727
3 changed files with 339 additions and 101 deletions

257
dist/tuicss.js vendored
View File

@ -1,78 +1,167 @@
/** /**
* Init * Replacement for jQuery's $(document).ready() function.
* This is handy in making sure stuff fires after the DOM is ready to be touched.
* Stolen from:https://stackoverflow.com/a/53601942/344028
*
* @param fn Callback.
*/ */
$(document).ready(function() { function domReady(fn) {
tabsController(); // If we're early to the party
datetimeController(); document.addEventListener('DOMContentLoaded', fn);
sidenavController();
modalController(); // If late; I mean on time.
}); if (document.readyState === 'interactive' || document.readyState === 'complete') {
fn();
}
}
/** /**
* TuiTabs controller * TuiTabs controller
*/ */
function tabsController() { function tabsController() {
$(".tui-tab").click(function(event) { // Get all the tab elements (typically li tags).
$(".tui-tab-content").hide(); const tabs = document.getElementsByClassName('tui-tab');
let tabContentid = $(this).attr('data-tab-content');
$(`#${tabContentid}`).show(); if (!tabs.length) {
$(".tui-tab").removeClass("active"); // No tabs found, return early and save a couple CPU cycles.
$(this).addClass("active"); return;
}
for (const tab of tabs) {
// Add click listeners to them.
tab.addEventListener('click', function (e) {
// Remove the 'active' class from any and all tabs.
for (const otherTab of tabs) {
otherTab.classList.remove('active');
}
// Get the content element.
const tabContents = document.getElementsByClassName('tui-tab-content');
if (tabContents) {
for (const tabContent of tabContents) {
// Hide all tab contents.
tabContent.style.display = 'none';
}
} else {
throw 'No tab content elements found.'
}
// Get the id of the tab contents we want to show.
const tabContentId = e.target.getAttribute('data-tab-content');
if (tabContentId) {
const tabContent = document.getElementById(tabContentId);
if (tabContent) {
// Show the tab contents.
tabContent.style.display = 'block';
} else {
throw 'No tab content element with id "' + tabContentId + '" found.';
}
}
// We are not going to throw an error here, since we could make the tab do something else that a tab
// normally wouldn't do.
// Set the clicked tab to have the 'active' class so we can use it in the next part.
e.target.classList.add('active');
}); });
$('.tui-tab.active').click(); }
// Grab the first tab with the active class.
const activeTab = document.querySelector('.tui-tab.active');
if (activeTab) {
// Now click it 'click' it.
activeTab.click();
} else {
// Nothing found, just click the first tab foud.
tabs[0].click()
}
} }
/** /**
* Date field controller * Date/time field controller
*/ */
function datetimeController() { function datetimeController() {
// Get date/time elements.
const clocks = document.getElementsByClassName('tui-datetime');
if(!$(".tui-datetime").length) return; if (!clocks.length) {
// No date time elements found, return early and save a couple CPU cycles.
return;
}
// Kick off our clock interval stuff.
datetimeInterval(); datetimeInterval();
setInterval(datetimeInterval, 1000); setInterval(datetimeInterval, 1000);
function datetimeInterval() { function datetimeInterval() {
let today = new Date(); for (const clock of clocks) {
// Set the interval.
const interval = setInterval(() => {
// Technically we should have already returned earlier in the code, but to be on the safe side.
if (clock === null) {
clearInterval(interval);
return;
}
$(".tui-datetime").each(function() { // Get the format we want to display in the element.
let clock = $(this); let format = clock.getAttribute('data-format');
let format = clock.attr("data-format"); // parse out the date and time into constants.
const today = new Date();
const month = (today.getMonth() + '').length === 2 ? today.getMonth() + 1 : '0' + (today.getMonth() + 1);
const day = (today.getDay() + '').length === 2 ? today.getDay() + 1 : '0' + (today.getDay() + 1);
const year = today.getFullYear() + '';
const hour = (today.getHours() + '').length === 2 ? today.getHours() : '0' + today.getHours();
const hour12 = (parseInt(hour) + 24) % '12' || '12';
const minute = (today.getMinutes() + '').length === 2 ? today.getMinutes() : '0' + today.getMinutes();
const second = (today.getSeconds() + '').length === 2 ? today.getSeconds() : '0' + today.getSeconds();
const ampm = parseInt(hour) >= 12 ? 'PM' : 'AM';
let month = (today.getMonth() + "").length == 2 ? today.getMonth() + 1 : "0" + (today.getMonth() + 1); // Replace based on the format.
let day = (today.getDay() + "").length == 2 ? today.getDay() + 1 : "0" + (today.getDay() + 1); format = format.replace('M', month);
let year = today.getFullYear(); format = format.replace('d', day);
let hour = (today.getHours() + "").length == 2 ? today.getHours() : "0" + today.getHours(); format = format.replace('y', year);
let hour12 = (parseInt(hour) + 24) % 12 || 12; format = format.replace('H', hour);
let minute = (today.getMinutes() + "").length == 2 ? today.getMinutes() : "0" + today.getMinutes(); format = format.replace('h', hour12);
let second = (today.getSeconds() + "").length == 2 ? today.getSeconds() : "0" + today.getSeconds(); format = format.replace('m', minute);
let ampm = parseInt(hour) >= 12 ? "PM" : "AM"; format = format.replace('s', second);
format = format.replace('a', ampm);
format = format.replace("M", month); // Show it in the element.
format = format.replace("d", day); clock.innerHTML = format;
format = format.replace("y", year);
format = format.replace("H", hour);
format = format.replace("h", hour12);
format = format.replace("m", minute);
format = format.replace("s", second);
format = format.replace("a", ampm);
clock.html(format);
}); });
} }
}
} }
/** /**
* Sidenav Controller * Sidenav Controller
* There should only side navigation element at the moment.
*/ */
function sidenavController() { function sidenavController() {
$(".tui-sidenav-button").click(function() { // Get the side navigation button (there should be only one, but if not, we are getting the first one).
let sidenav = $(".tui-sidenav"); const sideNavButton = document.querySelector('.tui-sidenav-button');
if(sidenav.hasClass("active")) {
$(".tui-sidenav").removeClass("active"); if (!sideNavButton) {
// No side navigation button found, return early and save a couple CPU cycles.
return;
}
// Add the click event listener to the buttons.
sideNavButton.addEventListener('click', () => {
// Get the side navigation element (there should be only one, but if not, we are getting the first one).
const sideNav = document.querySelector('.tui-sidenav');
if (sideNav) {
if (sideNav.classList.contains('active')) {
sideNav.classList.remove('active');
} else { } else {
$(".tui-sidenav").addClass("active"); sideNav.classList.add('active');
}
} else {
throw 'No sidenav element found.'
} }
}); });
} }
@ -81,14 +170,80 @@ function sidenavController() {
* Modal controller * Modal controller
*/ */
function modalController() { function modalController() {
$(".tui-modal-button").click(function() { // Get the overlap (overlay) element (there should be only one, but if not, we are getting the first one).
$(".tui-overlap").addClass("active"); const tuiOverlap = document.querySelector('.tui-overlap');
let modalId = $(this).attr("data-modal");
$(`#${modalId}`).addClass("active"); if (!tuiOverlap) {
// No overlap found element, return early and save a couple CPU cycles.
return;
}
// Find modal buttons.
const modalButtons = document.getElementsByClassName('tui-modal-button');
for (const modalButton of modalButtons) {
// Add the click event listener to the buttons.
modalButton.addEventListener('click', (e) => {
// Show the overlap.
tuiOverlap.classList.add('active');
// Get the display element for the modal.
const modalId = e.target.getAttribute('data-modal');
if (modalId) {
const modal = document.getElementById(modalId);
if (modal) {
// Show it.
modal.classList.add('active');
} else {
throw 'No modal element with id of "' + modalId + '" found.';
}
} else {
throw 'Modal close button data-modal attribute is empty or not set.'
}
}); });
$(".tui-modal-close-button").click(function() { }
$(".tui-overlap").removeClass("active");
let modalId = $(this).attr("data-modal"); // Find the close modal buttons.
$(`#${modalId}`).removeClass("active"); const modalCloseButtons = document.getElementsByClassName('tui-modal-close-button');
if (modalButtons.length > 0 && !modalCloseButtons.length) {
// A modal without a close button, is a bad modal.
throw 'No modal close buttons found.'
}
for (const modalCloseButton of modalCloseButtons) {
// Add the click event listener to the buttons.
modalCloseButton.addEventListener('click', (e) => {
// Hide the the overlap.
tuiOverlap.classList.remove('active');
// Get the display element id for the modal.
const modalId = e.target.getAttribute('data-modal');
if (modalId) {
// Get the modal element.
const modal = document.getElementById(modalId);
if (modal) {
// Hide it.
modal.classList.remove('active');
} else {
throw 'No modal element with id of "' + modalId + '" found.';
}
} else {
throw 'Modal close button data-modal attribute is empty or not set.'
}
}); });
}
} }
/**
* Init: This is at the bottom to make sure it is fired correctly.
*/
domReady(function () {
tabsController();
datetimeController();
sidenavController();
modalController();
});

2
dist/tuicss.min.js vendored
View File

@ -1 +1 @@
function tabsController(){$(".tui-tab").click(function(t){$(".tui-tab-content").hide();let e=$(this).attr("data-tab-content");$(`#${e}`).show(),$(".tui-tab").removeClass("active"),$(this).addClass("active")}),$(".tui-tab.active").click()}function datetimeController(){function t(){let t=new Date;$(".tui-datetime").each(function(){let e=$(this),a=e.attr("data-format"),n=2==(t.getMonth()+"").length?t.getMonth()+1:"0"+(t.getMonth()+1),l=2==(t.getDay()+"").length?t.getDay()+1:"0"+(t.getDay()+1),i=t.getFullYear(),o=2==(t.getHours()+"").length?t.getHours():"0"+t.getHours(),c=(parseInt(o)+24)%12||12,s=2==(t.getMinutes()+"").length?t.getMinutes():"0"+t.getMinutes(),r=2==(t.getSeconds()+"").length?t.getSeconds():"0"+t.getSeconds(),u=parseInt(o)>=12?"PM":"AM";a=(a=(a=(a=(a=(a=(a=(a=a.replace("M",n)).replace("d",l)).replace("y",i)).replace("H",o)).replace("h",c)).replace("m",s)).replace("s",r)).replace("a",u),e.html(a)})}$(".tui-datetime").length&&(t(),setInterval(t,1e3))}function sidenavController(){$(".tui-sidenav-button").click(function(){$(".tui-sidenav").hasClass("active")?$(".tui-sidenav").removeClass("active"):$(".tui-sidenav").addClass("active")})}function modalController(){$(".tui-modal-button").click(function(){$(".tui-overlap").addClass("active");let t=$(this).attr("data-modal");$(`#${t}`).addClass("active")}),$(".tui-modal-close-button").click(function(){$(".tui-overlap").removeClass("active");let t=$(this).attr("data-modal");$(`#${t}`).removeClass("active")})}$(document).ready(function(){tabsController(),datetimeController(),sidenavController(),modalController()}); function domReady(t){document.addEventListener("DOMContentLoaded",t),"interactive"!==document.readyState&&"complete"!==document.readyState||t()}function tabsController(){const t=document.getElementsByClassName("tui-tab");if(!t.length)return;for(const e of t)e.addEventListener("click",function(e){for(const e of t)e.classList.remove("active");const o=document.getElementsByClassName("tui-tab-content");if(!o)throw"No tab content elements found.";for(const t of o)t.style.display="none";const n=e.target.getAttribute("data-tab-content");if(n){const t=document.getElementById(n);if(!t)throw'No tab content element with id "'+n+'" found.';t.style.display="block"}e.target.classList.add("active")});const e=document.querySelector(".tui-tab.active");e?e.click():t[0].click()}function datetimeController(){const t=document.getElementsByClassName("tui-datetime");function e(){for(const e of t){const t=setInterval(()=>{if(null===e)return void clearInterval(t);let o=e.getAttribute("data-format");const n=new Date,a=2===(n.getMonth()+"").length?n.getMonth()+1:"0"+(n.getMonth()+1),s=2===(n.getDay()+"").length?n.getDay()+1:"0"+(n.getDay()+1),c=n.getFullYear()+"",l=2===(n.getHours()+"").length?n.getHours():"0"+n.getHours(),i=(parseInt(l)+24)%"12"||"12",r=2===(n.getMinutes()+"").length?n.getMinutes():"0"+n.getMinutes(),d=2===(n.getSeconds()+"").length?n.getSeconds():"0"+n.getSeconds(),u=parseInt(l)>=12?"PM":"AM";o=(o=(o=(o=(o=(o=(o=(o=o.replace("M",a)).replace("d",s)).replace("y",c)).replace("H",l)).replace("h",i)).replace("m",r)).replace("s",d)).replace("a",u),e.innerHTML=o})}}t.length&&(e(),setInterval(e,1e3))}function sidenavController(){const t=document.querySelector(".tui-sidenav-button");t&&t.addEventListener("click",()=>{const t=document.querySelector(".tui-sidenav");if(!t)throw"No sidenav element found.";t.classList.contains("active")?t.classList.remove("active"):t.classList.add("active")})}function modalController(){const t=document.querySelector(".tui-overlap");if(!t)return;const e=document.getElementsByClassName("tui-modal-button");for(const o of e)o.addEventListener("click",e=>{t.classList.add("active");const o=e.target.getAttribute("data-modal");if(!o)throw"Modal close button data-modal attribute is empty or not set.";{const t=document.getElementById(o);if(!t)throw'No modal element with id of "'+o+'" found.';t.classList.add("active")}});const o=document.getElementsByClassName("tui-modal-close-button");if(e.length>0&&!o.length)throw"No modal close buttons found.";for(const e of o)e.addEventListener("click",e=>{t.classList.remove("active");const o=e.target.getAttribute("data-modal");if(!o)throw"Modal close button data-modal attribute is empty or not set.";{const t=document.getElementById(o);if(!t)throw'No modal element with id of "'+o+'" found.';t.classList.remove("active")}})}domReady(function(){tabsController(),datetimeController(),sidenavController(),modalController()});

View File

@ -1,5 +1,6 @@
/** /**
* Replacement for jQuery's $(document).ready() function. * Replacement for jQuery's $(document).ready() function.
* This is handy in making sure stuff fires after the DOM is ready to be touched.
* Stolen from:https://stackoverflow.com/a/53601942/344028 * Stolen from:https://stackoverflow.com/a/53601942/344028
* *
* @param fn Callback. * @param fn Callback.
@ -18,36 +19,63 @@ function domReady(fn) {
* TuiTabs controller * TuiTabs controller
*/ */
function tabsController() { function tabsController() {
// Get all the tab elements (typically li tags).
const tabs = document.getElementsByClassName('tui-tab'); const tabs = document.getElementsByClassName('tui-tab');
for (const tab of tabs) { if (!tabs.length) {
tab.addEventListener('click', function (e) { // No tabs found, return early and save a couple CPU cycles.
// Deactivate the tab. return;
tab.classList.remove('active'); }
for (const tab of tabs) {
// Add click listeners to them.
tab.addEventListener('click', function (e) {
// Remove the 'active' class from any and all tabs.
for (const otherTab of tabs) {
otherTab.classList.remove('active');
}
// Get the content element.
const tabContents = document.getElementsByClassName('tui-tab-content'); const tabContents = document.getElementsByClassName('tui-tab-content');
if (tabContents) {
for (const tabContent of tabContents) { for (const tabContent of tabContents) {
// Hide all tab contents.
tabContent.style.display = 'none'; tabContent.style.display = 'none';
} }
} else {
const tabContentId = e.target.getAttribute('data-tab-content'); throw 'No tab content elements found.'
const tabContent = document.getElementById(tabContentId);
if (tabContent) {
tabContent.style.display = 'block';
} }
// Set the clicked tab to have the active click for the next part. // Get the id of the tab contents we want to show.
const tabContentId = e.target.getAttribute('data-tab-content');
if (tabContentId) {
const tabContent = document.getElementById(tabContentId);
if (tabContent) {
// Show the tab contents.
tabContent.style.display = 'block';
} else {
throw 'No tab content element with id "' + tabContentId + '" found.';
}
}
// We are not going to throw an error here, since we could make the tab do something else that a tab
// normally wouldn't do.
// Set the clicked tab to have the 'active' class so we can use it in the next part.
e.target.classList.add('active'); e.target.classList.add('active');
}); });
} }
// Grab the first tab with the active class.
const activeTab = document.querySelector('.tui-tab.active'); const activeTab = document.querySelector('.tui-tab.active');
if (activeTab) { if (activeTab) {
// There can only be one active tab, so click the first found. // Now click it 'click' it.
activeTab.click(); activeTab.click();
} else {
// Nothing found, just click the first tab foud.
tabs[0].click()
} }
} }
@ -55,26 +83,32 @@ function tabsController() {
* Date/time field controller * Date/time field controller
*/ */
function datetimeController() { function datetimeController() {
// Get date/time elements.
const clocks = document.getElementsByClassName('tui-datetime'); const clocks = document.getElementsByClassName('tui-datetime');
// No elements found, return early.
if (!clocks.length) { if (!clocks.length) {
// No date time elements found, return early and save a couple CPU cycles.
return; return;
} }
// Kick off our clock interval stuff.
datetimeInterval(); datetimeInterval();
setInterval(datetimeInterval, 1000); setInterval(datetimeInterval, 1000);
function datetimeInterval() { function datetimeInterval() {
for (const clock of clocks) { for (const clock of clocks) {
// Set the interval.
const interval = setInterval(() => { const interval = setInterval(() => {
// Technically we should have already returned earlier in the code, but to be on the safe side.
if (clock === null) { if (clock === null) {
clearInterval(interval); clearInterval(interval);
return; return;
} }
// Get the format we want to display in the element.
let format = clock.getAttribute('data-format'); let format = clock.getAttribute('data-format');
// parse out the date and time into constants.
const today = new Date(); const today = new Date();
const month = (today.getMonth() + '').length === 2 ? today.getMonth() + 1 : '0' + (today.getMonth() + 1); const month = (today.getMonth() + '').length === 2 ? today.getMonth() + 1 : '0' + (today.getMonth() + 1);
const day = (today.getDay() + '').length === 2 ? today.getDay() + 1 : '0' + (today.getDay() + 1); const day = (today.getDay() + '').length === 2 ? today.getDay() + 1 : '0' + (today.getDay() + 1);
@ -85,6 +119,7 @@ function datetimeController() {
const second = (today.getSeconds() + '').length === 2 ? today.getSeconds() : '0' + today.getSeconds(); const second = (today.getSeconds() + '').length === 2 ? today.getSeconds() : '0' + today.getSeconds();
const ampm = parseInt(hour) >= 12 ? 'PM' : 'AM'; const ampm = parseInt(hour) >= 12 ? 'PM' : 'AM';
// Replace based on the format.
format = format.replace('M', month); format = format.replace('M', month);
format = format.replace('d', day); format = format.replace('d', day);
format = format.replace('y', year); format = format.replace('y', year);
@ -94,6 +129,7 @@ function datetimeController() {
format = format.replace('s', second); format = format.replace('s', second);
format = format.replace('a', ampm); format = format.replace('a', ampm);
// Show it in the element.
clock.innerHTML = format; clock.innerHTML = format;
}); });
} }
@ -102,61 +138,108 @@ function datetimeController() {
/** /**
* Sidenav Controller * Sidenav Controller
* There should only side navigation element at the moment.
*/ */
function sidenavController() { function sidenavController() {
const sideNavButtons = document.getElementsByClassName('tui-sidenav-button'); // Get the side navigation button (there should be only one, but if not, we are getting the first one).
const sideNavButton = document.querySelector('.tui-sidenav-button');
for (const sideNavButton of sideNavButtons) { if (!sideNavButton) {
// No side navigation button found, return early and save a couple CPU cycles.
return;
}
// Add the click event listener to the buttons.
sideNavButton.addEventListener('click', () => { sideNavButton.addEventListener('click', () => {
const sideNavs = document.getElementsByClassName('tui-sidenav'); // Get the side navigation element (there should be only one, but if not, we are getting the first one).
for (const sideNav of sideNavs) { const sideNav = document.querySelector('.tui-sidenav');
if (sideNav) {
if (sideNav.classList.contains('active')) { if (sideNav.classList.contains('active')) {
sideNav.classList.remove('active'); sideNav.classList.remove('active');
} else { } else {
sideNav.classList.add('active'); sideNav.classList.add('active');
} }
} else {
throw 'No sidenav element found.'
} }
}); });
}
} }
/** /**
* Modal controller * Modal controller
*/ */
function modalController() { function modalController() {
// Attach to the button that shows the modal. // Get the overlap (overlay) element (there should be only one, but if not, we are getting the first one).
const modalButtons = document.getElementsByClassName('tui-modal-button'); const tuiOverlap = document.querySelector('.tui-overlap');
for (const modalButton of modalButtons) {
modalButton.addEventListener('click', (e) => { if (!tuiOverlap) {
const tuiOverlaps = document.getElementsByClassName('tui-overlap'); // No overlap found element, return early and save a couple CPU cycles.
for (const tuiOverlap of tuiOverlaps) { return;
tuiOverlap.classList.add('active');
} }
// Find modal buttons.
const modalButtons = document.getElementsByClassName('tui-modal-button');
for (const modalButton of modalButtons) {
// Add the click event listener to the buttons.
modalButton.addEventListener('click', (e) => {
// Show the overlap.
tuiOverlap.classList.add('active');
// Get the display element for the modal.
const modalId = e.target.getAttribute('data-modal'); const modalId = e.target.getAttribute('data-modal');
if (modalId) {
const modal = document.getElementById(modalId); const modal = document.getElementById(modalId);
if (modal) {
// Show it.
modal.classList.add('active'); modal.classList.add('active');
} else {
throw 'No modal element with id of "' + modalId + '" found.';
}
} else {
throw 'Modal close button data-modal attribute is empty or not set.'
}
}); });
} }
// Attach to the button that removes the modal. // Find the close modal buttons.
const modalCloseButtons = document.getElementsByClassName('tui-modal-close-button'); const modalCloseButtons = document.getElementsByClassName('tui-modal-close-button');
for (const modalCloseButton of modalCloseButtons) {
modalCloseButton.addEventListener('click', (e) => { if (modalButtons.length > 0 && !modalCloseButtons.length) {
const tuiOverlaps = document.getElementsByClassName('tui-overlap'); // A modal without a close button, is a bad modal.
for (const tuiOverlap of tuiOverlaps) { throw 'No modal close buttons found.'
tuiOverlap.classList.remove('active');
} }
for (const modalCloseButton of modalCloseButtons) {
// Add the click event listener to the buttons.
modalCloseButton.addEventListener('click', (e) => {
// Hide the the overlap.
tuiOverlap.classList.remove('active');
// Get the display element id for the modal.
const modalId = e.target.getAttribute('data-modal'); const modalId = e.target.getAttribute('data-modal');
if (modalId) {
// Get the modal element.
const modal = document.getElementById(modalId); const modal = document.getElementById(modalId);
if (modal) {
// Hide it.
modal.classList.remove('active'); modal.classList.remove('active');
} else {
throw 'No modal element with id of "' + modalId + '" found.';
}
} else {
throw 'Modal close button data-modal attribute is empty or not set.'
}
}); });
} }
} }
/** /**
* Init: This is at the bottom to make sure the functions are parsed. It's a CYA. * Init: This is at the bottom to make sure it is fired correctly.
*/ */
domReady(function () { domReady(function () {
tabsController(); tabsController();