プロジェクト

全般

プロフィール

機能 #42 » redmine-line-theme-js.js

Redmine Admin, 2025-05-11 06:05

 
/* LINE風Redmineテーマ - theme.js */
/* テーマ用JavaScript機能 */

// DOMが完全に読み込まれてから実行
document.addEventListener('DOMContentLoaded', function() {
// LINE風UIの拡張
enhanceHeader();
enhanceMainMenu();
enhanceFooter();
// 特定ページの拡張
if (isIssuePage()) {
enhanceIssuePage();
}
if (isIssueListPage()) {
enhanceIssueListPage();
}
// レスポンシブサポート
setupResponsiveBehavior();
// 共通アニメーション・エフェクト
setupAnimations();
});

/**
* ヘッダーをLINE風UIに拡張
*/
function enhanceHeader() {
const header = document.getElementById('top-menu');
if (!header) return;
// ロゴエリアの拡張
const homeLink = header.querySelector('a.home');
if (homeLink) {
const textContent = homeLink.textContent;
homeLink.innerHTML = '';
const logoImg = document.createElement('span');
logoImg.className = 'logo-icon';
homeLink.appendChild(logoImg);
const logoText = document.createElement('span');
logoText.className = 'home-text';
logoText.textContent = textContent;
homeLink.appendChild(logoText);
}
// ユーザーアバター追加
const loggedAs = document.getElementById('loggedas');
if (loggedAs) {
const userLink = loggedAs.querySelector('a');
if (userLink) {
const userName = userLink.textContent;
const initial = userName.charAt(0).toUpperCase();
userLink.setAttribute('title', userName);
userLink.textContent = initial;
}
}
// 検索ボックスの拡張
const searchForm = header.querySelector('form');
if (searchForm) {
searchForm.classList.add('enhanced-search');
const searchInput = searchForm.querySelector('input#q');
if (searchInput) {
searchInput.setAttribute('placeholder', '検索...');
}
}
}

/**
* メインメニュー(サイドバー)をLINE風UIに拡張
*/
function enhanceMainMenu() {
const mainMenu = document.getElementById('main-menu');
if (!mainMenu) return;
// メニュートグルボタン(モバイル用)
const toggleButton = document.createElement('div');
toggleButton.className = 'main-menu-toggle';
toggleButton.innerHTML = '☰'; // ハンバーガーアイコン
toggleButton.addEventListener('click', function() {
mainMenu.classList.toggle('open');
});
mainMenu.appendChild(toggleButton);
// メニューセクションのグループ化と改良
const menuSections = mainMenu.querySelectorAll('div.menu-section');
menuSections.forEach(section => {
const sectionTitle = section.querySelector('.menu-section-title');
if (sectionTitle) {
// 折りたたみボタンを追加
const collapseButton = document.createElement('span');
collapseButton.className = 'main-menu-collapse';
collapseButton.innerHTML = '−'; // マイナス記号
collapseButton.setAttribute('title', '折りたたむ');
collapseButton.addEventListener('click', function(e) {
e.stopPropagation();
const childList = section.querySelector('ul');
if (childList) {
childList.style.display = childList.style.display === 'none' ? 'block' : 'none';
this.innerHTML = childList.style.display === 'none' ? '+' : '−'; // プラス/マイナス記号
}
});
sectionTitle.appendChild(collapseButton);
}
});
// メニュー項目のアイコン化
const menuItems = mainMenu.querySelectorAll('div.menu-section a');
menuItems.forEach(item => {
// アイコンタイプを推測(文字列に基づく簡易ロジック)
let iconType = 'default';
const text = item.textContent.toLowerCase();
if (text.includes('home') || text.includes('ホーム') || text.includes('トップ')) {
icon
(5-5/8)