сервер пишет ошибку Status Code: 405 Method Not Allowed
Всем привет.
Курс "JavaScript - полный курс с нуля до результата!"
Урок 4.3 "Реализация скрипта отправки данных из формы ".
На 11:26 минуте делается проверка отправки данных. При просмотре в network выдаёт эту ошибку. Что может быть не так? Как это исправить?
html-code
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Yoga</title>
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab:300,400,700&subset=cyrillic-ext" rel="stylesheet">
<link rel="stylesheet" href="css/bootstrap-grid.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<header>
<div class="container">
<nav>
<ul>
<li><a href="#about">О нас</a></li>
<li><a href="#photo">Фото</a></li>
<li><a href="#price">Стоимость</a></li>
<li><a href="#contacts">Контакты</a></li>
</ul>
</nav>
</div>
</header>
<div class="main">
<div class="container">
<div class="row">
<div class="col-12">
<div class="main-block">
<div class="main-block-link">
Travel.org
</div>
<div class="main-block-title">
йога-туры в индию
</div>
<div class="main-block-descr">
океан / йога / путешествия / аюрведа
</div>
</div>
</div>
</div>
</div>
</div>
<div class="content">
<div class="container" id="about">
<div class="info" >
<div class="info-header">
<div class="info-header-tab">Лечение</div>
<div class="info-header-tab">Отдых</div>
<div class="info-header-tab">Природа</div>
<div class="info-header-tab">Йога</div>
</div>
<div class="info-tabcontent fade">
<div class="description">
<div class="description-title">Здоровый позвоночник</div>
<div class="description-text">Йога, массажи и плавание в море - помогут уставшей спине! Индийские йоги считали, что здоровье человека можно определить по тому, насколько здоров и гибок у него позвоночник.<br> Интересно, что бы древние йоги сказали, глядя на современного человека, который уже со школьного возраста мучается болями в спине, работает подолгу в неудобных сидячих позах и не умеет расслабляться, имеет искривление, которое в итоге приведет к болезням других органов? Йоги сказали бы – займись собой и срочно!
</div>
<div class="description-btn">
Узнать подробнее
</div>
</div>
<div class="photo">
<img src="img/massage.jpg" alt="Massage">
</div>
</div>
<div class="info-tabcontent fade">
<div class="description">
<div class="description-title">Антистресс</div>
<div class="description-text">Аюрведа и йога утверждают, что главным источником здоровья нашего организма является здоровый ум. Программа «Антистресс» сначала убирает последствия стресса на физическом уровне, потом помогает избавиться от негативных и навязчивых мыслей, затем повышает общий уровень энергии.<br> Вы наконец вспомните ощущение "свободной головы", ощутите прилив физических сил и вспомните, что такое счастье.</div>
<div class="description-btn">
Узнать подробнее
</div>
</div>
<div class="photo">
<img src="img/sunset.jpg" alt="sunset">
</div>
</div>
<div class="info-tabcontent fade">
<div class="description">
<div class="description-title">Восстановление</div>
<div class="description-text">Стрессы, жизнь в условиях города, плохая экология, загрязненные продукты и вода, напряженный ритм жизни - все это день ото дня отбирает у нас молодость и хорошее здоровье.<br> Одним кремом для лица не решить проблему омоложения организма, когда тебе за 40. Согласны?</div>
<div class="description-btn">
Узнать подробнее
</div>
</div>
<div class="photo">
<img src="img/sunrise.jpg" alt="sunrise">
</div>
</div>
<div class="info-tabcontent fade">
<div class="description">
<div class="description-title">Йога и аюрведа</div>
<div class="description-text">Несколько лет назад мы разработали специальные программы по йоге и аюрведе - и мы поняли, что они отлично работают - на опыте 530 наших туристов! В каждой из этих программ есть одна цель, на достижение которой будут направлены и асаны, и дыхательные практики, и медитации, и аюрведические процедуры, будут читаться лекции по этой теме. <br>Йога и аюрведа - два сильных война, которые сообща будут бороться с проблемами и болезнями.</div>
<div class="description-btn">
Узнать подробнее
</div>
</div>
<div class="photo">
<img src="img/yoga.jpg" alt="yoga">
</div>
</div>
</div>
<div class="timer">
<div class="timer-title">Успей забронировать место со скидкой</div>
<div class="timer-action">
До конца акции осталось
</div>
<div class="timer-numbers" id="timer">
<span class="hours">18</span>
<span>:</span>
<span class="minutes">20</span>
<span>:</span>
<span class="seconds">11</span>
</div>
</div>
<button class="more"> Узнать больше</button>
<div class="slider" id="photo">
<div class="slider-title">Фото с наших поездок
</div>
<div class="wrap">
<div class="slider-item fade">
<img src="img/slider_1.jpg" alt="slider">
</div>
<div class="slider-item fade">
<img src="img/slider_2.jpg" alt="slider">
</div>
<div class="slider-item fade">
<img src="img/slider_3.jpg" alt="slider">
</div>
<div class="slider-item fade">
<img src="img/slider_4.jpg" alt="slider">
</div>
<div class="prev"><div class="arrow-left"></div></div>
<div class="next"><div class="arrow-right"></div></div>
</div>
<div class="slider-dots">
<div class="dot dot-active"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
</div>
<div class="counter" id="price">
<div class="counter-title">Рассчитайте стоимость вашего отдыха
</div>
<div class="counter-block">
<div class="counter-block-option">Количество людей</div>
<input type="number" min="1" step="1" class="counter-block-input">
</div>
<div class="counter-block">
<div class="counter-block-option">На сколько дней</div>
<input type="number" min="1" step="1" class="counter-block-input">
</div>
<div class="counter-block">
<div class="counter-block-option">Выберете базу</div>
<select name="place" id="select">
<option id="mumbai" value="1">Индия, Мумбай</option>
<option id="kerala" value="1.5">Индия, Керала</option>
<option id="varanasi" value="1.8">Индия, Варанаси</option>
</select>
</div>
<div class="counter-total">
Общая сумма<br>
<span id="total">20456</span>
</div>
</div>
<div class="contact" id="contacts">
<div class="contact-img">
<img src="img/letter.png" alt="letter">
</div>
<div class="contact-form">
<div class="contact-form-title">
Мы с вами свяжемся
</div>
<form id="form">
<input required type="email" placeholder="Ваша почта">
<input required type="tel" placeholder="Ваш телефон">
<button type="submit">Отправить</button>
</form>
</div>
</div>
</div>
<footer>
<div class="container">
<div class="social">
<div class="social-block">
<a href="#">
<img src="logo/twitter-logo-silhouette.svg" alt="">
</a>
</div>
<div class="social-block">
<a href="#">
<img src="logo/facebook-logo.svg" alt="">
</a>
</div>
<div class="social-block">
<a href="#">
<img src="logo/instagram-social-network-logo-of-photo-camera.svg" alt="">
</a>
</div>
<div class="social-block">
<a href="#">
<img src="logo/pinterest-logo.svg" alt="">
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="overlay fade">
<div class="popup">
<div class="popup-close">×
</div>
<div class="popup-title">
Форма обратной связи</div>
<div class="popup-form">
<form action="#" class="main-form">
<div class="popup-form-header">
Узнайте больше о своём отдыхе
</div>
<label class="popup-form__label" for="phone">
Введите ваш номер телефона:
</label>
<input class="popup-form__input" name="phone" type="tel" required placeholder="+7(978) 973 33 45">
<button class="button popup-form__btn">
Оставить заявку!
</button>
</form>
</div>
</div>
</div>
<script src="js/script.js"></script>
</body>
</html>
js-code
window.addEventListener('DOMContentLoaded', function (){
'use strict';
let tab = document.querySelectorAll('.info-header-tab');
let info = document.querySelector('.info-header');
let tabContent = document.querySelectorAll('.info-tabcontent');
function fideTabContent(a) {
// функция которая скрывает все табы
for(let i = a; i < tabContent.length; i++){
tabContent[i].classList.remove('show');
tabContent[i].classList.add('hide');
}
}
fideTabContent(1);
function showTabContent(b) {
//функция показывающая выбранный в обработчике события таб
if(tabContent[b].classList.contains('hide')){
tabContent[b].classList.remove('hide');
tabContent[b].classList.add('show');
}
}
//навешиваем обработчик, который определяет нужный нам таб с помощью делегирования. Данный способ позволяет нам получить один обработчик событий, вместо 4 в данном случае, что значительно сокращает код и естественно ускоряет его работу.
info.addEventListener('click', function(event){
let target = event.target;
//показывает, что целью является тег содержащий нужный нам класс-лист(это может быть также и тег)
// event.target.tagName == 'BUTTON' // название тега большими буквами
if(target && target.classList.contains('info-header-tab')){
for(let i = 0; i < tab.length; i++){
if(target == tab[i]){
fideTabContent(0);
showTabContent(i);
break;
}
}
}
});
// делаем таймер
// создаем дэдлайн
let deadLine = '2022-10-15';
//получаем разницу между текущими временем и нашим дедлайном
function getTimeRemaining(endtime){
let t = Date.parse(endtime) - Date.parse(new Date());
let seconds = Math.floor((t/1000)%60);
let minutes = Math.floor((t/1000/60)%60);
let hours = Math.floor((t/1000/60/60));
return {
'total' : t,
'hours' : hours,
'minutes' : minutes,
'seconds' : seconds
};
}
//функция подстваляющая значения в html
function setClock(id, endtime) {
//первый аргумент id куда будем вставлять на страницу, второй заданный дедлайн
let timer = document.getElementById(id);
let docHours = timer.querySelector('.hours');
let docMinutes = timer.querySelector('.minutes');
let docSeconds = timer.querySelector('.seconds');
let timeInterval = setInterval(updateClock, 1000);
function updateClock(){
let t = getTimeRemaining(endtime);
docHours.textContent = t.hours;
docMinutes.textContent = t.minutes;
docSeconds.textContent = t.seconds;
if(t.total <= 0) {
clearInterval(timeInterval);
}
}
}
setClock('timer', deadLine);
//создаём модальное окно
let moreBtn = document.querySelector('.more');
let overlay = document.querySelector('.overlay');
let crossModal = overlay.querySelector('.popup-close');
moreBtn.addEventListener('click', showInfo);
function showInfo() {
overlay.style.display = 'block';
this.classList.add('more-splash');
document.body.style.overflow = 'hidden';
}
crossModal.addEventListener('click', closeInfo);
function closeInfo() {
overlay.style.display = 'none';
moreBtn.classList.remove('more-splash');
document.body.style.overflow = '';
}
let descriptionBtn = document.querySelector('.description-btn');
descriptionBtn.addEventListener('click', showInfo);
//форма
// создаем объект с сообщениями для пользователя
let message = {
loading: 'Загрузка',
succsess: 'Спасибо за заявку',
failure: 'Что-то пошло не так!'
};
let form = document.querySelector('.main-form');
let input = document.getElementsByTagName('input');
let statusMessage = document.createElement('div');
statusMessage.classList.add('status');
form.addEventListener('submit',function (event){
// основная ошибка заключается когда пытаются событие
//навешивать на кнопку. Нужно событие вешать на форму
event.preventDefault();
form.appendChild(statusMessage);
let request = new XMLHttpRequest();
request.open('POST', 'server.php');
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// получение данных от пользователя
// ключами для атрибута name в html будет формироваться
//ключ, а значение для него введет пользователь
let formData = new FormData(form);
request.send(formData);
});
});