The User Maldito's Web

?

Proyecto Maldito

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.

  1. 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>
                                        
  2. Then, put Your Neocities Username. Examples: mine is user-maldito (https://neocities.org/site/user-maldito)
    //Line 7:
    const username = "user-maldito";
                                        
  3. 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: 
                                        
  4. 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:

  1. Put the Masonry link:
    <script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
                                    
  2. 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>
                                    
More here

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...
  1. Grab some things in the page (the form to change the layout and all the CSS styles outside).
  2. Then listen if the user select other options and if it's true, do Something (explained in the third point)
  3. Also, I need if there is already other layout. Search if it's true.
  4. Am I in the Gallery? The gallery have a different layout.
  5. 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?

  1. Take all the CSS tags.
  2. Delete the Style (the CSS tags I gather before).
  3. Depending of the layout selected, use it (put new CSS tags).
  4. Put a funny log if someone is seeing the console command.
  5. OPTIONAL: If the user is in the mobile, change something.
  6. 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)?
  1. Target All The Links
  2. Delete It
function NoCSS() {
    //Remove All The Links (CSS Tags)
    DOM.allLinksCss.forEach((cssLink) => {
        cssLink.remove();
    });
}
                                

Put Your Style?
  1. Create a Tag (Yes, you can create a tag in JS)
  2. Insert the Attributes and Values
  3. 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);
}