Затухание в HTML коде, динамически создаваемом Java Сценарий не работает согласованно - PullRequest
0 голосов
/ 21 апреля 2020

Я создаю веб-сайт, который представляет собой музыкальное портфолио c для меня, как забавного проекта для начинающих программистов. Он работает, имея домашнюю страницу, которая представляет собой список кнопок, которые связаны с музыкальным проектом, с которым я связан. При нажатии кнопки вместо перехода к другому файлу html домашняя страница очищается. Значение этой кнопки отправляется в файл php, который будет извлекать песни, найденные в этом проекте, и перечислять их на странице с помощью кода сценария java, который динамически создает html по мере загрузки песен.

Вот как это выглядит в случае, если это помогает:

HTML

<button type="button" name="soloWork" id="solo-work" class="project-button" value="Solo Work">
    Solo Work
</button>
<p class="project-description">
    Music done by myself
</p>

JS:

const init = () => {

    // This will delegate what project is loaded depending on the button clicked by the user
    document.querySelectorAll(".project-button")
        .forEach(btn => btn .addEventListener("click", loadProject, false));
}

/**
 * 
 * This function will create the html template of the page based on the button selected
 * by the user, as well as load the song information from the database.
 * @param projectName name attached to the project button that is clicked on
 */
const loadProject = projectName => {

    // send project name to function that will create page display
    createProjectDisplay(projectName);

    // Grab the songs of the project from the data base
    httpRequest("PHP FILE", "get", loadSongs, projectName.target.value, "XML");
}

/**
 * This function will be the structure for making the http request
 * @param url 
 * @param method 
 * @param callback 
 * @param params 
 * @param responseType 
 */
const httpRequest = (url, method, callback, params, responseType, ) => {
    let xhr = new XMLHttpRequest();
    if(params && method == "get") {
        url += "?" + params;
    }
    xhr.open(method, url);
    xhr.onreadystatechange = () => {
        if(xhr.readyState == 4) {
            if(responseType == "JSON") {
                callback(JSON.parse(xhr.requestText));
            } else if (responseType == "XML") {
                callback(xhr.responseXML);
            } else {
                callback(xhr.responseText)
            }
        }
    }
    if (method == "post") {
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xhr.send(params);
    } else {
        xhr.send(null);
    }
}

/**
 *  Load the songs from the database tied with the specific project selected and then send them to be displayed dynamically
 *  @param projects the project that is called for
 */
const loadSongs = projects => {

    // Grab the data needed to make seperation more easy
    let projectNodes = projects.getElementsByTagName("project");

    // assign nodes to variables
    for(let i=0;i<projectNodes.length;i++) {
        let currentProject = projectNodes[i];
        let songId = currentProject.getElementsByTagName("SongId")[0].childNodes[0].nodeValue;
        let songName = currentProject.getElementsByTagName("Name")[0].childNodes[0].nodeValue;
        let projectName = currentProject.getElementsByTagName("ProjectName")[0].childNodes[0].nodeValue;
        let songDescription = currentProject.getElementsByTagName("Description")[0].childNodes[0].nodeValue;
        let filePath = currentProject.getElementsByTagName("FilePath")[0].childNodes[0].nodeValue;
        let projects = {"songId": songId, "name": songName, "projectName": projectName, "description": songDescription, "filePath": filePath};
        songsCollection =+ projects;
        createSongDisplay(projects);
    }
}

/**
 * Create the song display container as the songs are loaded from the database
 * 
 * @param projects the project now formatted 
 */
const createSongDisplay = projects => {

    let horizontalLine = document.createElement("hr");

    // create the audio player
    let songAudioFileContainer = document.createElement("audio");
    songAudioFileContainer.controls = "controls";
    let songAudioFile = document.createElement("source");
    songAudioFile.setAttribute("src", projects.filePath);
    songAudioFile.setAttribute("type", "audio/mpeg");
    songAudioFile.setAttribute("class", "page-audio");
    songAudioFileContainer.appendChild(songAudioFile);

    // create song name
    let songName = document.createElement("h3");
    songName.innerHTML = `"${projects.name}"`;

    // create description text
    let descriptionText = document.createElement("p");
    descriptionText.setAttribute("class", "song-description");
    descriptionText.innerHTML = projects.description;

    // append all above to the exisiting container
    let songContainer = document.getElementById("song-container");
    songContainer.appendChild(horizontalLine);
    songContainer.appendChild(songName);
    songContainer.appendChild(songAudioFileContainer);
    songContainer.appendChild(descriptionText);
}

/**
 * Using the song name sent from the button clicked, this fuction will create the html template of the page
 * @param projectName name attached to the project button that is clicked on
 */
createProjectDisplay = projectName => {

    // Add back arrow to header and change its color
    let header = document.querySelector("#header-text");
    header.innerHTML = "Back to Musical Projects &larr;";
    header.classList.add("back-button", "back-button");
    // Make header refresh button
    header.onclick = () => {
        location.reload();
    } 

    // clear the home page 
    let homePage = document.querySelector("#main");
    let homePageFooter = document.querySelector("#main-footer");
    document.body.removeChild(homePage);
    document.body.removeChild(homePageFooter)

    // Grab the data from the currently clicked on button
    let clickedProject = projectName.target.value;

    // create project title
    let projectTitleContainer = document.createElement("section");
    projectTitleContainer.setAttribute("id", "section-a");
    projectTitleContainer.setAttribute("class", "grid");
    let projectTitleContainerContentWrap = document.createElement("div");
    projectTitleContainerContentWrap.setAttribute("class", "content-wrap");
    let projectTitle = document.createElement("h1");
    projectTitle.innerHTML = clickedProject;
    projectTitleContainerContentWrap.appendChild(projectTitle);
    projectTitleContainer.appendChild(projectTitleContainerContentWrap);

    // Create song container to be used later
    let songContainer = document.createElement("section");
    songContainer.setAttribute("id", "section-b");
    songContainer.setAttribute("class", "grid");
    let songContainerContentWrap = document.createElement("div");
    songContainerContentWrap.setAttribute("id", "song-container");
    songContainerContentWrap.setAttribute("class", "content-wrap");
    songContainer.appendChild(songContainerContentWrap);

    // make sure display does not already exist before creating it... just in case
    if(!document.querySelector("#main")) {

        // Create main tag to contain content
        let project = document.createElement("main");
        project.setAttribute("id", "main");

        // Add each category to project container
        project.appendChild(projectTitleContainer);
        project.appendChild(songContainer);
        document.body.appendChild(project);

        // fade in the elements
        //setTimeout(fadeInElements(project), 100);
        fadeInElements(project)
    }
    projectName.stopPropagation();
}

/**
 * Fade in the html page containing the songs when it is loaded
 * @param project the entire project html main tag
 */
const fadeInElements = (project) => {
    project.classList.add("main-fade", "faded-out");

    requestAnimationFrame(() => {
        project.classList.remove("faded-out");
    })
}

CSS

/*
    Fade in styles
*/
.main-fade
, .footer-fade {
    transition: opacity 1000ms;
    will-change: opacity;
}

main.faded-out
, footer.faded-out {
    opacity: 0;
}

Моя проблема заключается в этих последних битах кода, относящихся к замиранию в элементах html, решение, которое я поднял отсюда https://medium.com/@felixblaschke / dynamicisch-erstellte- html -elemente-animieren- 6d165a37f685 :

JS:

/**
 * Fade in the html page containing the songs when it is loaded
 * @param project the entire project html main tag
 */
const fadeInElements = (project) => {
    project.classList.add("main-fade", "faded-out");

    requestAnimationFrame(() => {
        project.classList.remove("faded-out");
    })
}

CSS:

/*
    Fade in styles
*/
.main-fade
, .footer-fade {
    transition: opacity 1000ms;
    will-change: opacity;
}

main.faded-out
, footer.faded-out {
    opacity: 0;
}

Потому что, когда я очищаю домашнюю страницу и загружаю песни и тому подобное, это создает эффект резкого сбоя в некотором роде, я всегда думал, что исчезновение контента будет лучшим решением для того, чтобы сохранить этот сайт SPA (хотя я понимаю, что браузерные SPA являются своего рода болью в заднице и не Стоит, но я все еще с этим пока).

Это все работает функционально, и сайт даже исчезает ... иногда. Это проблема, которую я имею; мое решение работает, но я не могу заставить его работать постоянно и не могу понять, когда оно работает или не работает. Иногда это работает 5 раз подряд, иногда только 1 раз, иногда совсем нет; Мне просто нужно обновлять страницу и скрестить пальцы.

Кто-нибудь знает, как я мог бы сделать этот эффект более удобным? Я хочу иметь возможность загрузить домашнюю страницу, нажать кнопку, сделать так, чтобы содержимое исчезло, а затем нажать мою пользовательскую кнопку возврата (проблема, которую я обнаружил из-за слишком позднего выполнения SPA; кнопка возврата браузера не работает), чтобы вернул на домашнюю страницу.

...