PageSourceSearch

https://mortezavaezi.ir/wp-content/themes/TerminalOS/assets/js/main.js?ver=1764820300

js mortezavaezi.ir collected 2026-10-02 01:58:16 UTC 6,074 bytes, 179 lines download raw bytes

1// assets/js/main.js
2
3// 1. Import Core Modules
4import Terminal from './modules/Terminal.js';
5import PostType from './modules/PostType.js';
6
7// 2. Import Terminal Applications
8import ContactApp from './modules/apps/ContactApp.js';
9import AboutApp from './modules/apps/AboutApp.js';
10import NetworkScanApp from './modules/apps/NetworkScanApp.js';
11
12/**
13 * Utility function to pause execution for a given time.
14 * @param {number} ms - The number of milliseconds to sleep.
15 * @returns {Promise}
16 */
17export const sleep = (ms) => new Promise(r => setTimeout(r, ms));
18
19/**
20 * Main application entry point.
21 * Initializes the terminal, registers apps, and handles boot sequence.
22 */
23async function initializeTerminal() {
24    // Check if the terminal container exists before proceeding.
25    if (!document.getElementById('terminal')) {
26        console.error("Terminal container not found. Initialization failed.");
27        return;
28    }
29
30    // Instantiate the main Terminal system
31    const sys = new Terminal();
32
33    // ---------------------------------------------------------
34    // SECTION A: REGISTER APPLICATIONS
35    // ---------------------------------------------------------
36
37    const contactApp = new ContactApp(sys);
38    sys.registerApp(contactApp);
39
40    const aboutApp = new AboutApp(sys);
41    sys.registerApp(aboutApp);
42
43    const networkScanApp = new NetworkScanApp(sys);
44    sys.registerApp(networkScanApp);
45
46
47    // ---------------------------------------------------------
48    // SECTION B: REGISTER WORDPRESS POST TYPES
49    // ---------------------------------------------------------
50    if (window.terminalData && window.terminalData.post_type_configs) {
51        console.log("Terminal Data Configs:", window.terminalData.post_type_configs);
52        window.terminalData.post_type_configs.forEach(config => {
53            const renderFn = config.render_fn ? new Function('post', 'currentTranslations', config.render_fn) : null;
54
55            const postType = new PostType(
56                config.name,
57                config.slug,
58                config.cmd_config,
59                renderFn
60            );
61
62            if (window.terminalData[config.js_object_key]) {
63                postType.setPosts(window.terminalData[config.js_object_key]);
64            }
65
66            postType.register(sys);
67            sys.registerPostType(postType);
68        });
69    }
70
71    // ---------------------------------------------------------
72    // SECTION C: SYSTEM BOOT SEQUENCE
73    // ---------------------------------------------------------
74
75    if (window.terminalData.is_singular_post) {
76        await sys.openDeepLinkPost(window.terminalData.singular_post_id, window.terminalData.singular_post_type);
77
78    } else if (window.terminalData.is_404) {
79        await sys.display404Error();
80
81    } else {
82        await sys.boot(true);
83    }
84
85    window.sys = sys;
86}
87
88// Wait for the DOM to be fully loaded before initializing
89document.addEventListener('DOMContentLoaded', initializeTerminal);
90
91// Global Slider Function
92window.moveSlide = function (sliderId, direction) {
93    const slider = document.getElementById(sliderId);
94    if (!slider) return;
95
96    const slides = slider.querySelectorAll('.slide');
97    let activeIndex = -1;
98
99    slides.forEach((slide, index) => {
100        if (slide.classList.contains('active')) {
101            activeIndex = index;
102            slide.classList.remove('active');
103        }
104    });
105
106    let newIndex = activeIndex + direction;
107    if (newIndex >= slides.length) newIndex = 0;
108    if (newIndex < 0) newIndex = slides.length - 1;
109
110    slides[newIndex].classList.add('active');
111
112    // Update counter
113    const counter = slider.querySelector('.slide-counter');
114    if (counter) {
115        counter.innerText = `${newIndex + 1} / ${slides.length}`;
116    }
117};
118
119// Auto-Slider Logic
120(function () {
121    const observer = new MutationObserver((mutations) => {
122        mutations.forEach((mutation) => {
123            if (mutation.addedNodes.length) {
124                mutation.addedNodes.forEach((node) => {
125                    if (node.nodeType === 1 && node.querySelector('.portfolio-slider')) {
126                        initAutoSliders(node);
127                    } else if (node.classList && node.classList.contains('portfolio-slider')) {
128                        initAutoSliders(node.parentElement);
129                    }
130                });
131            }
132        });
133    });
134
135    // Start observing the document body for added nodes
136    observer.observe(document.body, { childList: true, subtree: true });
137
138    function initAutoSliders(container) {
139        const sliders = container.querySelectorAll('.portfolio-slider');
140        sliders.forEach(slider => {
141            if (slider.dataset.autoInitialized) return;
142            slider.dataset.autoInitialized = "true";
143
144            const slides = slider.querySelectorAll('.slide');
145            if (slides.length <= 1) return;
146
147            const nextSlide = () => {
148                // Check if slider is still in DOM
149                if (!document.body.contains(slider)) return;
150
151                // Check if hovered (pause on hover)
152                if (slider.matches(':hover')) {
153                    setTimeout(nextSlide, 1000); // Check again in 1s
154                    return;
155                }
156
157                // Get current active slide duration
158                const activeSlide = slider.querySelector('.slide.active');
159                let duration = 6000; // Default fallback
160                if (activeSlide && activeSlide.dataset.duration) {
161                    duration = parseInt(activeSlide.dataset.duration, 10);
162                }
163
164                // Safety check: Ensure duration is at least 1 second to prevent rapid loops
165                if (isNaN(duration) || duration < 1000) {
166                    duration = 6000;
167                }
168
169                setTimeout(() => {
170                    window.moveSlide(slider.id, 1);
171                    nextSlide(); // Recursive call
172                }, duration);
173            };
174
175            // Start the loop
176            nextSlide();
177        });
178    }
179})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.