News Generator — GitHub Wiki & David Lennuk - DavidMyrseth/BuketovPY GitHub Wiki

Project Description pilt

News Generator is a web application that allows users to:

Select a news category

Generate a random news article

Create their own custom news manually

Edit and delete news directly in the browser

The project is intended for learning web development and practicing the Extreme Programming (XP) methodology. How to Use

  1. Running the Project

    Download or clone the repository:

    git clone https://github.com/your-repository/news-generator.git

    Open the index.html file in your browser.

    Note: No server is required — everything works locally through HTML/CSS/JS.

  2. Working with the News Generator Action Description Select a category Choose the desired category from the dropdown list. Generate a news article Click the "Generate News" button to add a random news article from the database. Write your own news Enter a title and content, then click "Add Your News". Edit a news article Click the "Edit" button on the desired news item and update the content. Delete a news article Click the "Delete" button to remove a news item from the list.

  3. Project Structure

/news-generator ├── index.html # Main HTML page ├── style.css # Steam-style CSS styling └── script.js # Logic for news generation and management

Extreme Programming (XP) in the Project

The News Generator project was developed following the principles of Extreme Programming (XP): XP Principle Implementation Iterative Development The project was built step-by-step: starting with a basic generator, then adding custom news creation, editing functionality, and design improvements. Continuous Integration Each new feature was immediately tested in the browser to prevent error accumulation. Simplicity of Code Code is divided into simple, single-responsibility functions (generateNews, addCustomNews, renderNews). Manual Testing After each iteration, buttons, forms, and news display were manually tested. Refactoring Code was simplified after adding new features to avoid duplication and improve readability. Pair Programming (if working in a team) Possible to work in pairs: one writes the code, the other reviews and suggests improvements. Emphasis on Communication Before each new feature, there was a discussion about how it should work and look (e.g., adding animations, applying Steam-style design).

index.html

<title>News Generator with Categories</title>
<div class="container">
    <h1>News Generator</h1>

    <div class="news-form">
        <select id="news-category">
            <option value="">Select a Category</option>
            <option value="Politics">Politics</option>
            <option value="Sports">Sports</option>
            <option value="Technology">Technology</option>
            <option value="Entertainment">Entertainment</option>
        </select>

        <input type="text" id="custom-title" placeholder="Your Title">
        <textarea id="custom-content" placeholder="Your News Content"></textarea>

        <div class="buttons">
            <button onclick="generateNews()">Generate News</button>
            <button onclick="addCustomNews()">Add Your News</button>
        </div>
    </div>

    <div id="news-list"></div>
</div>

<script src="script.js"></script>

sript.js let newsList = [];

const newsDatabase = { "Политика": [ "Президент объявил о новых реформах.", "Парламент принял важный закон.", "Прошла международная встреча лидеров." ], "Спорт": [ "Команда выиграла чемпионат!", "Известный спортсмен установил рекорд.", "Сегодня состоится матч века." ], "Технологии": [ "Новая модель смартфона вышла в продажу.", "Учёные сделали прорыв в области ИИ.", "Запущена инновационная платформа." ], "Развлечения": [ "Популярный артист выпустил новый альбом.", "Премьера долгожданного фильма состоится скоро.", "Известный блогер запустил новый проект." ] };

function generateNews() { const categorySelect = document.getElementById('news-category'); const category = categorySelect.value;

if (!category) {
    alert('Пожалуйста, выберите категорию!');
    return;
}

const randomIndex = Math.floor(Math.random() * newsDatabase[category].length);
const title = newsDatabase[category][randomIndex];
const content = "Подробности читайте в полной версии статьи.";

newsList.push({ title, content, category });
renderNews();

}

function addCustomNews() { const categorySelect = document.getElementById('news-category'); const titleInput = document.getElementById('custom-title'); const contentInput = document.getElementById('custom-content');

const category = categorySelect.value;
const title = titleInput.value.trim();
const content = contentInput.value.trim();

if (!category) {
    alert('Пожалуйста, выберите категорию!');
    return;
}

if (!title || !content) {
    alert('Пожалуйста, заполните заголовок и текст новости!');
    return;
}

newsList.push({ title, content, category });
titleInput.value = '';
contentInput.value = '';
renderNews();

}

function renderNews() { const newsContainer = document.getElementById('news-list'); newsContainer.innerHTML = '';

newsList.forEach((news, index) => {
    const newsItem = document.createElement('div');
    newsItem.className = 'news-item';

    const newsTitle = document.createElement('h3');
    newsTitle.textContent = news.title;

    const newsContent = document.createElement('p');
    newsContent.textContent = news.content;

    const newsCategory = document.createElement('small');
    newsCategory.textContent = `Категория: ${news.category}`;

    const actions = document.createElement('div');
    actions.className = 'actions';

    const editButton = document.createElement('button');
    editButton.textContent = 'Редактировать';
    editButton.onclick = () => editNews(index);

    const deleteButton = document.createElement('button');
    deleteButton.textContent = 'Удалить';
    deleteButton.className = 'delete-btn';
    deleteButton.onclick = () => deleteNews(index);

    actions.appendChild(editButton);
    actions.appendChild(deleteButton);

    newsItem.appendChild(newsTitle);
    newsItem.appendChild(newsContent);
    newsItem.appendChild(newsCategory);
    newsItem.appendChild(actions);

    newsContainer.appendChild(newsItem);
});

}

function editNews(index) { const newTitle = prompt('Введите новый заголовок:', newsList[index].title); const newContent = prompt('Введите новый текст:', newsList[index].content);

if (newTitle !== null && newContent !== null) {
    newsList[index].title = newTitle.trim();
    newsList[index].content = newContent.trim();
    renderNews();
}

}

function deleteNews(index) { if (confirm('Точно удалить эту новость?')) { newsList.splice(index, 1); renderNews(); } }

style.css body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; background: #1b2838; margin: 0; padding: 20px; color: #c7d5e0; }

.container { max-width: 800px; margin: auto; background: #2a475e; padding: 20px; border-radius: 10px; box-shadow: 0 0 15px rgba(0, 0, 0, 0.6); }

h1 { text-align: center; color: #66c0f4; margin-bottom: 20px; }

.news-form { margin-bottom: 20px; display: flex; flex-direction: column; gap: 10px; }

#news-category, #custom-title, #custom-content { padding: 10px; font-size: 16px; width: 100%; background: #1b2838; border: 1px solid #66c0f4; border-radius: 5px; color: #c7d5e0; }

#news-category option { background: #1b2838; }

textarea { resize: vertical; min-height: 80px; }

.buttons { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }

button { background-color: #66c0f4; color: #1b2838; padding: 10px 15px; border: none; cursor: pointer; font-size: 16px; font-weight: bold; border-radius: 5px; transition: background-color 0.3s; }

button:hover { background-color: #417a9b; }

.news-item { background: #16202d; padding: 15px; margin-bottom: 10px; border-radius: 8px; position: relative; border: 1px solid #66c0f4; }

.news-item h3 { margin: 0 0 10px; color: #66c0f4; }

.news-item p { margin: 0; }

.news-item small { display: block; margin-top: 10px; color: #8f98a0; font-size: 12px; }

.actions { position: absolute; top: 10px; right: 10px; }

.actions button { margin-left: 5px; background-color: #66c0f4; color: #1b2838; padding: 5px 10px; font-size: 14px; border-radius: 4px; }

.actions .delete-btn { background-color: #be3144; }

.actions button:hover { opacity: 0.85; }

⚠️ **GitHub.com Fallback** ⚠️