PageSourceSearch

https://hattendo.jp/js/sys/ui.js

js hattendo.jp collected 2026-10-02 17:08:51 UTC 20,057 bytes, 650 lines download raw bytes

1/* 名前空間を定義 */
2var ecblib = ecblib || {};
3ecblib.ui = ecblib.ui || {};
4/*!
5 * UIの表示に関する関数群
6 * 
7 * @requires module:jquery1.11+
8 * @requires module:js.cookie.js
9 * @requires module:modernizr-custom.js
10 */
11(function () {
12	/* ローカル用の名前空間 */
13	var _ui = ecblib.ui;
14
15	/*!
16	 * megamenu ui
17	 */
18	jQuery(document).ready(function () {
19		var megamenuForHover = function () {
20			jQuery('.js-animation-megamenu-hover').hover(function () {
21				jQuery(this).children('.js-submenu-hover').stop(true, true).delay(20).slideDown(200);
22				jQuery(this).find('.block-icon-image--angle-up').addClass('block-icon-image--angle-down');
23			}, function () {
24				jQuery(this).children('.js-submenu-hover').stop(true, true).delay(20).slideUp(200);
25				jQuery(this).find('.block-icon-image--angle-up').removeClass('block-icon-image--angle-down');
26			});
27		}();
28
29		var megamenuForClick = function () {
30			jQuery('.js-animation-megamenu-click').children('a').on('click', function (e) {
31				var $this = jQuery(this);
32				jQuery('.js-animation-megamenu-click').children('a').each(function () {
33					if (!jQuery(this).is($this)) {
34						jQuery(this).siblings('.js-submenu-click').stop(true, true).slideUp(200);
35						jQuery(this).find('.block-icon-image--angle-up').removeClass('block-icon-image--angle-down');
36					}
37				});
38
39				jQuery(this).find('.block-icon-image--angle-up').addClass('block-icon-image--angle-down');
40				jQuery(this).siblings('.js-submenu-click').stop(true, true).slideDown(200);
41				return false;
42			});
43			jQuery(document).on('click touchstart', function (e) {
44				if (!jQuery(e.target).closest('.js-animation-megamenu-click').length) {
45					jQuery('.js-animation-megamenu-click').children('.js-submenu-click').stop(true, true).slideUp(200);
46					jQuery('.js-animation-megamenu-click').find('.block-icon-image--angle-up').removeClass('block-icon-image--angle-down');
47				}
48			});
49		}();
50	});
51
52	/*!
53	 * 動的なカテゴリを生成するAJAX
54	 */
55	jQuery(document).ready(function () {
56		jQuery('.js-dynamic-category').each(function () {
57			var category = jQuery(this).data('category') != undefined ? jQuery(this).data('category') : '';
58			jQuery(this).load(ecblib.sys.wwwroot + '/shop/js/category.aspx?category=' + category);
59		});
60	});
61
62	/*!
63	 * 動的なジャンルを生成するAJAX
64	 */
65	jQuery(document).ready(function () {
66		jQuery('.js-dynamic-genre').each(function () {
67			var genre = jQuery(this).data('genre') != undefined ? jQuery(this).data('genre') : '';
68			jQuery(this).load(ecblib.sys.wwwroot + '/shop/js/genre.aspx?genre=' + genre);
69		});
70	});
71
72	/*!
73	 * カート内件数のバッジ表示
74	 */
75	jQuery(document).ready(function () {
76		_ui.showCartCount();
77	});
78
79	_ui.showCartCount = function () {
80		if(!jQuery('.js-cart-count').length) return;
81		jQuery.ajax({
82			url: ecblib.sys.wwwroot + "/shop/js/cart.aspx?count=cart_qty",
83			cache: false,
84			dataType: "text",
85			success: function (text) {
86				if (text == "") {
87					jQuery('.js-cart-count').hide();
88				} else {
89					jQuery('.js-cart-count').text(text).show();
90				}
91			}
92		});
93	};
94
95	/*!
96	 * アラート表示
97	 */
98	_ui.alert = function (title, msg, options) {
99
100		jQuery(document.activeElement).blur();
101
102		var template = ecblib.tmpl.ui.ALERT;
103		template = ecblib.sys.render(template, { Title: title });
104
105		var defaults = { quit: function () { }, ok: function () { }, width: null, height: null };
106		var options = jQuery.extend({}, defaults, options);
107		var gloupId = 'stdui-dialog' + getUUID();
108
109		var $obj = jQuery(template);
110		var $overlay = jQuery('<div class="modal-overlay-alert" />');
111
112		var action = function () {
113			return {
114				close: function () {
115					$overlay.remove();
116					$obj.remove();
117
118					/* 一番最後に開かれたダイアログをアクティブにする */
119					jQuery(document).off('keyup.' + gloupId);
120
121					if (jQuery('.js-modal-alert,.js-modal-dialog').last().length > 0) {
122						jQuery('.js-modal-alert,.js-modal-dialog').last().addClass('js-active');
123					} else {
124						/* 背景固定解除 */
125						setBackGroundFixed(false);
126					}
127				}
128			};
129		}();
130
131		var showDialog = function () {
132			/* 他のダイアログはアクティブを削除する */
133			jQuery('.js-modal-alert,.js-modal-dialog').removeClass('js-active');
134
135			/* 背景を固定にする */
136			setBackGroundFixed(true);
137
138			/* 幅、高さの設定 */
139			if (options.width) {
140				$obj.css('width', options.width);
141			}
142			if (options.height) {
143				$obj.css('height', options.height);
144			}
145
146			$obj.find('.js-modal-body-wrapper').text(msg).html(function () {
147				return jQuery(this).text().replace(/\r?\n/g, '<br>');
148			});
149
150			$overlay.appendTo('body');
151			$obj.appendTo('body');
152
153			var screen = getCenterScreen($obj);
154			$obj.css('position', 'absolute')
155				.css('top', screen.y + 'px')
156				.css('left', screen.x + 'px');
157		};
158
159		/* OKボタン押下 */
160		$obj.find(':button').on('click', function () {
161			options.ok.apply(this, arguments);
162			action.close();
163		});
164
165		/* ×ボタン、オーバーレイ領域、ESC押下 */
166		$obj.find('.js-modal-close').on('click', function () {
167			options.quit.apply(this, arguments);
168			action.close();
169		});
170		$overlay.on('click', function () {
171			options.quit.apply(this, arguments);
172			action.close();
173		});
174		jQuery(document).on('keyup.' + gloupId, function (e) {
175			if ($obj.hasClass("js-active") && e.keyCode === 27) { // etc
176				options.quit.apply(this, arguments);
177				action.close();
178			}
179		});
180
181		showDialog();
182	};
183
184	/*!
185	 * ダイアログ表示
186	 * 
187	 * モーダル表示(引数はIDを指定)
188	 * ecblib.ui.dialog('modal');
189	 */
190	_ui.dialog = function (id, options, quitCallback) {
191
192		jQuery(document.activeElement).blur();
193
194		var template = ecblib.tmpl.ui.MODAL_DIALOG;
195
196		var defaults = { quit: function () { }, buttons: {}, links: {}, width: null, height: null };
197		var options = jQuery.extend({}, defaults, options);
198		var gloupId = 'stdui-dialog' + getUUID();
199		var $obj = jQuery(template);
200		var $overlay = jQuery('<div class="modal-overlay" />');
201		var $contents = jQuery("#" + id);
202
203		var action = function () {
204			return {
205				close: function () {
206					$overlay.remove();
207					$obj.remove();
208
209					/* 一番最後に開かれたダイアログをアクティブにする */
210					jQuery(document).off('keyup.' + gloupId);
211
212					if (jQuery('.js-modal-alert,.js-modal-dialog').last().length > 0) {
213						jQuery('.js-modal-alert,.js-modal-dialog').last().addClass('js-active');
214					} else {
215						/* 背景固定解除 */
216						setBackGroundFixed(false);
217					}
218				}
219			};
220		}();
221
222		var quitEvent = function () {
223			var ret = options.quit.apply(this, [action]);
224			if (ret == undefined || ret) {
225				action.close();
226				if (quitCallback) quitCallback();
227			}
228		};
229
230		var showDialog = function () {
231			/* 他のダイアログはアクティブを削除する */
232			jQuery('.js-modal-alert,.js-modal-dialog').removeClass('js-active');
233
234			/* 背景を固定にする */
235			setBackGroundFixed(true);
236
237			/* 幅、高さの設定 */
238			if (options.width) {
239				$obj.css('width', options.width);
240			}
241			if (options.height) {
242				$obj.css('height', options.height);
243			}
244
245			$obj.find('.js-modal-title').text($contents.data('title'));
246			$obj.find('.js-modal-content').append($contents.html());
247
248			$overlay.appendTo('body');
249			$obj.appendTo('body');
250
251			var screen = getCenterScreen($obj);
252			$obj.css('position', 'absolute')
253				.css('top', screen.y + 'px')
254				.css('left', screen.x + 'px');
255
256			/* ボタン押下 */
257			$obj.find(':button,:submit,:image').on('click', function () {
258				if (jQuery(this).attr('name') && options.buttons[jQuery(this).attr("name")]) {
259					var ret = options.buttons[jQuery(this).attr("name")].apply(this, [action]);
260					if (jQuery(this).attr('type') == 'submit' && (ret == undefined || ret)) {
261						$obj.find('form').submit();
262					}
263					return ret;
264				}
265			});
266
267			$obj.find('a').on('click', function () {
268				if (jQuery(this).attr('name') && options.links[jQuery(this).attr("name")]) {
269					return options.links[jQuery(this).attr("name")].apply(this, [action]);
270				}
271			});
272
273
274			/* ×ボタン、オーバーレイ領域、ESC押下 */
275			$obj.find('.js-modal-close').on('click', function () {
276				quitEvent.apply(this, arguments);
277			});
278			$overlay.on('click', function () {
279				quitEvent.apply(this, arguments);
280			});
281			jQuery(document).on('keyup.' + gloupId, function (e) {
282				if ($obj.hasClass("js-active") && e.keyCode === 27) {
283					quitEvent.apply(this, arguments);
284				}
285			});
286		};
287
288		showDialog();
289	};
290
291	/*!
292	 * ヘッダー警告表示
293	 */
294	_ui.showHeaderWarning = function (contentsHtml, options) {
295		var template = ecblib.tmpl.ui.WARNING;
296		template = ecblib.sys.render(template, { Contents: contentsHtml });
297
298		var defaults = { quit: function () { } };
299		var options = jQuery.extend({}, defaults, options);
300		var action = function () {
301			return {
302				close: function () {
303					$obj.slideUp(200);
304				}
305			};
306		}();
307
308		var $obj = jQuery(template);
309		$obj.find('.js-header-warning-close').on('click', function () {
310			var ret = options.quit.apply(this, [action]);
311			if (ret == undefined || ret) {
312				action.close();
313			}
314		});
315
316		$obj.hide();
317		$obj.prependTo('body');
318		$obj.slideDown(200);
319
320	};
321
322	/*!
323	 * ツールチップを表示する
324	 */
325	_ui.showToolTip = function (jQuerySelector, options) {
326		var uniqueClassName = 'js-' + Date.now();
327		var defaults = { tooltip: '', position: 'top', diptimeSec: 3, classname: 'balloontip ' + uniqueClassName };
328		var options = jQuery.extend({}, defaults, options);
329
330		jQuery(jQuerySelector).each(function () {
331			var $this = this;
332			jQuery($this).showBalloon({
333				classname: options.classname,
334				contents: options.tooltip,
335				position: options.position,
336				html: true
337			});
338			if (options.diptimeSec) {
339				setTimeout(function () {
340					if (jQuery($this).parents("body").length > 0 ) {
341						jQuery($this).hideBalloon();
342					} else {
343						jQuery('.' + uniqueClassName).hide();
344					}
345				}, 1000 * options.diptimeSec);
346
347			}
348		});
349	};
350
351	/*!
352	 * ツールチップを非表示にする
353	 */
354	_ui.hideToolTip = function (jQuerySelector) {
355		jQuery(jQuerySelector).hideBalloon();
356	};
357
358	/*!
359	 * コンテキストメニューを表示する
360	 */
361	_ui.showContextMenu = function (jQuerySelector, templateid, options) {
362		var defaults = { offsetY: 0, offsetX: 0, links: {} };
363		var options = jQuery.extend({}, defaults, options);
364		var $template = jQuery(templateid);
365		var gloupId = 'stdui-contextmenu' + getUUID();
366
367		var innerContextMenu = function () {
368			$offset = jQuery(jQuerySelector).offset();
369			$template.find('span').off('click');
370			$template.find('span').on('click', function () {
371				if (jQuery(this).attr('name') && options.links[jQuery(this).attr("name")]) {
372					return options.links[jQuery(this).attr("name")].apply(this, arguments);
373				}
374			});
375
376			if ($template.is(":hidden")) {
377				$template.css('position', 'absolute')
378					.css('top', $offset.top + options.offsetY + jQuery(jQuerySelector).outerHeight())
379					.css('left', $offset.left + options.offsetX)
380					.fadeIn().promise().done(function () {
381						jQuery(document).on('click.' + gloupId + ' touchend.' + gloupId, function () {
382							$template.fadeOut();
383							jQuery(document).off('click.' + gloupId + ' touchend.' + gloupId);
384						});
385					});
386			}
387		};
388
389		jQuery(jQuerySelector).each(function () {
390			innerContextMenu.apply(this, arguments);
391		});
392
393	};
394
395	/*!
396	 * ツールチップUI
397	 */
398	jQuery(document).ready(function () {
399		jQuery.balloon.defaults.css = null;
400		jQuery('[data-tooltip]').each(function () {
401
402			var tooltip = jQuery(this).data('tooltip').replace(/\r?\n/g, '<br>');
403			var position = jQuery(this).data('tooltip-position');
404			if (!position) {
405				position = 'top';
406			}
407
408			jQuery(this).on({
409				'focusin': function () {
410					jQuery(this).hideBalloon()
411						.showBalloon({
412							classname: 'balloontip',
413							contents: tooltip,
414							position: position,
415							html: true
416						});
417				},
418				'focusout': function () {
419					jQuery(this).hideBalloon();
420				}
421			});
422		});
423	});
424
425	/*!
426	 * 郵便番号サジェストUI
427	 */
428	/*  郵便番号検索 */
429	var timerId_lookupzip_ = null;
430	var zipcache_lookupzip_ = '';
431	var timerId_zipcache_ = null;
432	_ui.zipcodeSuggest = function (zip, pref, addr, addr2, cnt, offsetX, offsetY) {
433		var timerOffset = 300;
434		var zip_id = '#' + zip + cnt;
435		var pref_id = '#' + pref + cnt;
436		var addr_id = '#' + addr + cnt;
437		var addr2_id = '#' + addr2 + cnt;
438		var defaultXOffset = 0;
439		var defaultYOffset = jQuery(zip_id).outerHeight();
440		offsetX = offsetX + defaultXOffset;
441		offsetY = offsetY + defaultYOffset;
442		jQuery(zip_id).bind('keyup paste', function () {
443			jQuery('ul.js-ziplist').remove();
444			clearTimeout(timerId_zipcache_);
445			timerId_zipcache_ = setTimeout(function () {
446				if (zipcache_lookupzip_ == jQuery(zip_id).val()) {
447					zipcache_lookupzip_ = jQuery(zip_id).val();
448					return false;
449				}
450				zipcache_lookupzip_ = jQuery(zip_id).val();
451			}, timerOffset);
452			clearTimeout(timerId_lookupzip_);
453			timerId_lookupzip_ = setTimeout(function () {
454				if (!jQuery(zip_id).val().match(/^[0-9]{3}[\-]{0,1}[0-9]{0,4}$/)) {
455					return true;
456				}
457
458				jQuery.get('../search/lookupzipjson.aspx', {
459					zip: jQuery(zip_id).val(),
460					charset: 'UTF-8'
461				}, function (data, status) {
462					var of = jQuery(zip_id).offset();
463					var ul = jQuery('<ul></ul>').addClass('js-ziplist block-ziplist--ziplist-frame dropdown');
464					ul.css('position', "absolute");
465					ul.css('top', of.top + offsetY);
466					ul.css('left', of.left + offsetX);
467					var searchCount = 0;
468					var tempzip, temppref, tempaddr, tempaddr2;
469					jQuery.each(data, function (key, item) {
470						searchCount++;
471						tempzip = item.zip;
472						temppref = item.pref;
473						tempaddr = item.addr;
474						tempaddr2 = item.addr2;
475						var li = jQuery('<li><span>' + key + ' ' + item.pref + ' ' + item.addr + ' ' + item.addr2 + '</span></li>');
476						li.bind('click', function () {
477							jQuery(zip_id).val(item.zip);
478							jQuery(pref_id).val(item.pref);
479							jQuery(addr_id).val(item.addr);
480							jQuery(addr2_id).val(item.addr2);
481							jQuery('ul.js-ziplist').remove();
482							jQuery(zip_id).blur();
483							jQuery(pref_id).change();
484							jQuery(addr_id).focus();
485							jQuery(addr2_id).blur().focus();
486							return false;
487						});
488						ul.append(li);
489					});
490					if ((searchCount == 1) && (zipcache_lookupzip_.replace("-", "").length == 7)) {
491						jQuery(zip_id).blur().focus();
492						//IMEの入力を確定させた後に値を詰めなおし
493						setTimeout(function(){
494							jQuery(zip_id).val(tempzip);
495							jQuery(pref_id).val(temppref);
496							jQuery(addr_id).val(tempaddr);
497							jQuery(addr2_id).val(tempaddr2);
498							jQuery('ul.js-ziplist').remove();
499							jQuery(pref_id).change();
500							jQuery(addr_id).focus();
501							jQuery(addr2_id).focus();
502						}, 0);
503						return false;
504					} else if (searchCount != 0) {
505						jQuery(document.body).append(ul);
506					}
507				}, 'json');
508			}, timerOffset);
509		});
510	};
511
512	/*!
513	 * 非推奨ブラウザ警告表示
514	 * @requires module:js.cookie.js
515	 * @requires module:modernizr-custom.js
516	 */
517	jQuery(document).ready(function () {
518
519		/* スマートフォンでは非推奨ブラウザを警告しない */
520		if (ecblib.sys.isModeSmartPhone()) return;
521
522		if (Cookies.get("confirmOldbrowserBanner") == "true") {
523			return;
524		}
525
526		if (isOldIE() || isDetectBrowser()) {
527			_ui.showHeaderWarning(ecblib.msg.ui.TOO_OLD_BROWSER, {
528				quit: function (act) {
529					Cookies.set("confirmOldbrowserBanner", "true", {
530						expires: 365,
531						path: '/'
532					});
533				}
534			});
535		}
536
537		/* IE <= 10の場合、trueが返却される */
538		function isOldIE() {
539			var userAgent = window.navigator.userAgent.toLowerCase();
540			return userAgent.indexOf('msie') >= 0;
541		}
542
543		/* 非推奨ブラウザか? */
544		function isDetectBrowser() {
545
546			/* 対象ブラウザ */
547			var isTergetBrowser = function () {
548				var userAgent = window.navigator.userAgent.toLowerCase();
549				if (userAgent.indexOf('msie') >= 0 || userAgent.indexOf('trident') >= 0) {
550					return true;
551				}
552				if (userAgent.indexOf('edge') >= 0) {
553					return true;
554				}
555				if (userAgent.indexOf('firefox') >= 0) {
556					return true;
557				}
558				if (userAgent.indexOf('chrome') >= 0) {
559					return true;
560				}
561				if (userAgent.indexOf('safari') >= 0) {
562					return true;
563				}
564				return false;
565			};
566
567			if (!isTergetBrowser()) { return false; }
568			if (Modernizr.cssgrid || Modernizr.cssgridlegacy) {
569				return false;
570			}
571			/* 非推奨ブラウザ */
572			return true;
573		}
574
575	});
576
577
578	/** private method.... */
579
580	/* センタースクリーン取得 */
581	function getCenterScreen($obj) {
582		var x = ((jQuery(window).width() - $obj.outerWidth()) / 2) + jQuery(window).scrollLeft();
583		var y = ((jQuery(window).height() - $obj.outerHeight()) / 2);
584		if (x < 0) x = 0;
585		if (y < 0) y = 0;
586		return {
587			x: x, y: y
588		};
589	}
590
591	/* ユニークIDを取得する */
592	function getUUID() {
593		var randam = Math.floor(Math.random() * 1000);
594		return randam + new Date().getTime().toString();
595	}
596
597	/* 背景を固定する */
598	var _currentScrolltop = 0;
599	function setBackGroundFixed(isFixed) {
600		var $wrapper = jQuery('body').children('.wrapper');
601		if (isFixed) {
602			if ($wrapper.css('position') === 'fixed') { return; }
603			_currentScrolltop = jQuery(window).scrollTop();
604			$wrapper.css('position', 'fixed').css({ 'top': -_currentScrolltop, 'width': '100%'});
605		} else {
606			if ($wrapper.css('position') !== 'fixed') { return; }
607			$wrapper.css({'position': '', 'width': ''});
608			jQuery('html, body').prop({ scrollTop: _currentScrolltop });
609		}
610	}
611
612	/*!
613	 * ローディング(読み込み中)イメージ
614	 */
615	_ui.loadingImage = function () {
616		var result = '<div class="block-loading">'
617					+ '<div class="block-loading--balls">'
618					+ '<span class="block-loading--ball block-loading--ball-1"></span>'
619					+ '<span class="block-loading--ball block-loading--ball-2"></span>'
620					+ '<span class="block-loading--ball block-loading--ball-3"></span>'
621					+ '<span class="block-loading--ball block-loading--ball-4"></span>'
622					+ '<span class="block-loading--ball block-loading--ball-5"></span>'
623					+ '<span class="block-loading--ball block-loading--ball-6"></span>'
624					+ '<span class="block-loading--ball block-loading--ball-7"></span>'
625					+ '<span class="block-loading--ball block-loading--ball-8"></span>'
626					+ '</div>' 
627					+ '</div>';
628		return result;
629	};
630
631	/*!
632	 * ローディング(読み込み中)小サイズ イメージ
633	 */
634	_ui.loadingImageMin = function () {
635		var result = '<div class="block-loading-min">'
636					+ '<div class="block-loading-min--balls">'
637					+ '<span class="block-loading-min--ball block-loading-min--ball-1"></span>'
638					+ '<span class="block-loading-min--ball block-loading-min--ball-2"></span>'
639					+ '<span class="block-loading-min--ball block-loading-min--ball-3"></span>'
640					+ '<span class="block-loading-min--ball block-loading-min--ball-4"></span>'
641					+ '<span class="block-loading-min--ball block-loading-min--ball-5"></span>'
642					+ '<span class="block-loading-min--ball block-loading-min--ball-6"></span>'
643					+ '<span class="block-loading-min--ball block-loading-min--ball-7"></span>'
644					+ '<span class="block-loading-min--ball block-loading-min--ball-8"></span>'
645					+ '</div>' 
646					+ '</div>';
647		return result;
648	};
649
650})();

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.