PageSourceSearch

https://www.hanglung.com/js/vue-main.js?t=20260924173949

js hanglung.com collected 2026-09-24 09:40:22 UTC 10,506 bytes, 337 lines download raw bytes

1const { reactive, defineComponent, defineDirective, ref, computed, provide, inject, watch, h, TransitionGroup, onMounted, onUnmounted } = Vue;
2
3// function VMenu(slots) {
4//   const openmenu = ref(0)
5
6//   const open = function(){
7//     console.log('rets')
8//   }
9
10//   return /* html */ `
11//     <nav>
12//       ${slots}
13//     </nav>
14//   `
15// };
16
17// Global Click Outside document evnet listener 
18let clickOutsideEvents = [];
19const clickOutsideCheck = function (e) {
20
21    clickOutsideEvents.forEach(function (regEvt) {
22        if (!regEvt.el.contains(e.target)) {
23            regEvt.callback && regEvt.callback()
24        }
25    });
26}
27document.addEventListener('click', clickOutsideCheck, false);
28const VClickOutside = {
29    mounted(el, { value }) {
30        // document.addEventListener('click', ClickOutsideCheck(el, value), false);
31        if (value) clickOutsideEvents.push({ el, callback: value });
32    },
33    unmounted(el, { value }) {
34        // document.removeEventListener('click', ClickOutsideCheck(el, value), false);
35        if (value) {
36            clickOutsideEvents = clickOutsideEvents.filter(function (val) {
37                return val.el !== el;
38            });
39        }
40    }
41}
42
43// Custom Components
44const VHeader = defineComponent({
45    props: ['alwaysSticky'],
46    setup(props) {
47        const sticky = ref(false);
48        const requestSticky = ref(false)
49        const shouldSticky = computed(() => sticky.value || requestSticky.value || props.alwaysSticky);
50
51        const setRequestSticky = (value) => {
52            requestSticky.value = value;
53        }
54
55        provide('useRequestSticky', { requestSticky, setRequestSticky });
56
57        const detectScreen = function () {
58            sticky.value = window.scrollY > 10 || window.innerWidth < 1536;
59        }
60
61        window.addEventListener('scroll', function () {
62            detectScreen()
63        })
64        window.addEventListener('resize', function () {
65            detectScreen()
66        })
67
68        detectScreen();
69
70        return { sticky, setRequestSticky, shouldSticky }
71    },
72    template: /* html */ `
73    <header :class="{'bg-white': shouldSticky}">
74      <slot :requestSticky="setRequestSticky"></slot>
75    </header>
76  `
77})
78
79const VMenuItem = defineComponent({
80    props: {
81        item: String
82    },
83    setup(props, { emit, slots }) {
84        const isOpen = ref(false);
85        const isHover = ref(false);
86        const isSearch = ref(false);
87        const { requestSticky, setRequestSticky } = inject('useRequestSticky')
88
89
90        const open = function (e) {
91            setRequestSticky(true)
92            isHover.value = true;
93
94            // 
95            if (!slots.body) return;
96            isOpen.value = true;
97            setTimeout(redirectToGroup, 300);
98        }
99        const close = function (e) {
100            setRequestSticky(false)
101            isHover.value = false;
102
103            if (!slots.body) return;
104            isOpen.value = false;
105        }
106
107        const isActive = ref(false)
108
109        isActive.value = ((!props.item == "") ? props.item.toUpperCase() : props.item) === window.location.pathname.split("/")[2].replaceAll("-", " ").toUpperCase()
110
111        return { isOpen, isHover, open, close, isActive }
112    },
113    template: /* html */ `
114    <div :class="{'hover': isHover, 'active': isActive }" @mouseenter="open" @mouseleave="close">
115      <slot :isOpen="isOpen" :isHover="isHover"></slot>
116
117      <transition name="fx-submenu">
118      <div class="submenu-container" v-if="isOpen">
119        <div class="submenu">
120          <slot name="body"></slot>
121        </div>
122      </div>
123      </transition>
124    </div>
125  `
126})
127
128
129const VCollapse = defineComponent({
130    props: ['closeOnOutsideClick'],
131    setup(props, { slots }) {
132        const isOpen = ref(false);
133        const closeOnOutsideClick = props.closeOnOutsideClick !== undefined;
134
135        const toggleOpen = function () {
136            isOpen.value = !isOpen.value;
137        }
138
139        const handleClickOutside = function () {
140            if (closeOnOutsideClick) {
141                isOpen.value = false;
142            }
143        }
144
145        return { isOpen, toggleOpen, handleClickOutside };
146    },
147    directives: {
148        ClickOutside: VClickOutside
149    },
150    template: /* html */`
151  <div v-click-outside="handleClickOutside">
152    <div class="cursor-pointer" @click="toggleOpen()"><slot :isOpen="isOpen" :toggleOpen="toggleOpen"></slot></div>
153    <transition>
154      <div v-show="isOpen"><slot name="body"></slot></div>
155    </transition>
156  </div>
157  `
158})
159
160
161const VMobileMenu = defineComponent({
162    setup(props, { slots }) {
163        const isOpen = ref(false)
164        const { setRequestSticky } = inject('useRequestSticky')
165        const { setIsLockScroll } = inject('useLockScroll');
166
167        const toggleOpen = function () {
168            isOpen.value = !isOpen.value;
169            setTimeout(redirectToGroup, 300);
170            if (isOpen.value) {
171                setRequestSticky(true)
172                setIsLockScroll(true)
173            } else {
174                setRequestSticky(false)
175                setIsLockScroll(false)
176            }
177        }
178
179        return { isOpen, toggleOpen }
180    },
181    template: /* html */ `
182    <div>
183      <slot :isOpen="isOpen" :toggleOpen="toggleOpen"></slot>
184    </div>
185  `
186})
187
188const VMobileMenuItem = defineComponent({
189    props: ['label'],
190    setup(props, { slots }) {
191        const isOpen = ref(false);
192
193        const setIsOpen = function (val) {
194            isOpen.value = val;
195            setTimeout(redirectToGroup, 300);
196        }
197
198        const hasSubmenu = !!slots.default;
199
200        return { isOpen, setIsOpen, hasSubmenu };
201    },
202    template: /* html */ `
203    <a v-bind="$attrs" @click="setIsOpen(true)">{{label}}
204      <i v-if="hasSubmenu" class="fas fa-chevron-right"></i>
205    </a>
206    <transition name="custom-classes"
207      enter-active-class="animate__animated animate__slideInRight animate__faster"
208      leave-active-class="animate__animated animate__slideOutRight animate__faster">
209
210      <div class="fixed top-0 left-0 right-0 bottom-0 bg-white divide-y" v-if="isOpen && hasSubmenu">
211        <div class="h-16 relative px-8 flex justify-center items-center">
212          <a class="p-3 block absolute left-2 text-base" href="javascript:;" @click="setIsOpen(false)"><i class="fas fa-chevron-left"></i></a>
213          <span class="text-lg font-bold">{{label}}</span>
214        </div>
215        <slot v-if="isOpen" v-bind="{isOpen, setIsOpen}"></slot>
216      </div>
217    </transition>
218  `
219})
220
221
222const VTabs = defineComponent({
223    props: ['tabAlign'],
224    setup(props, { slots }) {
225        const formatHash = (str) => str ? str.toLowerCase().replace(/\s+/g, '-') : '';
226        const getInitialHash = () => window.location.hash ? decodeURIComponent(window.location.hash.replace("#", "")) : "";
227        const getTabKey = (tab) => formatHash(tab.props.hashKey || tab.props['hash-key'] || tab.props.label);
228
229        const currentIndex = ref(0);
230        let currentHash = ref(getInitialHash());
231
232        const tabs = slots.default();
233
234        const handleHashChange = () => {
235            currentHash.value = getInitialHash();
236        };
237
238        const changeTab = (idx, tab) => {
239            currentIndex.value = idx;
240            const newHash = getTabKey(tab);
241            window.location.hash = newHash;
242            currentHash.value = newHash;
243        }
244
245        const isActive = (tab, i, currentIndex) => {
246            let tempKey = getTabKey(tab);
247            if (currentHash.value != "")
248                return currentHash.value == tempKey
249            return i == currentIndex.value
250        }
251
252        onMounted(() => {
253            window.addEventListener('hashchange', handleHashChange);
254        });
255
256        onUnmounted(() => {
257            window.removeEventListener('hashchange', handleHashChange);
258        });
259
260        const renderControls = () => (
261            h('div', { class: 'overflow-y-auto flex content-container pb-2 mb-3 no-scrollbar-style' },
262                h('div', { class: ['flex space-x-6 xl:space-x-16', props.tabAlign == 'left' ? 'justify-start' : 'justify-center mx-auto'] },
263                    tabs.map((tab, i) => h('a', {
264                        class: [
265                            'uppercase whitespace-nowrap font-bold text-base pb-4 lg:text-xl pb-1 relative after:absolute after:h-1 after:bottom-0 after:bg-primary after:left-0 after:transition-all',
266                            isActive(tab, i, currentIndex) ? 'after:w-full text-primary' : 'after:w-0'
267                        ],
268                        href: tab.props.href,
269                        onClick: () => tab.props.href == 'javascript:;' && changeTab(i, tab),
270                    }, tab.props.label))
271                )
272            )
273        )
274
275        return () => ([
276            renderControls(),
277            h(TransitionGroup,
278                { class: 'v-tab-panes', tag: 'div', name: "tab-fade" },
279                {
280                    default: () =>
281                        tabs.map((tab, i) => ({ ...tab, key: tab.props.label, props: { ...tab.props, 'show': isActive(tab, i, currentIndex) } }))
282                }
283            )
284        ])
285    }
286})
287const VTab = defineComponent({
288    props: ['label', 'show', 'href', 'hashKey'],
289    template: /* html */`
290    <div class="v-tab" v-show="show">
291      <slot></slot>
292    </div>
293  `
294})
295
296
297
298
299// register components
300const App = Vue.createApp({
301    components: {
302        VHeader,
303        VMenuItem,
304        VMobileMenu,
305        VMobileMenuItem,
306        VCollapse,
307        VTabs,
308        VTab,
309    },
310    directives: {
311        ClickOutside: VClickOutside,
312    },
313    setup() {
314        const isLockScroll = ref();
315
316        const setIsLockScroll = function (value) {
317            isLockScroll.value = value;
318        }
319
320        provide('useLockScroll', {
321            isLockScroll,
322            setIsLockScroll
323        })
324
325        watch(isLockScroll, function (newValue, oldValue) {
326            if (newValue) {
327                document.body.classList.add('lock-scroll');
328            } else {
329                document.body.classList.remove('lock-scroll');
330            }
331
332        })
333
334        return { isLockScroll };
335    }
336})
337App.mount('#root')

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.