PageSourceSearch

https://global.canon/01cmn/js/common/header2025.js

js global.canon collected 2026-09-24 08:32:24 UTC 26,706 bytes, 618 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function() {
2    const header = '#header2025'
3
4    const header2025Navi = `${header} .header2025_navi`
5    const categoryWrapper = `${header} .category_wrapper`
6    const openGNaviBtn = `${header} button.category_top`
7    const headerAnchorLink = `${header} .header2025_navi a[href*="#"]`
8
9    const closeGNaviWrapper = `${header} .nav_close`
10    const closeGNaviBtn = `${header} button.navCloseBtn`
11
12    const secondLevelWrapper = `${header} .level_second`
13    const secondLevelBtn = `${header} .secondLevelBtn`
14
15    const spOpenGNaviBtn = `${header} button.openSpMenu`
16
17    const localNavi = '#localnavi2025'
18
19    const pulldownMenu = `${header} .pulldownBtn`
20    const pulldownOptions = `${header} .pulldown_wrapper .options`
21
22    // Tab操作調整
23    const submenuLastLinks = `${header2025Navi} a.lastChild`;
24    const closeSubmenu = document.querySelector(`${header2025Navi} .nav_close .navCloseBtn`);
25
26    const mode = window.innerWidth <= 767 ? 'sp' : 'pc'
27
28    const currentURL = window.location.pathname.split('/').filter(Boolean)
29
30    const current = {
31        page: '',
32        category: '',
33        hash: ''
34    }
35
36    const header2025NaviElm = document.querySelector(`${header2025Navi}`)
37
38    let currentPath = ''
39    let animFlg = false
40
41    function on(selector, event, handler) {
42        document.querySelectorAll(selector).forEach(el => {
43            el.addEventListener(event, handler)
44        })
45    }
46
47    on(closeGNaviBtn, 'click', closeGNavi)
48    on(openGNaviBtn, 'click', openGNavi)
49    on(secondLevelBtn, 'click', toggleSecondLevel)
50    on(pulldownMenu, 'click', toggleLanguageMenu)
51    on(spOpenGNaviBtn, 'click', toggleGNavi)
52
53    if(mode === 'sp') {
54        on(headerAnchorLink, 'click', toggleGNavi)
55    }else {
56        on(headerAnchorLink, 'click', closeGNavi)
57    }
58
59    /** ------------------------------
60     * グローバルナビを開く処理
61     * @param {Event} e - クリックイベント
62     * ------------------------------ */
63    function openGNavi(e) {
64        if(animFlg) return
65        const target = e.currentTarget
66        const parentElm = target.parentElement
67        const flg = target.classList.contains('active')
68    
69        const firstLevelWrapper = parentElm.querySelector('.nav_level_first_wrapper')
70        firstLevelWrapper.setAttribute('aria-hidden', flg ? 'true' : 'false')
71    
72        const firstLevelWrapperAll = [...document.querySelectorAll('.nav_level_first_wrapper')] // 配列化して効率化
73    
74        switch (mode) {
75            case 'sp':
76                document.querySelectorAll(openGNaviBtn).forEach(btn => {
77                    btn.classList.remove('active')
78                    btn.setAttribute('aria-expanded', 'false')
79                })
80    
81                if (flg) {
82                    // 開いていたら閉じる
83                    animFlg = true
84                    slideUp(firstLevelWrapper, 400, () => {
85                        document.querySelectorAll(closeGNaviWrapper).forEach(btn => {
86                            btn.style.display = 'none'
87                        })
88                        document.querySelector(categoryWrapper).classList.remove('active')
89                        animFlg = false
90                    })
91                    return;
92                }
93    
94                // 非表示処理を最適化
95                function updateCategoryWrapper(callback) {
96                    requestAnimationFrame(() => {
97                        document.querySelector(categoryWrapper).classList.remove('active');
98                        document.querySelectorAll(`${categoryWrapper} .nav_level_first_wrapper`).forEach(el => el.style.display = 'none');
99                
100                        if (callback) callback(); // コールバック関数を実行
101                    });
102                }
103                
104                updateCategoryWrapper(() => {
105                    target.classList.add('active')
106                    target.setAttribute('aria-expanded', 'true')
107                    parentElm.classList.add('active')
108        
109                    animFlg = true
110                    slideDown(firstLevelWrapper, 400, () => {
111                        animFlg = false
112                    })
113                });
114                
115                break
116    
117            default:
118                // PC
119                let maxH = 0
120    
121                requestAnimationFrame(() => {
122                    header2025NaviElm.querySelectorAll(`${categoryWrapper} .nav_level_first_wrapper`).forEach(elm => elm.style.display = 'none')
123
124                    allClose(() => {
125                        header2025NaviElm.querySelectorAll(openGNaviBtn).forEach(btn => {
126                            btn.classList.remove('active')
127                            btn.setAttribute('aria-expanded', 'false')
128                        });
129        
130                        if (flg) {
131                            closeGNavi()
132                            return
133                        }
134        
135                        header2025NaviElm.querySelector(categoryWrapper).classList.remove('active')
136                        parentElm.classList.add('active')
137                        header2025NaviElm.querySelectorAll(closeGNaviWrapper).forEach(btn => btn.style.display = 'block')
138        
139                        // 3階層目の高さ計算を最適化
140                        const heights = firstLevelWrapperAll.map(c => {
141                            c.style.display = 'block'
142                            let h = c.clientHeight
143                            c.querySelectorAll(`${header2025Navi} .nav_level_third_wrapper`).forEach(elm => {
144                                elm.style.display = 'block'
145                                h = Math.max(h, elm.clientHeight)
146                                elm.style.display = 'none'
147                            })
148                            c.style.display = 'none'
149                            return h
150                        })
151        
152                        maxH = Math.max(...heights)
153                        firstLevelWrapper.style.display = 'block'
154                        activeCurrentPage()
155        
156                        target.classList.add('active')
157                        target.setAttribute('aria-expanded', 'true')
158                        firstLevelWrapper.style.height = maxH ? `${maxH}px` : '500px'
159                    })
160                })
161                break
162        }
163    }
164    
165    // slideUp関数 (jQueryのslideUp代替)
166    function slideUp(element, duration = 400, callback) {
167        element.style.height = `${element.offsetHeight}px`
168        element.offsetHeight // reflow
169        element.style.transition = `height ${duration}ms`
170        element.style.overflow = 'hidden'
171        element.style.height = '0'
172    
173        setTimeout(() => {
174            element.style.display = 'none'
175            element.style.removeProperty('height')
176            element.style.removeProperty('transition')
177            element.style.removeProperty('overflow')
178            if (callback) callback()
179        }, duration)
180    }
181    
182    // slideDown関数 (jQueryのslideDown代替)
183    function slideDown(element, duration = 400, callback) {
184        element.style.removeProperty('display')
185        let display = window.getComputedStyle(element).display
186        if (display === 'none') display = 'block'
187        element.style.display = display
188    
189        const height = element.offsetHeight
190        element.style.overflow = 'hidden'
191        element.style.height = '0'
192        element.style.opacity = '0'
193        element.offsetHeight // reflow
194    
195        element.style.transition = `height ${duration}ms`
196        element.style.height = `${height}px`
197        element.style.opacity = '1'
198    
199        setTimeout(() => {
200            element.style.removeProperty('height')
201            element.style.removeProperty('opacity')
202            element.style.removeProperty('transition')
203            element.style.removeProperty('overflow')
204            if (callback) callback()
205        }, duration)
206    }
207
208    /** ------------------------------
209     * グローバルナビを閉じる処理
210     * ------------------------------ */
211    function closeGNavi() {
212        document.querySelector(categoryWrapper).classList.remove('active')
213        document.querySelectorAll(`${header} .nav_level_first_wrapper`).forEach(elm => elm.style.display = 'none')
214
215        document.querySelectorAll(openGNaviBtn).forEach(btn => btn.classList.remove('active'))
216        
217        document.querySelector(closeGNaviWrapper).style.display = 'none'
218    }
219
220    /** ------------------------------
221     * グローバルナビの開閉処理(SP)
222     * ------------------------------ */
223    function toggleGNavi() {
224        const headerElm = document.querySelector(header)
225        const navi = document.querySelector(header2025Navi)
226        const flg = navi.classList.contains('active')
227
228        if (flg) {
229            document.body.style.overflow = 'auto'
230            headerElm.classList.remove('fixed')
231        } else {
232            document.body.style.overflow = 'hidden'
233            headerElm.classList.add('fixed')
234        }
235
236        document.querySelector(spOpenGNaviBtn).classList.toggle('active')
237        document.querySelector(spOpenGNaviBtn).setAttribute('aria-expanded', flg ? 'false' : 'true')
238
239        navi.classList.toggle('active')
240        navi.setAttribute('aria-hidden', flg ? 'true' : 'false')
241
242        document.querySelectorAll(`${header2025Navi} .active .nav_level_first_wrapper, ${header2025Navi} .active .nav_level_third_wrapper`)
243            .forEach(el => el.style.display = 'none')
244
245        document.querySelectorAll(`${header2025Navi} .active`)
246            .forEach(el => {
247                el.classList.remove('active')
248                el.setAttribute('aria-expanded', 'false')
249            })
250
251        activeCurrentPage()
252    }
253
254    /** ------------------------------
255     * 第二階層の開閉処理
256     * @param {Event} e - クリックイベント
257     * ------------------------------ */
258    function toggleSecondLevel(e) {
259        if(animFlg) return
260        const btn = e.currentTarget
261        const parentElm = btn.parentElement
262        const isActive = parentElm.classList.contains('active')
263        const displayElm = parentElm.querySelector('.nav_level_third_wrapper')
264
265        // ボタンを全て非アクティブに
266        document.querySelectorAll(secondLevelBtn).forEach(btn => {
267            btn.classList.remove('active')
268            btn.setAttribute('aria-expanded', 'false')
269        })
270
271        // 閉じる処理
272        if(isActive) {
273            if(mode === 'pc') {
274                displayElm.style.display = 'none'
275                displayElm.setAttribute('aria-hidden', 'true')
276                allClose()
277            }else {
278                animFlg = true
279                slideUp(displayElm, 400, () => {
280                    displayElm.setAttribute('aria-hidden', 'true')
281                    allClose()
282                    animFlg = false
283                })
284            }
285            return
286        }
287
288        allClose(() => {
289            // ボタンアクティブ & 要素の表示
290            if (!isActive) {
291                btn.classList.add('active')
292                btn.setAttribute('aria-expanded', 'true')
293                parentElm.classList.add('active')
294                displayElm.setAttribute('aria-hidden', 'false')
295
296                if(mode === 'pc') {
297                    displayElm.style.display = 'block'
298                }else {
299                    animFlg = true
300                    slideDown(displayElm, 400, () => {
301                        animFlg = false
302                    })
303                }
304            }
305        })
306    }
307
308    /** ------------------------------
309     * 全ての第二階層を非アクティブにする処理
310     * ------------------------------ */
311    function allClose(callback) {
312        header2025NaviElm.querySelectorAll(secondLevelWrapper).forEach(wrapper => {
313            wrapper.classList.remove('active');
314            const navLevelThirdWrapper = wrapper.querySelector('.nav_level_third_wrapper');
315            if (navLevelThirdWrapper) {
316                navLevelThirdWrapper.setAttribute('aria-hidden', 'true');
317                navLevelThirdWrapper.style.display = 'none';
318            }
319        });
320
321        // 処理が終わった後にコールバックを実行
322        if (typeof callback === 'function') callback()
323    }
324
325    /** ------------------------------
326     * 言語メニューの開閉処理
327     * ------------------------------ */
328    function toggleLanguageMenu() {
329        document.querySelector(pulldownMenu).classList.toggle('active')
330        const options = document.querySelector(pulldownOptions)
331        options.style.display = options.style.display === 'block' ? 'none' : 'block'
332    }
333
334    /** ------------------------------
335     * カレントページのアクティブ処理
336     * ------------------------------ */
337    function activeCurrentPage() {
338        const currentPage = document.querySelector(`${header} .nav_${current.category} [data-url="${current.page}"]`) ? document.querySelector(`${header} .nav_${current.category} [data-url="${current.page}"]`) : document.querySelector(`${header} .nav_${current.category} [data-url="${current.page}.html"]`)
339        
340        const firstLevel = document.querySelector(`${header} .nav_${current.category}`)
341        const secondLevel = currentPage ? currentPage.closest('.level_second') : ''
342
343        document.querySelectorAll(`${categoryWrapper} .active`).forEach(el => {
344            el.classList.remove('active')
345            if(el.querySelector('.nav_level_first_wrapper')) el.querySelector('.nav_level_first_wrapper').style.display = 'none'
346        })
347
348        if(currentPage) currentPage.classList.add('current')
349
350        // SP時カレントカテゴリーを開く
351        if(mode === 'sp' && firstLevel) {
352            firstLevel.classList.add('active')
353            firstLevel.querySelector('.nav_level_first_wrapper').style.display = 'block'
354            firstLevel.querySelector('button.category_top').classList.add('active')
355        }
356
357        // SP時カレントカテゴリーを開く
358        if(secondLevel) {
359            secondLevel.classList.add('active')
360            if(secondLevel.querySelector('.nav_level_third_wrapper')) secondLevel.querySelector('.nav_level_third_wrapper').style.display = 'block'
361            if(secondLevel.querySelector('.secondLevelBtn')) secondLevel.querySelector('.secondLevelBtn').classList.add('active')
362        }
363    }
364
365    /** ------------------------------
366     * カレントページの取得・設定
367     * ------------------------------ */
368    function getCurrentPage() {
369        getHash()
370        setLocalNavi()
371
372        if (mode === 'pc') {
373            const categoryBtn = document.querySelector(`${categoryWrapper}.nav_${current.category} button.category_top`)
374            if(categoryBtn) categoryBtn.classList.add('current')
375        }
376    }
377
378    /** ------------------------------
379     * ハッシュの取得
380     * ------------------------------ */
381    function getHash() {
382        current.hash = window.location.hash.slice(1)
383    }
384
385    /** ------------------------------
386     * カレントページの取得・設定
387     * ------------------------------ */
388    function getCurrentLevel() {
389        let path = ''
390
391        /** ------------------------------
392         * currentURLはドメイン以降のURLを分割したもの
393         * 例) https://global.canon/ja/corporate/greeting/
394         * currentURL = ['ja','corporate','greeting']
395         * ------------------------------ */
396        switch(true) {
397            case 
398            currentURL[0] === 'en'
399            && currentURL[1] === 'business' && ((currentURL[2] == 'material.html' || currentURL[2] == 'components.html')):
400            // currentURL[0] === 'en' && currentURL[1] === 'business' && ((currentURL[2] == 'material.html' || currentURL[2] == 'components.html')):
401
402                // ENのみ businesカテゴリーとする
403                path = window.location.pathname
404                current.category = 'business'
405
406                if(currentURL[2] != 'material.html' && currentURL[2] != 'components.html') {
407                    current.page = currentURL[3]
408                }
409                break
410
411            case  
412            currentURL[0] === 'en' && currentURL[1] === 'product' && currentURL[2] === 'indtech' && ((currentURL[3] == 'semicon' || currentURL[3] == 'fpd')):
413            // currentURL[0] === 'en' && currentURL[1] === 'business' && ((currentURL[2] == 'material.html' || currentURL[2] == 'components.html')):
414
415                // ENのみ businesカテゴリーとする
416                path = current_2nd_level;
417                current.category = 'business'
418            
419				break          
420            
421            
422            case currentURL[0] === 'en'
423            && currentURL[1] === 'business'
424            && currentURL[2] === 'group'
425            && (currentURL[3] === 'printing-gr.html' || currentURL[3] === 'medical-gr.html' || currentURL[3] === 'imaging-gr.html' || currentURL[3] === 'industrial-gr.html'):
426                // ENのみ「corporate > new-business」とする
427                path = current_2nd_level;
428                current.category = 'business'
429                //current.page = 'group'
430                break
431            case currentURL[1] === 'design':
432                //「corporate > design」とする
433                path = '/ja/corporate/'
434                current.category = 'corporate'
435                current.page = 'design'
436                break
437            case currentURL[1] === 'quality':
438                // 「corporate > quality」とする
439                path = '/ja/corporate/'
440                current.category = 'corporate'
441                current.page = 'quality'
442                break
443            case typeof current_3rd_level !== 'undefined':
444                // current_3rd_level
445                path = current_3rd_level;
446                current.category = current_1st_level.split('/').filter(part => part.length > 0)[1]
447                break;
448            case typeof current_2nd_level !== 'undefined':
449                // current_2nd_level
450                path = current_2nd_level;
451                current.category = current_1st_level.split('/').filter(part => part.length > 0)[1]
452                break
453            case typeof current_1st_level !== 'undefined':
454                // current_1st_level
455                path = current_1st_level;
456                current.category = current_1st_level.split('/').filter(part => part.length > 0)[1]
457                break
458            default:
459                // パラメータがないもの
460                path = window.location.pathname
461                
462                switch(true) {
463                    case currentURL[1] === 'employ' || currentURL[1] === 'mfg':
464                        current.category = 'corporate'
465                        break
466                    default:
467                        current.category = currentURL[1]
468                        break
469                }
470                break
471        }
472
473        currentPath = path.split('/').filter(part => part.length > 0)
474
475        if(current.page == '') current.page = currentPath[currentPath.length > 0 ? currentPath.length - 1 : 0]
476        if(typeof current.page  === "undefined") current.page = ''
477        if(current.page.includes('.')) current.page = current.page.split('.')[0]
478    }
479
480    /** ------------------------------
481     * ローカルナビの表示処理
482     * ------------------------------ */
483    function setLocalNavi() {
484        if (currentPath.length === 0 || current.category === '' || currentPath[1] === 'mfg') return
485
486        // 親カテゴリーが存在しなければ終了
487        if (document.querySelectorAll(`${localNavi} .${current.category}`).length === 0) return
488    
489        const currentBtn = document.querySelector(`${localNavi} .${current.category} a[data-url="${current.page}"]`) ? document.querySelector(`${localNavi} .${current.category} a[data-url="${current.page}
489"]`) : document.querySelector(`${localNavi} .${current.category} a[data-url="${current.page}.html"]`)
490        let cb = document.querySelector(`${localNavi} .${current.category} [data-url="${current.page}"]`) ? document.querySelector(`${localNavi} .${current.category} [data-url="${current.page}"]`) : document.querySelector(`${localNavi} .${current.category} [data-url="${current.page}.html"]`)
491
492        switch (true) {
493            case 
494                (current.category === 'corporate' && current.page === 'v-square') ||
495                (current.category === 'corporate' && current.page === 'ad') ||
496                (current.category === 'corporate' && current.page === 'design') ||
497                (current.category === 'corporate' && current.page === 'quality') ||
498                (current.category === 'corporate' && current.page === 'mfg') ||
499                (current.category === 'corporate' && current.page === 'procurement'):
500                // ディレクトリ上 第二階層だが、会社概要配下とする
501    
502                cb.closest('.first_level').style.display = 'block'
503                cb.closest('.first_level').setAttribute('aria-hidden', 'false')
504    
505                cb.closest('.third_level_wrapper').style.display = 'block'
506                cb.closest('.third_level_wrapper').setAttribute('aria-hidden', 'false')
507    
508                cb.closest('.category_wrapper').style.display = 'block'
509                cb.closest('.category_wrapper').setAttribute('aria-hidden', 'false')
510    
511                document.querySelector(localNavi).classList.add('level3')
512                break
513    
514            case currentPath.length === 2 || currentPath[1] === 'employ':
515                // カテゴリートップ
516
517                document.querySelectorAll(`${localNavi} .${current.category} .first_level`)
518                .forEach(elm => {
519                    elm.style.display = 'block'
520                    elm.setAttribute('aria-hidden', 'false')
521                })
522    
523                document.querySelector(localNavi).classList.add('level2')
524                break
525
526// 				20251118不要            
527//             case currentPath[0] === 'en' // '英語ページ'
528//             && current.category === 'group'
529//             && (
530//                 current.page === 'printing-gr' 
531//                 || current.page === 'medical-gr'
532//                 || current.page === 'imaging-gr'
533//                 || current.page === 'industrial-gr'
534//             ):
535//                // 英語 Our Businessの一部
536//                 cb = document.querySelector(`${localNavi} .${current.category} [data-url="group"]`)
537// 
538//                 cb.closest('.first_level').style.display = 'block'
539//                 cb.closest('.first_level').setAttribute('aria-hidden', 'false')
540// 
541//                 cb.closest('.third_level_wrapper').style.display = 'block'
542//                 cb.closest('.third_level_wrapper').setAttribute('aria-hidden', 'false')
543// 
544//                 cb.closest('.category_wrapper').style.display = 'block'
545//                 cb.closest('.category_wrapper').setAttribute('aria-hidden', 'false')
546// 
547//                 document.querySelector(localNavi).classList.add('level3')
548// 
549//                 cb.style.display = 'inline'
550//                 cb.setAttribute('aria-hidden', 'false')
551// 
552//                 cb.classList.add('current')
553//                 break
554            
555            case currentPath.length >= 3:
556                // currentPath.lengthが3以上
557
558                if(!cb) {
559                    // カレントが存在しない
560                    document.querySelectorAll(`${localNavi} .${current.category} .first_level`).forEach(elm => {
561                        elm.style.display = 'block'
562                        elm.setAttribute('aria-hidden', 'false')
563                    })
564
565                    document.querySelector(`${localNavi} .${current.category} .first_level`).setAttribute('aria-hidden', 'false')
566                    document.querySelector(localNavi).classList.add('level2')
567                }else if (cb.closest('.second_level') === null) {
568                    document.querySelectorAll(`${localNavi} .${current.category} .first_level`).forEach(elm => {
569                        elm.style.display = 'block'
570                        elm.setAttribute('aria-hidden', 'false')
571                    })
572
573                    document.querySelector(`${localNavi} .${current.category} .first_level`).setAttribute('aria-hidden', 'false')
574                    document.querySelector(localNavi).classList.add('level2')
575                } else {
576                    switch (true) {
577                        case (current.category === 'sustainability' && current.page === 'environment')
578                        || (current.category === 'sustainability' && current.page === 'society')
579                        || (current.category === 'sustainability' && current.page === 'governance'):
580                            // サステナビリティ 3階層TOPページ
581                            cb.closest('.first_level').querySelector('.second_level .parent a').classList.add('current')
582                        
583
584    
585                        default:
586                            cb.closest('.first_level').style.display = 'block'
587                            cb.closest('.first_level').setAttribute('aria-hidden', 'false')
588    
589                            cb.closest('.third_level_wrapper').style.display = 'block'
590                            cb.closest('.third_level_wrapper').setAttribute('aria-hidden', 'false')
591    
592                            cb.closest('.category_wrapper').style.display = 'block'
593                            cb.closest('.category_wrapper').setAttribute('aria-hidden', 'false')
594    
595                            document.querySelector(localNavi).classList.add('level3')
596    
597                            cb.style.display = 'inline'
598                            cb.setAttribute('aria-hidden', 'false')
599                            break
600                    }
601                }
602                break
603            default:
604                // 該当無し
605                break
606        }
607    
608        if (currentBtn !== null) currentBtn.classList.add('current')
609    
610        document.querySelector(`${localNavi} .${current.category}`).style.display = 'block'
611        document.querySelector(`${localNavi} .${current.category}`).setAttribute('aria-hidden', 'false')
612    
613        document.querySelector(localNavi).style.display = 'block'
614    }
615    
616    getCurrentLevel()
617    getCurrentPage()
618})

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.