PageSourceSearch

https://www.galleryjapan.com/element/main_rwd/work_detail/script/orig/script.js

js galleryjapan.com collected 2026-10-02 05:10:40 UTC 56,517 bytes, 1,517 lines download raw bytes

1'use strict';
2
3$.main_rwd.work_detail = $.main_rwd.work_detail || {};
4var drag = false; // カルーセルのドラッグフラグ
5var swiper_work;
6
7$(function(){
8
9	// 作家情報が取得できなかった時は、以降の処理を行わない。
10	// (モジュール内の作家情報取得クエリで作家情報が取得できなかった時は処理中断によりscript_envに値が返却されない場合もある)
11	if(typeof TRAVELKO === 'undefined' || typeof(TRAVELKO.APP.creator_id) === 'undefined'){
12		return false;
13	}
14	// ツールチップのイベント設定
15	$.main_rwd.setArtistPriceRangeToolTip();
16
17	// 作品詳細 画像スライド(サムネイル)
18	var swiper_work_thumb = null;
19	if($('#Act_swiper_work_thumb').length > 0){
20		swiper_work_thumb = new Swiper("#Act_swiper_work_thumb", {
21			spaceBetween: 0,
22			slidesPerView: 'auto',
23			watchSlidesProgress: true
24		});
25	}
26	// 作品詳細 画像スライド ※ 画像拡大ライブラリでもswiper_work変数を使用するので、document.ready内で定義しない
27	swiper_work = new Swiper("#Act_swiper_work", {
28		pagination: {
29			el: "#Act_swiper_work_locationbar",
30			clickable: true
31		},
32		navigation: {
33			nextEl: "#Act_swiper_next_work",
34			prevEl: "#Act_swiper_prev_work"
35		},
36		loop: true,
37		freeMode: {
38			enabled: true,
39			sticky: true,
40			momentumRatio: 0.8,
41			momentumVelocityRatio: 0.8
42		},
43		slidesPerView: 'auto',
44		spaceBetween: 0,
45		thumbs: {
46			swiper: swiper_work_thumb
47		}
48	});
49	// スライドイベント設定
50	if(parseInt($('#Act_work_count').val()) > 1){
51		$("#Area_work_inner").hover(
52			function(){
53				$("#Act_swiper_next_work").addClass('is-hover');
54				$("#Act_swiper_prev_work").addClass('is-hover');
55			},function(){
56				$("#Act_swiper_next_work").removeClass('is-hover');
57				$("#Act_swiper_prev_work").removeClass('is-hover');
58			}
59		);
60	}
61
62	// 作品画像swiperのツールチップのイベント設定
63	$.main_rwd.setArtistPriceRangeToolTip('Act_swiper_work');
64
65	//-----------------------------------
66	// 作品一覧取得
67	//-----------------------------------
68	// SSR: サーバーサイドでレンダリング済みの場合、Swiper初期化のみ行う
69	$.main_rwd.work_detail.initSSRParts();
70	//==========================================================
71	// [Event]トグル開閉
72	//==========================================================
73	$('.Act_work_toggle').click(function(e) {
74		if($(this).closest('.Act_select_toggle_panel').attr('aria-expanded') === 'true'){
75			$(this).closest('.Act_select_toggle_panel').attr('aria-expanded','false');
76		}else{
77			$(this).closest('.Act_select_toggle_panel').attr('aria-expanded','true');
78		}
79		$.main_rwd.work_detail.saveState();
80		return null;
81	});
82
83	//==========================================================
84	// [Event]この作品のお問合せクリック
85	//==========================================================
86//	$('a#Act_Form').click(function(){
87//		if (typeof dataLayer !== 'undefined') {
88//			// GTM送信
89//			var creator_name = $('.artwork-header-hdg').text();
90//			var craft_name = $('.artwork-header-hdg-sup').text();
91//			dataLayer.push({'event': 'work_form_click',
92//				'creator_id': TRAVELKO.APP.creator_id,
93//				'creator_name': creator_name,
94//				'craft_id': TRAVELKO.APP.craft_id,
95//				'craft_name': craft_name
96//				});
97//		}
98//		$('#Act_formWork').submit();
99//		return false;
100//	});
101
102	/**
103	 * 作品画像拡大モーダル表示
104	 */
105	$('div.zoom').on('click', function(e) {
106		var ws_width = $(window).width();
107		if (!drag && ws_width >= $.main_rwd.breakpoint_l) {
108			var img = $('div.slick-current img').clone(true);
109			$('.modal-content').append(img);
110			$('div.str-container').addClass('is-modal-active');
111		}
112	});
113
114	/**
115	 * 拡大モーダル 閉じるボタン押下
116	 */
117	$(".modal-content-btn-close").on('click', function() {
118		$('div.str-container').removeClass('is-modal-active');
119		$('.modal-content img').remove();
120	});
121
122	/**
123	 * 拡大モーダルの領域外をクリックした場合の動作
124	 * 拡大モーダルを閉じる
125	 */
126	$(document).on('click', 'div.modal-image', function(e){
127		if (!$(e.target).parents('div.modal-image').length) {
128			$('div.str-container').removeClass('is-modal-active');
129			$('.modal-content img').remove();
130		}
131	});
132
133	//==========================================================
134	// [Event] テキスト省略
135	//==========================================================
136	$.main_rwd.work_detail.setOmitAboutWorkText('close');
137	$.main_rwd.work_detail.setOmitTechText('close');
138	$.main_rwd.work_detail.setOmitAwardCommentText('close');
139	//==========================================================
140	// [Event] 作品について もっと見る(続きを見る)ボタンクリック
141	//==========================================================
142	$('#Act_about_work_read_more').click(function(){
143		if($(this).hasClass('Act_about_work_text_open')){
144			$.main_rwd.work_detail.setOmitAboutWorkText('close');
145		}else{
146			$.main_rwd.work_detail.setOmitAboutWorkText('open');
147		}
148		// 項目名がページ外にある場合、項目名までスクロールする
149		if($('#Act_about_work_title').offset().top < $(window).scrollTop()){
150			var headerHeight = $('#Act_work_detail_upper').outerHeight(true);
151			$('html,body').animate({scrollTop: $('#Act_about_work_title').offset().top - headerHeight}, 300);
152		}
153		$.main_rwd.work_detail.setSessionStorage();
154	});
155	//==========================================================
156	// [Event] 技法 もっと見る(続きを見る)ボタンクリック
157	//==========================================================
158	$('#Act_tech_read_more').click(function(){
159		if($(this).hasClass('Act_tech_text_open')){
160			$.main_rwd.work_detail.setOmitTechText('close');
161		}else{
162			$.main_rwd.work_detail.setOmitTechText('open');
163		}
164		// 項目名がページ外にある場合、項目名までスクロールする
165		if($('#Act_tech_title').offset().top < $(window).scrollTop()){
166			var headerHeight = $('#Act_work_detail_upper').outerHeight(true);
167			$('html,body').animate({scrollTop: $('#Act_tech_title').offset().top - headerHeight}, 300);
168		}
169		$.main_rwd.work_detail.setSessionStorage();
170	});
171	//==========================================================
172	// [Event] 受賞コメント もっと見る(続きを見る)ボタンクリック
173	//==========================================================
174	$('#Act_award_comment_read_more').click(function(){
175		if($(this).hasClass('Act_award_comment_text_open')){
176			$.main_rwd.work_detail.setOmitAwardCommentText('close');
177		}else{
178			$.main_rwd.work_detail.setOmitAwardCommentText('open');
179		}
180		// 項目名がページ外にある場合、項目名までスクロールする
181		if($('#Act_award_comment_title').offset().top < $(window).scrollTop()){
182			var headerHeight = $('#Act_work_detail_upper').outerHeight(true);
183			$('html,body').animate({scrollTop: $('#Act_award_comment_title').offset().top - headerHeight}, 300);
184		}
185		$.main_rwd.work_detail.setSessionStorage();
186	});
187
188	/**
189	 * ウィンドウサイズを変更した場合の動作
190	 * 拡大モーダルサイズもウィンドウサイズに合わせて変更する
191	 */
192	$(window).on('resize', function() {
193		var d_modal_resize = $('div.modal-image');
194		var d_modal_block;
195		var modal_index;
196		$.each(d_modal_resize, function(index, modal) {
197			if (modal.style.display == 'block') {
198				modal_index = index;
199				return false;
200			}
201		});
202
203		if (modal_index != null) {
204			d_modal_block = $('div.modal-image').eq(modal_index);
205
206			var window_height = $(window).height();
207			var window_width = $(window).width();
208			var setting_value;
209
210			if (window_width < window_height) {
211				// windowの幅が高さより小さい場合、幅を基準に設定
212				setting_value = window_width - 80;
213
214			} else {
215				// それ以外の場合は、高さを基準に設定
216				setting_value = window_height - 80;
217			}
218			d_modal_block.css('width', setting_value);
219		}
220	});
221	// 存在しない作品の場合 タイトルを書き換える
222	if ($('.str-main').length == 0) {
223		$('title').html(TRANSLATE['gallery.seo.top.title']);
224	}
225
226	//-----------------------------------
227	// 購入手順モーダル表示
228	//-----------------------------------
229	$('#Act_modal_purchasing').click(function() {
230		$('body').addClass('is-active');
231		$('#Act_purchasing_procedures').addClass('is-active');
232		return null;
233	});
234
235	//-----------------------------------
236	// 購入手順モーダルトグルクリック
237	//-----------------------------------
238	$('.Act_purchasing_title').click(function() {
239		if ($(this).closest('.Act_purchasing_toggle').attr('aria-expanded') == 'false') {
240			$(this).closest('.Act_purchasing_toggle').attr('aria-expanded','true');
241		} else {
242			$(this).closest('.Act_purchasing_toggle').attr('aria-expanded','false');
243		}
244		return null;
245	});
246
247	//-----------------------------------
248	// SP:event:戻るボタン
249	//-----------------------------------
250	$('#Act_purchasing_close').click(function() {
251		setTimeout(function(){
252			$('body').removeClass('is-active').dequeue();
253			$('#Act_purchasing_procedures').removeClass('is-active');
254			$('.Act_purchasing_toggle').attr('aria-expanded','false');
255		},300);
256	});
257	$('#Act_modal_layer').click(function() {
258		$('#Act_purchasing_close').trigger('click');
259	});
260
261	// 別ページからブラウザ履歴で訪問した場合のみ、テキストの開閉状態の復元を行なう
262	if (window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
263		var sessionStorageKey = location.href;
264		var sessionItem = sessionStorage.getItem(sessionStorageKey);
265		// テキスト開閉状態の復元
266		var aboutWorkStatus = sessionItem ? JSON.parse(sessionItem).aboutWorkStatus : 'close';
267		var techniqueStatus = sessionItem ? JSON.parse(sessionItem).techniqueStatus : 'close';
268		var awardCommentStatus = sessionItem ? JSON.parse(sessionItem).awardCommentStatus : 'close';
269		var button = null;
270		// 作品について
271		button = document.getElementById('Act_about_work_read_more');
272		if(button !== null){
273			if(aboutWorkStatus === 'open'){
274				button.classList.replace('Act_about_work_text_close', 'Act_about_work_text_open');
275				$.main_rwd.work_detail.setOmitAboutWorkText('open');
276			}else{
277				button.classList.replace('Act_about_work_text_open', 'Act_about_work_text_close');
278				$.main_rwd.work_detail.setOmitAboutWorkText('close');
279			}
280		}
281		// 技法
282		button = document.getElementById('Act_tech_read_more');
283		if(button !== null){
284			if(techniqueStatus === 'open'){
285				button.classList.replace('Act_tech_text_close', 'Act_tech_text_open');
286				$.main_rwd.work_detail.setOmitTechText('open');
287			}else{
288				button.classList.replace('Act_tech_text_open', 'Act_tech_text_close');
289				$.main_rwd.work_detail.setOmitTechText('close');
290			}
291		}
292		// 受賞コメント
293		button = document.getElementById('Act_award_comment_read_more');
294		if(button !== null){
295			if(awardCommentStatus === 'open'){
296				button.classList.replace('Act_award_comment_text_close', 'Act_award_comment_text_open');
297				$.main_rwd.work_detail.setOmitAwardCommentText('open');
298			}else{
299				button.classList.replace('Act_award_comment_text_open', 'Act_award_comment_text_close');
300				$.main_rwd.work_detail.setOmitAwardCommentText('close');
301			}
302		}
303		// ローカルストレージの削除
304		sessionStorage.removeItem(sessionStorageKey);
305	}
306	// お気に入りボタンが押された際の動作を設定
307	setUpFavoriteButtonListeners();
308});
309
310/**************************************************
311 * パラメータ生成
312 *
313 * @returns false
314 **************************************************/
315$.main_rwd.work_detail.generateParam = function(ws_type) {
316
317	var wa_param = [];
318
319	var measure = 'cm';
320	if($.cookie('measure_f') !== null){
321		measure = $.cookie('measure_f');
322	}
323
324	switch (ws_type) {
325		case "other":
326			var wo_param = {
327				except_craft_id	: TRAVELKO.APP.craft_id,				// 作品ID
328				creator_id		: TRAVELKO.APP.creator_id,				// 作家ID
329				locale			: TRAVELKO.FW.LOCALE,					// 言語
330				currency		: $.cookie('currency_f'),				// 通貨
331				dimensions_unit	: measure								// サイズ
332			};
333			break;
334		case "recommend":
335			var wo_param = {
336				craft_id		: TRAVELKO.APP.craft_id,				// 作品ID
337				creator_id		: TRAVELKO.APP.creator_id,				// 作家ID
338				locale			: TRAVELKO.FW.LOCALE,					// 言語
339				currency		: $.cookie('currency_f'),				// 通貨
340				dimensions_unit	: measure								// サイズ
341			};
342			break;
343		default:
344			break;
345	}
346
347	for(var ws_key in wo_param){
348		if (wo_param[ws_key] !== "" && wo_param[ws_key] !== undefined) {
349			wa_param.push(ws_key + "=" + wo_param[ws_key]);
350		}
351	}
352
353	// パラメータ返却
354	return "" + wa_param.join("&");
355};
356
357/**************************************************
358 * 作風について テキストの省略
359 **************************************************/
360$.main_rwd.work_detail.setOmitAboutWorkText = function(status) {
361
362	var lineHeight=0;
363	var height=0;
364	var row=0;
365	var omit_flag=false;
366	var button = document.getElementById('Act_about_work_read_more');
367	// 要素がない場合は処理終了
368	if(button === null){
369		return false;
370	}
371	if(typeof status === 'undefined'){
372		status = button.classList.contains('Act_about_work_text_open') ? 'open' : 'close';
373	}
374	var element = document.getElementById('Act_omit_about_work_text');
375	// 一旦省略スタイルを削除(行の計算が出来なくなるので)
376	element.classList.remove('artwork-detail-data-content-ellipsis-3');
377	// 行数の計算(テキスト1行分の高さと行全体の高さから割り出して計算)
378	lineHeight = parseFloat(window.getComputedStyle(element).lineHeight);
379	height = element.clientHeight;
380	row = Math.round(height / lineHeight);
381	if(row >= 6){
382		omit_flag = true;
383		// 省略が必要なくらいテキストが長い場合はテキスト開閉ボタンを表示する。
384		button.classList.remove('artwork-detail-data-content-hidden');
385	}else{
386		// テキストの省略が不要の時はテキスト開閉ボタンを非表示にする。
387		button.classList.add('artwork-detail-data-content-hidden');
388	}
389	// status:open の時は、全コンテンツを表示
390	if(status == 'open'){
391		// 前処理で全ての省略スタイルが削除されているため、ここでは特にテキストの処理なし
392		// ボタンを開くスタイルに
393		button.classList.remove('Act_about_work_text_close');
394		button.classList.add('Act_about_work_text_open');
395		button.textContent = TRANSLATE['gallery.master.read_less'];
396	}else{
397		// status:close の時は、省略処理を行う
398		if(omit_flag){
399			// 6行以上の場合は、3行で語尾が「...」となるスタイルを適用する。
400			element.classList.add('artwork-detail-data-content-ellipsis-3');
401		}
402		// ボタンを閉じるスタイルに
403		button.classList.add('Act_about_work_text_close');
404		button.classList.remove('Act_about_work_text_open');
405		button.textContent = TRANSLATE['gallery.master.read_more'];
406	}
407}
408/**************************************************
409 * 受賞コメント テキストの省略
410 **************************************************/
411$.main_rwd.work_detail.setOmitAwardCommentText = function(status) {
412
413	var lineHeight=0;
414	var height=0;
415	var row=0;
416	var omit_flag=false;
417	var button = document.getElementById('Act_award_comment_read_more');
418	// 要素がない場合は処理終了
419	if(button === null){
420		return false;
421	}
422	if(typeof status === 'undefined'){
423		status = button.classList.contains('Act_award_comment_text_open') ? 'open' : 'close';
424	}
425	var element = document.getElementById('Act_omit_award_comment_text');
426	// 一旦省略スタイルを削除(行の計算が出来なくなるので)
427	element.classList.remove('artwork-detail-data-content-ellipsis-3');
428	// 行数の計算(テキスト1行分の高さと行全体の高さから割り出して計算)
429	lineHeight = parseFloat(window.getComputedStyle(element).lineHeight);
430	height = element.clientHeight;
431	row = Math.round(height / lineHeight);
432	if(row >= 6){
433		omit_flag = true;
434		// 省略が必要なくらいテキストが長い場合はテキスト開閉ボタンを表示する。
435		button.classList.remove('artwork-detail-data-content-hidden');
436	}else{
437		// テキストの省略が不要の時はテキスト開閉ボタンを非表示にする。
438		button.classList.add('artwork-detail-data-content-hidden');
439	}
440	// status:open の時は、全コンテンツを表示
441	if(status == 'open'){
442		// 前処理で全ての省略スタイルが削除されているため、ここでは特にテキストの処理なし
443		// ボタンを開くスタイルに
444		button.classList.remove('Act_award_comment_text_close');
445		button.classList.add('Act_award_comment_text_open');
446		button.textContent = TRANSLATE['gallery.master.read_less'];
447	}else{
448		// status:close の時は、省略処理を行う
449		if(omit_flag){
450			// 6行以上の場合は、3行で語尾が「...」となるスタイルを適用する。
451			element.classList.add('artwork-detail-data-content-ellipsis-3');
452		}
453		// ボタンを閉じるスタイルに
454		button.classList.add('Act_award_comment_text_close');
455		button.classList.remove('Act_award_comment_text_open');
456		button.textContent = TRANSLATE['gallery.master.read_more'];
457	}
458}
459/**************************************************
460 * 技法 テキストの省略
461 **************************************************/
462$.main_rwd.work_detail.setOmitTechText = function(status) {
463	var elements = document.querySelectorAll('.Act_omit_tech_text');
464	var lineHeight=0;
465	var height=0;
466	var row=0;
467	var total_row=0;
468	var omit_flag=false; //省略フラグ
469	var button=document.getElementById('Act_tech_read_more');
470	// 技法の要素がない場合は処理終了
471	if(button === null){
472		return false;
473	}
474	if(typeof status === 'undefined'){
475		status = button.classList.contains('Act_tech_text_open') ? 'open' : 'close';
476	}
477	// 総行数の計算と、総行数から省略が必要なテキストかどうか判定
478	elements.forEach(function(element){
479		// 一旦全ての要素から省略スタイルを削除、非表示の場合は表示状態に(行の計算が出来なくなるので)
480		// 省略スタイル削除
481		element.classList.remove('artwork-detail-data-content-ellipsis-1');
482		element.classList.remove('artwork-detail-data-content-ellipsis-2');
483		element.classList.remove('artwork-detail-data-content-ellipsis-3');
484		// 非表示テキストを表示に
485		element.classList.remove('artwork-detail-data-content-hidden');
486		// 技法詳細リンクがある時、aタグを表示する(配下の要素の技法名とテキストも表示される)
487		var elementContainsArea = element.closest('.Act_omit_tech_area');
488		var techName = null;
489		if(elementContainsArea){
490			elementContainsArea.classList.remove('artwork-detail-data-content-hidden');
491		}else{
492			// 技法詳細リンクがない時は1つ前の要素が技法名なので、それを表示する。
493			techName = element.previousElementSibling;
494			if(techName){
495				techName.classList.remove('artwork-detail-data-content-hidden');
496			}
497		}
498		// 行数の計算(テキスト1行分の高さと行全体の高さから割り出して計算)
499		lineHeight = parseFloat(window.getComputedStyle(element).lineHeight);
500		height = element.clientHeight;
501		row=Math.round(height / lineHeight);
502		total_row += row;
503		if(total_row >= 6 && !omit_flag){
504			omit_flag=true;
505		}
506	});
507	// status:open の時は、全コンテンツを表示
508	if(status == 'open'){
509		if(omit_flag){
510			// 前処理で全ての省略スタイルが削除されているため、ここでは特にテキストの処理なし
511			// 省略が必要なくらいテキストが長い場合はテキスト開閉ボタンを表示する。
512			button.classList.remove('artwork-detail-data-content-hidden');
513		}else{
514			// テキストの省略が不要の時はテキスト開閉ボタンを非表示にする。
515			button.classList.add('artwork-detail-data-content-hidden');
516		}
517		// ボタンを開くスタイルに
518		button.classList.remove('Act_tech_text_close');
519		button.classList.add('Act_tech_text_open');
520		button.textContent = TRANSLATE['gallery.master.read_less'];
521	}
522	// status:close の時は、省略処理を行う
523	if(status == 'close'){
524		if(omit_flag){
525			// 省略が必要なくらいテキストが長い場合はテキスト開閉ボタンを表示する。
526			button.classList.remove('artwork-detail-data-content-hidden');
527			// 総行数が3行を超える時に、そのテキストの語尾が「...」となるスタイルを適用する。
528			total_row=0;
529			elements.forEach(function(element){
530				lineHeight = parseFloat(window.getComputedStyle(element).lineHeight);
531				height = element.clientHeight;
532				row=Math.round(height / lineHeight);
533				total_row += row;
534				if(total_row > 3){
535					if(3-(total_row-row) == 1){
536						element.classList.add('artwork-detail-data-content-ellipsis-1');
537					}else if(3-(total_row-row) == 2){
538						element.classList.add('artwork-detail-data-content-ellipsis-2');
539					}else if(3-(total_row-row) == 3){
540						element.classList.add('artwork-detail-data-content-ellipsis-3');
541					}else{
542						// 総行数3行以降の技法は丸ごと表示しない。
543						// 技法詳細リンクがある時、aタグを非表示に(配下の要素の技法名とテキストも非表示)
544						var elementContainsArea = element.closest('.Act_omit_tech_area');
545						var techName = null;
546						if(elementContainsArea){
547							elementContainsArea.classList.add('artwork-detail-data-content-hidden');
548						}else{
549							// 技法詳細リンクがない時は1つ前の要素が技法名なので、それを非表示にする。
550							techName = element.previousElementSibling;
551							if(techName){
552								techName.classList.add('artwork-detail-data-content-hidden');
553							}
554						}
555						// 技法テキストも非表示にする
556						element.classList.add('artwork-detail-data-content-hidden');
557					}
558				}
559			});
560		}else{
561			// テキストの省略が不要の時はテキスト開閉ボタンを非表示にする。
562			button.classList.add('artwork-detail-data-content-hidden');
563		}
564		// ボタンを閉じるスタイルに
565		button.classList.remove('Act_tech_text_open');
566		button.classList.add('Act_tech_text_close');
567		button.textContent = TRANSLATE['gallery.master.read_more'];
568	}
569}
570$.main_rwd.work_detail.setSessionStorage = function() {
571// 開いてるタブ、その他諸々の状態を保存
572var aboutWorkElement = document.getElementById('Act_about_work_read_more');
573var aboutWorkStatus = aboutWorkElement && aboutWorkElement.classList.contains('Act_about_work_text_close') ? 'close' : 'open';
574var techniqueElement = document.getElementById('Act_tech_read_more');
575var techniqueStatus = techniqueElement && techniqueElement.classList.contains('Act_tech_text_close') ? 'close' : 'open';
576var awardCommentElement = document.getElementById('Act_award_comment_read_more');
577var awardCommentStatus = awardCommentElement && awardCommentElement.classList.contains('Act_award_comment_text_close') ? 'close' : 'open';
578sessionStorage.setItem(location.href,
579	JSON.stringify({
580		aboutWorkStatus: aboutWorkStatus,
581		techniqueStatus: techniqueStatus,
582		awardCommentStatus: awardCommentStatus}));
583}
584/**********************************************************
585 * SSR済みコンテンツ(作品一覧、作家の他作品レコメンド)の初期化
586 **********************************************************/
587$.main_rwd.work_detail.initSSRParts = function() {
588	//-----------------------------------
589	// 作品一覧初期化
590	//-----------------------------------
591	// 作家の他の作品の、作家名に作家詳細ページへのリンクをセット
592	$('#Act_artist_name_work_other').attr('href', '/locale/'+TRAVELKO.FW.LOCALE+'/artist/' + TRAVELKO.APP.creator_id + '/#tab=about');
593	// 作品詳細 画像スライド
594	var swiper_work_other = new Swiper("#Act_swiper_work_other", {
595		scrollbar: {
596			el: "#Act_swiper_work_other_locationbar",
597			draggable: true
598		},
599		navigation: {
600			nextEl: "#Act_swiper_next_work_other",
601			prevEl: "#Act_swiper_prev_work_other"
602		},
603		freeMode: {
604			enabled: true,
605			sticky: true,
606			momentumRatio: 0.8,
607			momentumVelocityRatio: 0.8
608		},
609		slidesPerView: 'auto',
610		spaceBetween: 12,
611		breakpoints:{
612			744: {
613				spaceBetween: 8
614			}
615		},
616		on: {
617			slideChange: function(){
618				// 画像をスライドさせた時に隣接画像も即時読み込みする
619				$.main_rwd.loadAdjacentImages(swiper_work_other);
620			}
621		}
622	});
623	// スライドイベント設定
624	$("#Act_swiper_work_other_container").hover(
625		function(){
626			$("#Act_swiper_next_work_other").addClass('is-hover');
627			$("#Act_swiper_prev_work_other").addClass('is-hover');
628		},function(){
629			$("#Act_swiper_next_work_other").removeClass('is-hover');
630			$("#Act_swiper_prev_work_other").removeClass('is-hover');
631		}
632	);
633	// ツールチップのイベント設定
634	$.main_rwd.setArtistPriceRangeToolTip('Act_swiper_work_other');
635	// お気に入りボタンが押された際の動作を設定
636	setUpFavoriteButtonListeners(document.getElementById("Act_detail_work_list"));
637	//-----------------------------------
638	// レコメンド初期化
639	//-----------------------------------
640	// 作品詳細 画像スライド
641	var swiper_work_recommend = new Swiper("#Act_swiper_work_recommend", {
642		scrollbar: {
643			el: "#Act_swiper_work_recommend_locationbar",
644			draggable: true
645		},
646		navigation: {
647			nextEl: "#Act_swiper_next_work_recommend",
648			prevEl: "#Act_swiper_prev_work_recommend"
649		},
650		freeMode: {
651			enabled: true,
652			sticky: true,
653			momentumRatio: 0.8,
654			momentumVelocityRatio: 0.8
655		},
656		slidesPerView: 'auto',
657		spaceBetween: 12,
658		breakpoints:{
659			744: {
660				spaceBetween: 8
661			}
662		},
663		on: {
664			slideChange: function(){
665				// 画像をスライドさせた時に隣接画像も即時読み込みする
666				$.main_rwd.loadAdjacentImages(swiper_work_recommend);
667			}
668		}
669	});
670	// スライドイベント設定
671	$("#Act_swiper_work_recommend_container").hover(
672		function(){
673			$("#Act_swiper_next_work_recommend").addClass('is-hover');
674			$("#Act_swiper_prev_work_recommend").addClass('is-hover');
675		},function(){
676			$("#Act_swiper_next_work_recommend").removeClass('is-hover');
677			$("#Act_swiper_prev_work_recommend").removeClass('is-hover');
678		}
679	);
680	// 画像コピーガード
681	$.main_rwd.imgCopyGuard();
682	// ツールチップのイベント設定
683	$.main_rwd.setArtistPriceRangeToolTip('Act_swiper_work_recommend');
684	// お気に入りボタンが押された際の動作を設定
685	setUpFavoriteButtonListeners(document.getElementById("Act_detail_recommend_list"));
686}
687// トグルの状態をローカルストレージに保存する関数
688$.main_rwd.work_detail.saveState = function() {
689	var toggles = document.querySelectorAll('.Act_work_toggle');
690	toggles.forEach(function(toggle){
691		var parentExpanded = toggle.closest(".Act_select_toggle_panel");
692		var attribution = parentExpanded.getAttribute('aria-expanded');
693		// trueとfalseを反転させて設定
694		if (attribution === 'true') {
695			sessionStorage.setItem(parentExpanded.id, 'true');
696		} else {
697			sessionStorage.removeItem(parentExpanded.id);
698		}
699	});
700}
701
702/**************************************************
703 * 画像拡大機能
704 *
705 **************************************************/
706import PhotoSwipeLightbox from '/element/main_rwd/shared/photoswipe/photoswipe-lightbox.esm.js';
707
708let maxDeviceZoomLevel = 2;
709let deviceZoomLevel = 0.4;
710let zoomValue = 0.3;
711//デバイス判定
712function isMobile() {
713  return /Mobi|Android/i.test(navigator.userAgent);
714}
715if (isMobile()) {
716  maxDeviceZoomLevel = 2;
717	deviceZoomLevel = 0.4;
718	zoomValue = 0.3;
719} else {
720	maxDeviceZoomLevel = 2;
721	deviceZoomLevel = 1;
722	zoomValue = 0.4;
723}
724
725//モーダル表示前画像の2本指タッチイベントを無効化
726//photoswipeのデフォルトで別タブ表示されるため
727// document.addEventListener('DOMContentLoaded', (event) => {
728//   const galleryItems = document.querySelectorAll('.pswp-gallery__item > a');
729//   galleryItems.forEach(item => {
730//     item.addEventListener('touchstart', (e) => {
731//       if (e.touches.length > 1) {
732//         e.preventDefault();
733//         // インデックスをタッチイベントごとに再計算
734//         const currentGalleryItems = document.querySelectorAll('.pswp-gallery__item > a');
735//         const index = Array.from(currentGalleryItems).indexOf(item);
736//         lightbox.loadAndOpen(index);
737//       }
738//     });
739//   });
740// });
741
742let setDeviceZoomLevel = maxDeviceZoomLevel;
743let currentZoomLevel = deviceZoomLevel;
744let deepZoomPlugin;
745// PhotoSwipe表示中のスクロールバー制御状態
746let isPswpScrollbarHidden = false;
747let originalHtmlOverflow = '';
748let originalHtmlOverflowPriority = '';
749let originalBodyOverflow = '';
750let originalBodyOverflowPriority = '';
751// モーダルを開いた時点のページ座標(close時に復元する)
752let pswpOpenScrollX = 0;
753let pswpOpenScrollY = 0;
754
755/**********************************************************
756 * PhotoSwipeモーダル表示中は背面ページのスクロールバーを非表示にする
757 * - 既存のinline styleを保存して復元可能にする
758 * - 本関数を使用する際は二重実行を避ける
759 **********************************************************/
760function hideScrollbarForPswp() {
761	if (isPswpScrollbarHidden) {
762		return;
763	}
764	// 元のoverflow設定を保持し、モーダル終了時に戻せるようにする
765	originalHtmlOverflow = document.documentElement.style.getPropertyValue('overflow');
766	originalHtmlOverflowPriority = document.documentElement.style.getPropertyPriority('overflow');
767	originalBodyOverflow = document.body.style.getPropertyValue('overflow');
768	originalBodyOverflowPriority = document.body.style.getPropertyPriority('overflow');
769	// モーダル表示中は背面ページのスクロールバーを非表示
770	document.documentElement.style.setProperty('overflow', 'hidden', 'important');
771	document.body.style.setProperty('overflow', 'hidden', 'important');
772	isPswpScrollbarHidden = true;
773}
774
775/**********************************************************
776 * hideScrollbarForPswpで変更したoverflow設定を元に戻す
777 * - 元が未設定ならremovePropertyでクリアする
778 **********************************************************/
779function showScrollbarForPswp() {
780	if (!isPswpScrollbarHidden) {
781		return;
782	}
783	// 保存していたoverflowを復元(未設定だった場合はstyleを削除)
784	if (originalHtmlOverflow) {
785		document.documentElement.style.setProperty('overflow', originalHtmlOverflow, originalHtmlOverflowPriority);
786	} else {
787		document.documentElement.style.removeProperty('overflow');
788	}
789	if (originalBodyOverflow) {
790		document.body.style.setProperty('overflow', originalBodyOverflow, originalBodyOverflowPriority);
791	} else {
792		document.body.style.removeProperty('overflow');
793	}
794	isPswpScrollbarHidden = false;
795}
796
797/**********************************************************
798 * モーダル表示前に保持したスクロール位置へ復元する
799 * - overflow復元直後はレイアウト再計算中のため、1フレーム待ってから戻す
800 **********************************************************/
801function restoreScrollPositionAfterPswpClose() {
802	window.requestAnimationFrame(function() {
803		window.scrollTo(pswpOpenScrollX, pswpOpenScrollY);
804	});
805}
806
807const lightboxOptions = {
808  gallery: '#gallery',
809  children: '.pswp-gallery__item > a',
810
811  pswpModule: () => import('/element/main_rwd/shared/photoswipe/photoswipe.esm.js'),
812
813  openPromise: () => {
814    if (!deepZoomPlugin) {
815      return import('/element/main_rwd/shared/photoswipe/index.js').then((deepZoomPluginModule) => {
816        deepZoomPlugin = new deepZoomPluginModule.default(lightbox, {});
817      });
818    }
819  },
820
821  // PhotoSwipeのオプション
822  allowPanToNext: false, // 画像がズームされているときに次のスライドにスワイプ可能にする
823  allowMouseDrag: true, // 最大ズームレベルでドラッグカーソルを表示する
824  wheelToZoom: true, // ホイールによるズームを有効にする
825  imageClickAction: 'none', // デフォルトの画像クリック時のアクションを無効にする
826  maxZoomLevel: setDeviceZoomLevel, // 最大ズームレベル
827  showHideAnimationType: 'none', // 画像を閉じた際のアニメーションを無効にする
828  closeOnVerticalDrag: 'none', // 縦方向のドラッグで閉じるアクションを無効にする
829  clickToCloseNonZoomable: false, // ズームされていない時にクリックで閉じないようにする
830  closeOnVerticalDrag: false, // 縦スライドで閉じないようにする
831  closeOnScroll: false, // スクロールで閉じないようにする
832  bgClickAction: false, // 背景クリックで閉じないようにする
833  bgOpacity: 1, // 背景の透明度
834
835	// getThumbBoundsFnを設定
836  getThumbBoundsFn: (index) => {
837    const thumbnail = document.querySelectorAll('.pswp-gallery__item > a img')[index];
838    const pageYScroll = window.pageYOffset || document.documentElement.scrollTop;
839    const rect = thumbnail.getBoundingClientRect();
840
841    return { x: rect.left, y: rect.top + pageYScroll, w: rect.width };
842  }
843};
844
845const lightbox = new PhotoSwipeLightbox(lightboxOptions);
846
847let zoomLevel = 1;
848let Pointermove = false;
849let startX = 0;
850let endX = 0;
851let startTime = 0;
852let endTime = 0;
853
854let initialPinchDistance = null;
855let initialZoomLevel = null;
856let isTwoFingerTouch = false;
857
858let shouldUpdate = false;
859
860//モーダル表示後に関数を実行
861lightbox.on('afterInit', () => {
862	// [Event] PhotoSwipeモーダル表示開始:
863	// close時に戻すための基準座標を確定し、背面スクロールバーを隠す
864	// クリック直前保存値とのズレ(画像読込やレイアウト変化)や別経路オープン時に備え、
865	// 「実際にモーダルが表示された時点」の座標でclose後の復元先を確定する
866	pswpOpenScrollX = window.pageXOffset || document.documentElement.scrollLeft || 0;
867	pswpOpenScrollY = window.pageYOffset || document.documentElement.scrollTop || 0;
868	hideScrollbarForPswp();
869  addClickEventToParent();
870  addCustomElement();
871  ClickButtonZoom();
872  handleRangeClick();
873	addModalClasses();
874	addWheelZoomEventListener();
875	preventRightClickOnImages();
876	setupButtonListeners();
877	if (isMobile()) {
878		const currentIndex = lightbox.pswp.currSlide.index;
879  	updateRangeMin(currentIndex);
880	}
881});
882
883lightbox.on('zoomPanUpdate', (e) => {
884  if (e.slide === lightbox.pswp.currSlide) {
885    zoomLevel = lightbox.pswp.currSlide.currZoomLevel;
886  }
887});
888
889lightbox.on('change', () => {
890	//既存のコピーガードをそのまま転用。pointerevents:noneはCSSで設定済み
891	$(function() {
892		// 画像の保存防止機能
893		$.main_rwd.imgCopyGuard = function() {
894				var userAgent = window.navigator.userAgent;
895				$("img").each(function() {
896						var img = $(this);
897						img.on('mousedown', function(event) {
898								event.preventDefault();
899						});
900						img.on('selectstart', function(event) {
901								event.preventDefault();
902						});
903						img.on('contextmenu', function(event) {
904								event.preventDefault();
905						});
906				});
907
908				var longpressTimeout;
909				$(window).on('mousedown touchstart', function(event) {
910						longpressTimeout = setTimeout(function() {
911								$(event.target).trigger("longpress");
912						}, 1000);
913				}).on('mouseup mouseleave touchend', function() {
914						clearTimeout(longpressTimeout);
915				});
916
917				$("img").on("longpress", function() {
918						var img = $(this);
919						img.on('mousedown', function(event) {
920								event.preventDefault();
921						});
922						img.on('selectstart', function(event) {
923								event.preventDefault();
924						});
925						img.on('contextmenu', function(event) {
926								event.preventDefault();
927						});
928				});
929		};
930		$("img").length && $.fn.jquery == "3.4.1" && $.main_rwd.imgCopyGuard();
931	});
932  addClickEventToParent();
933	if (lightbox.pswp && lightbox.pswp.currSlide) {
934    lightbox.pswp.currSlide.zoomTo(currentZoomLevel);
935		updateRangeFromZoom(currentZoomLevel);
936		preventRightClickOnImages();
937  }
938	if (isMobile()) {
939		const currentIndex = lightbox.pswp.currSlide.index;
940    updateRangeMin(currentIndex);
941	}
942	//画像拡大されていない場合のレンジの位置調整
943	if (shouldUpdate) {
944		updateRangePinchPosition();
945	}
946});
947
948function updateRangeMin(index) {
949  const galleryItems = document.querySelectorAll('.pswp-gallery__item > a');
950  const item = galleryItems[index];
951  if (item) {
952    const rangeMin = item.getAttribute('range-min') || '60';
953    const resizeInput = document.getElementById('RESIZE');
954    if (resizeInput) {
955      resizeInput.setAttribute('min', rangeMin);
956    }
957  }
958}
959
960lightbox.on('pointerDown', (e) => {
961  Pointermove = false;
962  // ドラッグ開始時の座標と時間を取得
963  if (isMobile()) {
964    startX = e.originalEvent.clientX;
965    startTime = new Date().getTime();
966  }
967});
968
969lightbox.on('pointerMove', (e) => {
970	Pointermove = true;
971  if (isMobile()) {
972    // ドラッグ中の座標を取得
973    endX = e.originalEvent.clientX;
974  }
975});
976
977lightbox.on('pointerUp', (e) => {
978  // Pointermoveの状態を保持
979  setTimeout(() => {
980    Pointermove = false; // 少し遅延させてリセット
981  }, 0.01);
982
983  if (isMobile()) {
984    // ドラッグ終了時の時間を取得
985    endTime = new Date().getTime();
986
987    // ドラッグ量と時間差を計算
988    const swipeThreshold = 200;
989    const timeThreshold = 200; // 速いドラッグの閾値(ミリ秒)
990    const distance = endX - startX;
991    const timeDiff = endTime - startTime;
992    const speed = Math.abs(distance / timeDiff); // ピクセル/ミリ秒
993
994    if (Pointermove && !isNaN(distance) && distance !== 0) {
995      if (Math.abs(distance) > swipeThreshold && timeDiff < timeThreshold) {
996        if (distance > 0) {
997          // 右ドラッグ
998          lightbox.pswp.prev();
999        } else {
1000          // 左ドラッグ
1001          lightbox.pswp.next();
1002        }
1003      }
1004    }
1005  }
1006});
1007
1008lightbox.on('close', () => {
1009	// [Event] PhotoSwipeモーダル終了:
1010	// スクロールバー表示とページ位置を復元する
1011	showScrollbarForPswp();
1012	restoreScrollPositionAfterPswpClose();
1013
1014  const currentItem = lightbox.pswp.currSlide.data.element;
1015	const currentSlide = currentItem.closest('.swiper-slide');
1016	const realIndex = parseInt(currentSlide.getAttribute('data-swiper-slide-index'), 10);
1017
1018	if (!isNaN(realIndex)) {
1019		//swiperの画像をモーダルに表示されていたものに変更
1020		swiper_work.slideToLoop(realIndex, 0);
1021	}
1022
1023	//ズームレベル初期化
1024	currentZoomLevel = deviceZoomLevel;
1025	//右クリック禁止の初期化
1026	resetImages();
1027});
1028
1029lightbox.on('destroy', () => {
1030	// [Event] PhotoSwipeモーダル破棄:
1031	// closeイベントを通らない終了経路でも復元漏れしないようにする
1032	showScrollbarForPswp();
1033	restoreScrollPositionAfterPswpClose();
1034});
1035
1036lightbox.init();
1037
1038// 画像サイズ設定
1039let imgElements = document.querySelectorAll('img.main_image'); // クラス名がmain_imageのすべての<img>要素を取得
1040let img_src_array = [];
1041let sizes = [];
1042let range = [];
1043// 読み込み失敗した画像のみを除外対象として管理する属性。
1044// img.complete 依存だと初回モーダル起動時に未読込画像が件数から外れ、counter(1 / n)のnが実数より小さくなるため、
1045// 失敗画像だけを明示的にフラグ管理して件数の揺れを防ぐ。
1046const PSWP_DISABLED_ATTR = 'data-pswp-disabled';
1047
1048// imgElements の順序を保持するために、サイズを格納する配列に null を初期値として設定
1049imgElements.forEach((imgElement, index) => {
1050  sizes[index] = null; // サイズ配列にnullを初期値として設定
1051  let imgSrc = imgElement.src; // 各img要素のsrc属性の値を取得
1052  img_src_array.push({ src: imgSrc, index: index }); // インデックスも一緒に格納
1053});
1054
1055function loadImage({ src, index }) {
1056  return new Promise((resolve) => {
1057    let img = new Image();
1058    img.src = src;
1059    img.onload = function() {
1060      let originalWidth = img.width;
1061      let originalHeight = img.height;
1062
1063      let width, height;
1064      if (originalHeight < originalWidth) {
1065        width = 1000 + 'px';
1066        height = (originalHeight / originalWidth) * 1000 + 'px';
1067      } else {
1068        height = window.innerHeight + 'px';
1069        width = (originalWidth / originalHeight) * window.innerHeight + 'px';
1070      }
1071
1072      if (isMobile()) {
1073        let rangevalue = 40;
1074        let widthmobile = window.innerWidth;
1075        let heightmobile = (originalHeight / originalWidth) * window.innerWidth;
1076
1077        widthmobile = Math.round(widthmobile);
1078        heightmobile = Math.round(heightmobile);
1079
1080				if (widthmobile > heightmobile) {
1081					range[index] = { rangevalue };
1082				} else {
1083					let scale = calculatePhotoswipeScale(window.innerWidth, window.innerHeight, widthmobile, heightmobile);
1084        	range[index] = { rangevalue: Math.round(scale * 100) }; // 計算した値をrangevalueにセット
1085				}
1086      }
1087      sizes[index] = { width, height };
1088			const element = document.querySelectorAll('.pswp-gallery__item > a')[index];
1089			if (element) {
1090				// 再読込や遅延読込で復帰した画像は除外フラグを外し、モーダル件数に再度含める。
1091				element.removeAttribute(PSWP_DISABLED_ATTR);
1092			}
1093      resolve();
1094    };
1095    img.onerror = function() {
1096      // 画像の読み込みに失敗した場合、サイズをnullに設定
1097      sizes[index] = null;
1098      const element = document.querySelectorAll('.pswp-gallery__item > a')[index];
1099      if (element) {
1100				// 実際に読み込み失敗した画像のみ除外対象としてマークする。
1101				element.setAttribute(PSWP_DISABLED_ATTR, '1');
1102        const imgElement = element.querySelector('img');
1103        if (imgElement) {
1104          imgElement.style.display = 'none';  // 画像を非表示にする
1105
1106          // 既存のaltテキストを取得し、新しいdivを作成
1107          const altText = imgElement.getAttribute('alt');
1108          let altElement = element.querySelector('.img-error');
1109          if (!altElement) {
1110            altElement = document.createElement('div');
1111            altElement.className = 'img-error';
1112            altElement.textContent = altText;
1113            element.appendChild(altElement);
1114          }
1115
1116          // クリックイベントを無効にする
1117          element.style.pointerEvents = 'none';
1118        }
1119      }
1120      resolve();
1121    };
1122  });
1123}
1124
1125Promise.all(img_src_array.map(loadImage))
1126.then(() => {
1127  let galleryElements = document.querySelectorAll('.pswp-gallery__item a');
1128  galleryElements.forEach((element, index) => {
1129    if (sizes[index]) {
1130			// 画像読み込みに成功した場合、除外フラグは外す。
1131			element.removeAttribute(PSWP_DISABLED_ATTR);
1132      element.setAttribute('data-pswp-width', parseInt(sizes[index].width));
1133      element.setAttribute('data-pswp-height', parseInt(sizes[index].height));
1134      if (isMobile()) {
1135        element.setAttribute('range-min', parseInt(range[index].rangevalue));
1136      }
1137    } else {
1138			// 画像読み込みに失敗した場合、除外フラグを付与する。
1139			element.setAttribute(PSWP_DISABLED_ATTR, '1');
1140      // 画像の読み込みに失敗した場合、altテキストを表示する
1141      const imgElement = element.querySelector('img');
1142      if (imgElement) {
1143        imgElement.style.display = 'none';
1144        const altText = imgElement.getAttribute('alt');
1145        let altElement = element.querySelector('.img-error');
1146        if (!altElement) {
1147          altElement = document.createElement('div');
1148          altElement.className = 'img-error';
1149          altElement.textContent = altText;
1150          element.appendChild(altElement);
1151        }
1152
1153        // クリックイベントを無効にする
1154        element.style.pointerEvents = 'none';
1155      }
1156    }
1157  });
1158
1159	lightbox.init();
1160})
1161.catch((error) => {
1162  console.error('Some images failed to load.', error);
1163});
1164
1165//拡大率を計算する関数
1166function calculatePhotoswipeScale(screenWidth, screenHeight, imageWidth, imageHeight) {
1167	let widthScale = imageWidth / screenWidth;
1168	let heightScale = imageHeight / screenHeight;
1169	return Math.min(widthScale, heightScale);
1170}
1171
1172document.addEventListener('DOMContentLoaded', (event) => {
1173  const galleryItems = document.querySelectorAll('.pswp-gallery__item > a');
1174  galleryItems.forEach(item => {
1175    item.addEventListener('click', (e) => {
1176      e.preventDefault();
1177      e.stopPropagation();
1178
1179      const currentGalleryItems = Array.from(document.querySelectorAll('.pswp-gallery__item > a'));
1180			// 読み込み未完了画像は件数に含め、読み込み失敗フラグ付きのみ除外する。
1181			// これにより初回起動時でもcounterの総数nが安定する。
1182			const validGalleryItems = currentGalleryItems.filter(element => {
1183				return element.getAttribute(PSWP_DISABLED_ATTR) !== '1';
1184			});
1185
1186			// Swiperのloop処理でDOM順が変わるため、元のスライド順に並べ直す。
1187			validGalleryItems.sort((a, b) => {
1188				const aIndex = parseInt(a.closest('.swiper-slide').getAttribute('data-swiper-slide-index'), 10);
1189				const bIndex = parseInt(b.closest('.swiper-slide').getAttribute('data-swiper-slide-index'), 10);
1190				return aIndex - bIndex;
1191			});
1192
1193      const index = validGalleryItems.indexOf(item);
1194      if (index !== -1) {
1195				// [Event] 画像クリックでモーダル起動:
1196				// 起動直前の座標を保持しておき、close時の復元候補にする
1197				pswpOpenScrollX = window.pageXOffset || document.documentElement.scrollLeft || 0;
1198				pswpOpenScrollY = window.pageYOffset || document.documentElement.scrollTop || 0;
1199        lightbox.options.children = validGalleryItems;
1200        lightbox.loadAndOpen(index);
1201      }
1202    });
1203  });
1204});
1205
1206// クラスを追加する関数
1207function addModalClasses() {
1208  const modalContainer = document.querySelector('.pswp');
1209  if (modalContainer) {
1210    modalContainer.classList.add('modal-zoom');
1211  }
1212  const counterElement = document.querySelector('.pswp__counter');
1213  if (counterElement) {
1214    counterElement.classList.add('modal-zoom-counter');
1215  }
1216  const closeButton = document.querySelector('.pswp__button--close');
1217  if (closeButton) {
1218    closeButton.classList.add('modal-zoom-btn-close');
1219  }
1220  const prevButton = document.querySelector('.pswp__button--arrow--prev');
1221  if (prevButton) {
1222    prevButton.classList.add('modal-zoom-btn-prev');
1223  }
1224  const nextButton = document.querySelector('.pswp__button--arrow--next');
1225  if (nextButton) {
1226    nextButton.classList.add('modal-zoom-btn-next');
1227  }
1228}
1229
1230// カスタム要素を追加する関数
1231function addCustomElement() {
1232  const customElement = document.createElement('div');
1233  customElement.id = 'modaal-gallery-scale-wrap';
1234  customElement.className = 'fixed';
1235	if (isMobile()) {
1236  	customElement.innerHTML = `
1237    	<div class="modal-zoom-slider">
1238				<button id="decrease_size" class="modal-zoom-slider-btn-out">-</button>
1239				<button id="increase_size" class="modal-zoom-slider-btn-in">+</button>
1240				<span id="SCALE" style="display:none;">100%</span>
1241				<input id="RESIZE" type="range" min="40" max="200" value="40" class="modal-zoom-slider-bar"/>
1242			</div>
1243  	`;
1244	} else {
1245		customElement.innerHTML = `
1246    	<div class="modal-zoom-slider">
1247      	<button id="decrease_size" class="modal-zoom-slider-btn-out">-</button>
1248      	<button id="increase_size" class="modal-zoom-slider-btn-in">+</button>
1249      	<span id="SCALE" style="display:none;">100%</span>
1250      	<input id="RESIZE" type="range" min="100" max="200" value="100" class="modal-zoom-slider-bar"/>
1251    	</div>
1252  	`;
1253	}
1254  const pswpElement = document.querySelector('.pswp');
1255  if (pswpElement) {
1256    pswpElement.appendChild(customElement);
1257  }
1258}
1259
1260//右クリック禁止
1261function preventRightClickOnImages() {
1262  const images = document.querySelectorAll('.pswp__img');
1263  images.forEach(img => {
1264    img.addEventListener('contextmenu', (e) => {
1265      e.preventDefault();
1266    });
1267  });
1268}
1269
1270// 画像の初期化処理
1271function resetImages() {
1272	const zoomWraps = document.querySelectorAll('.pswp__zoom-wrap');
1273	zoomWraps.forEach(zoomWrap => {
1274		const img = zoomWrap.querySelector('img.pswp__img');
1275		if (img) {
1276			// 右クリック禁止のイベントリスナーを削除
1277			img.removeEventListener('contextmenu', (e) => {
1278				e.preventDefault();
1279			});
1280		}
1281	});
1282}
1283
1284//+ボタン-ボタン
1285function ClickButtonZoom(zoomIn) {
1286const pswpElement = document.querySelector('.pswp__container');
1287  if (pswpElement) {
1288    const increaseButton = document.getElementById('increase_size');
1289    const decreaseButton = document.getElementById('decrease_size');
1290
1291    if (increaseButton && decreaseButton) {
1292      increaseButton.addEventListener('click', (event) => {
1293        event.stopImmediatePropagation();
1294        handleZoom(true);
1295      });
1296      decreaseButton.addEventListener('click', (event) => {
1297        event.stopImmediatePropagation();
1298        handleZoom(false);
1299      });
1300    }
1301  }
1302}
1303
1304function handleZoom(zoomIn) {
1305  if (lightbox && lightbox.pswp && lightbox.pswp.currSlide) {
1306    let currentZoom = lightbox.pswp.currSlide.currZoomLevel;
1307		zoomLevel = zoomIn ? currentZoom + zoomValue : currentZoom - zoomValue;
1308    zoomLevel = Math.min(Math.max(zoomLevel, deviceZoomLevel), lightbox.pswp.options.maxZoomLevel);
1309    lightbox.pswp.currSlide.zoomTo(zoomLevel);
1310		currentZoomLevel = zoomLevel;
1311		updateRangeFromZoom(zoomLevel);
1312  }
1313}
1314
1315// スクロールによる拡大率を取得するためのイベントリスナーを追加する関数
1316function addWheelZoomEventListener() {
1317  const pswpContainer = document.querySelector('.pswp__container');
1318  if (pswpContainer) {
1319    pswpContainer.addEventListener('wheel', handleWheelZoom);
1320		pswpContainer.addEventListener('touchstart', handleTouchStart);
1321  	pswpContainer.addEventListener('touchmove', handleTouchMove);
1322  	pswpContainer.addEventListener('touchend', handleTouchEnd);
1323	}
1324}
1325
1326// スクロール拡大
1327function handleWheelZoom(event) {
1328  event.preventDefault(); // スクロールのデフォルト動作を無効にする
1329  const delta = Math.sign(event.deltaY); // スクロールの方向を取得
1330
1331  if (lightbox && lightbox.pswp && lightbox.pswp.currSlide) {
1332    const zoomFactor = 0.1; // ズームの速度を調整する係数
1333    let newZoomLevel = lightbox.pswp.currSlide.currZoomLevel - delta * zoomFactor;
1334    newZoomLevel = Math.min(Math.max(newZoomLevel, deviceZoomLevel), lightbox.pswp.options.maxZoomLevel);
1335    lightbox.pswp.currSlide.zoomTo(newZoomLevel);
1336
1337    // ズームレベルに基づいてスライダーを更新
1338    updateRangeFromZoom(newZoomLevel);
1339    currentZoomLevel = newZoomLevel;
1340  }
1341}
1342
1343// 画像クリックで拡大
1344function addClickEventToParent() {
1345  const parentElement = document.querySelector('.pswp__container'); // 親要素を指定
1346
1347  parentElement.addEventListener('click', function(event) {
1348    if (event.target && event.target.matches('img.pswp__img') && !Pointermove && !isTwoFingerTouch) {
1349      event.stopImmediatePropagation(); // 他のイベントリスナーの呼び出しを防ぐ
1350			if (zoomLevel > maxDeviceZoomLevel -0.1) {
1351        zoomLevel = deviceZoomLevel; // 初期ズームレベルを使用
1352			} else {
1353				zoomLevel += zoomValue; // zoomToの値を0.3増加
1354			}
1355      if (lightbox && lightbox.pswp && lightbox.pswp.currSlide) {
1356        lightbox.pswp.currSlide.zoomTo(zoomLevel);
1357      }
1358			currentZoomLevel = zoomLevel;
1359			updateRangeFromZoom(zoomLevel);
1360    }
1361  });
1362}
1363
1364//スケール操作時
1365function handleRangeClick() {
1366  const resizeInput = document.getElementById("RESIZE");
1367  if (resizeInput) {
1368    resizeInput.addEventListener("input", function () {
1369      let resizeValue = parseInt(this.value, 10);
1370      let scaleValue = resizeValue + "%";
1371      document.getElementById("SCALE").textContent = scaleValue;
1372      let scale = resizeValue / 100;
1373      zoomTo(scale);  // スライダーの値に基づいてズームレベルを設定
1374			currentZoomLevel = scale;
1375    });
1376  }
1377}
1378
1379function zoomTo(scale) {
1380  if (lightbox && lightbox.pswp && lightbox.pswp.currSlide) {
1381    let maxZoomLevel = lightbox.pswp.options.maxZoomLevel;
1382    zoomLevel = Math.min(scale, maxZoomLevel);
1383    lightbox.pswp.currSlide.zoomTo(zoomLevel);
1384		currentZoomLevel = zoomLevel;
1385		updateRangeFromZoom(zoomLevel);
1386  }
1387}
1388
1389//スケールの位置を変更
1390function updateRangeFromZoom(zoomLevel) {
1391  const resizeInput = document.getElementById("RESIZE");
1392  if (resizeInput) {
1393    let sliderValue = Math.round(zoomLevel * 100);
1394    resizeInput.value = sliderValue;
1395    document.getElementById("SCALE").textContent = sliderValue + "%";
1396		currentZoomLevel = zoomLevel;
1397  }
1398}
1399
1400// ピンチイン・アウト
1401function getDistance(touch1, touch2) {
1402  return Math.sqrt(
1403    Math.pow(touch2.clientX - touch1.clientX, 2) +
1404    Math.pow(touch2.clientY - touch1.clientY, 2)
1405  );
1406}
1407
1408function handleTouchStart(event) {
1409
1410	isTwoFingerTouch = true;
1411  if (event.touches.length === 2) {
1412    const touch1 = event.touches[0];
1413    const touch2 = event.touches[1];
1414    initialPinchDistance = getDistance(touch1, touch2);
1415    initialZoomLevel = lightbox.pswp.currSlide.currZoomLevel;
1416  }
1417}
1418
1419function handleTouchMove(event) {
1420  if (event.touches.length === 2 && initialPinchDistance) {
1421    const touch1 = event.touches[0];
1422    const touch2 = event.touches[1];
1423    const currentPinchDistance = getDistance(touch1, touch2);
1424    const zoomChange = currentPinchDistance / initialPinchDistance;
1425    let newZoomLevel = initialZoomLevel * zoomChange;
1426    newZoomLevel = Math.min(Math.max(newZoomLevel, deviceZoomLevel), lightbox.pswp.options.maxZoomLevel);
1427
1428    lightbox.pswp.currSlide.zoomTo(newZoomLevel);
1429    updateRangeFromZoom(newZoomLevel);
1430  }
1431}
1432
1433function handleTouchEnd(event) {
1434  if (initialPinchDistance) {
1435    initialPinchDistance = null;
1436    initialZoomLevel = null;
1437  }
1438	setTimeout(() => {
1439    isTwoFingerTouch = false;
1440  }, 5);
1441}
1442
1443//タッチ判定
1444let recentTouchEvent;
1445
1446document.body.ontouchstart = handleGlobalTouchStart;
1447document.body.ontouchend = handleGlobalTouchEnd;
1448
1449function handleGlobalTouchStart(event) {
1450  recentTouchEvent = event;
1451}
1452
1453function handleGlobalTouchEnd(event) {
1454  if (event.touches.length === 0) {
1455    if (recentTouchEvent.touches.length === 1) {
1456      isTwoFingerTouch = false;
1457    }
1458    if (recentTouchEvent.touches.length === 2) {
1459      isTwoFingerTouch = true;
1460    }
1461  }
1462}
1463
1464// ボタンのイベントリスナーを設定する関数
1465function setupButtonListeners() {
1466  const nextButton = document.querySelector('.pswp__button--arrow--next');
1467  const prevButton = document.querySelector('.pswp__button--arrow--prev');
1468
1469  if (nextButton) {
1470    nextButton.addEventListener('mouseup', () => {
1471      const resizeElement = document.getElementById('RESIZE');
1472      const resizeMinValue = parseInt(resizeElement.min, 10);
1473
1474			let zoomValue =zoomLevel*100;
1475      // ズームレベルとminの値の差が1以内かをチェック
1476      if (Math.abs(zoomValue - resizeMinValue) <= 1.5) {
1477        shouldUpdate = true; // 条件を満たす場合にフラグを設定
1478      } else {
1479        shouldUpdate = false;
1480      }
1481    });
1482  }
1483
1484  if (prevButton) {
1485    prevButton.addEventListener('mouseup', () => {
1486      const resizeElement = document.getElementById('RESIZE');
1487      const resizeMinValue = parseInt(resizeElement.min, 10);
1488
1489			let zoomValue =zoomLevel*100;
1490
1491      // ズームレベルとminの値の差が1以内かをチェック
1492      if (Math.abs(zoomValue - resizeMinValue) <= 1.5) {
1493        shouldUpdate = true; // 条件を満たす場合にフラグを設定
1494      } else {
1495        shouldUpdate = false;
1496      }
1497    });
1498  }
1499}
1500
1501//レンジのずれ修正
1502function updateRangePinchPosition() {
1503  const resizeInput = document.getElementById("RESIZE");
1504  if (resizeInput && lightbox.pswp && lightbox.pswp.currSlide) {
1505    const zoomLevel = lightbox.pswp.currSlide.currZoomLevel;
1506    let sliderValue = Math.round(zoomLevel * 100);
1507
1508    // 初期表示時にスライダーを一番左に設定
1509    resizeInput.setAttribute('value', resizeInput.min);
1510    resizeInput.value = resizeInput.min; // ここでスライダーを左端に設定
1511
1512    // ズームレベルに基づいてスライダーを更新
1513    requestAnimationFrame(() => {
1514      resizeInput.value = sliderValue;
1515    });
1516  }
1517}

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.