PageSourceSearch

https://www.aiful.co.jp/assets/js/faq-parts.js

js aiful.co.jp collected 2026-10-02 07:38:25 UTC 13,989 bytes, 423 lines download raw bytes

1
2
3"use strict";
4//@ts-check
5/* ▼ 41692.body / faq-parts.js / assets/js/faq-parts.js / start ▼ */
6class FaqCard {
7    /**
8     * クラスコンストラクタ
9     * @param {string} targetEle 挿入先のクラス名(初期値:.js-faqSlider)
10     * @returns
11     */
12    constructor(targetEle = '.js-faqSlider') {
13        this.targetEle = targetEle;
14        this.target = document.querySelectorAll(this.targetEle);
15        if (!this.target.length)
16            return;
17        this.init();
18    }
19    /**
20     * スライダーの実行
21     */
22    init() {
23        let qaSlideClass = `${this.targetEle}`;
24        const qaCard = new Swiper(qaSlideClass, {
25            centeredSlides: true,
26            slidesPerView: 1.4,
27            speed: 600,
28            spaceBetween: 10,
29            initialSlide: 0,
30            loop: true,
31            observer: true,
32            observeParents: true,
33            navigation: {
34                nextEl: qaSlideClass + ' .swiper-button-next',
35                prevEl: qaSlideClass + ' .swiper-button-prev',
36            },
37            breakpoints: {
38                769: {
39                    slidesPerView: 2,
40                    slidesPerGroup: 1,
41                    spaceBetween: 32,
42                    centeredSlides: true,
43                },
44                1120: {
45                    slidesPerView: 2,
46                },
47                1240: {
48                    slidesPerView: 2.4,
49                    spaceBetween: 32,
50                    slidesPerGroup: 1,
51                    centeredSlides: true,
52                }
53            }
54        });
55    }
56}
57//TOPスライダー用のアクション
58class FaqCardTop extends FaqCard {
59    /**
60     * クラスコンストラクタ
61     * @param {string} targetEle 挿入先のクラス名(初期値:.js-faqSlider__other)
62     * @returns
63     */
64    constructor(targetEleContainer = '.js-faqSlider__other') {
65        super();
66        this.targetEleContainer = targetEleContainer;
67        this.targetEle = '.js-faqSlider';
68        // console.log(this.targetEleContainer);
69        // console.log(this.targetEle);
70        this._targets = document.querySelectorAll(this.targetEleContainer);
71        if (!this._targets.length) {
72            console.log('ありません');
73            return;
74        }
75    }
76    /**
77     * FaqCardクラスのinitメソッドをオーバライドして活用
78     */
79    init() {
80        let initialSlide = 0;
81        if (window.innerWidth > 768) {
82            initialSlide = 1;
83        }
84        const swiper = new Swiper(`${this.targetEle}`, {
85            centeredSlides: true,
86            slidesPerView: 1.4,
87            speed: 600,
88            spaceBetween: 10,
89            initialSlide: initialSlide,
90            loop: true,
91            navigation: {
92                nextEl: `.js-faqSlider__other .swiper-button-next`,
93                prevEl: `.js-faqSlider__other .swiper-button-prev`,
94            },
95            breakpoints: {
96                768: {
97                    slidesPerView: 2,
98                    slidesPerGroup: 1,
99                    spaceBetween: 52,
100                    centeredSlides: true,
101                },
102                1024: {
103                    slidesPerView: 3.5,
104                    spaceBetween: 42,
105                    centeredSlides: true,
106                },
107                1693: {
108                    slidesPerView: 4,
109                    spaceBetween: 52,
110                    centeredSlides: true,
111                },
112            },
113        });
114		if (document.getElementById("top_wrapper") || document.getElementById("membership_wrapper")) {
115			// TOPページのみパララックス
116	        window.addEventListener("scroll", () => this.onScroll());
117		}
118    }
119    onScroll() {
120        let scrollTop = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
121        scrollTop = scrollTop + window.innerHeight / 1.5;
122        if (this._targets[0].offsetTop < scrollTop) {
123            this.show(this._targets[0]);
124        }
125    }
126    show(target) {
127        target.classList.add("show");
128        // console.log('FAQ表示')
129    }
130}
131
132class FaqAccordion {
133    /**
134     * クラスコンストラクタ
135     * @param {string} targetEle 挿入先のクラス名(初期値:.qa_list dt)
136     * @returns
137     */
138    constructor(targetEle = ".qa_list dt") {
139        this.targetEle = targetEle;
140        this._target = document.querySelectorAll(targetEle);
141        if (!this._target.length) {
142            return;
143        }
144        this.init();
145    }
146    /**
147     * アコーディオンの実行
148     */
149    init() {
150        for (let i = 0; i < this._target.length; i++) {
151            this._target[i].addEventListener("click", this.onClickHD.bind(this), false);
152        }
153    }
154    /**
155     * アコーディオンの状態管理
156     * @param event
157     */
158    onClickHD(event) {
159        const targetElement = event.currentTarget;
160        const parentElement = targetElement.parentNode;
161        const nextElement = targetElement.nextElementSibling;
162        if (parentElement.classList.contains("active")) {
163            Velocity(nextElement, "slideUp", {
164                duration: 300,
165                easing: "easeInOutSine",
166                begin: function () {
167                    parentElement.classList.remove("active");
168                },
169            });
170        }
171        else {
172            Velocity(nextElement, "slideDown", {
173                duration: 300,
174                easing: "easeInOutSine",
175                begin: function () {
176                    parentElement.classList.add("active");
177                },
178            });
179        }
180    }
181}
182//FAQコンポーネントのベースクラス
183class FaqBaseComponent {
184    /**
185     * クラスコンストラクタ
186     * @param {string} filename 読み込むファイルのパス
187     */
188    constructor(filename) {
189        this.filename = filename;
190    }
191    /**
192     * ファイルデータからオブジェクトデータを取得
193     * @returns {dynamicType[]} オブジェクト配列
194     */
195    async init() {
196        const fetchFaq = new FetchData(this.filename);
197        let data = await fetchFaq.publishedData();
198        return data;
199    }
200
201	/**
202 * 構造化データを設置する
203 * @param type 構造化タイプ
204 * @param objects オブジェクト配列
205 */
206	setSchemaDocument(type, objects) {
207		const entities = [];
208		objects.forEach((obj) => {
209			// 質問そのものの抽出
210			let question = obj.title;
211			// 回答そのものの抽出
212			let answer = obj.summary.trim();
213			entities.push(createQuestionEntity(question, answer));
214		});
215		const schemaBody = {
216			"@context": "https://schema.org",
217			"@type": type,
218			mainEntity: entities,
219		};
220		createSchemaElement(JSON.stringify(schemaBody));
221		/**
222		 * mainEntityの中のオブジェクト情報を生成する
223		 * @param question 質問内容
224		 * @param answer 回答内容
225		 * @returns mainEntityの中のオブジェクト
226		 */
227		function createQuestionEntity(question, answer) {
228			if (!question || !answer) {
229				return false;
230			}
231			return {
232				"@type": "Question",
233				name: `${question}`,
234				acceptedAnswer: {
235					"@type": "Answer",
236					text: `${answer}`,
237				},
238			};
239		}
240		/**
241		 * 入力されたJSONテキストをschema.orgとしてheadタグに追加する
242		 * @param structuredDataText JSONデータ(schema.org用の形式に変換済みの状態で入力)
243		 */
244		function createSchemaElement(structuredDataText) {
245			const script = document.createElement("script");
246			script.setAttribute("type", "application/ld+json");
247			script.textContent = structuredDataText;
248			document.head.appendChild(script);
249		}
250	}
251
252}
253//FAQアコーディオン用クラス
254class FaqAccordionList extends FaqBaseComponent {
255    /**
256     * クラスコンストラクタ
257     * @param filename 読み込むファイルのパス
258     * @param IDArr FAQのIDの配列
259     * @param targetEl 挿入先のクラス名(初期値:.qa_list_content)
260     */
261    constructor(filename, IDArr, targetEl = '.qa_list_content') {
262        super(filename);
263        this.IDArr = IDArr;
264        this.targetEl = targetEl;
265        TsFontKeyArray && TsFontKeyArray.push('accordion');
266    }
267    /**
268     * データをフェッチしてからアコーディオンをセットする
269     */
270    preInit() {
271        (async () => {
272            const objects = await super.init();
273            await this.setAccordion(objects);
274            await new FaqAccordion();
275            await TsObserve && TsObserve.push('accordion fin');
276            // Ts.loadFont()
277        })();
278        // const t = new ObserveClass(this.targetEl,'js-faq__finished',() => {
279        // 	Ts.loadFont()
280        // })
281    }
282    /**
283     * アコーディオンをセットする
284     * @param {faqObj[]} objects 銀行情報オブジェクトの配列
285     */
286    setAccordion(objects) {
287        const wrapper = document.querySelector(this.targetEl);
288        if (!wrapper) {
289            console.error('挿入先のクラスが設定されていません');
290            return false;
291        }
292        const pickObjects = [];
293        for (let target of this.IDArr) {
294            for (let object of objects) {
295                if (Number(object.id) == target) {
296                    pickObjects.push(object);
297                    wrapper.insertAdjacentHTML('beforeend', this.setFaqAccordionItem(object));
298                    break;
299                }
300            }
301        }
302        this.setSchemaDocument("FAQPage", pickObjects);
303    }
304    /**
305     * FAQアコーディオンの各アイテムを作成
306     * @param {faqObj} object FAQ情報オブジェクト
307     * @returns html
308     */
309    setFaqAccordionItem(object) {
310        // <dt onclick="ga('send','event','FAQaccodion','${object.title}')"><span>Q</span>${object.title}</dt>\n
311        const html = `
312		<dl data-no="${object.id}">\n
313			<dt onclick="ga('send','event','FAQaccodion','${object.title}')"><span>Q</span>${object.title}</dt>\n
314			<dd><span>A</span>\n
315				${object.summary}
316				<div><em><a href='${object.url}'>もっと見る</a></em></div>\n
317			</dd>\n
318		</dl>
319		`;
320        return html;
321    }
322}
323//FAQスライダー用クラス
324class FaqSliderList extends FaqBaseComponent {
325    /**
326     * クラスコンストラクタ
327     * @param filename 読み込むファイルのパス
328     * @param IDArr FAQのIDの配列
329     * @param slideSelector スライダーがページ内に複数ある場合は、.js-faqSliderに任意のクラスを付与する(.slide01,.slide02など)
330     * @param targetEle スライダーにさせるul要素
331     * @param pattern pattern:スライダーのパターン('normal'か'top',初期値は'normal')
332     */
333	constructor(filename, IDArr, slideSelector = '.js-faqSlider', pattern = 'normal') {
334        super(filename);
335		this.IDArr = IDArr;
336		this.slideSelector = `${slideSelector}`;
337		this.targetEle = `${slideSelector} .js-faqSlider__list`;
338        this.pattern = pattern;
339        // this.preInit()
340        TsFontKeyArray && TsFontKeyArray.push('slider');
341    }
342    /**
343     * データをフェッチしてからスライダーをセットする
344     */
345    preInit() {
346        (async () => {
347            const objects = await super.init();
348            await this.setSlider(objects);
349            switch (this.pattern) {
350                case 'normal':
351					await new FaqCard(this.slideSelector);
352                    break;
353                case 'top':
354                    await new FaqCardTop();
355                    break;
356            }
357            await TsObserve && TsObserve.push('slider fin');
358        })();
359    }
360    /**
361     * スライダーをセットする
362     * @param {faqObj[]} objects 銀行情報オブジェクトの配列
363     */
364    setSlider(objects) {
365        const wrapper = document.querySelectorAll(this.targetEle);
366        if (!wrapper) {
367            console.error('挿入先のクラスが設定されていません');
368            return false;
369        }
370        let count = 0;
371		const pickObjects = [];
372        for (let i = 0; i < wrapper.length; i++) {
373            for (let target of this.IDArr) {
374                for (let object of objects) {
375                    if (Number(object.id) == target) {
376                        count++;
377						pickObjects.push(object);
378                        wrapper[i].insertAdjacentHTML('beforeend', this.setFaqSliderItem(object, count));
379                        break;
380                    }
381                }
382            }
383			count = 0;
384        }
385		if (!document.querySelector(".qa_list_content")) {
386			this.setSchemaDocument("FAQPage", pickObjects);
387		}
388    }
389
390    /**
391     * FAQスライダーの各アイテムを作成
392     * @param {faqObj} object FAQ情報オブジェクト
393     * @returns html
394     */
395    setFaqSliderItem(object, index) {
396        const html = `
397		<li class="swiper-slide">\n
398			<p class="num">${this.toDoubleDigits(index)}</p>\n
399			<p class="ttl">${object.title}</p>\n
400			<div class="bottom">\n
401				<p class="text">${object.summary.replace(/(\<\p\>(.*)+\<\/\p>|(<([^>
401]+)>))/gi, '')}</p><a class="btn_arr" href="${object.url}">もっと見る</a>\n
402			</div>\n
403		</li>\n
404		`;
405        return html;
406    }
407    /**
408     * 1桁の数字を0埋めで2桁にする
409     * @param num 数値
410     * @returns 2桁表示の数値
411     */
412    toDoubleDigits(num) {
413        num += "";
414        if (num.toString().length === 1) {
415            num = "0" + num;
416        }
417        return num.toString();
418    }
419}
420/* ▲ 41692.body / faq-parts.js / assets/js/faq-parts.js / end ▲ */
421
422
423

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.