/** * Template Name: Invent * Template URL: https://bootstrapmade.com/invent-bootstrap-business-template/ * Updated: May 12 2025 with Bootstrap v5.3.6 * Author: BootstrapMade.com * License: https://bootstrapmade.com/license/ */ (function() { "use strict"; /** * Apply .scrolled class to the body as the page is scrolled down */ function toggleScrolled() { const selectBody = document.querySelector('body'); const selectHeader = document.querySelector('#header'); if (!selectHeader.classList.contains('scroll-up-sticky') && !selectHeader.classList.contains('sticky-top') && !selectHeader.classList.contains('fixed-top')) return; window.scrollY > 100 ? selectBody.classList.add('scrolled') : selectBody.classList.remove('scrolled'); } document.addEventListener('scroll', toggleScrolled); window.addEventListener('load', toggleScrolled); /** * Mobile nav toggle */ const mobileNavToggleBtn = document.querySelector('.mobile-nav-toggle'); function mobileNavToogle() { document.querySelector('body').classList.toggle('mobile-nav-active'); mobileNavToggleBtn.classList.toggle('bi-list'); mobileNavToggleBtn.classList.toggle('bi-x'); } if (mobileNavToggleBtn) { mobileNavToggleBtn.addEventListener('click', mobileNavToogle); } // ============================ // Sidebar Toggle // ============================ document.addEventListener('DOMContentLoaded', () => { const toggleBtns = document.querySelectorAll('.toggle-sidebar-btn'); if (toggleBtns.length > 0) { toggleBtns.forEach(btn => { btn.addEventListener('click', function () { document.body.classList.toggle('toggle-sidebar'); }); }); } else { console.warn('⚠️ .toggle-sidebar-btn tidak ditemukan di DOM.'); } // 2. Line Chart Implementation const chartElement = document.querySelector("#reportsChart"); if (!chartElement) { console.error("❌ Element #reportsChart not found"); return; } // Get chart data from data attribute const chartDataJson = chartElement.getAttribute('data-chart-data'); let chartData = []; try { chartData = JSON.parse(chartDataJson || '[]'); console.log("📊 Chart data loaded:", chartData); } catch (e) { console.error("❌ Error parsing chart data:", e); chartData = [0, 0, 0, 0]; } // Check if ApexCharts is loaded if (typeof ApexCharts === 'undefined') { console.error("❌ ApexCharts library not loaded"); return; } // Create and render chart try { const chart = new ApexCharts(chartElement, { series: [{ name: 'Jumlah Data', data: chartData, }], chart: { height: 350, type: 'line', toolbar: { show: true }, zoom: { enabled: true }, events: { mounted: function(chartContext, config) { console.log("✅ Chart mounted successfully"); // Hide fallback when chart is rendered const fallback = chartElement.querySelector('.chart-fallback'); if (fallback) { fallback.style.display = 'none'; } }, error: function(error) { console.error("❌ Chart error:", error); } } }, dataLabels: { enabled: false }, stroke: { curve: 'smooth', width: 3 }, colors: ['#4154f1', '#2eca6a', '#ff771d', '#ff0000'], grid: { row: { colors: ['#f3f3f3', 'transparent'], opacity: 0.5 }, }, markers: { size: 5, colors: ['#4154f1'], strokeColors: '#fff', strokeWidth: 2 }, xaxis: { categories: ['Guru', 'Jurusan', 'Fasilitas', 'Ekstrakurikuler'], labels: { style: { fontSize: '14px', fontWeight: 'bold' } } }, yaxis: { min: 0, title: { text: 'Jumlah', style: { fontSize: '14px', fontWeight: 'bold' } }, labels: { style: { fontSize: '12px' } } }, tooltip: { y: { formatter: function(value) { return value + " data"; } } } }); // Render chart after a small delay to ensure DOM is ready setTimeout(() => { chart.render(); console.log("🔄 Chart rendering started"); }, 100); } catch (error) { console.error("❌ Error creating chart:", error); } }); /** * Hide mobile nav on same-page/hash links */ document.querySelectorAll('#navmenu a').forEach(navmenu => { navmenu.addEventListener('click', () => { if (document.querySelector('.mobile-nav-active')) { mobileNavToogle(); } }); }); /** * Toggle mobile nav dropdowns */ document.querySelectorAll('.navmenu .toggle-dropdown').forEach(navmenu => { navmenu.addEventListener('click', function(e) { e.preventDefault(); this.parentNode.classList.toggle('active'); this.parentNode.nextElementSibling.classList.toggle('dropdown-active'); e.stopImmediatePropagation(); }); }); /** * Preloader */ const preloader = document.querySelector('#preloader'); if (preloader) { window.addEventListener('load', () => { preloader.remove(); }); } /** * Scroll top button */ let scrollTop = document.querySelector('.scroll-top'); function toggleScrollTop() { if (scrollTop) { window.scrollY > 100 ? scrollTop.classList.add('active') : scrollTop.classList.remove('active'); } } scrollTop.addEventListener('click', (e) => { e.preventDefault(); window.scrollTo({ top: 0, behavior: 'smooth' }); }); window.addEventListener('load', toggleScrollTop); document.addEventListener('scroll', toggleScrollTop); /** * Animation on scroll function and init */ function aosInit() { AOS.init({ duration: 600, easing: 'ease-in-out', once: true, mirror: false }); } window.addEventListener('load', aosInit); /** * Initiate glightbox */ const glightbox = GLightbox({ selector: '.glightbox' }); /** * Init isotope layout and filters */ document.querySelectorAll('.isotope-layout').forEach(function(isotopeItem) { let layout = isotopeItem.getAttribute('data-layout') ?? 'masonry'; let filter = isotopeItem.getAttribute('data-default-filter') ?? '*'; let sort = isotopeItem.getAttribute('data-sort') ?? 'original-order'; let initIsotope; imagesLoaded(isotopeItem.querySelector('.isotope-container'), function() { initIsotope = new Isotope(isotopeItem.querySelector('.isotope-container'), { itemSelector: '.isotope-item', layoutMode: layout, filter: filter, sortBy: sort }); }); isotopeItem.querySelectorAll('.isotope-filters li').forEach(function(filters) { filters.addEventListener('click', function() { isotopeItem.querySelector('.isotope-filters .filter-active').classList.remove('filter-active'); this.classList.add('filter-active'); initIsotope.arrange({ filter: this.getAttribute('data-filter') }); if (typeof aosInit === 'function') { aosInit(); } }, false); }); }); /** * Frequently Asked Questions Toggle */ document.querySelectorAll('.faq-item h3, .faq-item .faq-toggle, .faq-item .faq-header').forEach((faqItem) => { faqItem.addEventListener('click', () => { faqItem.parentNode.classList.toggle('faq-active'); }); }); /** * Init swiper sliders */ function initSwiper() { document.querySelectorAll(".init-swiper").forEach(function(swiperElement) { let config = JSON.parse( swiperElement.querySelector(".swiper-config").innerHTML.trim() ); if (swiperElement.classList.contains("swiper-tab")) { initSwiperWithCustomPagination(swiperElement, config); } else { new Swiper(swiperElement, config); } }); } window.addEventListener("load", initSwiper); /** * Correct scrolling position upon page load for URLs containing hash links. */ window.addEventListener('load', function(e) { if (window.location.hash) { if (document.querySelector(window.location.hash)) { setTimeout(() => { let section = document.querySelector(window.location.hash); let scrollMarginTop = getComputedStyle(section).scrollMarginTop; window.scrollTo({ top: section.offsetTop - parseInt(scrollMarginTop), behavior: 'smooth' }); }, 100); } } }); /** * Navmenu Scrollspy */ let navmenulinks = document.querySelectorAll('.navmenu a'); function navmenuScrollspy() { navmenulinks.forEach(navmenulink => { if (!navmenulink.hash) return; let section = document.querySelector(navmenulink.hash); if (!section) return; let position = window.scrollY + 200; if (position >= section.offsetTop && position <= (section.offsetTop + section.offsetHeight)) { document.querySelectorAll('.navmenu a.active').forEach(link => link.classList.remove('active')); navmenulink.classList.add('active'); } else { navmenulink.classList.remove('active'); } }) } window.addEventListener('load', navmenuScrollspy); document.addEventListener('scroll', navmenuScrollspy); })(); /** * Template Name: NiceAdmin * Updated: Jan 29 2024 with Bootstrap v5.3.2 * Template URL: https://bootstrapmade.com/nice-admin-bootstrap-admin-html-template/ * Author: BootstrapMade.com * License: https://bootstrapmade.com/license/ */ (function() { "use strict"; /** * Easy selector helper function */ const select = (el, all = false) => { el = el.trim() if (all) { return [...document.querySelectorAll(el)] } else { return document.querySelector(el) } } /** * Easy event listener function */ const on = (type, el, listener, all = false) => { if (all) { select(el, all).forEach(e => e.addEventListener(type, listener)) } else { select(el, all).addEventListener(type, listener) } } /** * Easy on scroll event listener */ const onscroll = (el, listener) => { el.addEventListener('scroll', listener) } /** * Search bar toggle */ if (select('.search-bar-toggle')) { on('click', '.search-bar-toggle', function(e) { select('.search-bar').classList.toggle('search-bar-show') }) } /** * Navbar links active state on scroll */ let navbarlinks = select('#navbar .scrollto', true) const navbarlinksActive = () => { let position = window.scrollY + 200 navbarlinks.forEach(navbarlink => { if (!navbarlink.hash) return let section = select(navbarlink.hash) if (!section) return if (position >= section.offsetTop && position <= (section.offsetTop + section.offsetHeight)) { navbarlink.classList.add('active') } else { navbarlink.classList.remove('active') } }) } window.addEventListener('load', navbarlinksActive) onscroll(document, navbarlinksActive) /** * Toggle .header-scrolled class to #header when page is scrolled */ let selectHeader = select('#header') if (selectHeader) { const headerScrolled = () => { if (window.scrollY > 100) { selectHeader.classList.add('header-scrolled') } else { selectHeader.classList.remove('header-scrolled') } } window.addEventListener('load', headerScrolled) onscroll(document, headerScrolled) } /** * Back to top button */ let backtotop = select('.back-to-top') if (backtotop) { const toggleBacktotop = () => { if (window.scrollY > 100) { backtotop.classList.add('active') } else { backtotop.classList.remove('active') } } window.addEventListener('load', toggleBacktotop) onscroll(document, toggleBacktotop) } /** * Initiate tooltips */ var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) var tooltipList = tooltipTriggerList.map(function(tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl) }) /** * Initiate quill editors */ if (select('.quill-editor-default')) { new Quill('.quill-editor-default', { theme: 'snow' }); } if (select('.quill-editor-bubble')) { new Quill('.quill-editor-bubble', { theme: 'bubble' }); } if (select('.quill-editor-full')) { new Quill(".quill-editor-full", { modules: { toolbar: [ [{ font: [] }, { size: [] }], ["bold", "italic", "underline", "strike"], [{ color: [] }, { background: [] } ], [{ script: "super" }, { script: "sub" } ], [{ list: "ordered" }, { list: "bullet" }, { indent: "-1" }, { indent: "+1" } ], ["direction", { align: [] }], ["link", "image", "video"], ["clean"] ] }, theme: "snow" }); } /** * Initiate TinyMCE Editor */ const useDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; const isSmallScreen = window.matchMedia('(max-width: 1023.5px)').matches; tinymce.init({ selector: 'textarea.tinymce-editor', plugins: 'preview importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap quickbars emoticons', editimage_cors_hosts: ['picsum.photos'], menubar: 'file edit view insert format tools table help', toolbar: 'undo redo | bold italic underline strikethrough | fontfamily fontsize blocks | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | forecolor backcolor removeformat | pagebreak | charmap emoticons | fullscreen preview save print | insertfile image media template link anchor codesample | ltr rtl', toolbar_sticky: true, toolbar_sticky_offset: isSmallScreen ? 102 : 108, autosave_ask_before_unload: true, autosave_interval: '30s', autosave_prefix: '{path}{query}-{id}-', autosave_restore_when_empty: false, autosave_retention: '2m', image_advtab: true, link_list: [{ title: 'My page 1', value: 'https://www.tiny.cloud' }, { title: 'My page 2', value: 'http://www.moxiecode.com' } ], image_list: [{ title: 'My page 1', value: 'https://www.tiny.cloud' }, { title: 'My page 2', value: 'http://www.moxiecode.com' } ], image_class_list: [{ title: 'None', value: '' }, { title: 'Some class', value: 'class-name' } ], importcss_append: true, file_picker_callback: (callback, value, meta) => { /* Provide file and text for the link dialog */ if (meta.filetype === 'file') { callback('https://www.google.com/logos/google.jpg', { text: 'My text' }); } /* Provide image and alt text for the image dialog */ if (meta.filetype === 'image') { callback('https://www.google.com/logos/google.jpg', { alt: 'My alt text' }); } /* Provide alternative source and posted for the media dialog */ if (meta.filetype === 'media') { callback('movie.mp4', { source2: 'alt.ogg', poster: 'https://www.google.com/logos/google.jpg' }); } }, templates: [{ title: 'New Table', description: 'creates a new table', content: '