PageSourceSearch

https://www.group.dentsu.com/common/js/common.js

js dentsu.com collected 2026-10-09 21:51:57 UTC 16,858 bytes, 484 lines download raw bytes

1(function($){
2  'use strict';
3  /*var
4  ----------------------------------------------------------------------*/
5  var DATAPREF = '-cmnjs';
6  var globalKey = 'cmnjs';
7
8  if(globalKey && window[globalKey]==null){
9    window[globalKey]={};
10  }else{
11    globalKey = false;
12  }
13
14  /*utility
15  ----------------------------------------------------------------------*/
16  /**
17  * UA判別
18  */
19  var UAINFO = (function(){
20    var ua = navigator.userAgent.toLowerCase();
21    //browser
22    var ie = !!ua.match(/(msie|trident)/i);
23    var edge = !!ua.match(/edge/i);
24    var chrome = edge ? false : !!ua.match(/(chrome|crios)/i);
25    var safari = (edge || chrome) ? false : !!ua.match(/safari/i);
26    var firefox = !!ua.match(/firefox/i);
27    //mobile device and os
28    var iPhone = ua.indexOf('iphone') >= 0;
29    var iPod = ua.indexOf('ipod') >= 0;
30    var iPad = ua.indexOf('ipad') >= 0 || (ua.indexOf('macintosh') >= 0 && navigator.standalone != null);
31    var iOS = (iPhone || iPod || iPad);
32    var Android = ua.indexOf('android') >= 0;
33    var TB = (iPad || (Android && ua.indexOf('mobile') < 0));
34    var SP = (!TB && (iOS || Android));
35    return {
36      IE: ie,
37      Edge: edge,
38      Chrome: chrome,
39      Safari: safari,
40      Firefox: firefox,
41      
42      iOS: iOS,
43      iOS_SP: (iOS && SP),
44      iOS_TB: (iOS && TB),
45      Android: Android,
46      Android_SP: (Android && SP),
47      Android_TB: (Android && TB),
48      TB: TB,
49      SP: SP,
50      iOS_Android: (iOS || Android)
51    };
52  })();
53  if(globalKey){window[globalKey].UAINFO = UAINFO;}
54
55  /**
56  * クエリデータ取得
57  */
58  var QUERYDATA = (function(){
59    var data={};
60    if(location.search){
61      var arr=location.search.substring(1,location.search.length).split('&');
62      for(var i=0;i<arr.length;i++){data[arr[i].split('=')[0]] = arr[i].split('=')[1];}
63    }
64    return data;
65  })();
66  if(globalKey){window[globalKey].QUERYDATA = QUERYDATA;}
67
68  /**
69  * クッキー操作
70  */
71  var COOKIECTRL = {
72    get: function(name) {
73      var cookies = document.cookie.split(';');
74      for (var index = 0, length = cookies.length; index < length; index += 1) {
75        var temp = cookies[index].replace(/\s/g, '').split('=');
76        if(temp[0] === name){
77          return decodeURIComponent(temp[1]);
78        }
79      }
80      return null;
81    },
82    set: function(name, value, expires, path, domain, secure, samesite){
83      var d = document;
84      var today = new Date();
85      if (expires){
86        expires = expires * 1000 * 60 * 60 * 24;
87      }
88      var expires_date = new Date( today.getTime() + (expires));
89      samesite = (function () {
90        samesite = '' + samesite;
91        samesite = samesite.toLowerCase();
92        return samesite === 'strict' || samesite === 'lax' ? samesite : '';
93      })();
94      d.cookie = name+'='+encodeURIComponent(value) +
95        ((expires)? ';expires='+expires_date.toUTCString() : '') +
96        ((path)? ';path=' + path : '')+
97        ((domain)? ';domain=' + domain : '')+
98        ((secure)? ';secure' : '' ) +
99        (samesite ? ';samesite=' + samesite : '');
100    },
101    del: function(name, path, domain){
102      var d = document;
103      if (this.get(name)){
104        d.cookie = name + '=' +
105          ((path)? ';path=' + path : '') +
106          ((domain)? ';domain=' + domain : '') +
107          ';expires=Thu, 01-Jan-1970 00:00:01 GMT';
108      }
109    }
110  };
111  if(globalKey){window[globalKey].COOKIECTRL = COOKIECTRL;}
112
113
114  /*module
115  ----------------------------------------------------------------------*/
116
117  /**
118  * スムーズスクロール
119  * 対象 [href^="#"][data-cmnjs-smoothscroll]
120  */
121  $(function() {
122    var dataName = 'data'+DATAPREF+'-smoothscroll';
123    var speed = 300;
124    var easing = 'swing';
125    var $scroller = $('html,body');
126    $(document).on('click', '[href^="#"]['+dataName+']', function(){
127      var $this = $(this);
128      var pos;
129      var href = $this.attr('href');
130      var $target = $(href === '#'? 'html' : href);
131
132      var headerHeight = $('header.header').innerHeight();
133
134      if($target.length){
135        pos = $target.offset().top;
136        $scroller.animate({scrollTop:pos - headerHeight}, speed, easing);
137        return false;
138      }else{
139        return true;
140      }
141    });
142  });
143
144  /**
145   * 画面遷移を伴うページ内アンカーリンクのスムーススクロール処理
146   */
147  $(window)
148    .on('load', function () {
149      var speed = 300;
150      var easing = 'swing';
151      var $scroller = $('html,body');
152
153      var hash = {};
154      location.search.substr(1).split('&').forEach(function (keyValue) {
155        var _keyValue = keyValue.split('=');
156        hash[decodeURIComponent(_keyValue[0])] = decodeURIComponent(_keyValue[1]);
157      });
158
159      var $target = $('#' + hash['in-page-hash']);
160      if ($target.length) {
161        var headerHeight = $('header.header').innerHeight();
162        var pos = $target.offset().top;
163        $scroller.delay(200).animate({scrollTop:pos - headerHeight}, speed, easing);
164      }
165    });
166
167  /**
168  * 電話番号リンク
169  * 対象 *[data-cmnjs-tellink]
170  * 対象要素に対し上記属性値の値でtel:プロトコルのhref属性を持ったaタグに変換
171  * Android、iOSのUAのみ実行
172  * ex) <span data-cmnjs-tellink="117">時報</span> → <a href="tel:117">時報</a>
173  */
174  $(function(){
175    var dataName = 'data'+DATAPREF+'-tellink';
176    if(UAINFO.iOS_Android){
177      $('['+dataName+']').each(function(){
178        var $this = $(this);
179        $this.wrapInner('<a href="tel:'+$this.attr(dataName)+'" />').children().unwrap();
180      });
181    }
182  });
183
184
185  /**
186  * タブ切替
187  * ボタンのクリックでボタンと対象エリアにアクティブクラスを付与
188  * ボタンとエリアの紐付けはDOM順番に依存
189  */
190  
191  //constructor
192  var TabChange = function(opt){
193    var thisO = this;
194    var def = opt.def-0||0;
195    this.curSeq = -1;
196    this.$btns = opt.$btns;
197    this.$areas = opt.$areas;
198    this.activeBtnClass = opt.activeBtnClass || '';
199    this.activeAreaClass = opt.activeAreaClass || '';
200    this.onChanged = (typeof opt.onChanged === 'function')?opt.onChanged:function(){};
201    this.$btns.each(function(seq){
202      var $this = $(this);
203      $this.on('click',function(){
204        this.blur();
205        thisO.changeTab(seq);
206      });
207    });
208    this.changeTab(def,true);
209  };
210  TabChange.prototype.changeTab = function(seq,firstFlg){
211    if(this.curSeq === seq){
212      return;
213    }
214    var $activeArea = this.$areas.eq(seq);
215    if(!firstFlg && $activeArea.is(':visible')){
216      return;
217    }
218    this.$btns.removeClass(this.activeBtnClass);
219    this.$btns.eq(seq).addClass(this.activeBtnClass);
220    this.$areas.removeClass(this.activeAreaClass);
221    $activeArea.addClass(this.activeAreaClass);
222    this.curSeq = seq;
223    this.onChanged(seq);
224  };
225  if(globalKey){window[globalKey].TabChange = TabChange;}
226  
227  $(function(){
228    /**
229    * ラッパー汎用型 TabChange の生成
230    *  ラッパー:[data-cmnjs-tabchange-role="wrap"]
231    *  ボタン :[data-cmnjs-tabchange-role="wrap"] [data-cmnjs-tabchange-role="btn"]
232    *  エリア :[data-cmnjs-tabchange-role="wrap"] [data-cmnjs-tabchange-role="area"]
233    *  アクティブボタン・エリアに付与されるクラス:tabActive
234    *  ラッパーの data-cmnjs-tabchange-def 属性で初期タブのシーケンスを指定可
235    */
236    var wrapData = 'data'+DATAPREF+'-tabchange-role=wrap';
237    var btnData = 'data'+DATAPREF+'-tabchange-role=btn';
238    var areaData = 'data'+DATAPREF+'-tabchange-role=area';
239    var defaultSeqData = 'data'+DATAPREF+'-tabchange-def';
240    var activeClass = 'tabActive';
241
242    $('['+wrapData+']').each(function(){
243      var $wrap = $(this);
244      var $nested = $wrap.find('['+wrapData+']'+' *');//ネストを考慮
245      var $btns = $wrap.find('['+btnData+']').not($nested);
246      var $areas = $wrap.find('['+areaData+']').not($nested);
247      if($btns.length && $areas.length){
248        new TabChange({
249          $btns: $btns,
250          $areas: $areas,
251          activeBtnClass: activeClass,
252          activeAreaClass: activeClass,
253          def: $wrap.attr(defaultSeqData),
254        });
255      }
256    });
257  });
258
259
260  /**
261  * アコーディオン
262  * ボタンのクリックでボタンにアクティブクラスを付与し、対応ã
262™ã‚‹ã‚¨ãƒªã‚¢ã‚’開閉アニメーション
263  * 開閉後displayスタイルを取り除き、エリアにアクティブクラスを付与する
264  */
265  //constructor
266  var Accordion = function(opt){
267    var thisO = this;
268    this.$btn = opt.$btn;
269    this.$area = opt.$area;
270    this.activeBtnClass = opt.activeBtnClass || '';
271    this.activeAreaClass = opt.activeAreaClass || '';
272    this.openedFlg = opt.openedFlg;
273    this.speed = opt.speed||200;
274    this.onBeforeDisplayChange = opt.onBeforeDisplayChange || function(){};
275    this.onAfterDisplayChange  = opt.onAfterDisplayChange  || function(){};
276    this.busyFlg = false;
277    this.useDisplayCheck = !!opt.useDisplayCheck;
278    this.$btn.on('click',function(){
279      this.blur();
280      thisO.displayChange(!thisO.openedFlg);
281    });
282    this.displayChange(thisO.openedFlg, true, true);
283  };
284  Accordion.prototype.displayChange = function(flg, noAnimationFlg, initFlg){
285    var visibleCheck,hasActiveClass;
286    if(!initFlg && this.useDisplayCheck){
287      if(flg){
288        hasActiveClass = this.$area.hasClass(this.activeAreaClass);
289        visibleCheck = this.$area.is(':visible');
290        if(visibleCheck){return;}
291        this.$area.addClass(this.activeAreaClass);
292        visibleCheck = this.$area.is(':visible');
293        if(!hasActiveClass){
294          this.$area.removeClass(this.activeAreaClass);
295        }
296        if(!visibleCheck){return;}
297      }else{
298        hasActiveClass = this.$area.hasClass(this.activeAreaClass);
299        visibleCheck = this.$area.is(':visible');
300        if(!visibleCheck){return;}
301        this.$area.removeClass(this.activeAreaClass);
302        visibleCheck = this.$area.is(':visible');
303        if(hasActiveClass){
304          this.$area.addClass(this.activeAreaClass);
305        }
306        if(visibleCheck){return;}
307      }
308    }
309    if(this.busyFlg){return;}
310    this.busyFlg = true;
311    if(this.onBeforeDisplayChange(flg) === false){
312      this.busyFlg = false;
313      return;
314    }
315    var thisO = this;
316    var speed = noAnimationFlg? 0: this.speed;
317    if(flg){//open
318      this.$btn.addClass(this.activeBtnClass);
319      this.$area.slideDown(speed,'swing',function(){thisO.displayChangeCallback(flg);});
320    }else{//close
321      this.$btn.removeClass(this.activeBtnClass);
322      this.$area.slideUp(speed,'swing',function(){thisO.displayChangeCallback(flg);});
323    }
324  };
325  Accordion.prototype.displayChangeCallback = function(flg){
326    this.openedFlg = flg;
327    if(flg){
328      this.$area.addClass(this.activeAreaClass);
329    }else{
330      this.$area.removeClass(this.activeAreaClass);
331    }
332    this.$area.css({display:''});
333    this.onAfterDisplayChange(flg);
334    this.busyFlg = false;
335  };
336  if(globalKey){window[globalKey].Accordion = Accordion;}
337  
338  $(window).on('load', function() {
339    /**
340    * ラッパー汎用型Accordionの生成
341    *  ラッパー:[data-cmnjs-accordion-role="wrap"]
342    *  ボタン :[data-cmnjs-accordion-role="wrap"] [data-cmnjs-accordion-role="btn"]
343    *  エリア :[data-cmnjs-accordion-role="wrap"] [data-cmnjs-accordion-role="area"]
344    *  アクティブボタン・エリアに付与されるクラス:accordionActive
345    *  ラッパーの data-cmnjs-accordion-active 属性の指定があれば初期状態で開く
346    */
347    var wrapData = 'data'+DATAPREF+'-accordion-role=wrap';
348    var btnData = 'data'+DATAPREF+'-accordion-role=btn';
349    var areaData = 'data'+DATAPREF+'-accordion-role=area';
350    var activeClass = 'accordionActive';
351    var defaultOpendData = 'data'+DATAPREF+'-accordion-active';
352
353    //ラッパー汎用型生成
354    $('['+wrapData+']').each(function(){
355      var $wrap = $(this);
356      var $nested = $wrap.find('['+wrapData+']'+' *');//ネストを考慮
357      var $btn = $wrap.find('['+btnData+']').not($nested);
358      var $area = $wrap.find('['+areaData+']').not($nested);
359      if($btn.length && $area.length){
360        new Accordion({
361          $btn: $btn,
362          $area: $area,
363          activeBtnClass: activeClass,
364          activeAreaClass: activeClass,
365          openedFlg: (typeof $wrap.attr(defaultOpendData) !== 'undefined'),
366          useDisplayCheck: true
367        });
368      }
369    });
370  });
371
372  /*
373  * ポジション監視コンストラクタ
374  */
375  var Poswatch = function(opt){
376    var thisO = this;
377    this.$target = opt.$target;
378    this.infrontClass = opt.infrontClass || '';
379    this.scrolledClass = opt.scrolledClass || '';
380    this.scrollThreshold = opt.scrollThreshold || 0;
381    this.posClasses = $.extend({
382      bottomDw: '',
383      bottomOn: '',
384      bottomUp: '',
385      topDw: '',
386      topOn: '',
387      topUp: ''
388    },opt.posClasses || {});
389
390    $(window).on('scroll resize',function(){
391      thisO.checkPosition();
392    });
393    this.checkPosition();
394  };
395  Poswatch.prototype.checkPosition = (function(){
396    var $body = $();
397    $(function(){$body = $('body');});
398    return function(){
399      //しきい値のスクロール判定
400      if(window.pageYOffset >= this.scrollThreshold){
401        this.$target.addClass(this.scrolledClass);
402      }else{
403        this.$target.removeClass(this.scrolledClass);
404      }
405      //ベース位置の通過判定
406      var bodyBorderTop =  0;//offset().topがbodyのborderTopを反映しないため補正
407      if($body.length){
408        bodyBorderTop = Number($body.css('borderTopWidth').replace('px',''));
409        bodyBorderTop = isNaN(bodyBorderTop)?0:bodyBorderTop;
410      }
411      var targetH = this.$target.outerHeight();
412      var targetT = this.$target.offset().top+bodyBorderTop;
413
414      if(window.pageYOffset > targetT+targetH){
415        this.$target.removeClass(this.posClasses.topOn+' '+this.posClasses.topDw).addClass(this.posClasses.topUp);
416      }else if(window.pageYOffset > targetT){
417        this.$target.removeClass(this.posClasses.topUp+' '+this.posClasses.topDw).addClass(this.posClasses.topOn);
418      }else{
419        this.$target.removeClass(this.posClasses.topUp+' '+this.posClasses.topOn).addClass(this.posClasses.topDw);
420      }
421      if(window.pageYOffset+window.innerHeight < targetT){
422        this.$target.removeClass(this.posClasses.bottomUp+' '+this.posClasses.bottomOn
422).addClass(this.posClasses.bottomDw);
423      }else if(window.pageYOffset+window.innerHeight < targetT+targetH){
424        this.$target.removeClass(this.posClasses.bottomUp+' '+this.posClasses.bottomDw).addClass(this.posClasses.bottomOn);
425      }else{
426        this.$target.removeClass(this.posClasses.bottomDw+' '+this.posClasses.bottomOn).addClass(this.posClasses.bottomUp);
427      }
428    };
429  })();
430  if(globalKey){window[globalKey].Poswatch = Poswatch;}
431  $(function(){
432    /*
433    * 汎用ポジション監視
434    * 対象要素:[data-cmnjs-poswatch]
435    * 100px以上スクロールした場合に付与するクラス:poswatchLittleSclolled
436    * 要素がウィンドウの下辺よりも下にいる場合に付与するクラス:poswatchBottomDw
437    * 要素がウィンドウの下辺に重なっている場合に付与するクラス:poswatchBottomOn
438    * 要素がウィンドウの下辺よりも上にいる場合に付与するクラス:poswatchBottomUp
439    * 要素がウィンドウの上辺よりも下にいる場合に付与するクラス:poswatchTopDw
440    * 要素がウィンドウの上辺に重なっている場合に付与するクラス:poswatchTopOn
441    * 要素がウィンドウの上辺よりも上にいる場合に付与するクラス:poswatchTopUp
442    */
443    var poswatchData = 'data'+DATAPREF+'-poswatch';
444    $('['+poswatchData+']').each(function(){
445      new Poswatch({
446        $target: $(this),
447        posClasses: {
448          bottomDw: 'poswatchBottomDw',
449          bottomOn: 'poswatchBottomOn',
450          bottomUp: 'poswatchBottomUp',
451          topDw: 'poswatchTopDw',
452          topOn: 'poswatchTopOn',
453          topUp: 'poswatchTopUp',
454        },
455        scrolledClass: 'poswatchLittleSclolled',
456        scrollThreshold: 64
457      });
458    });
459  });
460
461      /**
462    * SPメニュー
463    */
464
465    $(function(){
466      var $menuBtn = $('.header .menu-icon'),
467          $body = $('body');
468      // メニューボタンをクリックした時の動き
469      $menuBtn.on('click', function(){
470        $body.toggleClass('open-menu');
471        $('header.header nav.inner-head .visible').removeClass('visible');
472      });
473    });
474    $(function(){
475      var $menuBtn = $('.header .search-icon'),
476          $body = $('body');
477      // メニューボタンをクリックした時の動き
478      $menuBtn.on('click', function(){
479        $body.toggleClass('search-menu');
480      });
481    });
482
483
484})(jQuery);

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.