Загрузка данных


load.js:
function load(url){
    let content = document.getElementById('content');
    let loading = document.getElementById('loading');
    content.innerHTML = loading.innerHTML;
    fetch(url)
    .then(response => {
        if (!response.ok) { throw new Error('Ошибка сети: ' + response.status); }
        return response.text();
    })
    .then(html => { content.innerHTML = html; })
    .catch(error => {
        console.error('Ошибка:', error);
        content.innerHTML = '<p>Не удалось загрузить данные.</p>';
    });
}

function picture(){
    cnt = document.getElementById('content');
    cnt.innerHTML = '<div class="mx-auto p-4"><img class="img-thumbnail img-fluid rounded" src=""><p>Асинхронная загрузка в JavaScript</p></div>';
    setTimeout(function () { cnt.firstElementChild.firstElementChild.src = "images/img-1.png"; }, 0);
    setTimeout(function () { cnt.firstElementChild.firstElementChild.src = "images/img-2.jpg"; }, 2000);
    setTimeout(function () { cnt.firstElementChild.firstElementChild.src = "images/img-3.jpg"; }, 4000);
}

class clTable {
    constructor(tbody, row_new='', td='') {
        const arrTR = ['',
            '<input name="tovar" style="width: 100%;">',
            '<input name="col" style="width: 100%;">',
            '<input name="price" style="width: 100%;">',
            '<input name="sum" readonly style="width: 100%;">',
            '<button class="btn btn-sm btn-info" title="Удалить" onClick="delTR(this.parentNode.parentNode)">-</button>'];
        row_new = document.createElement('tr');
        this.tbody = tbody;
        this.arrTR = arrTR;
        this.row_new = row_new;
        this.td = td;
    }
    add(){
        this.tbody.appendChild(this.row_new);
        for (let i=0; i < this.arrTR.length; i++){
            this.TR(this.row_new, this.arrTR[i]);
        }
    }
    TR(tr, value){
        this.td = document.createElement('td');
        this.td.innerHTML = value;
        tr.appendChild(this.td);
    }
}

function addTR(){
    tbody = document.getElementById('id_tbody');
    row = new clTable(tbody);
    row.add();
}

function delTR(tr){
    const table = document.getElementById('id_table');
    table.deleteRow(tr.rowIndex);
}

function sumTable(){
    let numbers = document.getElementsByName("col").length;
    let sum;
    let s = 0;
    for (let i = 0; i < numbers; i++){
        n = document.getElementsByName("col")[i].value;
        price = document.getElementsByName("price")[i].value;
        sum = Number(n) * Number(price);
        document.getElementsByName("sum")[i].value = sum;
        s = s + sum;
    }
    let nds = s * 0.20;
    document.getElementById('nds').innerHTML = 'НДС (20%): ' + nds + ' руб.';
    let total = s + nds;
    document.getElementById('result').innerHTML = 'Итого: ' + total.toFixed(2) + ' руб.';
}

//3. Canvas
class clCanvas {
    constructor(canvas='', context='', dpr='', width='', height='') {
        canvas = document.getElementById("Canvas");
        context = canvas.getContext("2d");
        dpr = window.devicePixelRatio || 1;
        canvas.width = width = canvas.offsetWidth * dpr;
        canvas.height = height = Math.floor(canvas.width/1.6);
        context.scale(dpr, dpr);
        this.context = context;
        this.width = width;
        this.height = height;
    }
    Line(x1, y1, x2, y2, lineWidth, color) {
        this.context.beginPath();
        this.context.lineWidth = lineWidth;
        this.context.moveTo(x1, y1);
        this.context.lineTo(x2, y2);
        this.context.strokeStyle = color;
        this.context.stroke();
    }
    xy(x1,y1,x2,y2){
        this.context.strokeStyle = "red";
        this.context.strokeText("ось X", x1, y1);
        this.context.strokeText("ось Y", x2, y2);
    }
    async func(x0,y0,type){
        const m=50;
        const xmin=-4;
        const xmax=4;
        this.context.beginPath();
        this.context.strokeStyle = "green";
        let startY = type=='sin' ? Math.sin(xmin) : (type=='xx' ? xmin*xmin : xmin*xmin*xmin);
        this.context.moveTo(Math.floor(x0+xmin*m), Math.floor(y0-startY*m));
        for (let x = xmin; x <= xmax; x+=0.2) {
            await new Promise(resolve => setTimeout(resolve, 100));
            let y = type=='sin' ? Math.sin(x) : (type=='xx' ? x*x : x*x*x);
            this.context.strokeStyle = "green";
            this.context.lineTo(Math.floor(x0+x*m), Math.floor(y0-y*m));
            this.context.stroke();
        }
    }
}

function here(type){
    let xy = new clCanvas();
    xy.context.clearRect(0, 0, xy.width, xy.height);
    x1 = 20; y1 = Math.floor(xy.height/2); x2 = Math.floor(xy.width); y2=y1;
    xy.Line(x1, y1, x2, y2, 1,"black");
    x1 = Math.floor(xy.width/2); y1 = 20; x2 = x1; y2=Math.floor(xy.height);
    xy.Line(x1, y1, x2, y2, 1,"black");
    xy.xy(Math.floor(xy.width),Math.floor(xy.height/2), Math.floor(xy.width/2), 20);
    xy.func(Math.floor(xy.width/2),Math.floor(xy.height/2),type);
}

//4. Крестики-нолики
var obj={first: true};
function Click(){
    let element = document.querySelector('.gamebox');
    let box = document.getElementsByClassName('btn');
    let btn = document.getElementById("btn_reload");
    btn.addEventListener("click", function () {
        load(url + "view/flexbox.html");
    });
    element.addEventListener('click', function(e) {
        if (e.target.nodeName != 'DIV') return 0;
        if (e.target.innerHTML == "") {
            e.target.innerHTML = "X";
            ii(box, obj.first);
            obj.first=false;
        }
    });
}

function ii(gamebox, log) {
    var arr = [
        [0, 1, 2],[3, 4, 5],[6, 7, 8],[0, 3, 6],
        [1, 4, 7],[2, 5, 8],[0, 4, 8],[2, 4, 6]
    ];
    if (log) {
        if (gamebox[4].innerHTML == "") {
            gamebox[4].innerHTML = "0";
        } else {
            gamebox[0].innerHTML = "0";
        }
    } else {
        for (var i = 0; i < arr.length; i++) {
            let rnd = Math.round(Math.random() * 2);
            if (gamebox[arr[i][rnd]].innerHTML == "") {
                gamebox[arr[i][rnd]].innerHTML = "0";
                break;
            }
        }
    }
    for (let i = 0; i < arr.length; i++) {
        if (gamebox[arr[i][0]].innerHTML == "X" &&
            gamebox[arr[i][1]].innerHTML == "X" &&
            gamebox[arr[i][2]].innerHTML == "X") {
            gamebox[arr[i][0]].style.backgroundColor = "var(--bs-warning)";
            gamebox[arr[i][1]].style.backgroundColor = "var(--bs-warning)";
            gamebox[arr[i][2]].style.backgroundColor = "var(--bs-warning)";
            alert("Победили X");
            break;
        } else if (gamebox[arr[i][0]].innerHTML == "0" &&
            gamebox[arr[i][1]].innerHTML == "0" &&
            gamebox[arr[i][2]].innerHTML == "0") {
            gamebox[arr[i][0]].style.backgroundColor = "var(--bs-warning)";
            gamebox[arr[i][1]].style.backgroundColor = "var(--bs-warning)";
            gamebox[arr[i][2]].style.backgroundColor = "var(--bs-warning)";
            alert("Победили 0");
            break;
        }
    }
}

//5.Мультимедиа
var video;
var display;
function play() {
    video = document.getElementById("videoPlayer");
    video.play();
}
function pause() {
    video.pause();
}
function stop() {
    video.pause();
    video.currentTime = 0;
}
function speedUp() {
    video.play();
    video.playbackRate = 2;
}
function slowDown() {
    video.play();
    video.playbackRate = 0.5;
}
function normalSpeed() {
    video.play();
    video.playbackRate = 1;
}
function progressUpdate() {
    var positionBar = document.getElementById("positionBar");
    positionBar.style.width = (video.currentTime / video.duration * 100) + "%";
    displayStatus = document.getElementById("displayStatus");
    displayStatus.innerHTML = (Math.round(video.currentTime*100)/100) + " сек";
}
canvas.html:
<div class="d-flex">
    <p class="mx-auto">Элемент HTML5 – <b>Canvas</b></p>
</div>
<figure class="d-flex">
    <div class="alert alert-warning m-auto col-md-4 p-2">
        <div class="form-check">
            <input class="form-check-input" type="radio" name="flexRadioDefault"
                id="Radio1" onClick="here('sin');">
            <label class="form-check-label">Синусоида Sin(x)</label>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="radio" name="flexRadioDefault"
                id="Radio2" onClick="here('xx');">
            <label class="form-check-label">Квадратичная функция</label>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="radio" name="flexRadioDefault"
                id="Radio3" onClick="here('xxx');">
            <label class="form-check-label">Кубическая функция</label>
        </div>
    </div>
</figure>
<div class="row">
    <canvas class="mx-auto w-75 h-100 p-3" id="Canvas"
        style="border:1px solid black; background: #FFFFE0;">
    </canvas>
</div>
flexbox.html:
<style>
    .bs {
        color: var(--bs-dark);
        background-color: var(--bs-light);
    }
</style>
<div class="container align-items-center justify-content-center p-2">
    <p class="fs-3 text-center">Игра: Крестики-нолики</p>
    <div class="gamebox">
        <div class="d-flex justify-content-center g-2">
            <div class="btn p-4 bs border border-success m-1" onClick="Click();"></div>
            <div class="btn p-4 bs border border-success m-1" onClick="Click();"></div>
            <div class="btn p-4 bs border border-success m-1" onClick="Click();"></div>
        </div>
        <div class="d-flex justify-content-center g-2">
            <div class="btn p-4 bs border border-success m-1" onClick="Click();"></div>
            <div class="btn p-4 bs border border-success m-1" onClick="Click();"></div>
            <div class="btn p-4 bs border border-success m-1" onClick="Click();"></div>
        </div>
        <div class="d-flex justify-content-center g-2">
            <div class="btn p-4 bs border border-success m-1" onClick="Click();"></div>
            <div class="btn p-4 bs border border-success m-1" onClick="Click();"></div>
            <div class="btn p-4 bs border border-success m-1" onClick="Click();"></div>
        </div>
        <div class="d-flex justify-content-center g-2 m-3">
            <div id="btn_reload" class="btn btn-warning" onClick="Click();">Повторить?</div>
        </div>
    </div>
</div>
media.html:
<style>
#positionBar {
    height: 30px;
    color: white;
    font-weight: bold;
    background: steelblue;
    text-align: center;
}
#positionBar span {
    display: inline-block;
    margin-top: 5px;
}
#durationBar {
    border: solid 1px black;
    width: 600px;
    margin-bottom: 5px;
}
</style>
<div class="container align-items-center justify-content-center p-2">
    <p class="fs-3 text-center">Мультимедиа проигрыватель</p>
    <video id="videoPlayer" controls onTimeUpdate="progressUpdate()"
        width="600" height="400" poster="images/photo.png">
        <source src="images/video.mp4" type="video/mp4">
    </video>
    <!-- Индикатор прогресса - progress bar -->
    <div class="barContainer">
        <div id="durationBar">
            <div id="positionBar"><span id="displayStatus">0</span></div>
        </div>
    </div>
    <br>
    <!-- Кнопки управления видео -->
    <div>
        <button class="btn btn-outline-primary" onclick="play()">Play</button>
        <button class="btn btn-outline-primary" onclick="pause()">Pause</button>
        <button class="btn btn-outline-danger" onclick="stop()">Stop</button>
        <button class="btn btn-outline-success" onclick="speedUp()">Быстрей</button>
        <button class="btn btn-outline-info" onclick="slowDown()">Медленее</button>
        <button class="btn btn-outline-info" onclick="normalSpeed()">Нормальная скорость</button>
    </div>
</div>
table.html:
<style type="text/css">
table { counter-reset: rowNumber;}
table tr > td:first-child { counter-increment: rowNumber; }
table tr td:first-child::before { content: counter(rowNumber); }
</style>
<div class="mx-auto p-2">
    <p><b>Номенклатура:</b> Товары/Услуги.</p>
    <div class="table-responsive">
        <table class="table table-bordered table-success table-hover" id="id_table">
            <thead>
                <tr>
                    <th scope="col">№</th>
                    <th scope="col">Наименование</th>
                    <th scope="col">Количество</th>
                    <th scope="col">Цена</th>
                    <th scope="col">Сумма</th>
                    <th scope="col">Del</th>
                </tr>
            </thead>
            <tbody id="id_tbody"></tbody>
        </table>
    </div>
    <button type="button" class="btn btn-danger btn-sm float-end" title="Добавить" onClick="addTR()">+</button>
    <button class="btn btn-danger btn-sm" onClick="sumTable();">Расчитать сумму</button>
    <p id="nds">НДС 20%</p>
    <p id="result">Итоговая сумма:</p>
</div>
tabs.html:
<table>
    <tr>
        <td>
            <img class="img-fluid" src="images/product.png" align="left" style="margin-top: 5%;">
        </td>
    </tr>
    <tr>
        <td>
            <div>
                <!-- Навигационные элементы -->
                <ul class="nav nav-tabs" id="myTab" role="tablist">
                    <li class="nav-item" role="presentation">
                        <button class="nav-link active" id="home-tab" data-bs-toggle="tab"
                            data-bs-target="#home" type="button" role="tab"
                            aria-controls="home" aria-selected="true">Описание</button>
                    </li>
                    <li class="nav-item" role="presentation">
                        <button class="nav-link" id="profile-tab" data-bs-toggle="tab"
                            data-bs-target="#profile" type="button" role="tab"
                            aria-controls="profile" aria-selected="false">Инструкция</button>
                    </li>
                    <li class="nav-item" role="presentation">
                        <button class="nav-link" id="contact-tab" data-bs-toggle="tab"
                            data-bs-target="#contact" type="button" role="tab"
                            aria-controls="contact" aria-selected="false">О бренде</button>
                    </li>
                </ul>
                <div class="tab-content" id="myTabContent">
                    <div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
                        <p><b>Hercules TopSpeed FX66</b> — горный велосипед для активного отдыха и городских поездок.
                        Надёжная стальная рама выдержит любые нагрузки, а широкие покрышки обеспечат уверенное сцепление с дорогой.</p>
                        <p><b>Бренд:</b> Hercules</p>
                        <p><b>Тип:</b> Горный (MTB)</p>
                        <p><b>Сезон:</b> 2026</p>
                        <p><b>Возраст:</b> для взрослых</p>
                        <p><b>Цвет рамы:</b> чёрный</p>
                    </div>
                    <div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">
                        <p><b>Инструкция по эксплуатации:</b></p>
                        <p>1. Перед каждой поездкой проверяйте давление в шинах: 2.5–3.5 bar.</p>
                        <p>2. Регулярно смазывайте цепь специальной смазкой.</p>
                        <p>3. Храните велосипед в сухом помещении, защищённом от прямых солнечных лучей.</p>
                        <p>4. Не превышайте максимальную нагрузку: 100 кг.</p>
                    </div>
                    <div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">
                        <p><b>О бренде Hercules:</b></p>
                        <p>Компания Hercules основана в 1886 году в Великобритании. Один из старейших производителей велосипедов в мире.</p>
                        <p>Сегодня бренд выпускает велосипеды для всех возрастов и уровней подготовки.</p>
                        <p><b>Официальный сайт:</b> hercules-cycles.com</p>
                    </div>
                </div>
            </div>
        </td>
    </tr>
</table>
index.html:
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>УП ПМ.08 Замула Артём</title>
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <style>
        ul li {cursor:pointer;}
    </style>
</head>
<body>
<div class="container">

    <!-- Вертикальная навигация -->
    <nav class="navbar navbar-expand-lg navbar-light bg-warning">
        <div class="container-fluid">
            <img src="images/ui-ux.png" style="height:36px">
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav">
                    <li class="nav-item"><a class="nav-link active" href="#">Главная</a></li>
                    <li class="nav-item"><a class="nav-link" href="#">Услуги</a></li>
                    <li class="nav-item"><a class="nav-link" href="#">Прайс</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <!-- end vertical nav -->

    <!-- Основная -->
    <div class="row my-2">

        <!-- Левая колонка (Подменю) -->
        <div class="col-md-4 bg-light">

            <p><a class="nav-link" id="first" data-bs-toggle="collapse" href="#menu-1">
                <span style="pointer-events:none">&#9744;</span> Раздел 1. Азы JavaScript
            </a></p>
            <div class="collapse" id="menu-1">
                <div class="card card-body">
                    <ul class="list-group">
                        <li class="list-group-item active">1.1.Асинхронность</li>
                        <li class="list-group-item">1.2.Таблица</li>
                        <li class="list-group-item">1.3.Вкладки</li>
                        <li class="list-group-item">1.4.Canvas</li>
                        <li class="list-group-item">1.5.Крестики-нолики</li>
                    </ul>
                </div>
            </div>

            <p><a class="nav-link" data-bs-toggle="collapse" href="#menu-2">
                <span style="pointer-events:none">&#9744;</span> Раздел 2
            </a></p>
            <div class="collapse" id="menu-2">
                <div class="card card-body">
                    <ul class="list-group">
                        <li class="list-group-item active">2.1.Мультимедиа</li>
                        <li class="list-group-item">A second item</li>
                        <li class="list-group-item">A third item</li>
                        <li class="list-group-item">A fourth item</li>
                        <li class="list-group-item">And a fifth one</li>
                    </ul>
                </div>
            </div>

        </div>
        <!-- end подменю -->

        <!-- Правая колонка (Содержание) -->
        <div class="col-md-8 bg-light">
            <!-- контент -->
            <div class="content d-grid bg-light" id="content">
                <div class="mx-auto p-4">
                    <p>JavaScript – это язык управления интерактивностью контента.</p>
                </div>
            </div>
            <!-- Блок сообщений пользователю -->
            <div id="loading" style="display:none">Идет загрузка..</div>
        </div>

    </div>

    <!-- Подвал -->
    <footer class="container bg-warning">
        &copy; Колледж АлтГУ 2026
    </footer>

</div>
<script src="js/bootstrap.min.js"></script>
<script src="myjs/load.js"></script>
<script>
    const on = String.fromCharCode(9745);
    const off = String.fromCharCode(9744);
    const first = document.getElementById('first');
    first.click();
    first.firstElementChild.innerHTML = on;

    let url = "http://localhost/www/pm08/";

    document.addEventListener("click", (e) => {
        if (e.target.nodeName == 'A') {
            const s = e.target.firstElementChild;
            s.innerHTML = (s.innerHTML == off) ? on : off;
        }
        if (e.target.nodeName == 'LI') {
            document.querySelectorAll('.list-group-item').forEach(el => el.classList.remove('active'));
            switch(e.target.innerHTML) {
                case "1.1.Асинхронность":
                    e.target.classList.add('active');
                    picture();
                    break;
                case "1.2.Таблица":
                    e.target.classList.add('active');
                    load(url + "view/table.html");
                    break;
                case "1.3.Вкладки":
                    e.target.classList.add('active');
                    load(url + "view/tabs.html");
                    break;
                case "1.4.Canvas":
                    e.target.classList.add('active');
                    load(url + "view/canvas.html");
                    break;
                case "1.5.Крестики-нолики":
                    e.target.classList.add('active');
                    load(url + "view/flexbox.html");
                    break;
                case "2.1.Мультимедиа":
                    e.target.classList.add('active');
                    load(url + "view/media.html");
                    break;
            }
        }
    });
</script>
</body>
</html>