0

My goal is to understand why the div with the id of product is not shown when the page is loaded.

I would expect the product div to be displayed as a grid by default because that is what it is set as in the stylesheet. In reality, the product div doesn't show until the submit event attached to the search field is fired.

I am unable to understand why product is referenced in the javascript at the bottom of the productUpdate() function, even though it is never actually defined as a const or var.

if(!flag_error){
                product.style.display = "grid";
                hint.style.display = "none";
                forwardBtn.style.display = "inline";
                backBtn.style.display = "inline";

I have tried extensively to understand exactly which bit of code turns product div on and off. The code is below and I've also uploaded it to http://va.ogs17.brighton.domains/.

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>V&A online item search</title>
    <link rel="stylesheet" type="text/css" href="index.css">
    <script src="index.js"></script>
</head>
<body>
    <div class="main-container">
        <div class="welcome-container">
            <h1>Search the V&A Online</h1>
            <h2>Start searching now by entering in a keyword in the searchbar below</h2>
        </div>
        
        <div id="search-container">
            <form>
                <fieldset>
                    <legend><strong>Search for an item here:</strong></legend>
                    <p>The V&A Museum is the world's leading museum of of art, design and performance, housing a permanent collection of over 2.27 million objects. You can search for them here.</p>
                    <img class="info-icon" src="info-icon2.png">
                    <p class="search-hint"> Stuck for ideas? Try searching for an object like a throne or vase. You could try a person or a place. Is there certain techniques or materials you are loooking for? Any keyword will work, even dragons!</p>
                    <label for="search-bar"></label>
                    <input id="search-bar" type="search">
                    <input type="submit" value="Search" href="#product-top">
                    <div class="nav-btn-container">
                        <a href="" type="button" class="back-button">Previous Item</a>
                        <a href="" type="button" class="forward-button">Next Item</a>
                        <span id="hint">This is the last item in the list.</span>
                    </div>
                </fieldset>
            </form>
        </div>

        <div id="loading">
            <img class="loading-img" src="Bean Eater-1s-200px.gif">     
        </div>

        <div id="product">
            <a id="product-top"></a>
            <div class="title">
                <h2 class="">No title found</h2>
            </div>
            <div class="photo-container"><img class="photo" src="image-not-found.png"></div>
            <div class="information">
                <p class="artist">Artist: Unknown</p>
                <p class="object">Object: Unkown</p>
                <p class="date_text">Date: Unkown</p>
                <p class="place">Place: Unkown</p>
                <p class="location">Location: Unknown</p>
                <p class="object_number">Object Number: Unkown</p>
                <p class="museum_number">Museum Number Token: Unkown</p>
            </div>
        </div>

        

        <div id="success">
            <p>Success!</p>
            <!-- Link back to empty form -->
        </div>

        <div id="error">
            <p>error...</p>
            <!-- Link back to empty form -->
        </div>
    </div>
</body>
</html>

CSS

body {
    font-family:'Roboto',sans-serif;
    padding: 32px;
    margin: 0;
    background-image: url("vanda-front.jpg");
    background-size: 100%;
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-position: center;
}

img {
    width: 100%;
}

.welcome-container {
    color:honeydew;
    text-shadow: black;
    margin-top: 2rem;
    margin-left: 3rem;
    margin-bottom: 18rem;
}

.welcome-container h1 {
    font-size: 3.5rem;
}

fieldset {
    padding: 20px;
    width: 60%;
    margin: auto;
    background-color: black;
    opacity: 0.9;
    border-style: none;
}

fieldset label, p, legend {
    color: blanchedalmond;
}

fieldset img{
    max-width: 1rem;
}

/* Button style partly by Frederico Dossena fdossena.com/?p=html5cool/buttons/i.frag */
.nav-btn-container a, input[type=submit] {
    padding:0.35em 1.2em;
    border:0.1em solid #FFFFFF;
    margin:0 0.3em 0.3em 0;
    border-radius:0.12em;
    box-sizing: border-box;
    background-color: black;
    text-decoration:none;
    font-weight:300;
    color:#FFFFFF;
    text-align:center;
    transition: all 0.2s;
    cursor: pointer;
    
}

input[type=submit] {
    font-size: 1.5rem;
}

input[type=search] {
    /* padding:0.35em 1.2em; */
    border:0.1em solid #FFFFFF;
    margin:0 0.3em 0.3em 0;
    border-radius:0.12em;
    box-sizing: border-box;
    text-decoration:none;
    /* min-height: 2.5rem; */
    font-size: 3rem;
}

.nav-btn-container a:hover, input[type=submit]:hover {
    color:#000000;
    background-color:#FFFFFF;
}

.nav-btn-container {
    margin-top: 1.2rem;
}

.search-hint{
    display: none;
}

#product {
    display: grid;
    grid-template-columns: repeat(9, 1fr);
    grid-template-rows: 10rem 1fr;
    gap: 0.2rem;
    padding: 10px;
    box-sizing: border-box;
    /* in the internal divs use grid-column-start and grid-row-end: ;
    basic vid here - https://www.youtube.com/watch?v=Y9rHsdCxU8Q */

}

.photo-container {
    opacity: 1;
}

/* text-overflow code by Jokesterfr stackoverflow.com/questions/7711490/prevent-text-from-overflowing-a-padded-container-in-html */
.title {
    background-color: black;
    opacity: 0.9;
    border-style: none;
    color: blanchedalmond;
    font-size: 3rem;
    overflow: hidden;
    border-left:1em solid transparent;
    border-right:1em solid transparent;
    text-overflow: ellipsis;
}

.information {
    background-color: black;
    opacity: 0.9;
    border-style: none;
    color: blanchedalmond;
}

.back-button, .forward-button {
    display: none;
}

.forward-button{
    float: right;
}

.title {
    grid-column-start: 1;
    grid-column-end: 10;
    grid-row-start: 1;
    grid-row-end: 1;
}

.photo-container {
    grid-column-start: 1;
    grid-column-end: 6;
    grid-row-start: 2;
    grid-row-end: 3;
}

.information{
    grid-column-start:6;
    grid-column-end: 10;
    grid-row-start: 2;
    grid-row-end: 3;
}

input {
    display: block;
    Margin: 5px;
    width: 100%;
}



#hint {
    color:red;
    display: none;
}

#success, #error, #product {
    text-align: center;
    display: none;
}

.loading-img{
    display: none;
}

/* Android A70 */
/* @media(min-width: 751px) and (max-width: 1080px) {
    body{background-color: red;}
} */

/* iPhone 6 */
@media(max-width: 750px) {
    /* body{
        background-color: orangered;
        background-image: none;
    } */

    .welcome-container {
        margin-bottom: 12rem;
    }

    .title {
        grid-column-start: 1;
        grid-column-end: 10;
        grid-row-start: 1;
        grid-row-end: 1;
    }
    
    .photo-container {
        grid-column-start: 1;
        grid-column-end: 10;
        grid-row-start: 2;
        grid-row-end: 3;
    }
    
    .information{
        grid-column-start:1;
        grid-column-end: 10;
        grid-row-start: 3;
        grid-row-end: 4;
    }

}

JavaScript

window.addEventListener('load', function() {
    //global varaibles

    var searchHint = document.querySelector('.search-hint');
    //by defualt, the first item is always shown. Position is incremented using next and previous buttons to show new items.
    var position = 0;
    var maxCap = 45;
    //code by Ry stackoverflow.com/questions/21147832/convert-camel-case-to-human-readable-string
    function toCapitalizedWords(name) {
        var words = name.match(/[A-Za-z][a-z]*/g) || [];
    
        return words.map(capitalize).join(" ");
    }
    
    function capitalize(word) {
        return word.charAt(0).toUpperCase() + word.substring(1);
    }

    function productUpdate(step) {
        if(position + step >= maxCap - 1){
            //show hint
            var hint = document.querySelector("#hint");
            hint.style.display = "inline";
        }
        else {
            // var loading = document.querySelector('#loading');
            
            position += step;
            var flag_error = false;

            // get all form fields
            var search = document.querySelector("#search-bar").value.trim();

            var hint = document.querySelector("#hint");

            var backBtn = document.querySelector(".back-button");
            var forwardBtn = document.querySelector(".forward-button");

            var productTitle = document.querySelector(".title");
            var productPhoto = document.querySelector(".photo");
            var productInformation = document.querySelectorAll(".information");

            var xhrSearch = new XMLHttpRequest();
            xhrSearch.onreadystatechange = function() {
                
                //readystate 4 means oporation is complete developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
                //status 200 means OK
                if(this.readyState == 4 && this.status == 200) {
                    console.log(search);
                    //TODO
                    //if there is response text, do this, if not, display hint saying product not found
                    const result = JSON.parse(xhrSearch.responseText);
                    productTitle.textContent = result.records[position].fields.title;

                    //js loops god post stackoverflow.com/questions/3010840/loop-through-an-array-in-javascript

                    for (let item of productInformation[0].children) {
                        console.log(item);
                        itemClass = item.className;
                        item.textContent = toCapitalizedWords(itemClass) + ": " + result.records[position].fields[itemClass];
                    }

                    var xhrFullRecord = new XMLHttpRequest();
                    xhrFullRecord.onreadystatechange = function() {
                        if(this.readyState == 4 && this.status == 200) {
                            const fullRecordResult = JSON.parse(xhrFullRecord.responseText);
                            productPhoto.src = "https://framemark.vam.ac.uk/collections/" + fullRecordResult[0].fields.image_set[0].fields.image_id + "/full/735,/0/default.jpg";
                        }
                    }
                    fullRecordUrl = "https://www.vam.ac.uk/api/json/museumobject/" + result.records[position].fields.object_number;
                    xhrFullRecord.open("GET", fullRecordUrl);
                    xhrFullRecord.send();
                }
            };
            //what happens to URL if £$&^%$£ is put in search?
            url = "https://www.vam.ac.uk/api/json/museumobject/search?q=" + search + "&limit=" + maxCap;
            //do I want any other params here?
            xhrSearch.open("GET", url);
            xhrSearch.send();

            if(!flag_error){
                //setTimeout(loading.style.display = "none", 5000);
                product.style.display = "grid";
                hint.style.display = "none";
                forwardBtn.style.display = "inline";
                backBtn.style.display = "inline";
            }
        }
    }
    
    document.querySelector('#search-container').addEventListener("submit", function(evt){
        // stop page reload default action
        evt.preventDefault();
        position = 0;
        productUpdate(0);
    })

    document.querySelector('.info-icon').addEventListener("click", function(evt){
        // stop page reload default action
        // evt.preventDefault();
        if(searchHint.style.display == "inline"){
            searchHint.style.display = "none";
        } else {
            searchHint.style.display = "inline";
        }
    })

    document.querySelector('.back-button').addEventListener("click", function(evt){
        // stop page reload default action
        evt.preventDefault();
        productUpdate(-1);
    })

    document.querySelector('.forward-button').addEventListener("click", function(evt){
        // stop page reload default action
        evt.preventDefault();
        productUpdate(1);
    })

    function displayLoading(){
        var loadIcon = document.querySelector(".loadingImg");
        product.style.display = "none";
        loadIcon.style.display = "inline";

    }

});
NewForOlly
  • 35
  • 5

1 Answers1

1

you have onload event but onload there is no call to productUpdate()

window.addEventListener('load', function() {
     ........
     ........
    // append this line before closing
    productUpdate(0);
})
uingtea
  • 6,002
  • 2
  • 26
  • 40
  • I understand that productUpdate() displays the product div but why is the div hidden in the first place? I haven't set it to display: none; or visibility: hidden; anywhere in my code. – NewForOlly Mar 11 '21 at 19:08
  • in your css `#success, #error, #product {text-align: center; display: none;}` – uingtea Mar 11 '21 at 19:11
  • In the javascript, I haven't defined a variable called product or used a querySelector() on the product div but I still use it successfully in the productUpdate function. How is this possible? – NewForOlly Mar 11 '21 at 19:43
  • it is because element that has `id` is automatically stored as global variable, you can directly call it without using document.querySelector – uingtea Mar 11 '21 at 19:54
  • Is it considered acceptable practice to call directly from id and omit the querySelector? Which documentation can I read to further understand the relationship between ids/classes and javascript? – NewForOlly Mar 11 '21 at 20:01
  • 1
    for id become global variable you can read it [here](https://stackoverflow.com/questions/3434278/do-dom-tree-elements-with-ids-become-global-variables), they said it bad idea to call it directly. – uingtea Mar 11 '21 at 20:13