How is made?
This Neocities Website is front-end only so, no logic stuff (except a little bit of JS). My main goal was and is to make a fully understandable code in form of a website. Now I will explain how and why I do some of "this code".
Main Attraction Of My Website
The fundamental hook is: You can hover everything, there is so much info.
How Did I Accomplish This?
HTML
The key is to put a lot of Title attributes. I mean, eeeeverywheeere.
<span class="title" title="Hypertext Markup Languaje">HTML</span>
In the first place, I was using the abbr tag (abbreviation). But when I saw that almost every tag can have a title attribute, I deleted all the abbr tag and replaced it with title.
But one problem arise (well, many problems), the user can not know that a certain word/phrase have a information associated. The solution: CSS style.
The other problem? Mobile-users. So scary! But I wanna give them the opportunity to have a 100% experience like in the PC. Solution: JS and StackOverFlow (God Bless Them).
CSS
If I do a distinctive pattern in order to have the curiosity of the user, eventually, will hover it and discover the information beneath that. And once discovered, it'll know that that specific pattern of colors means info. Soemthing like:
//Example to have the attention of the user *[title]{ background-color: red; color: green; &:hover{ //Once hover, invert the background and the letter colors color: red; background-color: green; } }Real Example
JS
As you can see in my script devices.js:
1. First I need to gather all the attibutes, but JS doesn't support it.
//Solution: Cry, beg and put a class in every title attribute. //Then, gather all the classes named "title" var deltaTouch; //Global variable defined let abreviationList = document.querySelectorAll(".title");
2. Check if the user is in a mobile ('cause this is only for mobile-users).
//In my PC, firefox says this (putting this command in the web command): window.navigator.userAgent "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0" //But when I emulate a mobile browser and run the same command it says: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1"
Knowing that, I just need to know if this string have a "Mobile" in any part of it.
//The "function" indexOf() return "-1" only if it not found the word "Mobile" //And in this line I'm saying: //Can you find the word "Mobile" here? //And will respond "true" or "false" let isScriptMobile = (window.navigator.userAgent.indexOf("Mobile") != -1);
If it has been found, I'll put an Event in every single title saying: if the user touch you twice, then appear the info you have inside as a popup.
//For Every Title Attribute abreviationList.forEach(abbr => { //I'll put an Event where detected a touch abbr.addEventListener("touchstart", function(e){ //2. Confirm if is a doubleTap let doubleTap = isDoubleTap(e); if (doubleTap) { //if is true, show the content as a popup e.preventDefault(); //3. ShowAbbreviation(abbr); } }) }); //The Other Functions: //3. Just to show the content of the title function ShowAbbreviation(abbr){ alert(abbr.title); } //2. The parameter is an event (advanced stuff) function isDoubleTap(e) { const maxTime = 700; //Time between taps let doubleTapDetected = false; let touch = e.touches.length; if (touch === 1) { //If has no value, I will put one if (!deltaTouch) { //Time given between taps deltaTouch = e.timeStamp + maxTime; } else{ let isNotExpired = (e.timeStamp <= deltaTouch); if (isNotExpired) { e.preventDefault(); //reset the variable deltaTouch = null; console.log("Double Tap detected!"); doubleTapDetected = true; } else{ //Reset timer for the Double Tap/Touch deltaTouch = e.timeStamp + maxTime; } } } return doubleTapDetected; }
THE END!!!
The Counter / Visitors
Here is the code of the counter
This counter will put three things: Your views, time created (the website) and the last update.
If you are going to use it, make sure to read the last part ("Show your own website").
0. Put All The Functions Together
async function Search(){ const siteInfo = "https://weirdscifi.ratiosemper.com/neocities.php?sitename="; //Search This Site And Give Me All The Info. //I will wait for you, okay? let theInfo = await GetSiteInfo(siteInfo, username); //You found it for real? if (theInfo.success) { //Let's Show The Data =D SetCounterInfo(theInfo); } }
1. Fetching The Information
To make a search ("request"), you have to use the keyword fetch (can be multitasking, a perfect synonym: asyncronous with Promises) like this:
//Telling that the function is "asynchronous" async function GetSiteInfo(urlSite, username){ //Making a Web Mould Of All the data I need is more EZ (and more just in case) let yourWebsiteData = { success: false, views: 0, hits: 0, created: "", updated: "", domain: "", tags: [], } //Search this and Wait until I respond, please await fetch(urlSite + username) .then(resp => { //If there is answer, Yey! if (resp.ok) { // console.log("Yey, I found you!"); //Go to the next ".then" with the data return resp.json(); } else{ throw new Error("You have NOT been found :c"); } }) .then(data => { //If the data is retrived nice, perfect! if (data.result == "success") { const separatorDate = "/"; let created = new Date(data.info.created_at); let updated = new Date(data.info.last_updated); //Let's put the data into the Mould yourWebsiteData.success = true; yourWebsiteData.name = data.info.sitename; yourWebsiteData.views = data.info.views; yourWebsiteData.hits = data.info.hits; yourWebsiteData.created = created; yourWebsiteData.updated = updated; yourWebsiteData.domain = data.info.domain; yourWebsiteData.tags = data.info.tags; console.log("I have your website data, jiji"); // console.log(yourWebsiteData); } }) //".catch" can catch an error and handle it appropriately c= .catch(error => console.error(error)); //return the data I get return yourWebsiteData; }
2. Show The Info I Get
function SetCounterInfo(webData){ //Search this Id on the HTML (to write the data) let viewBox = document.querySelector("#views"); let createdBox = document.querySelector("#created"); let updatedBox = document.querySelector("#updated"); //if the user selected 0 -> default view (1234) let views = webData.views; switch (viewSelector) { case 1: views = BetterViewsInfo(webData.views); //Let's transform it into this 1.234 break; case 2: views = BestViewInfo(webData.views); //Fancy, let's do it like Youtube break; //If is -1 or other thing, Don't Show Anything case -1: views = ""; break; } let betterCreatedDate = ""; let betterUpdatedDate = ""; //REMEMBER: -1 means hide the result / data if (createdType != -1) { betterCreatedDate = BetterDateInfo(webData.created, createdType); } if (updatedType != -1) { betterUpdatedDate = BetterDateInfo(webData.updated, updatedType); } //If the value is MORE THAN 0, show the result with proud if (viewSelector > 0) { viewBox.innerText ="My views: " + views; } if (createdType >= 0) { createdBox.innerText = 'Created: ' + betterCreatedDate; } if (updatedType >= 0) { updatedBox.innerText = `Updated: ${betterUpdatedDate}`; } // console.log("Write it down"); }
Show Your Own Website
I explain how this works in the script TnT, but I'll do it again.
-
First, you need this structure (to target and write your website's data):
<section id="stats-box"> <article class="stat"> <p id="views"></p> <p id="created"></p> <p id="updated"></p> </article> </section>
-
Then, put Your Neocities Username. Examples: mine is user-maldito (https://neocities.org/site/user-maldito)
//Line 7: const username = "user-maldito";
-
Select The Type of View: Default (0), Separator(1 & ","), Fancy(2) or None(-1)
const viewSelector = 0; //Output: 123456 const viewSelector = 1; const separator = ' '; //Output: 123 456 const viewSelector = 1; const separator = '.'; //Output: 123.456 const viewSelector = 2; //Output: 123K const viewSelector = -1; //Output:
-
Date Output Variation
const createdType = -1; //Output: Hidden const updatedType = 1; // Output: 19 day(s) ago //------ const createdType = 2; // Output: 2 week(s) ago const updatedType = 3; // Output: Less than a Month ago //------ const createdType = 4; // Output: Less than a Year ago //putting 0 or other thing will display this: const updatedType = 5; // Output: X year(s) Y Month(s) aprox
Using Masonry
It's so simple that only have 2 steps:
-
Put the Masonry link:
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
-
Write The Masonry Syntaxis (HTML) [tag1 data-masonry='{ "itemSelector": ".(theClass)", "columnWidth": 200 }' + tag2 class="theClass"]:
//Set the desired class (Not Tested Example) <div data-masonry='{ "itemSelector": ".masonry-class", "columnWidth": 200 }'> <img class="masonry-class" src="/folder/img/photo1.png"> <img class="masonry-class" src="/folder/img/photo2.png"> <img class="masonry-class" src="/folder/img/photo3.png"> <img class="masonry-class" src="/folder/img/photo4.png"> </div>
Using Bootstrap
It's almost the same as Masonry: Using their link/script and using class to change the behavior of the page. Example:
<head> //With this links (via CDN) you can use Bootstrap //(Not working offline) <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script> </head>
With Bootstrap in our Website, I wanna change (for example) my nav into Flex mode, row and all centered (common problem)
<body> <div id="container"> <p>I am inside a container, help!</p> </div> <nav class="d-flex flex-row justify-content-center align-items-center"> <ul> <li> <a href="/folder/home">C:/ Home </a> </li> <li> <a href="/folder/shrine">C:/ Shrine </a> </li> <li> <a href="/folder/about">C:/ About </a> </li> </ul> </nav> </body>
Theme Changer
Wanna look cool making different styles on your website but you have 0 knowledge of JS? If you can understand it, this code is for you (I wanna credits, that's all)
1. When The Window/Document is loading...
- Grab some things in the page (the form to change the layout and all the CSS styles outside).
- Then listen if the user select other options and if it's true, do Something (explained in the third point)
- Also, I need if there is already other layout. Search if it's true.
- Am I in the Gallery? The gallery have a different layout.
- Oh, and if my layout isn't there, then let's put the Default Layout (Hacker) in the page. I'll write it somewhere the name to not forget it.
window.onload = () => { //Definition of all the Elements of the Web DOM.layoutSelect = document.getElementById("changingLayout"); //The Select in the form DOM.allLinksCss = document.querySelectorAll("link"); //All links in the HTML right now //Listening Events DOM.layoutSelect.addEventListener("change", ChangeLayout); //Set items let localLayout = localStorage.getItem("layoutName"); let isGallery = window.location.pathname.includes("Online/Gallery/My-Camera-Roll/index.html"); // If we are in my gallery (with that url/link/whatever), wanna load my css gallery super-duper-special // If not, go to default layout: hacker if ((localLayout == "retro") || (localLayout == "hacker") || (localLayout == "gallery_retro")){ localLayout = "hacker"; if (isGallery) { localLayout = "gallery_retro"; } } /* Default Layout: Hacker (Gallery included) */ if ((localLayout.length == 0) & DOM.allLinksCss.length == 0) { localLayout = "hacker"; if (isGallery){ localLayout = "gallery_retro"; } } VerifingNewLayout(localLayout); localStorage.setItem("layoutName", localLayout); };
2. Veryfing The Layout Name...
If the name of the Layout is valid and correct, then change it. How?
- Take all the CSS tags.
- Delete the Style (the CSS tags I gather before).
- Depending of the layout selected, use it (put new CSS tags).
- Put a funny log if someone is seeing the console command.
- OPTIONAL: If the user is in the mobile, change something.
- Remember the name of the Layout!
function VerifingNewLayout(newLayout){ //Refreshing the definition (of all the links) [necessary] DOM.allLinksCss = document.querySelectorAll("link"); let newLayoutName = ""; switch (newLayout) { case "nothing": newLayoutName = "nothing"; break; case "default": NoCSS(); BootstrapCSS(); console.log("Default Default Default Default Default :)"); newLayoutName = "default"; break; case "css_hater": NoCSS(); console.log("CSS Hater Spotted"); newLayoutName = "css_hater"; break; case "retro": NoCSS(); let message = "Please, don't hack me. I'll do anything, but don't hurt me TnT"; let isCSSMobile = (window.navigator.userAgent.indexOf("Mobile") != -1); if (isCSSMobile) { message = "Oh, I see..."; //Music let musicPlayer = document.querySelector("iframe"); // musicPlayer.width = "90%"; musicPlayer.height= "152px"; } HackerCSS("hacker"); console.log(message); newLayoutName = "hacker"; break; //Gallery Layout case "gallery_retro": NoCSS(); HackerGalleryCSS("hacker"); BootstrapCSS(); console.log("STOP HACKING ME! I'M SCARED!! PLS, I'LL DO ANYTHING!!!"); newLayoutName = "gallery_retro"; break; default: newLayoutName = "trolling"; //do the barrel roll? idk console.log("So funny touching the code I made, right? C:"); break; } return newLayoutName; }
3. And If I Choose Another?
When the user choose another style, we're gonna change it.
//function inside window.onload //If the select tag change the value, execute ChangeLayout DOM.layoutSelect.addEventListener("change", ChangeLayout); //function outside window.onload function ChangeLayout(){ //Weird form of getting the name of the selected option let selectedTheme = DOM.layoutSelect.options[DOM.layoutSelect.selectedIndex].value; let layoutName = VerifingNewLayout(selectedTheme); localStorage.setItem("layoutName", layoutName); }
4. And How Do You...?
Remove The Style (CSS)?
- Target All The Links
- Delete It
function NoCSS() { //Remove All The Links (CSS Tags) DOM.allLinksCss.forEach((cssLink) => { cssLink.remove(); }); }
Put Your Style?
- Create a Tag (Yes, you can create a tag in JS)
- Insert the Attributes and Values
- Attach them to the Head
//Simplify Version //folder = "hacker" -> that why you should have a //CSS folder with the name of the layout function HackerCSS(folder) { //I Create The Element "Link" and Attach them with a the Relative Path let link_1 = document.createElement("link"); let link_2 = document.createElement("link"); let link_3 = document.createElement("link"); link_2.setAttribute("rel", "stylesheet"); link_3.setAttribute("rel", "stylesheet"); link_1.setAttribute("rel", "stylesheet"); link_3.setAttribute("href", "/css/"+folder+"/header/header.css"); link_2.setAttribute("href", "/css/"+folder+"/footer/footer.css"); link_1.setAttribute("href", "/css/"+folder+folder+".css"); //The basis of my style is in: /css/hacker/hacker.css //Putting it in the end before the close tag //The ORDER could be IMPORTANT here, but not before document.head.appendChild(link_1); document.head.appendChild(link_2); document.head.appendChild(link_3); }