Я создаю веб-сайт, который представляет собой музыкальное портфолио 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 ←";
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; кнопка возврата браузера не работает), чтобы вернул на домашнюю страницу.