PageSourceSearch

https://cdn-contents.toranoana.jp/static/systemfiles/scripts/core.js?v=20260915152700

js toranoana.jp collected 2026-09-24 09:07:12 UTC 79,452 bytes, 3,009 lines download raw bytes

1$(function () {
2  replaceWithBr();
3  cookieAgreementPopUp();
4
5  // とらTOPにリダイレクト
6  const aqua_path = "/aqua/ec";
7  const aqua_r_path = "/aqua_r/ec";
8  if (~location.href.indexOf(aqua_path)) {
9    location.href = "https://" + settings.cartHost + "/tora/ec/";
10  } else if (~location.href.indexOf(aqua_r_path)) {
11    location.href = "https://ec.toranoana.jp/tora_r/ec/";
12  }
13});
14
15/*
16 * 処理中の場合はEnter無効 F5無効追加の場合はキーコードの条件に116を追加して下さい。
17 */
18$(function () {
19  window.document.onkeydown = function (e) {
20    if (
21      ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) &&
22      processing
23    ) {
24      return false;
25    } else {
26      return true;
27    }
28  };
29});
30/**
31 * short url group.
32 */
33var commonSettings = {
34  shortUrlGroup: ["commodity", "category", "campaign", "brand"],
35  siteCode: "0000",
36  logLevel: "debug",
37};
38
39/**
40 * Common preview objects.
41 */
42var previewFunctionList = new Array();
43
44/**
45 * Final execute function list.
46 */
47var finalFunctionList = new Array();
48
49/**
50 * import script
51 */
52function importScript(jsUrl) {
53  var js = document.createElement("script");
54  js.type = "text/javascript";
55  js.src = jsUrl;
56  js.charset = "UTF-8";
57
58  $("head").append(js);
59}
60
61/**
62 * Actionの情報+CallBack等のAction全体を表すクラス
63 */
64var Action = function (packageId, beanId, actionId, callback) {
65  this.actionInfo = new ActionInfo(packageId, beanId, actionId);
66  this.callback = callback;
67};
68
69var ActionInfo = function (packageId, beanId, actionId) {
70  this.packageId = packageId;
71  this.beanId = beanId;
72  this.actionId = actionId;
73};
74
75var actionList = new Array();
76
77function addAction(actionId) {
78  var action = new Action(actionId);
79  actionList.push(action);
80}
81
82/** パーツの初期化functionList */
83var partsInitializeList = new Array();
84
85function anlyzeUrlParameter(location, doDecode) {
86  var arg = new Object();
87  var pair = location.search.substring(1).split("&");
88  for (var i = 0; pair[i]; i++) {
89    var kv = pair[i].split("=");
90    arg[kv[0]] = doDecode ? decodeURIComponent(kv[1]) : kv[1];
91  }
92  return arg;
93}
94
95var AccessSet = function () {
96  this.packageId = "";
97  this.actionId = "";
98  this.beanId = "";
99  this.shortUrlId = "";
100  this.otherPathInfo = new Array();
101};
102
103// 共通関数系
104
105/**
106 * URLを解析する
107 *
108 * @param url
109 * @returns {___accessSet0}
110 */
111function analyzeAccessSet(url) {
112  var path = url.substring(
113    url.indexOf(settings.servletMapping + "/") +
114      settings.servletMapping.length +
115      1
116  );
117  var paths = path.split("/");
118  var accessSet = new AccessSet();
119
120  var baseIndex = 0;
121  if (url.indexOf(settings.servletMapping + "/") != -1) {
122    if (paths.length > baseIndex) {
123      accessSet.packageId = paths[baseIndex];
124      log("AnalyzeAccessSet-packageId : " + accessSet.packageId);
125      baseIndex++;
126    }
127    if (paths.length > baseIndex) {
128      accessSet.beanId = paths[baseIndex];
129      log("AnalyzeAccessSet-beanId : " + accessSet.beanId);
130      baseIndex++;
131    }
132  } else {
133    // shortUrlFilterを使われている場合は、baseIndexをfrontが見つかるまでカウントする
134    for (var i = 0; i < paths.length; i++) {
135      if ("/" + paths[i] == settings.context) {
136        break;
137      }
138      baseIndex++;
139    }
140    // front分+shortUrl識別キー分+する
141    baseIndex += 2;
142    accessSet.shortUrlId = paths[baseIndex - 1];
143  }
144  for (var i = baseIndex; i < paths.length; i++) {
145    var info = paths[i];
146    if (info != "") {
147      // log("AnalyzeAccessSet-other index[" + (i - baseIndex + 1) + "] :
148      // " + info);
149      accessSet.otherPathInfo.push(info);
150    }
151  }
152  return accessSet;
153}
154
155/**
156 * ユーザエージェント判別
157 */
158var _ua = (function (u) {
159  return {
160    Tablet:
161      (u.indexOf("windows") != -1 && u.indexOf("touch") != -1) ||
162      u.indexOf("ipad") != -1 ||
163      (u.indexOf("android") != -1 && u.indexOf("mobile") == -1) ||
164      (u.indexOf("firefox") != -1 && u.indexOf("tablet") != -1) ||
165      u.indexOf("kindle") != -1 ||
166      u.indexOf("silk") != -1 ||
167      u.indexOf("playbook") != -1,
168    Mobile:
169      (u.indexOf("windows") != -1 && u.indexOf("phone") != -1) ||
170      u.indexOf("iphone") != -1 ||
171      u.indexOf("ipod") != -1 ||
172      (u.indexOf("android") != -1 && u.indexOf("mobile") != -1) ||
173      (u.indexOf("firefox") != -1 && u.indexOf("mobile") != -1) ||
174      u.indexOf("blackberry") != -1,
175  };
176})(window.navigator.userAgent.toLowerCase());
177
178/**
179 *
180 */
181var fillCommodityAmount = function (target, max) {
182  if (!target) {
183    return;
184  }
185
186  $(target).empty();
187  if (!max) {
188    max = 99;
189  }
190
191  var optionFmt = '<option value="{0}">{0}</option>';
192  for (var i = 1; i <= max; i++) {
193    $(target).append(optionFmt.format(i));
194  }
195};
196
197/**
198 * コンポボックス作成
199 *
200 * @param target
201 *            対象コンポボックス
202 * @param optionDataList
203 *            データリスト
204 * @param nameId
205 *            ラベルID
206 * @param valueId
207 *            データID
208 */
209function fillComboxElement(target, optionDataList, nameId, valueId) {
210  if (typeof target == "undefined") {
211    return;
212  }
213
214  var name = "name";
215  var value = "value";
216  if (typeof nameId != "undefined") {
217    name = nameId;
218  }
219  if (typeof valueId != "undefined") {
220    value = valueId;
221  }
222
223  $(target).empty();
224  var optionFmt = '<option value="{0}">{1}</option>';
225  for (var i = 0; i < optionDataList.length; i++) {
226    var optionData = optionDataList[i];
227    $(target).append(optionFmt.format(optionData[value], optionData[name]));
228  }
229}
230
231/**
232 * 住所を表すオブジェクト
233 */
234var PostalAddress = function (
235  postalCodeId,
236  postalGuideId,
237  prefectureCodeId,
238  cityId,
239  addressId,
240  prefectureNameId
241) {
242  this.postalCodeId = postalCodeId;
243  this.postalGuideId = postalGuideId;
244  this.prefectureCodeId = prefectureCodeId;
245  this.cityId = cityId;
246  this.addressId = addressId;
247  this.prefectureNameId = prefectureNameId;
248};
249
250PostalAddress.prototype = {
251  setPostalValue: function (postalId, postalValue) {
252    if (postalId) {
253      var element = $("#" + postalId);
254      element.val(postalValue);
255      if (element.data("placed") == "true") {
256        element.css("color", element.data("placeholder-color"));
257        element.data("placed", "false");
258      }
259    }
260  },
261  setPostalGuideInfo: function (guideHtml) {
262    if (this.postalGuideId) {
263      $("#" + this.postalGuideId).html(guideHtml);
264    }
265  },
266};
267
268/**
269 * 郵便番号検索
270 */
271function sendPostalSearchRequest(
272  postalCodeId,
273  postalGuideId,
274  prefectureCodeId,
275  cityId,
276  addressId,
277  prefectureNameId,
278  displayLoading
279) {
280  var parameters = createBaseParametersForAjaxApi(
281    "customer",
282    "postal",
283    "search"
284  );
285
286  var postalAddress = new PostalAddress(
287    postalCodeId,
288    postalGuideId,
289    prefectureCodeId,
290    cityId,
291    addressId,
292    prefectureNameId
293  );
294  var postalCodeElement = $("#" + postalAddress.postalCodeId);
295  var inputPostalCode = postalCodeElement.val();
296  inputPostalCode = inputPostalCode.replace(/-/g, "");
297  postalCodeElement.val(inputPostalCode);
298  if (postalCodeElement.data("placed") == "true") {
299    parameters.postalCode = "";
300  } else {
301    parameters.postalCode = inputPostalCode;
302  }
303
304  var postalSearchCallback = function (data, messages, parameter) {
305    if (!data.address) {
306      postalAddress.setPostalGuideInfo(message.noFoundPostal);
307      return;
308    }
309    var resultAddress = data.address;
310    postalAddress.setPostalValue(
311      postalAddress.prefectureNameId,
312      resultAddress.prefecture
313    );
314    postalAddress.setPostalValue(
315      postalAddress.prefectureCodeId,
316      resultAddress.prefectureCode
317    );
318    postalAddress.setPostalValue(postalAddress.cityId, resultAddress.city);
319    postalAddress.setPostalValue(
320      postalAddress.addressId,
321      resultAddress.address
322    );
323    postalAddress.setPostalGuideInfo(message.postalSearchCaution);
324  };
325
326  var loadingFmt = '<img src="{0}" width="16" height="16"> 検索しています...';
327  postalAddress.setPostalGuideInfo(loadingFmt.format(images.smallLoading));
328  var functions = createAjaxFunctions(null, null, postalSearchCallback);
329
330  var param = {
331    parameters: parameters,
332    functions: functions,
333    uri: "/common/topic_path/move/",
334    dataType: "json",
335    async: true,
336  };
337  sendAjaxToApi(param);
338}
339
340function changeDisplay(jObj, display) {
341  if (display) {
342    jObj.removeClass("hidden");
343  } else {
344    jObj.addClass("hidden");
345  }
346}
347
348/**
349 * ログのハンドリング処理
350 */
351var Logger = function () {
352  this.errors = new Array();
353  this.debugs = new Array();
354};
355
356Logger.prototype = {
357  error: function (message) {
358    this.errors.push(message);
359    try {
360      if ("console" in window) {
361        console.error("[WS_ERROR]" + message);
362      }
363    } catch (e) {}
364  },
365  debug: function (message) {
366    if (commonSettings.logLevel === "debug") {
367      this.debugs.push(message);
368    }
369    if ("console" in window) {
370      console.log(message);
371    }
372  },
373  transport: function () {
374    // Ajaxでログを転送
375    if (logger.errors.length <= 0) {
376      return;
377    }
378
379    var param = {
380      errorLogs: logger.errors,
381      debugLogs: logger.debugs,
382      browser: $.stringify($.support),
383    };
384    //$.ajax({
385    //    ifModified : true,
386    //    type : "POST",
387    //    url : settings.apiContext + settings.logServ,
388    //    dataType : "json",
389    //    data : param,
390    //    headers : {
391    //        "pragma" : "no-cache"
392    //    },
393    //    complete : function(event) {
394    //    }
395    //});
396    this.errors = new Array();
397    this.debugs = new Array();
398  },
399};
400var logger = new Logger();
401
402window.onerror = function (message, url, lineNo) {
403  logger.error(url + " : " + lineNo + " : " + message);
404  // windowのエラーは処理が中断されるため、ためずに送信する
405  logger.transport();
406};
407$.error = function (message) {
408  // jQueryのエラーは処理が中断されるため、ためずに送信する
409  logger.error(message);
410};
411function log(message) {
412  if (typeof console != "undefined") {
413    logger.debug("[WS_LOG]:" + message);
414  }
415}
416
417/**
418 * 該当のAタグを任意のタグに置き換える
419 *
420 * @param dom
421 */
422function changeDisabeleLink(dom, tag) {
423  var message = dom.html();
424  dom.before("<" + tag + ">" + message + "</" + tag + ">");
425  var newDom = dom.prev();
426  dom.remove();
427  return newDom;
428}
429
430function serializeForm(form, actionInfo) {
431  $(form)
432    .find(":input")
433    .each(function (i) {
434      if ($(this).closest(".listTemplate.hidden").length == 0) {
435        var fields = $(this).serializeArray();
436        jQuery.each(fields, function (i, field) {
437          var values = new Array();
438          if (actionInfo[field.name]) {
439            values = actionInfo[field.name];
440          }
441          values.push(field.value);
442          actionInfo[field.name] = values;
443        });
444      }
445    });
446  return actionInfo;
447}
448
449function changedate(namebase) {
450  // フォームと各年月日のname属性を指定
451  var tYear = document.getElementsByName(namebase + "_year")[0];
452  var tMonth = document.getElementsByName(namebase + "_month")[0];
453  var tDays = document.getElementsByName(namebase + "_day")[0];
454
455  var selectY = tYear.options[tYear.selectedIndex].value;
456  var selectM = tMonth.options[tMonth.selectedIndex].value;
457  var selectD = tDays.options[tDays.selectedIndex].value;
458
459  if (selectY == "" || selectM == "") {
460    return;
461  }
462
463  var dateObj = new Date(selectY, selectM, 0);
464
465  tDays.length = 0;
466
467  // 選択された月によって、日のオプションを生成
468  for (var i = 1; i <= dateObj.getDate(); i++) {
469    var name = "" + i + "日";
470    var value = i > 9 ? "" + i : "0" + i;
471    tDays.options[i - 1] = new Option(name, value);
472  }
473
474  if (selectD.indexOf("0") == 0) {
475    selectD = selectD.substring(1, 2);
476  }
477  if (selectD > tDays.length) {
478    tDays.options[0].selected = true;
479  } else {
480    if (selectD == "") {
481      return;
482    }
483    tDays.options[selectD - 1].selected = true;
484  }
485}
486
487function blockDoubleClick(id) {
488  var style;
489  if (!$.support.opacity) {
490    style = "-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(opacity=0)';";
491  } else {
492    style = "background-color:rgba(255, 255, 255, 0.0);";
493  }
494
495  if ($.mobile) {
496    style = style + " height: " + $(document).height() + "px";
497  }
498
499  var blockFmt = '<div id="{0}" class="blockDoubleClick" style="{1}" ></div>';
500
501  $("body").prepend(blockFmt.format(id, style));
502}
503
504/**
505 * 規格名作成
506 *
507 * @param targetRoot
508 */
509function scanStandardName(targetRoot) {
510  var stndNameFmt = "<span class='standardDetailName'>({0}{1}{2})</span>";
511
512  var standardDetail1Name;
513  if (targetRoot) {
514    standardDetail1Name = $(targetRoot).find("span.standardDetail1Name");
515  } else {
516    standardDetail1Name = $("span.standardDetail1Name");
517  }
518
519  $(standardDetail1Name).each(function (i) {
520    var stndName1 = $(this).html();
521    var stndName2 = $(this).next("span.standardDetail2Name").html();
522    if (stndName1 && stndName2) {
523      $(this).next("span.standardDetail2Name").remove();
524      $(this).replaceWith(stndNameFmt.format(stndName1, "/", stndName2));
525    } else if (stndName1 || stndName2) {
526      $(this).next("span.standardDetail2Name").remove();
527      $(this).replaceWith(stndNameFmt.format(stndName1, "", stndName2));
528    }
529  });
530}
531
532/**
533 * 要素を削除
534 *
535 * @param target
536 * @param removeFlg
537 * @returns
538 */
539function removeElementIf(target, removeFlg) {
540  if (removeFlg == true && target) {
541    $(target).remove();
542  }
543  return removeFlg;
544}
545/**
546 * レンダリング
547 */
548var CellRenderContainer = function (data) {
549  this.cellRenderList = new Array();
550  this._init(data);
551};
552
553CellRenderContainer.prototype = {
554  _init: function (data) {
555    this.data = data;
556  },
557  push: function (cellRender) {
558    this.cellRenderList.push(cellRender);
559  },
560  draw: function () {
561    for (var i = 0; i < this.cellRenderList.length; i++) {
562      var cellRender = this.cellRenderList[i];
563      cellRender.data = this.data;
564      cellRender.execute();
565    }
566  },
567};
568
569var CellRender = function (data, targetDom, callBack) {
570  if (callBack) {
571    this.data = data;
572    this.targetDom = targetDom;
573    this.callBack = callBack;
574  } else {
575    this.targetDom = data;
576    this.callBack = targetDom;
577  }
578  this.execute = function () {
579    for (var i = 0; i < this.targetDom.length; i++) {
580      var target = this.targetDom[i];
581      this.callBack(this.data, $(target), i);
582    }
583  };
584};
585
586/**
587 * 文字フォーマット
588 */
589String.prototype.format = function () {
590  var result = this;
591
592  for (var i = 0; i < arguments.length; i++) {
593    var reg = new RegExp("\\{s*" + i + "s*\\}", "g");
594    result = result.replace(reg, arguments[i]);
595  }
596
597  return result;
598};
599
600/**
601 * 開始文字チェック
602 */
603if (typeof String.prototype.startsWith != "function") {
604  String.prototype.startsWith = function (str) {
605    return this.substring(0, str.length) == str;
606  };
607}
608
609/**
610 * 結末文字チェック
611 */
612if (typeof String.prototype.endsWith != "function") {
613  String.prototype.endsWith = function (str) {
614    return this.substring(this.length - str.length, this.length) == str;
615  };
616}
617
618/**
619 * 日付フォーマット処理
620 */
621var DateFormat = function (pattern) {
622  this._init(pattern);
623};
624
625DateFormat.prototype = {
626  _init: function (pattern) {
627    this.pattern = pattern;
628    this._patterns = [];
629
630    for (var i = 0; i < pattern.length; i++) {
631      var ch = pattern.charAt(i);
632      if (this._patterns.length == 0) {
633        this._patterns[0] = ch;
634      } else {
635        var index = this._patterns.length - 1;
636        if (this._patterns[index].charAt(0) == "'") {
637          if (
638            this._patterns[index].length == 1 ||
639            this._patterns[index].charAt(this._patterns[index].length - 1) !=
640              "'"
641          ) {
642            this._patterns[index] += ch;
643          } else {
644            this._patterns[index + 1] = ch;
645          }
646        } else if (this._patterns[index].charAt(0) == ch) {
647          this._patterns[index] += ch;
648        } else {
649          this._patterns[index + 1] = ch;
650        }
651      }
652    }
653  },
654
655  format: function (date) {
656    var result = [];
657    for (var i = 0; i < this._patterns.length; i++) {
658      result[i] = this._formatWord(date, this._patterns[i]);
659    }
660    return result.join("");
661  },
662  _formatWord: function (date, pattern) {
663    var formatter = this._f
663ormatter[pattern.charAt(0)];
664    if (formatter) {
665      return formatter.apply(this, [date, pattern]);
666    } else {
667      return pattern;
668    }
669  },
670  _formatter: {
671    y: function (date, pattern) {
672      // Year
673      var year = String(date.getFullYear());
674      if (pattern.length <= 2) {
675        year = year.substring(2, 4);
676      } else {
677        year = this._zeroPadding(year, pattern.length);
678      }
679      return year;
680    },
681    M: function (date, pattern) {
682      // Month in year
683      return this._zeroPadding(String(date.getMonth() + 1), pattern.length);
684    },
685    d: function (date, pattern) {
686      // Day in month
687      return this._zeroPadding(String(date.getDate()), pattern.length);
688    },
689    H: function (date, pattern) {
690      // Hour in day (0-23)
691      return this._zeroPadding(String(date.getHours()), pattern.length);
692    },
693    m: function (date, pattern) {
694      // Minute in hour
695      return this._zeroPadding(String(date.getMinutes()), pattern.length);
696    },
697    s: function (date, pattern) {
698      // Second in minute
699      return this._zeroPadding(String(date.getSeconds()), pattern.length);
700    },
701    S: function (date, pattern) {
702      // Millisecond
703      return this._zeroPadding(String(date.getMilliseconds()), pattern.length);
704    },
705    "'": function (date, pattern) {
706      // escape
707      if (pattern == "''") {
708        return "'";
709      } else {
710        return pattern.replace(/'/g, "");
711      }
712    },
713  },
714
715  _zeroPadding: function (str, length) {
716    if (str.length >= length) {
717      return str;
718    }
719
720    return new Array(length - str.length + 1).join("0") + str;
721  },
722};
723
724/**
725 * WebShopping用serializeArray
726 */
727var r20 = /%20/g,
728  rbracket = /\[\]$/,
729  rCRLF = /\r?\n/g,
730  rinput =
731    /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
732  rselectTextarea = /^(?:select|textarea)/i;
733
734jQuery.fn.extend({
735  siSerializeArray: function () {
736    return this.map(function () {
737      return this.elements ? jQuery.makeArray(this.elements) : this;
738    })
739      .filter(function () {
740        return (
741          this.name &&
742          !this.disabled &&
743          (this.checked ||
744            rselectTextarea.test(this.nodeName) ||
745            rinput.test(this.type))
746        );
747      })
748      .filter(function () {
749        // Listのtemplate情報は除去
750        var parent = $(this).parents(".listTemplate");
751        return !parent || parent.length <= 0;
752      })
753      .map(function (i, elem) {
754        var val = jQuery(this).val();
755        // placeholderが有効なら処理を必要としないので終了
756        if (!("placeholder" in document.createElement("input"))) {
757          if (
758            !(
759              $(this).data("placed") === undefined ||
760              $(this).data("placed") === "false"
761            )
762          ) {
763            val = "";
764          }
765        }
766        log(val);
767
768        return val == null
769          ? null
770          : jQuery.isArray(val)
771          ? jQuery.map(val, function (val, i) {
772              return {
773                name: elem.name,
774                value: val.replace(rCRLF, "\r\n"),
775              };
776            })
777          : {
778              name: elem.name,
779              value: val.replace(rCRLF, "\r\n"),
780            };
781      })
782      .get();
783  },
784});
785
786/**
787 * 改行コードを<br />
788 * に変換
789 */
790function encodeHtml(value) {
791  var domData = $("<div>").text(value).html();
792  return domData.replace(rCRLF, "<br />");
793}
794
795/**
796 * 画面が初期表示時に、クラス属性が「replaceWithBr」のDomを取得し、改行コードを<br />
797 * に変換
798 */
799function replaceWithBr() {
800  $(".replaceWithBr").each(function () {
801    $(this).html(encodeHtml($(this).text()));
802  });
803}
804
805/**
806 * elementの文字数を指定したサイズで切り捨てる
807 */
808function toHeadelineValue(element, maxline, lineSize) {
809  var orgVal = $(element).html();
810  if (!orgVal) {
811    return false;
812  }
813  var resultVal = "";
814  var splitedVal = orgVal.split(/<br[^>]*>/gi);
815  var toShorten = false;
816  for (var i = 0, line = 0; i < splitedVal.length; i++, line++) {
817    var val = splitedVal[i];
818    if (line >= maxline) {
819      toShorten = true;
820      break;
821    } else if (i != 0) {
822      resultVal += "<br/>";
823    }
824    // 追加可能な文字数
825    var addabaleSize = maxline * lineSize - line * lineSize;
826    if (val.length > addabaleSize) {
827      // 足そうとした文字列がはみ出す場合
828      val = val.substring(0, addabaleSize - 1);
829      toShorten = true;
830    }
831    resultVal += val;
832    if (val.length > lineSize) {
833      line += parseInt(val.length / lineSize);
834    }
835  }
836  if (toShorten) {
837    resultVal += "...";
838  }
839  $(element).html(resultVal);
840
841  return toShorten;
842}
843
844function toHeadlineValueText(text, maxSize) {
845  if (text.length > maxSize) {
846    text = text.substring(0, maxSize) + "...";
847  }
848  return text;
849}
850
851/**
852 * jQueryのhoverにdataを渡せるようにしたもの
853 */
854(function ($) {
855  $.fn.siHover = function (data, on, out) {
856    $(this).hover(
857      function (event) {
858        on(event, data, this);
859      },
860      function (event) {
861        out(event, data, this);
862      }
863    );
864  };
865})(jQuery);
866
867/*******************************************************************************
868 * 商品共通
869 ******************************************************************************/
870/**
871 * セット品の有効在庫数の計算
872 *
873 * セット構成品に規格商品がある場合、規格を選択毎に在庫数の変更が必要になる。
874 * 在庫数のパターンが膨大になる可能性があり、リクエストを投げるほどの処理でないためjavascriptにて計算。
875 *
876 * 同一構成品でセット品を組んだ場合、1つのセット品購入で構成品の在庫が2減る。
877 *
878 */
879function computeAvailableStockOfSetCatalog(orgSelectSkuDataList) {
880  // 同一商品(同一skuCode)ごとにまとめる
881  var newSelectDataList = packSameSkuData(orgSelectSkuDataList);
882  var availableStockQuantity;
883
884  for (var i = 0; i < newSelectDataList.length; i++) {
885    var skuData = newSelectDataList[i].skuData;
886    var quantity = Number.MAX_VALUE;
887
888    // 在庫がない場合
889    if (!skuData.hasStock) {
890      return 0;
891    }
892
893    // 在庫管理しない場合
894    if (skuData.hasStock && skuData.availableStockQuantity == 0) {
895      continue;
896    }
897
898    // 有効在庫数 / セット品に含まれるそのSKUコードの個数
899    quantity =
900      Number(skuData.availableStockQuantity) /
901      Number(newSelectDataList[i].itemCount);
902
903    if (quantity < 1) {
904      return 0;
905    }
906
907    // 最小値を採用する
908    if (!availableStockQuantity || Number(availableStockQuantity) > quantity) {
909      // 小数点以下は切り捨て
910      availableStockQuantity = Math.floor(quantity);
911    }
912  }
913
914  return availableStockQuantity;
915}
916
917function packSameSkuData(selectSkuDataList) {
918  var skuDataList = new Array();
919
920  for (i = 0; i < selectSkuDataList.length; i++) {
921    var selectSkuData = selectSkuDataList[i];
922    if (!selectSkuData.skuCode) {
923      continue;
924    }
925
926    var skuData = {
927      skuCode: "",
928      itemCount: 0,
929      skuData: "",
930    };
931
932    var sameFlag = false;
933    for (j = 0; j < skuDataList.length; j++) {
934      if (selectSkuData.skuCode == skuDataList[j].skuCode) {
935        skuDataList[j].itemCount += 1;
936        sameFlag = true;
937        break;
938      }
939    }
940
941    if (!sameFlag) {
942      skuData.skuCode = selectSkuData.skuCode;
943      skuData.itemCount = 1;
944      skuData.skuData = selectSkuData;
945      skuDataList.push(skuData);
946    }
947  }
948
949  return skuDataList;
950}
951
952/**
953 * 注文上限数の比較
954 */
955function compareLimitOrderQuantity(
956  limitOrderQuantity,
957  availableStockQuantity,
958  oneshotOrderLimit
959) {
960  var limitQuantity = Number.MAX_VALUE;
961  if (!oneshotOrderLimit) {
962    oneshotOrderLimit = Number.MAX_VALUE;
963  }
964  if (!availableStockQuantity) {
965    availableStockQuantity = Number.MAX_VALUE;
966  }
967
968  if (Number(availableStockQuantity) < Number(oneshotOrderLimit)) {
969    limitQuantity = availableStockQuantity;
970  } else if (Number(availableStockQuantity) > Number(oneshotOrderLimit)) {
971    limitQuantity = oneshotOrderLimit;
972  }
973
974  if (Number(limitOrderQuantity) > Number(limitQuantity)) {
975    limitOrderQuantity = limitQuantity;
976  }
977
978  return limitOrderQuantity;
979}
980
981/**
982 * 文字列構築処理
983 */
984function insertStringBetweenString(
985  beforeString,
986  afterString,
987  insertString,
988  doInsert
989) {
990  var before = beforeString;
991  if (before == undefined || before == null) {
992    before = "";
993  }
994
995  var after = afterString;
996  if (after == undefined || after == null) {
997    after = "";
998  }
999
1000  var insert = insertString;
1001  if (insert == undefined || insert == null) {
1002    insert = "";
1003  }
1004
1005  var resultString;
1006  if (doInsert) {
1007    resultString = before + insert + after;
1008  } else {
1009    resultString = before + after;
1010  }
1011
1012  return resultString;
1013}
1014
1015/**
1016 * パンくずリストを作成する。
1017 */
1018function initializeTopicPath(topicPathList) {
1019  var topicPathArea = $("#topicPath");
1020  var relAttribute = "";
1021  if ($.mobile) {
1022    relAttribute = ' rel="external" ';
1023  }
1024
1025  var topicPathUrlFmt = 'javascript:topicPathMove("{0}")';
1026  var moveTopPageFmt = "javascript:moveTopPage()";
1027
1028  var html =
1029    "<a href=" +
1030    moveTopPageFmt.format("") +
1031    ">" +
1032    sanitizeSpecialChara(message.topPage) +
1033    "</a>";
1034  var delimiter =
1035    '<span class="delimiter">' +
1036    sanitizeSpecialChara(message.topicPathDelimiter) +
1037    "</span>";
1038
1039  for (var topicPath in topicPathList) {
1040    var url = topicPathList[topicPath];
1041    var label =
1042      '<span class="topicPath">' +
1043      sanitizeHtml(encodeHtml(topicPath)) +
1044      "</span>";
1045    if (url != "") {
1046      html +=
1047        delimiter +
1048        "<a href=" +
1049        sanitizeSpecialChara(topicPathUrlFmt.format(topicPathList[topicPath])) +
1050        relAttribute +
1051        ">" +
1052        label +
1053        "</a>";
1054    } else {
1055      html += delimiter + label;
1056    }
1057  }
1058  topicPathArea.html(html);
1059}
1060
1061function showLoading() {
1062  loadingTimer = setTimeout(function () {
1063    var wrapper = $(".wrapper");
1064    wrapper.before("<div id='loading' class='hidden'></div>");
1065    $("#loading").html(
1066      '<div><img src="' +
1067        settings.context +
1068        '/files/commonfiles/images/loading-circle.gif"/><br>NowLoading...</div>'
1069    );
1070    popup("loading", {
1071      closeClick: false,
1072      overlaySpeed: 0,
1073      lightboxSpeed: 0,
1074    });
1075    clearTimeout(loadingTimer);
1076  }, 500);
1077}
1078
1079/**
1080 * noPhoto画像
1081 */
1082function noPhoto(image, noPhotoType) {
1083  image.src = images[noPhotoType];
1084}
1085
1086/**
1087 * disable
1088 */
1089function disable(selector) {
1090  selector.attr("disabled", "disabled");
1091}
1092
1093/**
1094 * remove_disable
1095 */
1096function removeDisable(selector) {
1097  selector.removeAttr("disabled");
1098}
1099
1100/**
1101 * 数量設定
1102 *
1103 * @param quantityAreaElement
1104 * @param commodityData
1105 */
1106function createQuantityList(quantityAreaElement, addCartLimitQuantity) {
1107  var maxQuantity = quantityAreaElement.data("maxquantity");
1108  if (!maxQuantity) {
1109    maxQuantity = 20;
1110  }
1111  if (addCartLimitQuantity) {
1112    if (Number(maxQuantity) > Number(addCartLimitQuantity)) {
1113      maxQuantity = addCartLimitQuantity;
1114    }
1115  }
1116  $(quantityAreaElement).empty();
1117  for (var i = 1; i <= maxQuantity; i++) {
1118    $(quantityAreaElement).append(
1119      '<option value="' + i + '">' + i + "</option>"
1120    );
1121  }
1122}
1123
1124/**
1125 * 入荷お知らせ登録
1126 */
1127function addArrivalGoods(shopCode, commodityCode, skuCode) {
1128  if (typeof arrivalGoodsInit == "function") {
1129    arrivalGoodsInit(shopCode, commodityCode, skuCode);
1130  }
1131}
1132
1133function addSaleAgainHopeOrder(
1134  shopCode,
1135  commodityCode,
1136  messageDisplayType,
1137  brandCode,
1138  enPasscode,
1139  commodityName = "",
1140  commodityGenre = "",
1141  coupling = "",
1142  commodityKindName = "",
1143  clickPartsName = ""
1144) {
1145  // 二重押下防止:フラッシュが表示されている場合は処理を中断
1146  var showingFlash = $(".js-flash-message").length;
1147  if (showingFlash) return;
1148  if ($(".js-again-hope-popup").css("display") === "block") return;
1149  // ローディング画像を表示
1150  displayLoadingImage();
1151
1152  var parameters = createBaseParametersForAjaxApi(
1153    "order",
1154    "sale_again_hope_order",
1155    "add"
1156  );
1157  parameters.shopCode = shopCode;
1158  parameters.commodityCode = commodityCode;
1159  parameters.brandCode = brandCode;
1160  parameters.enPasscode = enPasscode;
1161
1162  var currentUrl = location.href;
1163  var separator = currentUrl.includes('?') ? '&' : '?';
1164  parameters.loginAfterUrl = currentUrl + separator + 'addSaleAgainHope=' + encodeURIComponent(commodityCode);
1165  parameters.messageDisplayType = messageDisplayType;
1166
1167  var successFunction = function (data, messages) {
1168    var errors = messages.errorMessages;
1169    // ローディング画像を削除
1170    removeLoadingImage();
1171    // DataLayer設定
1172    wishToRestockDataLayer(
1173      commodityCode,
1174      brandCode,
1175      commodityName,
1176      commodityGenre,
1177      coupling,
1178      commodityKindName,
1179      clickPartsName
1180    );
1181
1182    if (
1183      errors.length == 0 &&
1184      (data.againHopeOrderSuccessFlg || data.alreadyHopeOrderRegistFlg)
1185    ) {
1186      // 同じ商品コードを持つDOM上の該当ボタンを「再販希望済み」表示に切り替え(投票直後の即時切替)
1187      if (typeof switchSaleAgainHopeButtonsByCommodityCode === "function") {
1188        switchSaleAgainHopeButtonsByCommodityCode(commodityCode);
1189      }
1190      if (
1191        parameters.messageDisplayType == "detail_page" ||
1192        parameters.messageDisplayType == "card_modal"
1193      ) {
1194        var closeHopeOrderButtons = document.querySelectorAll(
1195          ".js-close-again-hope-order-modal"
1196        );
1197        for (var index = 0; index < closeHopeOrderButtons.length; index++) {
1198          closeHopeOrderButtons[index].addEventListener(
1199            "click",
1200            closeAgainHopeOrderModal
1201          );
1202        }
1203
1204        var modalFadeIn = document.querySelector("#js-again-hope-order-modal");
1205        modalFadeIn.classList.add("js-add-cart-modal-fade-in");
1206        var closeButtons = document.querySelectorAll(
1207          "#js-again-hope-order-modal"
1208        );
1209
1210        if (data.againHopeOrderSuccessFlg) {
1211          // 初回登録
1212          $("#again_hope_order_success").show();
1213          $("#again_hope_order_registed").hide();
1214        } else {
1215          // 登録済み
1216          $("#again_hope_order_success").hide();
1217          $("#again_hope_order_registed").show();
1218        }
1219
1220        if (!data.loginFlg) {
1221          // 未ログイン
1222          $("#arrival_notice_add_success").hide();
1223          $("#arrival_notice_regist_link").hide();
1224        }
1225
1226        // モーダルに関連作品(カップリング or キャラクター
1226)を追加
1227        if (parameters.messageDisplayType == "card_modal") {
1228          createRecommendDom(".js-add-modal-related-item", commodityCode, {
1229            partsType: "4",
1230            quantity: "20",
1231            relationType: "3",
1232          });
1233        } else {
1234          createRecommendDom(".js-add-modal-related-item", commodityCode);
1235        }
1236      }
1237      if (parameters.messageDisplayType == "under_popup") {
1238        var popup_message = "";
1239        if (data.againHopeOrderSuccessFlg) {
1240          popup_message = "再販希望を受け付けました。";
1241        } else {
1242          popup_message = "すでに再販希望を受け付けています。";
1243        }
1244        if (data.loginFlg) {
1245          popup_message +=
1246            "商品入荷の際は入荷アラートによるメールでご連絡します。";
1247          $(".js-sales_again_hope_popup_alert_link").show();
1248        } else {
1249          $(".js-sales_again_hope_popup_alert_link").hide();
1250        }
1251
1252        $(".js-sales_again_hope_popup_message").text(popup_message);
1253
1254        $(".js-again-hope-popup").fadeIn(300);
1255        $(".p-again-hope-popup-close").on("click", function () {
1256          $(".js-again-hope-popup").fadeOut();
1257        });
1258        setTimeout(function () {
1259          $(".js-again-hope-popup").fadeOut();
1260        }, 5000);
1261      }
1262    } else {
1263      $("#sale_again_hope_and_add_cart_alert_modal").css("display", "inline");
1264      document.getElementById(
1265        "sale_again_hope_and_add_cart_alert_text"
1266      ).innerHTML =
1267        "再販希望を登録できませんでした。<br>商品ページを確認しますか?";
1268
1269      // 商品詳細に遷移
1270      var modalLinkButton = document.getElementById(
1271        "sale_again_hope_and_add_cart_alert_modal_link"
1272      );
1273      modalLinkButton.addEventListener(
1274        "click",
1275        function () {
1276          window.location.href =
1277            "https://" +
1278            document.domain +
1279            "/" +
1280            settings.urlBrandCode +
1281            "/" +
1282            settings.urlChannel +
1283            "/item/" +
1284            commodityCode +
1285            "/";
1286        },
1287        false
1288      );
1289
1290      // モーダルクローズ
1291      var modalCloseButton = document.getElementById(
1292        "sale_again_hope_and_add_cart_alert_modal_close"
1293      );
1294      modalCloseButton.addEventListener(
1295        "click",
1296        function () {
1297          $("#sale_again_hope_and_add_cart_alert_modal").css("display", "none");
1298        },
1299        false
1300      );
1301    }
1302  };
1303
1304  var functions = createAjaxFunctions(null, null, successFunction);
1305
1306  var param = {
1307    parameters: parameters,
1308    functions: functions,
1309    uri: "/order/sale_again_hope_order/add/",
1310    messageType: "saleagain",
1311    messageDisplayType: messageDisplayType,
1312    dataType: "json",
1313    async: true,
1314  };
1315  sendAjaxToApi(param);
1316}
1317
1318function closeAgainHopeOrderModal() {
1319  document
1320    .querySelector("#js-again-hope-order-modal")
1321    .classList.remove("js-add-cart-modal-fade-in");
1322  document.body.style.overflow = "visible";
1323  document.body.style.height = "auto";
1324  document.getElementsByTagName("html")[0].style.overflow = "visible";
1325  document.getElementsByTagName("html")[0].style.height = "auto";
1326}
1327
1328/**
1329 * お問い合わせ画面遷移
1330 */
1331function moveInquiry(shopCode, commodityCode) {
1332  location.href =
1333    settings.context +
1334    settings.servletMapping +
1335    "/customer/inquiry/commodity/" +
1336    shopCode +
1337    "/" +
1338    commodityCode +
1339    "/";
1340}
1341
1342function convertDetailInfo(commodityData) {
1343  // 返品特約の表示制御
1344  var descriptionElement = $(".commodityDescriptionArea");
1345
1346  convertDisplayReturnPolicy(
1347    $(descriptionElement).find(".returnPolicyArea"),
1348    commodityData.returnPolicy
1349  );
1350
1351  // 商品属性の表示制御
1352  convertDisplayCommodityAttribute(
1353    $(descriptionElement).find(".commodityAttributeArea"),
1354    commodityData.commodityAttribute
1355  );
1356
1357  var linkAreaElement = $(".linkArea");
1358  // 検索タグの表示制御
1359  convartDisplayTagList(
1360    $(linkAreaElement).find(".tagListArea"),
1361    commodityData.shopCode,
1362    commodityData.tagList
1363  );
1364
1365  // リンクURLの表示制御
1366  convertDisplayLinkUrl(
1367    $(linkAreaElement).find(".linkUrlArea"),
1368    commodityData.linkUrl
1369  );
1370
1371  $(descriptionElement).show();
1372
1373  $(linkAreaElement).show();
1374}
1375
1376/**
1377 * 返品表示制御
1378 *
1379 * @param returnPolicyAreaDom
1380 * @param commodityData
1381 */
1382function convertDisplayReturnPolicy(returnPolicyAreaElement, returnPolicy) {
1383  if (!returnPolicy) {
1384    $(returnPolicyAreaElement).remove();
1385  }
1386}
1387
1388/**
1389 * 商品属性表示制御
1390 *
1391 * @param commodityAttributeAreaElement
1392 * @param commodityData
1393 */
1394function convertDisplayCommodityAttribute(
1395  commodityAttributeAreaElement,
1396  commodityAttribute
1397) {
1398  if (commodityAttribute.length == 0) {
1399    $(commodityAttributeAreaElement).remove();
1400  }
1401}
1402
1403/**
1404 * タグリスト表示制御
1405 *
1406 * @param tagListElement
1407 * @param commodityData
1408 */
1409function convartDisplayTagList(tagListElement, shopCode, tagList) {
1410  if (tagList.length == 0) {
1411    $(tagListElement).remove();
1412  } else {
1413    var tagLink = $(tagListElement).find(".tagLink");
1414    for (var i = 0; i < tagLink.length; i++) {
1415      var link = $(tagLink[i]).find("a");
1416      var tagCode = $(tagLink[i]).find("input").val();
1417      link.attr("onclick", "searchTag('" + shopCode + "', '" + tagCode + "')");
1418    }
1419  }
1420}
1421
1422/**
1423 * リンクURL表示制御
1424 *
1425 * @param linkUrlAreaElement
1426 * @param commodityData
1427 */
1428function convertDisplayLinkUrl(linkUrlAreaElement, linkUrl) {
1429  if (!linkUrl) {
1430    $(linkUrlAreaElement).remove();
1431  }
1432}
1433
1434/**
1435 *
1436 * @param tagCode
1437 */
1438function searchTag(shopCode, tagCode) {
1439  location.href =
1440    settings.context +
1441    settings.servletMapping +
1442    "/catalog/list/?searchShopCode=" +
1443    shopCode +
1444    "&searchTagCode=" +
1445    tagCode;
1446}
1447
1448/**
1449 * 付属ポイント情報の表示制御
1450 *
1451 * @param attPointContentsAreaElement
1452 * @param attPointContents
1453 */
1454function convertDisplayAttPointContents(
1455  attPointContentsAreaElement,
1456  attPointContents
1457) {
1458  if (!attPointContents) {
1459    $(attPointContentsAreaElement).remove();
1460  }
1461}
1462
1463/**
1464 * 関連画像表示の制御
1465 */
1466function convertRelatedImages(
1467  relatedImageElement,
1468  imagePath,
1469  relatedImageAreaElement
1470) {
1471  var imageElement = $(relatedImageElement).find("img");
1472
1473  $(imageElement).on("error", function () {
1474    $(this).remove();
1475  });
1476
1477  $(imageElement).on("load", function () {
1478    $(relatedImageAreaElement).removeClass("hidden");
1479  });
1480  $(imageElement).attr("src", imagePath);
1481
1482  $(imageElement).click(function () {
1483    var id = $(this).parent().attr("id") + "_popup";
1484    if ($(relatedImageAreaElement).find("#" + id).length == 0) {
1485      var $popupImage = $(
1486        '<img src="' +
1487          $(this).attr("src") +
1488          '" class="hidden" id="' +
1489          id +
1490          '" />'
1491      );
1492      $(relatedImageAreaElement).after($popupImage);
1493    }
1494    pcPopup(id);
1495  });
1496}
1497
1498/**
1499 * 関連画像のhoverの処理
1500 */
1501function relatedImageHover(commodityImageArea, relatedImageElement) {
1502  var commonImageElement = $(commodityImageArea).find("img");
1503  var commodityImageSrc = $(commonImageElement).attr("src");
1504
1505  $(relatedImageElement).mouseover(function () {
1506    $(commodityImageArea)
1507      .find("input[name='commonImagePath']")
1508      .attr("value", $(commonImageElement).attr("src"));
1509
1510    $(commonImageElement).attr("src", $(this).find("img").attr("src"));
1511  });
1512
1513  $(relatedImageElement).mouseout(function () {
1514    commodityImageSrc = $(commodityImageArea)
1515      .find("input[name='commonImagePath']")
1516      .attr("value");
1517
1518    $(commonImageElement).attr("src", commodityImageSrc);
1519  });
1520}
1521
1522function addCartFromDetail(
1523  formId,
1524  agreeFlg,
1525  quantity,
1526  compositionList,
1527  purchaseMethodType
1528) {
1529  var parameters = {
1530    quantity: quantity,
1531    purchaseMethodType: purchaseMethodType,
1532  };
1533
1534  // 付帯情報を設定
1535  var incWorkChecks = $(".incWorkCheck");
1536  var index = 0;
1537  for (var i = 0; i < incWorkChecks.length; i++) {
1538    var incWorkCheck = incWorkChecks[i];
1539
1540    if (incWorkCheck.checked) {
1541      var key = "incWorkCode_" + i;
1542      var incWorkCode = $(incWorkCheck).val();
1543      var postKey = "incWorkCode_" + index;
1544      index++;
1545      parameters[postKey] = incWorkCode;
1546
1547      var selectKey = "incWorkSelect_" + incWorkCode;
1548      var incWorkSelect = $("#" + selectKey);
1549      var selectValue = incWorkSelect.val();
1550      parameters[selectKey] = selectValue;
1551
1552      var textKey = "incWorkText_" + incWorkCode;
1553      var incWorkText = $("#" + textKey);
1554      var textValue = incWorkText.val();
1555      parameters[textKey] = textValue;
1556    }
1557  }
1558
1559  addCart(formId, compositionList, agreeFlg, parameters);
1560}
1561
1562/**
1563 * カート追加
1564 *
1565 * @param formId
1566 * @param compositionList
1567 * @param purchasingAgreementFlg
1568 * @param parameterAssociationArray
1569 */
1570function addCart(
1571  formId,
1572  compositionList,
1573  purchasingAgreementFlg,
1574  parameterAssociationArray
1575) {
1576  var uri = "/cart/cart/add_cart/";
1577
1578  var successFunction = function (data) {
1579    initializeMiniCart(miniCartAddCallBack);
1580  };
1581
1582  if (!compositionList) {
1583    compositionList = new Array();
1584  }
1585
1586  if (!purchasingAgreementFlg) {
1587    purchasingAgreementFlg = false;
1588  }
1589
1590  var parameters = createBaseParametersForAjaxApi("cart", "cart", "add_cart");
1591
1592  if (compositionList && compositionList.length != 0) {
1593    parameters.compositionList = new Array();
1594    for (var i = 0; i < compositionList.length; i++) {
1595      parameters.compositionList.push(compositionList[i]);
1596    }
1597  }
1598
1599  parameters["purchasingAgreementFlg"] = purchasingAgreementFlg;
1600
1601  if (parameterAssociationArray) {
1602    for (key in parameterAssociationArray) {
1603      parameters[key] = parameterAssociationArray[key];
1604    }
1605  }
1606
1607  var functions = createAjaxFunctions(null, null, successFunction);
1608
1609  var param = {
1610    parameters: parameters,
1611    functions: functions,
1612    formId: formId,
1613    uri: uri,
1614    messageType: "addcart",
1615    dataType: "json",
1616    async: true,
1617  };
1618  sendAjaxToApi(param);
1619}
1620
1621/**
1622 * 画像エリアにLoading画像の追加
1623 */
1624function insertLoadingImageAtImageArea(imageAreaElement) {
1625  imageAreaElement.append(
1626    '<div id="commonImageLoading"><img src="' +
1627      images.circleLoading +
1628      '" /></div>'
1629  );
1630}
1631
1632function removeLoadingImageAtImageArea() {
1633  $("#commonImageLoading").remove();
1634}
1635
1636/**
1637 * パーツリストからファンクションを削除
1638 */
1639function removeDefermentInitializeFunction() {
1640  var recommendA;
1641  if (typeof initializeRecommendA == "function") {
1642    recommendA = initializeRecommendA;
1643  }
1644  var recommendB;
1645  if (typeof initializeRecommendB == "function") {
1646    recommendB = initializeRecommendB;
1647  }
1648  var reviewList;
1649  if (typeof initializeReviewList == "function") {
1650    reviewList = initializeReviewList;
1651  }
1652  if (!recommendA && !recommendB && !reviewList) {
1653    return;
1654  }
1655
1656  for (var i = 0; i < partsInitializeList.length; i++) {
1657    if (partsInitializeList[i] == recommendA) {
1658      partsInitializeList.splice(i, 1);
1659      i--;
1660      continue;
1661    }
1662
1663    if (partsInitializeList[i] == initializeRecommendB) {
1664      partsInitializeList.splice(i, 1);
1665      i--;
1666      continue;
1667    }
1668
1669    if (partsInitializeList[i] == initializeReviewList) {
1670      partsInitializeList.splice(i, 1);
1671      i--;
1672      continue;
1673    }
1674  }
1675}
1676
1677/**
1678 * パンくずリスト生成
1679 */
1680function createTopicPathListForCatalogDetail() {
1681  var topicPathList = {};
1682
1683  var topicPathElements = $(".topicPath");
1684
1685  for (var i = 0; i < topicPathElements.length; i++) {
1686    var topicPathData = topicPathElements[i];
1687    var url = $(topicPathData).data("value");
1688    topicPathList[$(topicPathData).data("name")] = url + "/";
1689  }
1690
1691  initializeTopicPath(topicPathList);
1692}
1693
1694/**
1695 * 付帯サービス変更時
1696 */
1697function changeIncwork(checkId, chagedObj) {
1698  if ($(chagedObj).val() != "") {
1699    var incCheck = $("#" + checkId);
1700    $(incCheck).prop("checked", true);
1701  }
1702}
1703
1704/*******************************************************************************
1705 * ページング
1706 ******************************************************************************/
1707/**
1708 * レビュータイトルの件数更新
1709 *
1710 * @param pagerRowCountDom
1711 *            更新対象
1712 * @param data
1713 *            データ
1714 */
1715function updateReviewPagerRowCountArea(pagerRowCountDom, data) {
1716  if (
1717    !pagerRowCountDom ||
1718    $(pagerRowCountDom).length == 0 ||
1719    !data ||
1720    data.pager == null
1721  ) {
1722    return;
1723  }
1724  var startSize = 1;
1725  var endSize = data.pager.currentPage * data.pager.pageSize;
1726  if (endSize > data.pager.rowCount) {
1727    endSize = data.pager.rowCount;
1728  }
1729  var pagerRowCountFmt =
1730    "<span class='pagerRowCount'>" + sanitizeSpecialChara(message.allPageCount);
1731  if (data.pager.rowCount > 0 && data.pager.rowCount > data.pager.pageSize) {
1732    pagerRowCountFmt +=
1733      sanitizeSpecialChara(message.pageCountFromTo) + "</span>";
1734  } else {
1735    pagerRowCountFmt += "</span>";
1736  }
1737  $(pagerRowCountDom).each(function () {
1738    $(this).html(
1739      pagerRowCountFmt.format(
1740        sanitizeSpecialChara(data.pager.rowCount),
1741        startSize,
1742        endSize
1743      )
1744    );
1745  });
1746}
1747
1748function appendParamToUrl(param) {
1749  var url = "",
1750    key,
1751    value;
1752
1753  for (key in param) {
1754    value = param[key];
1755    delete param[key];
1756    if (value) {
1757      param[decodeURIComponent(key)] = decodeURIComponent(value);
1758    }
1759  }
1760
1761  var pairs = location.search.substring(1).split("&");
1762  for (var i = 0; i < pairs.length; i++) {
1763    key = pairs[i].split("=")[0];
1764    if (!param[key]) {
1765      url = [url, url ? "&" : "?", pairs[i]].join("");
1766    }
1767  }
1768
1769  for (key in param) {
1770    url = [url, url ? "&" : "?", key, "=", param[key]].join("");
1771  }
1772  return url;
1773}
1774
1775/**
1776 * ページ遷移
1777 *
1778 * @param currentPage
1779 *            ページ番号
1780 * @param fn
1781 *            callback
1782 */
1783function goNextPage(currentPage, pageSize, fn, pagerActionInfo) {
1784  var accessSet = analyzeAccessSet(location.toString());
1785  var parameters = createBaseParametersForAjaxApi(
1786    accessSet.packageId,
1787    accessSet.beanId,
1788    "init"
1789  );
1790  if (typeof pagerActionInfo != "undefined") {
1791    for (var key in pagerActionInfo) {
1792      if (pagerActionInfo[key]) {
1793        parameters[key] = pagerActionInfo[key];
1794      }
1795    }
1796  }
1797  parameters.currentPage = currentPage;
1798  parameters.pageSize = pageSize;
1799
1800  var url = "/" + accessSet.packageId + "/" + accessSet.beanId + "/init/";
1801  var functions = createAjaxFunctions(null, null, fn);
1802
1803  var param = {
1804    parameters: parameters,
1805    functions: functions,
1806    uri: uri,
1807    dataType: "json",
1808    async: true,
1809  };
1810  sendAjaxToApi(param);
1811}
1812
1813/**
1814 * ページサイズの設定
1815 *
1816 * @param pager
1817 *            ページングデータ
1818 */
1819function doRenderPageSize(pager, pageSizeArea) {
1820  var pageSizeType = $(pageSizeArea).data("type");
1821  if (pageSizeType == "link") {
1822    doRenderPageSizeLink(pager, pageSizeArea);
1823  } else {
1824    doRenderPageSizeSelect(pager, pageSizeArea);
1825  }
1826}
1827
1828function doRenderPageSizeSelect(pager, pageSizeArea) {
1829  var pageSizeDom = $(pageSizeArea).find("select[name='pageSize'].pagerSize");
1830  if (pageSizeDom.length == 0) {
1831    return;
1832  }
1833  $(pageSizeDom).empty();
1834
1835  var pageSizeOption = new Array();
1836  var pageSizeOptionTmp = $(pageSizeDom).parent().data("list-option");
1837  if (typeof pageSizeOptionTmp != "undefined") {
1838    var splited = pageSizeOptionTmp.split(",");
1839    for (option in splited) {
1840      pageSizeOption.push(splited[option]);
1841    }
1842  } else {
1843    pageSizeOption = new Array(8, 16, 32, 64);
1844  }
1845
1846  for (var i = 0; i < pageSizeOption.length; i++) {
1847    var ps = pageSizeOption[i];
1848    $(pageSizeDom).append(new Option(ps + " 件表示", ps));
1849    if (pager.rowCount <= ps) {
1850      break;
1851    }
1852  }
1853  $(pageSizeDom).val(pager.pageSize);
1854  if ($(pageSizeDom).children().length <= 1) {
1855    $(pageSizeDom).parent().hide();
1856  }
1857}
1858
1859function doRenderPageSizeLink(pager, pageSizeArea) {
1860  var pageSizeDom = $(pageSizeArea).find("a[name='pagerSize'].pagerSize");
1861  if ($(pageSizeDom).length == 0) {
1862    return;
1863  }
1864
1865  $(pageSizeDom).before(" | ");
1866
1867  var pageSizeOption = new Array();
1868  var pageSizeOptionTmp = $(pageSizeArea).data("list-option");
1869  if (typeof pageSizeOptionTmp != "undefined") {
1870    var splited = pageSizeOptionTmp.split(",");
1871    for (option in splited) {
1872      pageSizeOption.push(splited[option]);
1873    }
1874  } else {
1875    pageSizeOption = new Array(10, 20, 50, 100);
1876  }
1877  for (var i = 0; i < pageSizeOption.length; i++) {
1878    var ps = pageSizeOption[i];
1879    var newPageSize = $(pageSizeDom).clone();
1880    var $newPageSize = $(newPageSize);
1881    $newPageSize.html(ps + $(pageSizeDom).html());
1882
1883    if (pager.pageSize == ps) {
1884      $(pageSizeDom).before(
1885        '<input type="hidden" name="pageSize" value="' +
1886          ps +
1887          '" class="pagerSize">'
1888      );
1889      $(pageSizeDom).before($newPageSize.html() + " | ");
1890    } else {
1891      $(newPageSize).attr("data-pagesize", ps);
1892      $(pageSizeDom).before($newPageSize);
1893      $(pageSizeDom).before(" | ");
1894    }
1895
1896    if (pager.rowCount <= ps) {
1897      break;
1898    } else {
1899      $newPageSize.before("  ");
1900    }
1901  }
1902  $(pageSizeDom).remove();
1903}
1904
1905/**
1906 * ページ遷移イベントを設定する
1907 */
1908function bindPager() {
1909  var callBackFunc = null;
1910  var pagerActionInfo = null;
1911  var pagerArea = null;
1912
1913  if (arguments.length > 2) {
1914    callBackFunc = arguments[0];
1915    pagerActionInfo = arguments[1];
1916    pagerArea = arguments[2];
1917  } else if (arguments.length > 1) {
1918    if (jQuery.isFunction(arguments[0])) {
1919      callBackFunc = arguments[0];
1920      pagerActionInfo = arguments[1];
1921    } else {
1922      pagerActionInfo = arguments[0];
1923      pagerArea = arguments[1];
1924    }
1925  } else if (arguments.length > 0) {
1926    if (jQuery.isFunction(arguments[0])) {
1927      callBackFunc = arguments[0];
1928    } else if (arguments[0] instanceof ActionInfo) {
1929      pagerActionInfo = arguments[0];
1930    } else {
1931      pagerArea = arguments[0];
1932    }
1933  }
1934
1935  var isPost = callBackFunc && jQuery.isFunction(callBackFunc);
1936  var pageSizeDataElement = $("[name='pageSize']");
1937  var pageLinkElement = $("a.pagingLink");
1938  var selectPageSizeElement = $("select[name='pageSize'].pagerSize");
1939  var aPageSizeElement = $("a[name='pagerSize'].pagerSize");
1940
1941  if (pagerArea != null && typeof pagerArea != "undefined") {
1942    pageLinkElement = $(pagerArea).find("a.pagingLink");
1943    pageSizeDataElement = $(pagerArea).find("[name='pageSize']");
1944    selectPageSizeElement = $(pagerArea).find(
1945      "select[name='pageSize'].pagerSize"
1946    );
1947    aPageSizeElement = $(pagerArea).find("a[name='pagerSize'].pagerSize");
1948  }
1949
1950  $(pageLinkElement).removeAttr("onclick");
1951  $(pageLinkElement).click(function (event) {
1952    var pageSize = $(pageSizeDataElement).val();
1953    var currentPage = $(this).data("pageno");
1954    if (isPost) {
1955      goNextPage(currentPage, pageSize, callBackFunc, pagerActionInfo);
1956    } else {
1957      var param = {
1958        pageSize: pageSize,
1959        currentPage: currentPage,
1960      };
1961      location.href = appendParamToUrl(param);
1962    }
1963    event.preventDefault();
1964  });
1965
1966  // ページサイズのchangeイベントを登録
1967  $(selectPageSizeElement).change(function (event) {
1968    var pageSize = $(this).val();
1969    var currentPage = 1;
1970    if (isPost) {
1971      goNextPage(currentPage, pageSize, callBackFunc, pagerActionInfo);
1972    } else {
1973      var param = {
1974        pageSize: pageSize,
1975        currentPage: currentPage,
1976      };
1977      location.href = appendParamToUrl(param);
1978    }
1979    event.preventDefault();
1980  });
1981
1982  $(aPageSizeElement).click(function (event) {
1983    var pageSize = $(this).data("pagesize");
1984    var currentPage = 1;
1985    if (isPost) {
1986      goNextPage(1, pageSize, callBackFunc, pagerActionInfo);
1987    } else {
1988      var param = {
1989        pageSize: pageSize,
1990        currentPage: currentPage,
1991      };
1992      location.href = appendParamToUrl(param);
1993    }
1994    event.preventDefault();
1995  });
1996}
1997
1998function pagerDataBind(param) {
1999  // pageデータマッピング
2000  var pagerElement = $("#pager");
2001  var pageListElements = $(".pageList");
2002  var data = new Object();
2003  var pager = new Object();
2004  pager.currentPage = $(pagerElement).data("currentpage");
2005  pager.maxFetchSize = $(pagerElement).data("maxfetchsize");
2006  pager.maxPage = $(pagerElement).data("maxpage");
2007  pager.overflow = $(pagerElement).data("overflow");
2008  pager.pageSize = $(pagerElement).data("pagesize");
2009  pager.rowCount = $(pagerElement).data("rowcount");
2010
2011  var pageListArray = new Array();
2012  for (var i = 0; i < pageListElements.length; i++) {
2013    var pageList = pageListElements[i];
2014    pageListArray.push($(pageList).data("pageno"));
2015  }
2016  pager.pageList = pageListArray;
2017
2018  data.pager = pager;
2019
2020  var pagerElements = $(".pagerArea").children();
2021  pagerElements.push($("#pagerSizeArea"));
2022
2023  for (var i = 0; i < pagerElements.length; i++) {
2024    var dom = pagerElements[i];
2025    // html構成を作成
2026    initializePager(data, $(dom));
2027  }
2028
2029  // 作成したhtml構成のonclick処理を設定
2030  bindPager(param);
2031}
2032
2033function initializePager(data, dom) {
2034  var key = dom.data("item");
2035
2036  if (key == "pager") {
2037    // ページング情報
2038    var html = "";
2039    var pagerInfo = data.pager;
2040    if (pagerInfo == null) {
2041      return;
2042    }
2043
2044    if (pagerInfo.overflow && pagerInfo.pageList.length > 50) {
2045      pagerInfo.pageList.length = 50;
2046    }
2047
2048    var onclick = ' onclick="") ';
2049
2050    if (pagerInfo.currentPage > 1) {
2051      // 最初のページでなければ前へを追加
2052      html +=
2053        "<a href='#' data-pageNo=\"" +
2054        (pagerInfo.currentPage - 1) +
2055        '" ' +
2056        onclick +
2057        "class='pagingPrev pagingLink'><span class='c-arrow c-arrow-01 c-arrow-left'></span></a>";
2058    }
2059
2060    html += "&nbsp;";
2061    if (pagerInfo.maxPage > 1) {
2062      // 表示する数字の数 1... x x x x ... Max
2063      var lineSize = settings.pagingLineSize;
2064      // 表示する最大ページ数
2065      var maxSize = settings.pagingMaxSize;
2066
2067      var startPage = 1;
2068      if (
2069        pagerInfo.currentPage - Math.floor(lineSize / 2) > 1 &&
2070        pagerInfo.pageList.length > lineSize
2071      ) {
2072        startPage = pagerInfo.currentPage - Math.floor(lineSize / 2);
2073        // 1ページ目とPager開始ページと連続すれば「…」を付けない
2074        html +=
2075          "<a href='#' data-pageNo=\"" +
2076          1 +
2077          '" ' +
2078          onclick +
2079          ' class="pagingCount pagingLink">' +
2080          1 +
2081          "</a>";
2082        if (startPage - 1 != 1) {
2083          html += '<span class="paging_omit">…</span>';
2084        } else {
2085          html += "&nbsp;";
2086        }
2087      }
2088
2089      var lastPage = startPage + lineSize - 1;
2090      if (lastPage > maxSize) {
2091        lastPage = maxSize;
2092        startPage = lastPage - lineSize + 1;
2093      } else if (lastPage > pagerInfo.pageList.length) {
2094        lastPage = pagerInfo.pageList.length;
2095      }
2096      if (maxSize > pagerInfo.maxPage) {
2097        maxSize = pagerInfo.maxPage;
2098      }
2099
2100      for (var i = startPage; i <= lastPage; i++) {
2101        try {
2102          var pageNo = i;
2103          if (pageNo == pagerInfo.currentPage) {
2104            html +=
2105              "<a href='#' class=\"current\"><span class='pagingCount activepage'>" +
2106              pageNo +
2107              "</span></a> ";
2108          } else {
2109            html +=
2110              "<a href='#' data-pageNo=\"" +
2111              pageNo +
2112              '" ' +
2113              onclick +
2114              ' class="pagingCount pagingLink">' +
2115              pageNo +
2116              "</a> ";
2117          }
2118        } catch (e) {}
2119      }
2120      // 最終ページとPager終わりページと連続すれば「…」を付けない
2121      if (lastPage != maxSize) {
2122        if (lastPage + 1 != maxSize) {
2123          html += '<span class="paging_omit">…</span>';
2124        } else {
2125          html += "&nbsp;";
2126        }
2127        html +=
2128          " <a href='#' data-pageNo=\"" +
2129          sanitizeSpecialChara(maxSize) +
2130          '" ' +
2131          onclick +
2132          ' class="pagingCount pagingLink">' +
2133          sanitizeSpecialChara(maxSize) +
2134          "</a> ";
2135      }
2136    }
2137
2138    if (pagerInfo.currentPage < maxSize && pagerInfo.pageList.length > 0) {
2139      // 最終ページでなければ次へを追加
2140      html +=
2141        "<a href='#' data-pageNo=\"" +
2142        (pagerInfo.currentPage + 1) +
2143        '"' +
2144        onclick +
2145        "class='pagingNext pagingLink'><span class='c-arrow c-arrow-01 c-arrow-right'></span></a> ";
2146    }
2147
2148    dom.html(html);
2149    return;
2150  } else if (key == "pagerRowCount") {
2151    if (data.pager == null) {
2152      return;
2153    }
2154
2155    var startSize = (data.pager.currentPage - 1) * data.pager.pageSize + 1;
2156    var endSize = startSize + data.pager.pageSize - 1;
2157    if (endSize > data.pager.rowCount) {
2158      endSize = data.pager.rowCount;
2159    }
2160    var pagerRowCountFmt = "全{0}件";
2161    if (data.pager.rowCount > 0 && data.pager.rowCount > data.pager.pageSize) {
2162      pagerRowCountFmt += ":{1}件 ~ {2}件";
2163    } else {
2164      pagerRowCountFmt += "";
2165    }
2166    $(".pagerMessage").text(
2167      pagerRowCountFmt.format(data.pager.rowCount, startSize, endSize)
2168    );
2169
2170    return;
2171  } else if (key == "pagerSize") {
2172    if (data.pager == null) {
2173      return;
2174    }
2175    var pageSizeType = $(dom).data("type");
2176    var dataRole = "";
2177    if ($.mobile) {
2178      dataRole = ' data-role="none" ';
2179    }
2180    var pageSizeHtml =
2181      '<select name="pageSize" class="pagerSize"' + dataRole + "></select>";
2182    if (pageSizeType == "link") {
2183      pageSizeHtml = '<a href="#" name="pagerSize" class="pagerSize">ä»¶</a>';
2184    }
2185    dom.html(pageSizeHtml);
2186    doRenderPageSize(data.pager, $(dom));
2187    return;
2188  } else if (key == "appendPager") {
2189    var pagerInfo = data.pager;
2190    if (pagerInfo == null || data.pager.overflow) {
2191      return;
2192    }
2193    if (pagerInfo.currentPage < maxSize) {
2194      var html = "";
2195      html += '<div class="nextPageBar">';
2196      html +=
2197        '<a href="' +
2198        (pagerInfo.currentPage + 1) +
2199        '" class="pagingLink"><input type="button" class="buttonLarge appendNextPage" value="' +
2200        message.next +
2201        pagerInfo.pageSize +
2202        message.count +
2203        '" /></a>';
2204      html += "</div>";
2205      dom.html(html);
2206    } else {
2207      dom.html("");
2208    }
2209  } else if (key == "readMore") {
2210    // ページング情報
2211    var html = "";
2212    var pagerInfo = data.pager;
2213
2214    if (pagerInfo == null || pagerInfo.rowCount == 0) {
2215      $(".readMoreArea").hide();
2216      return;
2217    }
2218
2219    var openReadMoreMessage = $(dom).find(".openReadMore").html();
2220    if (!openReadMoreMessage) {
2221      openReadMoreMessage = "もっと見る";
2222    }
2223    var closeReadMoreMessage = $(dom).find(".closeReadMore").html();
2224    if (!closeReadMoreMessage) {
2225      closeReadMoreMessage = "閉じる";
2226    }
2227
2228    // もっと見るのリンク
2229    if (pagerInfo.currentPage < pagerInfo.maxPage) {
2230      html += '<div class="openReadMoreArea">';
2231    } else {
2232      html += '<div class="openReadMoreArea hidden">';
2233    }
2234    html +=
2235      "<a href='#' data-pageNo=\"" +
2236      (pagerInfo.currentPage + 1) +
2237      '"' +
2238      onclick +
2239      ' class="openReadMore">' +
2240      openReadMoreMessage +
2241      "</a> ";
2242    html += "</div>";
2243
2244    // 閉じるのリンク
2245    if (pagerInfo.currentPage > 1) {
2246      html += '<div class="closeReadMoreArea">';
2247    } else {
2248      // 最初のページでは表示しない
2249      html += '<div class="closeReadMoreArea hidden">';
2250    }
2251    html +=
2252      "<a href='#' data-pageNo=\"1\" " +
2253      onclick +
2254      ' class="closeReadMore">' +
2255      closeReadMoreMessage +
2256      "</a>";
2257    html += "</div>";
2258    log(html);
2259
2260    dom.html(html);
2261  }
2262}
2263
2264function reviewListReadMore(init) {
2265  var currentPage = 0;
2266  if (!init) {
2267    $(".readMoreArea").before(
2268      '<div id="readMoreLoading"><img src="' +
2269        settings.context +
2270        '/files/commonfiles/images/loading-small.gif" /></div>'
2271    );
2272    var currentPageVal = $("#currentPage").val();
2273    currentPage = Number(currentPageVal) + 1;
2274  }
2275
2276  var pathInfo = analyzeAccessSet(location.href).otherPathInfo;
2277  var shopCode = pathInfo[0];
2278  var commodityCode = pathInfo[1];
2279  var uri =
2280    "/catalog/review_list/search/" + shopCode + "/" + commodityCode + "/";
2281  var parameters = createBaseParametersForAjaxApi(
2282    "catalog",
2283    "review_list",
2284    "search"
2285  );
2286  parameters.shopCode = shopCode;
2287  parameters.commodityCode = commodityCode;
2288  parameters.pageSize = 3;
2289  parameters.currentPage = currentPage;
2290
2291  if ($.mobile) {
2292    parameters.clientType = "sp";
2293  }
2294
2295  var functions = createAjaxFunctions(null, null, reviewListCallBack);
2296
2297  var param = {
2298    parameters: parameters,
2299    functions: functions,
2300    uri: uri,
2301    dataType: "json",
2302    async: true,
2303  };
2304  sendAjaxToApi(param);
2305}
2306
2307function closeRreviewList() {
2308  var readMoreDataDom = $("[class^=readMoreDataType]");
2309  $(readMoreDataDom).not(".readMoreDataType").remove();
2310  var pathInfo = analyzeAccessSet(location.href).otherPathInfo;
2311  var shopCode = pathInfo[0];
2312  var commodityCode = pathInfo[1];
2313  var uri =
2314    "/catalog/review_list/search/" + shopCode + "/" + commodityCode + "/";
2315  var parameters = createBaseParametersForAjaxApi(
2316    "catalog",
2317    "review_list",
2318    "search"
2319  );
2320  $("#currentPage").val(0);
2321  parameters.currentPage = 0;
2322  parameters.pageSize = 3;
2323  parameters.shopCode = shopCode;
2324  parameters.commodityCode = commodityCode;
2325
2326  if ($.mobile) {
2327    parameters.clientType = "sp";
2328  }
2329
2330  var successFunction = function (data) {
2331    $("#reviewList").children("#reviewInfo").remove();
2332    reviewListCallBack(data);
2333  };
2334  var functions = createAjaxFunctions(null, null, successFunction);
2335
2336  var param = {
2337    parameters: parameters,
2338    functions: functions,
2339    uri: uri,
2340    dataType: "json",
2341    async: true,
2342  };
2343  sendAjaxToApi(param);
2344}
2345
2346var reviewListCallBack = function (data) {
2347  for (index in data.reviewList) {
2348    var reviewInfo = data.reviewList[index];
2349    var reviewInfoDom = $("#reviewList")
2350      .children("#reviewInfoTemplate")
2351      .clone();
2352    bindDataToDomDataAttribute(reviewInfoDom, reviewInfo);
2353    reviewInfoDom.removeClass("hidden");
2354    reviewInfoDom.attr("id", "reviewInfo");
2355    $("#reviewList").append(reviewInfoDom);
2356  }
2357
2358  if (Number($("#currentPage").val()) > 0) {
2359    $("#closeReadMore").removeClass("hidden");
2360  } else {
2361    $("#closeReadMore").addClass("hidden");
2362  }
2363
2364  $("#currentPage").val(Number($("#currentPage").val()) + 1);
2365  var pagerData = data.pager;
2366
2367  var readMoreDataType = $(".readMoreDataType");
2368  var dataTypeName = $(readMoreDataType).data("type");
2369  if (pagerData.currentPage && pagerData.currentPage != 1) {
2370    $("#readMoreLoading").remove();
2371  }
2372
2373  // タイトルエリアの処理
2374  var reviewListAreaDom = $("#reviewListArea");
2375  var titleDom = $(reviewListAreaDom).find(".titleArea");
2376
2377  if (data.reviewList.length == 0) {
2378    // 投稿なし
2379    titleDom.find(".hasReviewPost").remove();
2380    $(".reviewListBody").remove();
2381  } else {
2382    // 投稿ある
2383    $(".noReviewPost").remove();
2384  }
2385
2386  // おすすめ度の処理
2387  var reviewListDom = $(reviewListAreaDom).find(".reviewArea");
2388
2389  for (var i = 0; i < reviewListDom.length; i++) {
2390    var reviewPostDom = reviewListDom[i];
2391    var reviewScore = $(reviewPostDom).find(".reviewScore").val();
2392    if (!reviewScore) {
2393      continue;
2394    }
2395
2396    // イメージの処理
2397    var revieScoreImageDom = $(reviewPostDom)
2398      .find(".reviewScoreImageArea")
2399      .children();
2400    $(revieScoreImageDom)
2401      .not(".reviewScore" + reviewScore)
2402      .remove();
2403  }
2404
2405  // レビューローディングバーを削除
2406  $("#readMoreLoading").remove();
2407  $("#reviewListArea").show();
2408  // レビュータイトル件数更新
2409
2410  updateReviewPagerRowCountArea($('span[data-item="pagerRowCount"]'), data);
2411
2412  if (data.pager.rowCount > 3) {
2413    if (Number($("#currentPage").val()) == data.pager.maxPage) {
2414      $("#openReadMore").addClass("hidden");
2415    } else {
2416      $("#openReadMore").removeClass("hidden");
2417    }
2418  } else {
2419    $("#openReadMore").addClass("hidden");
2420  }
2421
2422  // レビューtoggle
2423  if ($(".textOverFlow").length > 0) {
2424    $(".textOverFlow").each(function () {
2425      var target = $(this);
2426      var noescapeTxt = target.text();
2427      var escapeFullTxt = target.html();
2428      var count = 75; // デフォルトで表示する文字数
2429
2430      // 短縮形式表示判定
2431      if (noescapeTxt.length > count) {
2432        var escapeSplitTxts = escapeFullTxt.split("<br>"); // 改行(<br>)毎の文字列を取得(サニタイジング済み)
2433        var sanitizedTxt = "";
2434
2435        $.each(escapeSplitTxts, function (index, escapeTxt) {
2436          var unescapeTxt = jQuery("<span/>").html(escapeTxt).text();
2437          count -= unescapeTxt.length;
2438          if (count < 0) {
2439            // 短縮形式加工(サニタイジング処理も)
2440            unescapeTxt =
2441              unescapeTxt.substr(0, unescapeTxt.length + count) + "…";
2442            sanitizedTxt += jQuery("<span/>").text(unescapeTxt).html() + "<br>";
2443            return false;
2444          } else {
2445            // サニタイジング処理
2446            sanitizedTxt += jQuery("<span/>").text(unescapeTxt).html() + "<br>";
2447          }
2448        });
2449        target.html(sanitizedTxt);
2450
2451        var moreLead = $(
2452          '<span class="moreLead"><img src="' +
2453            settings.context +
2454            '/files/commonfiles/images/icon_plus_b.gif" alt="すべて表示" /></span>'
2455        );
2456
2457        target.append(moreLead);
2458        moreLead.on("click", function () {
2459          target.html(escapeFullTxt);
2460          $(this).remove();
2461        });
2462      }
2463    });
2464  }
2465};
2466
2467/**
2468 * レビュータイトルの件数更新
2469 *
2470 * @param pagerRowCountDom
2471 *            更新対象
2472 * @param data
2473 *            データ
2474 */
2475function updateReviewPagerRowCountArea(pagerRowCountDom, data) {
2476  if (
2477    !pagerRowCountDom ||
2478    $(pagerRowCountDom).length == 0 ||
2479    !data ||
2480    data.pager == null
2481  ) {
2482    return;
2483  }
2484  var startSize = 1;
2485  var endSize = Number($("#currentPage").val()) * data.pager.pageSize;
2486  if (endSize > data.pager.rowCount) {
2487    endSize = data.pager.rowCount;
2488  }
2489  var pagerRowCountFmt =
2490    "<span class='pagerRowCount'>" + sanitizeSpecialChara(message.allPageCount);
2491  if (data.pager.rowCount > 0 && data.pager.rowCount > data.pager.pageSize) {
2492    pagerRowCountFmt += message.pageCountFromTo + "</span>";
2493  } else {
2494    pagerRowCountFmt =
2495      "<span>全</span>" + data.pager.rowCount + "<span>件</span>";
2496  }
2497  $(pagerRowCountDom).each(function () {
2498    $(this).html(
2499      pagerRowCountFmt.format(data.pager.rowCount, startSize, endSize)
2500    );
2501  });
2502}
2503
2504/**
2505 * レビュー投稿画面遷移
2506 */
2507function moveReviewPost() {
2508  var pathInfo = analyzeAccessSet(location.href).otherPathInfo;
2509  var shopCode = pathInfo[0];
2510  var commodityCode = pathInfo[1];
2511  var url = "/catalog/review/" + shopCode + "/" + commodityCode + "/";
2512
2513  window.location =
2514    settings.context + settings.servletMapping + url + "?init=true";
2515}
2516
2517function detailPreviewFromBackCallback() {
2518  removeAttribute($("a"), "href");
2519  removeAttribute($(":button"), "onclick");
2520
2521  $(function () {
2522    $(document).keydown(function (event) {
2523      // クリックされたキーコードを取得する
2524      var keyCode = event.keyCode;
2525
2526      // F5 の場合は falseをリターン
2527      if (keyCode === 116) {
2528        return false;
2529      }
2530
2531      // バックスペースキーを制御する
2532      if (keyCode === 8) {
2533        return false;
2534      }
2535    });
2536  });
2537}
2538
2539function removeAttribute($element, attribute) {
2540  if ($element[0]) {
2541    $element.removeAttr(attribute);
2542  }
2543}
2544
2545function showDetailImage() {
2546  var flipsnapArea = $(".flipsnap");
2547
2548  if (flipsnapArea.length > 0) {
2549    var imagePointer = $(".imagePointer img");
2550    var imageWidth = (imagePointer.length + 2) * 300;
2551    flipsnapArea.css("width", imageWidth);
2552    var flipsnap = Flipsnap(".flipsnap", {});
2553
2554    flipsnap.element.addEventListener(
2555      "fspointmove",
2556      function (ev) {
2557        imagePointer.filter(".currentImage").removeClass("currentImage");
2558        imagePointer.eq(flipsnap.currentPoint - 1).addClass("currentImage");
2559        if (!flipsnap.hasNext()) {
2560          flipsnap.moveToPoint(1);
2561        }
2562        if (!flipsnap.hasPrev()) {
2563          flipsnap.moveToPoint(imagePointer.length);
2564        }
2565      },
2566      false
2567    );
2568
2569    $(".imageLinkButton").click(function () {
2570      var imageIndex = $(imagePointer).index(this);
2571      flipsnap.moveToPoint(imageIndex + 1);
2572    });
2573    flipsnap.moveToPoint(1);
2574  }
2575}
2576
2577function setFocus(selector) {
2578  if ($(selector)[0]) {
2579    $(selector).focus();
2580  }
2581}
2582
2583function toggleDetailRegular(salesType) {
2584  // キャンペーン・VD
2585  var disMsg = $(".amiToggle");
2586  disMsg.toggleClass("discoColor");
2587  disMsg.toggleClass("discoColorDisable");
2588
2589  var addCartLabel = $(".addCartLabel");
2590  var incWorkArea = $(".incWorkArea");
2591  var radioArea = $(".regularCel");
2592  var cautionRegular = $(".cautionRegular");
2593  var regularRateMessage = $("#regularRateMessage");
2594
2595  radioArea.toggleClass("regularSelect");
2596
2597  if (salesType == "1") {
2598    addCartLabel.html("定期購入を申し込む");
2599    incWorkArea.addClass("hidden");
2600    cautionRegular.removeClass("hidden");
2601    regularRateMessage.removeClass("regularSaleNot");
2602    regularRateMessage.addClass("regularSale");
2603  } else {
2604    addCartLabel.text("カートに入れる");
2605    incWorkArea.removeClass("hidden");
2606    cautionRegular.addClass("hidden");
2607    regularRateMessage.removeClass("regularSale");
2608    regularRateMessage.addClass("regularSaleNot");
2609  }
2610}
2611
2612function arrivalGoodsInit(shopCode, commodityCode, skuCode) {
2613  var parameters = createBaseParametersForAjaxApi(
2614    "catalog",
2615    "arrival_goods",
2616    "init"
2617  );
2618  parameters.shopCode = shopCode;
2619  parameters.commodityCode = commodityCode;
2620  parameters.skuCode = skuCode;
2621  var successFunction = function (data) {
2622    $("#email").siValidation({});
2623    pcPopup("arrivalGoodsArea");
2624  };
2625  var functions = createAjaxFunctions(null, null, successFunction);
2626
2627  var param = {
2628    parameters: parameters,
2629    functions: functions,
2630    uri: "/catalog/arrival_goods/init/",
2631    dataType: "json",
2632    async: true,
2633  };
2634  sendAjaxToApi(param);
2635}
2636
2637/**
2638 * 商品詳細ズーム画像設定
2639 */
2640function setZoomImages() {
2641  var zoomEnabled;
2642  if (_ua.Tablet || _ua.Mobile) {
2643    zoomEnabled = false;
2644  } else {
2645    zoomEnabled = true;
2646  }
2647  $("#mainImage").elevateZoom({
2648    zoomEnabled: zoomEnabled,
2649    gallery: "relatedImageArea",
2650    cursor: "pointer",
2651    galleryActiveClass: "active",
2652    imageCrossfade: false,
2653    scrollZoom: true,
2654  });
2655}
2656
2657/**
2658 * 商品詳細拡大画像設定
2659 */
2660function setLightBoxImages() {
2661  if (_ua.Tablet || _ua.Mobile) {
2662    // SPの場合は画像のURLで閲覧
2663    var w = $("#mainImage").width();
2664    var h = $("#mainImage").height();
2665    var link = $("<div id='spImageLink'></div>").width(w).height(h);
2666    $("#mainImage").before(link);
2667    $("#spImageLink").on("click", function (e) {
2668      var url = $("#mainImage").attr("src");
2669      window.open(url, null, "resizable=1");
2670    });
2671  } else {
2672    // PCの場合はファンシーboxで画像を表示
2673    $("#mainImage").click(function (e) {
2674      var ez = $("#mainImage").data("elevateZoom");
2675      $.fancybox(ez.getGalleryList());
2676      return false;
2677    });
2678  }
2679}
2680
2681/**
2682 * メールアドレスのバリデーション処理
2683 */
2684function validateEmail() {
2685  if ($(".validate-mail").length) {
2686    var input = $(".validate-mail");
2687    if (
2688      input[0].value.match(
2689        /^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/
2690      )
2691    ) {
2692      $(this).css("background-color", "#fff");
2693      $(this).prev().text("");
2694    }
2695  }
2696}
2697
2698/**
2699 * テキストエリアのバリデーション処理
2700 */
2701function validateInputArea(id) {
2702  var val = false;
2703  $("#" + id)
2704    .find("input")
2705    .each(function (index, element) {
2706      var $thisObj = $(this);
2707      var type = $thisObj.attr("type");
2708      if (type != "text" && type != "tel") {
2709        return true;
2710      }
2711      if ($thisObj.val().match(/[^\s ]/)) {
2712        $thisObj.css("background-color", "#fff");
2713        $thisObj.prev("span").text("");
2714      } else {
2715        val = true;
2716      }
2717    });
2718  if (!val) {
2719    $("#" + id)
2720      .find("span[class='red']")
2721      .text("");
2722  }
2723}
2724
2725/**
2726 * セレクトボックスのバリデーション処理
2727 */
2728function validateSelectBoxArea(id) {
2729  var input = $("#" + id).find("select");
2730  var val = $("#" + input.id).value;
2731  if (
2732    $("#" + input.id).prop("selectedIndex") != 0 ||
2733    $("#" + input.id).value != undefined
2734  ) {
2735    $("#" + input.id).css("background-color", "#fff");
2736    $("#" + id)
2737      .find("span[class='red']")
2738      .text("");
2739  }
2740}
2741
2742/**
2743 * セレクトボックス(複数)のバリデーション処理
2744 */
2745function validateMultiSelectBoxArea(id) {
2746  var val = false;
2747  $("#" + id)
2748    .find("select")
2749    .each(function (index, element) {
2750      if (
2751        $(this)
2752          .val()
2753          .match(/[^\s ]/)
2754      ) {
2755        $(this).css("background-color", "#fff");
2756        $(this).prev("span").text("");
2757      } else {
2758        val = true;
2759      }
2760    });
2761  if (!val) {
2762    $("#" + id)
2763      .find("span[class='red']")
2764      .text("");
2765  }
2766}
2767
2768function updateViewHistory(codeList, brand) {
2769  var ctorahis = getCookie("ctorahis");
2770  ctorahis = decodeURI(ctorahis);
2771  var newCookies = [];
2772  if (ctorahis) {
2773    var ctorahisList = ctorahis.split("|");
2774    for (var i = ctorahisList.length; i > 0; i--) {
2775      var val = ctorahisList[i - 1].split("<>");
2776      if (val.length == 2) {
2777        if (codeList.indexOf(val[0]) == -1) {
2778          var cookie = {};
2779          cookie.id = val[0];
2780          cookie.brand = val[1];
2781          newCookies.push(cookie);
2782        }
2783      }
2784    }
2785  }
2786  if (codeList && codeList.length > 0 && brand) {
2787    for (var i = 0; i < codeList.length; i++) {
2788      var cookie = {};
2789      cookie.id = codeList[i];
2790      cookie.brand = brand;
2791      newCookies.push(cookie);
2792      if (newCookies.length > 30) {
2793        newCookies.splice(0, 1);
2794      }
2795    }
2796  }
2797  var setCookies = "";
2798  for (var i = 0; i < newCookies.length; i++) {
2799    setCookies =
2800      newCookies[i].id + "<>" + newCookies[i].brand + "|" + setCookies;
2801  }
2802  setCookies = setCookies.substr(0, setCookies.lastIndexOf("|"));
2803  setCookies = encodeURI(setCookies);
2804  var expires = new Date();
2805  expires.setDate(expires.getDate() + 7);
2806  document.cookie = [
2807    "ctorahis=" + setCookies,
2808    "Path=/",
2809    "Expires=" + expires,
2810    "Secure",
2811    "samesite=Lax",
2812  ].join(";");
2813}
2814
2815function sendAdultCheckRequest(domain, value) {
2816  if (domain && value) {
2817    if (/1|0|-/.exec(value)) {
2818      $.ajax({
2819        url: [
2820          "https://",
2821          domain,
2822          settings.context,
2823          settings.apiServ,
2824          "/common/adult_check/done/",
2825          value + "/",
2826        ].join(""),
2827        dataType: "jsonp",
2828        async: false,
2829        success: function () {},
2830        error: function () {},
2831      });
2832      return true;
2833    }
2834  }
2835  return false;
2836}
2837
2838function sanitizeSpecialChara(str) {
2839  if (typeof str !== "string") {
2840    return str;
2841  }
2842  if (str === "" || str === null || str === undefined) {
2843    return str;
2844  }
2845  //? OWASPのチートシートと同じエスケープ処理になっていることを確認済み https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
2846  str = str.replace(/&/g, "&amp;");
2847  str = str.replace(/</g, "&lt;");
2848  str = str.replace(/>/g, "&gt;");
2849  str = str.replace(/"/g, "&quot;");
2850  str = str.replace(/'/g, "&#39;");
2851  return str;
2852}
2853
2854function sanitizeHtml(html) {
2855  if (typeof html !== "string") {
2856    return html;
2857  }
2858  if (html === "" || html === null || html === undefined) {
2859    return html;
2860  }
2861  return DOMPurify.sanitize(html);
2862}
2863
2864function cookieAgreementPopUp() {
2865  const ua = window.navigator.userAgent.toLowerCase();
2866  const isBot = ua.indexOf("googlebot") > -1;
2867  const userLanguage = (
2868    window.navigator.userLanguage ||
2869    window.navigator.language ||
2870    window.navigator.browserLanguage
2871  ).substr(0, 2);
2872  if (userLanguage !== "ja" && !isBot) {
2873    if (
2874      document.cookie.indexOf("cookie-popup-close=true") === -1 &&
2875      document.cookie.indexOf("cookie-popup-agreement=true") === -1
2876    ) {
2877      $(".js-cookie-popup").show();
2878
2879      $(".js-cookie-popup-close-btn").on("click", function () {
2880        document.cookie =
2881          "cookie-popup-agreement=true; path=/; domain=toranoana.jp; secure; samesite=Lax;";
2882        $(".js-cookie-popup").fadeOut();
2883      });
2884      $(".js-cookie-popup-agreement-btn").on("click", function () {
2885        document.cookie =
2886          "cookie-popup-agreement=true; path=/; max-age=31536000; domain=toranoana.jp; secure; samesite=Lax;";
2887        $(".js-cookie-popup").fadeOut();
2888      });
2889    }
2890  }
2891}
2892
2893/**
2894 * 要素のIDを指定して値を取得する。存在しないIDが指定された場合は空文字を返す
2895 * @param {string} elementId
2896 * @returns 要素のIDをもとに取得した値。IDが存在しない場合空文字。
2897 */
2898function getElementValById(elementId) {
2899  const element = document.getElementById(elementId);
2900  let val = "";
2901  if (typeof element !== "undefined" && element !== null) {
2902    val = element.value;
2903  }
2904  return val;
2905}
2906
2907/**
2908 * 入力された郵便番号、都道府県、市区町村、町名を利用してチェックを行う
2909 * このチェックの後で必須チェックが行われている前提の処理となっている
2910 * @param {string} postalCodeId 郵便番号のID
2911 * @param {string} prefectureCodeId 都道府県のID
2912 * @param {string} cityId 市区町村のID
2913 * @param {string} addressId 町名のID
2914 * @returns 郵便番号、都道府県、市区町村、町名のいずれかが未入力、もしくはエラーチェックで問題ない場合、もしくはエラーがあってもOKが押下された場合true
2915 */
2916function getParametersForAddressEdit(
2917  postalCodeId = "postalCode",
2918  prefectureCodeId = "prefectureCode",
2919  cityId = "address2",
2920  addressId = "address3"
2921) {
2922  const parameters = createBaseParametersForAjaxApi(
2923    "customer",
2924    "address",
2925    "check"
2926  );
2927  const postalCode = getElementValById(postalCodeId);
2928  const prefectureCode = getElementValById(prefectureCodeId);
2929  const city = getElementValById(cityId);
2930  const address = getElementValById(addressId);
2931
2932  //この4つはいずれも必須項目のため、住所チェックはこれら4つが入力されている場合のã
2932¿å®Ÿæ–½ã™ã‚‹
2933  //いずれかが設定されていない場合はここでreturnして、住所チェックはスルーする
2934  if (
2935    postalCode === "" ||
2936    prefectureCode === "" ||
2937    city === "" ||
2938    address === ""
2939  ) {
2940    return parameters;
2941  }
2942  const CHECK_TYPE_INPUT_ADDRESS = "0";
2943  parameters.checkType = CHECK_TYPE_INPUT_ADDRESS;
2944  parameters.postalCode = postalCode;
2945  parameters.prefectureCode = prefectureCode;
2946  parameters.city = city;
2947  parameters.address = address;
2948  return parameters;
2949}
2950
2951/**
2952 * 住所チェックを行うAPIへ渡すパラメーターを設定する
2953 * @param {Object} parameters
2954 * @param {function} functions
2955 * @returns 住所チェックを行う際の共通パラーメーター
2956 */
2957function getAddressCheckApiParam(parameters, functions) {
2958  const param = {
2959    parameters: parameters,
2960    functions: functions,
2961    uri: "/common/topic_path/move/",
2962    dataType: "json",
2963    async: true,
2964  };
2965  return param;
2966}
2967
2968/**
2969 * このメソッドは、住所チェックの結果によって、アラートを表示するかどうかを判断するためのもので、
2970 * returnは常にtrueを返す。
2971 * @param {string} addressCheckMessage
2972 * @returns 常にtrue
2973 */
2974function isAddressConfirmed(addressCheckMessage) {
2975  let isValid = true;
2976  if (typeof addressCheckMessage === "undefined") {
2977    return isValid;
2978  }
2979  if (addressCheckMessage !== "") {
2980    alert(addressCheckMessage);
2981  }
2982  return isValid;
2983}
2984
2985/**
2986 * dataLayer設定(再販希望押下時)
2987 */
2988function wishToRestockDataLayer(
2989  commodityCode,
2990  brandCode,
2991  commodityName,
2992  commodityGenre,
2993  coupling,
2994  commodityKindName,
2995  clickPartsName
2996) {
2997  // dataLayer の初期化処理
2998  window.dataLayer = window.dataLayer || [];
2999  dataLayer.push({
3000    event: "wish_to_restock",
3001    add_item_id: commodityCode,
3002    add_item_name: commodityName,
3003    add_item_brand: brandCode,
3004    add_item_category1: commodityKindName,
3005    add_item_category2: commodityGenre,
3006    add_item_category3: coupling,
3007    click_to_parts: clickPartsName,
3008  });
3009}

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.