index.js 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872
  1. let userAgent;
  2. let isSafari = false;
  3. let browserName;
  4. // pagination variables
  5. let num_per_page = 9;
  6. let n = 0;
  7. let totalPages = {
  8. intro: 0,
  9. video: 0,
  10. columns: 0,
  11. vr360: 0,
  12. company: 0,
  13. };
  14. window.onload = function () {
  15. // hhh_user_api();
  16. if (screen.width < 991) {
  17. window.location.href = `https://m.hhh.com.tw/`;
  18. }
  19. userAgent = navigator.userAgent;
  20. detectBrowser(userAgent);
  21. // detectDirection();
  22. // let result;
  23. // $.ajax({
  24. // method: "GET",
  25. // url: "./hhh_index/json/realtime.json",
  26. // dataType: "json",
  27. // }).done(function (msg) {
  28. // result = [...msg];
  29. // console.log('result', result);
  30. // renderTopCarousel(result);
  31. // // renderBanner(result);
  32. // });
  33. // $('#navbar').load('https://hhh.com.tw/hhh-test/template/navbar.html');
  34. // $('#footer').load('https://hhh.com.tw/hhh-test/template/footer.html');
  35. // $('#btn-box').load('https://hhh.com.tw/hhh-test/template/button.html');
  36. // $('#topCarousel').load('https://hhh.com.tw/hhh-test/template/top_carousel.html');
  37. };
  38. function hhh_user_api_login() {
  39. window.location.href = `https://hhh.com.tw/users`;
  40. }
  41. let user_data = [];
  42. function hhh_user_api() {
  43. $.ajax({
  44. method: "post",
  45. url: "https://hhh.com.tw/adapter/index?http_method=GET&api_url=/base/v1/member/index",
  46. // async: false,
  47. dataType: "json",
  48. }).done(function (msg) {
  49. user_data = msg;
  50. let app_user = "";
  51. console.log('hhh_user_msg', msg);
  52. if (msg.status == "Success") {
  53. app_user += `
  54. <div class="dropdown">
  55. <button class="btn dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false" onclick="hhh_user_api_login()">
  56. <div class="d-flex align-items-center">
  57. <img src="${msg.data["user_avatar"]}" alt="" style="height: 32px; width: 32px;border-radius: 100px;">
  58. <p class="ms-2">${msg.data["name"]}</p>
  59. </div>
  60. </button>
  61. <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
  62. <li><a class="dropdown-item" href="https://hhh.com.tw/users">會員專區</a></li>
  63. </ul>
  64. </div>`;
  65. } else {
  66. app_user += `
  67. <a class="nav-link" href="javascript:;" onclick="hhh_user_api_login()">
  68. <section class="d-flex align-items-center">
  69. <img src="./img/icon/material-people.svg" alt="login" class="me-2" style="padding-top: 2px;" />
  70. <span class="pt-1">登入</span>
  71. </section>
  72. </a>`;
  73. }
  74. $("#app_user").html(app_user);
  75. }).fail(function (err) {
  76. console.log('err', err);
  77. });
  78. }
  79. hhh_user_api();
  80. // function detectDirection() {
  81. // let height = (window.screen.width * 5) / 12;
  82. // $(".sec-02 .slide-item").css("height", `${height}px`);
  83. // }
  84. function detectBrowser(agent) {
  85. if (userAgent.match(/chrome|chromium|crios/i)) {
  86. browserName = "chrome";
  87. } else if (userAgent.match(/firefox|fxios/i)) {
  88. browserName = "firefox";
  89. } else if (userAgent.match(/safari/i)) {
  90. browserName = "safari";
  91. } else if (userAgent.match(/opr\//i)) {
  92. browserName = "opera";
  93. } else if (userAgent.match(/edg/i)) {
  94. browserName = "edge";
  95. } else {
  96. browserName = "No browser detection";
  97. }
  98. if (browserName === "safari") {
  99. isSafari = true;
  100. }
  101. }
  102. // 範圍內取隨機整數(0-8)
  103. function getRandomInt(max) {
  104. return Math.floor(Math.random() * max);
  105. }
  106. function renderBanner(data) {
  107. let temp = data[1]["data"];
  108. // renderBullet(temp);
  109. // renderBannerStr("banner-slider", temp);
  110. let str = "";
  111. let img = "";
  112. if (window.innerWidth < 767) {
  113. // 手機版
  114. img = "imgUrl";
  115. } else {
  116. // 電腦版
  117. img = "Dwebp";
  118. }
  119. let adNamesMain = [];
  120. for (let i = 0; i < temp.length; i++) {
  121. let adNameMain = `${temp[i]["id"]}${temp[i]["alt"]}`;
  122. adNamesMain.push(adNameMain);
  123. str += `
  124. <a href="${temp[i]["link"]}" target="_blank" data-ga4="${temp[i]["id"]}${temp[i]["alt"]}">
  125. <section class="info-item">
  126. <span class="logo-img">
  127. <img class="img-${temp[i].logo_icon} ${temp[i].logo_icon === "" ? "d-none" : ""}" src="./img/index/banner_logo/${temp[i].logo_icon}.png">
  128. </span>
  129. <section class="${temp[i].index_char_1 === "" || temp[i].index_char_2_1 === "" || temp[i].index_char_2_2 === "" ? "d-none" : ""}">
  130. <h3>${temp[i].index_char_1}</h3>
  131. <div>
  132. <h2>${temp[i].index_char_2_1}</h2>
  133. <h2>
  134. ${temp[i].index_char_2_2}
  135. <small>${temp[i].index_char_2_3}</small>
  136. </h2>
  137. </div>
  138. </section>
  139. </section>
  140. <img class="banner-slider-${i + 1} slide-item img-fluid" src="${temp[i][`${img}`]}" data-bg="${temp[i][`${img}`]}" alt="${temp[i]["alt"]}" data_id="${temp[i]["id"]}${temp[i]["alt"]}">
  141. </a>`;
  142. }
  143. $(`.banner-slider`).html(str);
  144. //ga4-banners
  145. adNamesMain.forEach((adNameMain) => {
  146. document.querySelectorAll(`a[data-ga4="${adNameMain}"]`).forEach((element) => {
  147. element.addEventListener('click', function () {
  148. dataLayer.push({
  149. 'event': 'Banner_Click',
  150. 'ad_name': adNameMain,
  151. 'ad_location': '首頁大Banner'
  152. });
  153. });
  154. });
  155. });
  156. let randomInt = getRandomInt(8);
  157. let list_Top_Banner;
  158. let ad_first;
  159. //首頁大Banner ga4(一開始近來先送)剩下輪播送
  160. list_Top_Banner = document.querySelectorAll('.banner-slider .slide-item');
  161. //console.log('list_TOP:',list_Top_Banner[randomInt].getAttribute('data_id'))
  162. try {
  163. ad_first = list_Top_Banner[randomInt].getAttribute('data_id');
  164. } catch (e) {
  165. ad_first = '加載問題,所以請無視';
  166. console.log(ad_first);
  167. }
  168. dataLayer.push({
  169. 'event': 'Banner_Impression',
  170. 'ad_name': ad_first,
  171. 'ad_location': '首頁大Banner'
  172. });
  173. // 輪播設定
  174. $('.banner-slider').slick({
  175. dots: true,
  176. infinite: true,
  177. speed: 300,
  178. arrows: true,
  179. autoplay: true,
  180. autoplaySpeed: 4000,
  181. slidesToShow: 1,
  182. slidesToScroll: 1,
  183. centerMode: true,
  184. variableWidth: true,
  185. initialSlide: randomInt, // 起始順序
  186. prevArrow:
  187. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="color: white;transform: translateY(-10px);"></i></button>',
  188. nextArrow:
  189. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="color: white;transform: translateY(-10px);"></i></button>',
  190. responsive: [
  191. {
  192. breakpoint: 575,
  193. settings: {
  194. dots: false,
  195. arrows: false,
  196. }
  197. }
  198. ]
  199. });
  200. // 初始輪播外層新增 className
  201. try {
  202. list_Top_Banner[randomInt].parentNode.classList.add("slick-now");
  203. } catch (e) {
  204. console.log(e);
  205. }
  206. // On before slide change
  207. $('.banner-slider').on('beforeChange', function (event, { slideCount: count }, currentSlide, nextSlide) {
  208. let selectors = [nextSlide, nextSlide - count, nextSlide + count].map(n => `[data-slick-index="${n}"]`).join(', ');
  209. $('.slick-now').removeClass('slick-now');
  210. $(selectors).addClass('slick-now');
  211. });
  212. $('[data-slick-index="0"]').addClass('slick-now');
  213. }
  214. function renderBannerStr(sec, data) {
  215. let adNamesTop = [];
  216. let str = "";
  217. for (let i = 0; i < data.length; i++) {
  218. let adNameTop = `${data[i]["id"]}${data[i]["alt"]}`;
  219. adNamesTop.push(adNameTop);
  220. if (data[i]["Dwebp"]) {
  221. str += `
  222. <a href="${data[i]["link"]}" data-ga4="${data[i]["id"]}${data[i]["alt"]}">
  223. <img class="${sec}-${i + 1} slide-item img-fluid" src="${data[i]["Dwebp"]}" data-bg="${data[i]["Dwebp"]}" alt="${data[i]["alt"]}" data_id="${data[i]["id"]}${data[i]["alt"]}">
  224. </a>`;
  225. } else {
  226. str += `
  227. <a href="${data[i]["link"]}" data-ga4="${data[i]["id"]}${data[i]["alt"]}">
  228. <img class="${sec}-${i + 1} slide-item img-fluid" src="${data[i]["DimgUrl"]}" data-bg="${data[i]["DimgUrl"]}" alt="${data[i]["alt"]}" data_id="${data[i]["id"]}${data[i]["alt"]}">
  229. </a>`;
  230. }
  231. }
  232. $(`.${sec}`).html(str);
  233. //ga4-banners
  234. adNamesTop.forEach((adNameTop) => {
  235. document.querySelectorAll(`a[data-ga4="${adNameTop}"]`).forEach((element) => {
  236. element.addEventListener('click', function () {
  237. dataLayer.push({
  238. 'event': 'Banner_Click',
  239. 'ad_name': adNameTop,
  240. 'ad_location': '新刊頭'
  241. });
  242. });
  243. });
  244. });
  245. }
  246. $(window)
  247. .scroll(function () {
  248. if ($(this).scrollTop() > 800) {
  249. $(".fixed-btn").fadeIn(222);
  250. } else {
  251. $(".fixed-btn").stop().fadeOut(222);
  252. }
  253. })
  254. .scroll();
  255. $("#top-btn").click(function () {
  256. $("html, body").animate(
  257. {
  258. scrollTop: 0,
  259. },
  260. 500
  261. );
  262. });
  263. $(".slider-close-btn").click(function () {
  264. $(this).css("display", "none");
  265. sticky = 0;
  266. });
  267. document.addEventListener("lazybeforeunveil", function (e) {
  268. var bg = e.target.getAttribute("data-bg");
  269. if (bg) {
  270. e.target.style.backgroundImage = "url(" + bg + ")";
  271. }
  272. });
  273. function addToFavorite(cid) {
  274. if (user_data.data["uid"] == undefined) {
  275. Swal.fire({
  276. title: "請先登入",
  277. showConfirmButton: false,
  278. });
  279. $.ajax({
  280. url: "https://hhh.com.tw/hhhajax/save_http_referer",
  281. type: "post",
  282. datatype: "json",
  283. data: { http_referer: location.href },
  284. success: function () {
  285. location.href = "/login/index";
  286. },
  287. });
  288. }
  289. $.ajax({
  290. url: `https://hhh.com.tw/favorite/set?type=column&id=${cid}`,
  291. }).done(function (data) {
  292. if (data == 1) {
  293. $(".like").css("display", "block");
  294. $(".like-o").css("display", "none");
  295. } else {
  296. $(".like").css("display", "none");
  297. $(".like-o").css("display", "block");
  298. }
  299. });
  300. }
  301. function putEmail() {
  302. const emailPattern =
  303. /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  304. if ($("#email").val() !== null && emailPattern.test($("#email").val())) {
  305. $("#error").hide();
  306. $("#putEmail_hidden").css("display", "block");
  307. $("#add_email").text($("#email").val());
  308. $("#email").val("");
  309. } else {
  310. $("#error").show();
  311. $("#error").text("email 格式有誤");
  312. }
  313. }
  314. $(".fm-close").click(() => {
  315. $("#putEmail_hidden").css("display", "none");
  316. $("#add_email").text("");
  317. });
  318. $("#putEmail").click(function (event) {
  319. $("#putEmail_hidden").show();
  320. const vm = $("#email").val();
  321. const emailPattern =
  322. /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  323. if (vm.length == 0) {
  324. $("#error").show();
  325. $("#error").text("請輸入Email");
  326. $("#email").addClass("border-revise");
  327. $("#button-fm").addClass("fm-btn-border");
  328. $("#email").focus();
  329. return false;
  330. } else if (!emailPattern.test(vm)) {
  331. $("#error").show();
  332. $("#error").text("email 格式有誤");
  333. $("#email").addClass("border-revise");
  334. $("#button-fm").addClass("fm-btn-border");
  335. $("#email").focus();
  336. return false;
  337. // } else if (vm.length >= 5) {
  338. // $('#error').show();
  339. // $('#error').text('最多一次轉寄 5 封');
  340. // $('#email').addClass('border-revise');
  341. // $('#button-fm').addClass('fm-btn-border');
  342. //
  343. // $('#email').focus();
  344. // return false;
  345. } else {
  346. $("#email").removeClass("border-revise");
  347. $("#button-fm").removeClass("fm-btn-border");
  348. $("#error").hide();
  349. $("#add_email").text($("#email").val());
  350. $("#email").val("");
  351. }
  352. });
  353. $("#doSend").click(function (event) {
  354. stop = 0;
  355. var emailPattern =
  356. /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  357. let this_url = window.location.href;
  358. // 如果 uid 為空代表沒登入(由於此寄信功能需要 uid 故需要先登入)
  359. if (user_data.data["uid"] == undefined) {
  360. $("#error").text("請先登錄/註冊會員帳號");
  361. stop = 1;
  362. } else if ($("#email").val() == "") {
  363. $("#error").text("收件人不得為空");
  364. stop = 1;
  365. } else {
  366. if (!emailPattern.test($("#email").val())) {
  367. $("#error").text("請以 email 格式填寫");
  368. stop = 1;
  369. }
  370. }
  371. if (stop == 0) {
  372. $("#error").text();
  373. $.ajax({
  374. url: "https://hhh.com.tw/adapter/index?http_method=POST&api_url=/base/v1/member/forward",
  375. type: "post",
  376. datatype: "json",
  377. data: {
  378. data: JSON.stringify({
  379. uid: user_data.data["uid"],
  380. sender: user_data.data["email"],
  381. recipient: $("#email").val(),
  382. url: this_url,
  383. subject: $("#title").val(),
  384. content: $("#content").val(),
  385. }),
  386. },
  387. success: function (result) {
  388. $("#forward_modal").modal("hide");
  389. Swal.fire({
  390. title: "發送成功",
  391. showConfirmButton: false,
  392. });
  393. $("#emailModal").modal("hide");
  394. },
  395. });
  396. }
  397. });
  398. /* 手機版輪播進度條 */
  399. //ga4-頂部廣告banner參數
  400. let adTop_count = []
  401. let time_top_count = 0
  402. $('.banner-slider').on('beforeChange', function (event, slick, currentSlide, nextSlide) { // 頂部輪播(首頁大Banner)
  403. let list = document.querySelectorAll('.banner-slider .slide-item');
  404. //console.log(list[nextSlide+2].getAttribute('data_id'))
  405. let ad1 = list[nextSlide + 2].getAttribute('data_id');
  406. //由於剛進來就會送首頁大Banner的ga4,所以之後輪播時就不再送出
  407. if (time_top_count == 0) {
  408. let ad2 = list[nextSlide + 1].getAttribute('data_id');
  409. adTop_count.push(ad2);
  410. time_top_count = 1
  411. }
  412. //送dataLayer(要看得到廣告才送(電腦手機板不一樣))
  413. if ($('.banner-slider .slide-item').offset().top - $(window).scrollTop() > -330) {
  414. if (!adTop_count.includes(ad1)) {
  415. dataLayer.push({
  416. 'event': 'Banner_Impression',
  417. 'ad_name': ad1,
  418. 'ad_location': '首頁大Banner'
  419. });
  420. adTop_count.push(ad1);
  421. }
  422. }
  423. // 以下才是輪播
  424. let calc = ((nextSlide) / (slick.slideCount - 1)) * 100;
  425. $('.banner-content .progress')
  426. .css('background-size', calc + '% 100%')
  427. .attr('aria-valuenow', calc);
  428. });
  429. //ga4-中間廣告banner參數
  430. let ad_count = []
  431. $('.sub-banner-slider').on('beforeChange', function (event, slick, currentSlide, nextSlide) { // 廣告區塊
  432. //ga4-送參數(電腦手機不一樣)
  433. let list = document.querySelectorAll('.sub-banner-slider .slide-item');
  434. let max_v = (list.length - 2) / 2
  435. let ad1 = list[currentSlide > 0 ? currentSlide - 1 : max_v - 1].getAttribute('data_id')
  436. let ad2 = list[currentSlide].getAttribute('data_id')
  437. //console.log(currentSlide-1,currentSlide)
  438. //console.log(ad1,ad2)
  439. //廣告位置(電腦手機不一樣)
  440. if ($('.container-fluid.py-4.sub-banner-content').offset().top - $(window).scrollTop() < 800 && $('.container-fluid.py-4.sub-banner-content').offset().top - $(window).scrollTop() > -154) {
  441. //送dataLayer
  442. if (!ad_count.includes(ad1)) {
  443. dataLayer.push({
  444. 'event': 'Banner_Impression',
  445. 'ad_name': ad1,
  446. 'ad_location': '首頁列表'
  447. });
  448. ad_count.push(ad1);
  449. }
  450. if (!ad_count.includes(ad2)) {
  451. dataLayer.push({
  452. 'event': 'Banner_Impression',
  453. 'ad_name': ad2,
  454. 'ad_location': '首頁列表'
  455. });
  456. ad_count.push(ad2);
  457. }
  458. }
  459. // 以下才是輪播
  460. let calc = ((nextSlide) / (slick.slideCount - 1)) * 100;
  461. $('.sub-banner-content .progress')
  462. .css('background-size', calc + '% 100%')
  463. .attr('aria-valuenow', calc);
  464. });
  465. let optionsSliderList = document.querySelectorAll('.options-slider'); // 廣告上方列表
  466. for (let i = 0; i < optionsSliderList.length; i++) {
  467. let count;
  468. let element;
  469. const progressBar = $(`.progress.item-0${i}`);
  470. const progressBarLabel = $('.slider-label');
  471. if (i === 0) {
  472. count = 2;
  473. element = $(`.space-slider.slider-0${i}`);
  474. } else {
  475. window.innerWidth < 415 ? count = 2 : count = 3;
  476. element = $(`.options-slider.slider-0${i}`);
  477. }
  478. element.on('beforeChange', function (event, slick, currentSlide, nextSlide) {
  479. let calc = ((nextSlide) / (slick.slideCount - count)) * 100;
  480. progressBar
  481. .css('background-size', calc + '% 100%')
  482. .attr('aria-valuenow', calc);
  483. progressBarLabel.text(calc + '% completed');
  484. });
  485. }
  486. let mainSliderList = document.querySelectorAll('.main-content .slider'); // 廣告下方列表
  487. let count;
  488. window.innerWidth < 415 ? count = 1 : count = 2;
  489. for (let i = 0; i < mainSliderList.length; i++) {
  490. let element = $(`.main-content .slider.item-0${i}`);
  491. const progressBar = $(`.main-content .progress.item-0${i}`);
  492. const progressBarLabel = $('.main-content .slider-label');
  493. element.on('beforeChange', function (event, slick, currentSlide, nextSlide) {
  494. let calc = ((nextSlide) / (slick.slideCount - count)) * 100;
  495. progressBar
  496. .css('background-size', calc + '% 100%')
  497. .attr('aria-valuenow', calc);
  498. progressBarLabel.text(calc + '% completed');
  499. });
  500. }
  501. /* 2024/02/21關閉 */
  502. // 廣告彈跳視窗 Modal
  503. /*
  504. (function createModal() {
  505. const newDiv = document.createElement("div");
  506. let str = `
  507. <div class="modal fade" id="adModal" tabindex="-1" aria-labelledby="adModalLabel" aria-hidden="true">
  508. <div class="modal-dialog modal-dialog-centered" style="max-width: 900px;">
  509. <div class="modal-content">
  510. <div class="modal-header">
  511. <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
  512. </div>
  513. <div class="modal-body p-0">
  514. <a href="https://hhh.style/hh12fMF7i" target="_blank">
  515. <img src="./img/20240207year.jpg" alt="" class="img-fluid">
  516. </a>
  517. </div>
  518. </div>
  519. </div>
  520. </div>`;
  521. newDiv.innerHTML = str;
  522. document.body.appendChild(newDiv);
  523. })();
  524. */
  525. /* 判斷閒置 */
  526. let defaultNum = 60; // 60 秒
  527. let maxTime = defaultNum;
  528. let intervalId;
  529. let time = maxTime;
  530. $('body').on('keydown mousemove mousedown', function (e) {
  531. maxTime = defaultNum; // Seconds
  532. time = maxTime; // Reset
  533. });
  534. runSetInterval();
  535. function runSetInterval() {
  536. intervalId = setInterval(function () {
  537. time--;
  538. if (time <= 0) {
  539. ShowInvalidLoginMessage();
  540. clearInterval(intervalId);
  541. }
  542. }, 1000)
  543. }
  544. $('#adModal').on('hide.bs.modal', function () {
  545. dialogTimeclose();
  546. runSetInterval();
  547. $('body').addClass('scrollable');
  548. });
  549. function dialogTimeclose() {
  550. time = maxTime;
  551. }
  552. function ShowInvalidLoginMessage() {
  553. $('#adModal').modal('show');
  554. }
  555. /* genjson_new 新版首頁 */
  556. let result;
  557. $.ajax({
  558. method: "get",
  559. url: "./json/data_index.json",
  560. // url: "https://m3.hhh.com.tw:18689/genjson_new?filename=realtime.json",
  561. dataType: "json",
  562. }).done((data) => {
  563. result = [...data];
  564. // 隱藏 loading
  565. $('body').removeClass('unscrollable');
  566. $('.loading-item').addClass('loading-hide');
  567. let ad = localStorage.getItem('ad');
  568. if (!ad) {
  569. localStorage.setItem('ad', true);
  570. $('#adModal').modal('show');
  571. } else {
  572. $('#adModal').modal('hide');
  573. $('body').addClass('scrollable');
  574. }
  575. // renderTopCarousel(result);
  576. renderBanner(result);
  577. renderData(result); // 廣告上方列表
  578. renderEventAd(result); // 廣告輪播
  579. renderTopic(); // 主題企劃
  580. renderDesigner(result); // 推薦設計師
  581. renderTabContent(result); // 最夯設計, 影音實錄, 專欄文章
  582. //ga4_Click
  583. document.querySelectorAll('a[data-ga4="By_Style"]').forEach(function (element) {
  584. element.addEventListener('click', function () {
  585. dataLayer.push({
  586. 'event': 'Inner_Click',
  587. 'section_name': '依照風格瀏覽設計'
  588. });
  589. });
  590. });
  591. document.querySelectorAll('a[data-ga4="By_Space"]').forEach(function (element) {
  592. element.addEventListener('click', function () {
  593. dataLayer.push({
  594. 'event': 'Inner_Click',
  595. 'section_name': '依照空間瀏覽設計'
  596. });
  597. });
  598. });
  599. document.querySelectorAll('a[data-ga4="By_Specialty"]').forEach(function (element) {
  600. element.addEventListener('click', function () {
  601. dataLayer.push({
  602. 'event': 'Inner_Click',
  603. 'section_name': '依照專長尋找專家'
  604. });
  605. });
  606. });
  607. document.querySelectorAll('a[data-ga4="By_Topic"]').forEach(function (element) {
  608. element.addEventListener('click', function () {
  609. dataLayer.push({
  610. 'event': 'Inner_Click',
  611. 'section_name': '主題企劃'
  612. });
  613. });
  614. });
  615. document.querySelectorAll('a[data-ga4="By_Designer"]').forEach(function (element) {
  616. element.addEventListener('click', function () {
  617. dataLayer.push({
  618. 'event': 'Inner_Click',
  619. 'section_name': '本週推薦設計師'
  620. });
  621. });
  622. });
  623. document.querySelectorAll('a[data-ga4="By_Editor"]').forEach(function (element) {
  624. element.addEventListener('click', function () {
  625. dataLayer.push({
  626. 'event': 'Inner_Click',
  627. 'section_name': '編輯精選'
  628. });
  629. });
  630. });
  631. document.querySelectorAll('a[data-ga4="Best_Design"]').forEach(function (element) {
  632. element.addEventListener('click', function () {
  633. dataLayer.push({
  634. 'event': 'Inner_Click',
  635. 'section_name': '最夯設計'
  636. });
  637. });
  638. });
  639. document.querySelectorAll('a[data-ga4="Latest_Video"]').forEach(function (element) {
  640. element.addEventListener('click', function () {
  641. dataLayer.push({
  642. 'event': 'Inner_Click',
  643. 'section_name': '最新影音實錄'
  644. });
  645. });
  646. });
  647. }).fail((error) => {
  648. console.log('genjson_new error', error);
  649. });
  650. $.ajax({
  651. method: "get",
  652. url: "./json/index-slider.json",
  653. async: false,
  654. dataType: "json",
  655. }).done((data) => {
  656. renderJsonData(data); // 依照空間尋找商品, 依照專長尋找設計師
  657. }).fail((error) => {
  658. console.log('error', error);
  659. });
  660. function renderJsonData(data) {
  661. data.map(e => {
  662. if (e.tab === "依照空間尋找商品") {
  663. let str = "";
  664. let SpaceProducts = [];
  665. for (let i = 0; i < e.data.length; i++) {
  666. let item = e.data[i];
  667. let SpaceProduct = `${item.name}`;
  668. SpaceProducts.push(SpaceProduct);
  669. str += `
  670. <div>
  671. <section>
  672. <span class="slide-img">
  673. <a href="${item.url}" target="_blank" data-ga4="${item.name}">
  674. <img class="slide-item img-fluid" src="${item.image}" alt="${item.name}">
  675. <h3>${item.name}</h3>
  676. </a>
  677. </span>
  678. </section>
  679. </div>`
  680. }
  681. $(".space-slider").html(str);
  682. //ga4-banners
  683. SpaceProducts.forEach((SpaceProduct) => {
  684. document.querySelectorAll(`a[data-ga4="${SpaceProduct}"]`).forEach((element) => {
  685. element.addEventListener('click', function () {
  686. dataLayer.push({
  687. 'event': 'ShopBanner_Click',
  688. 'product_name': SpaceProduct
  689. });
  690. });
  691. });
  692. });
  693. // 輪播設定
  694. $('.space-slider').slick({
  695. infinite: false,
  696. slidesToShow: 4,
  697. slidesToScroll: 1,
  698. variableWidth: false,
  699. prevArrow:
  700. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  701. nextArrow:
  702. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  703. responsive: [
  704. {
  705. breakpoint: 991,
  706. settings: {
  707. slidesToShow: 3,
  708. slidesToScroll: 1
  709. }
  710. },
  711. {
  712. breakpoint: 767,
  713. settings: {
  714. slidesToShow: 2,
  715. slidesToScroll: 1,
  716. }
  717. },
  718. {
  719. breakpoint: 575,
  720. settings: {
  721. slidesToShow: 2,
  722. slidesToScroll: 1,
  723. variableWidth: true,
  724. arrows: false,
  725. }
  726. }
  727. ]
  728. });
  729. } else {
  730. let str = "";
  731. for (let i = 0; i < e.data.length; i++) {
  732. let item = e.data[i];
  733. str += `
  734. <div>
  735. <section>
  736. <span class="slide-img">
  737. <a href="${item.url}" target="_blank" data-ga4="By_Specialty">
  738. <img class="slide-item img-fluid" src="${item.image}" alt="${item.name}">
  739. <h3>${item.name}</h3>
  740. </a>
  741. </span>
  742. </section>
  743. </div>`
  744. }
  745. $(".options-slider.designer").html(str);
  746. }
  747. hideSlickArrow();
  748. })
  749. }
  750. let locationUrl = '';
  751. window.innerWidth > 767 ? locationUrl = "https://hhh.com.tw" : locationUrl = "https://m.hhh.com.tw";
  752. // 首頁廣告上方列表
  753. function renderData(data) {
  754. data.map((e) => {
  755. if (e._comment === "加好物商品") {
  756. renderDom("slider-01", e.data);
  757. } else if (e._comment === "首頁photo頁") {
  758. e.data.map((list, index) => {
  759. renderDom(`slider-0${index + 2}`, list.data);
  760. // $(`.slider-0${index + 1}-title`).text(list.tab);
  761. })
  762. }
  763. })
  764. // 輪播設定
  765. $('.options-slider').slick({
  766. infinite: false,
  767. slidesToShow: 6,
  768. slidesToScroll: 6,
  769. variableWidth: false,
  770. prevArrow:
  771. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  772. nextArrow:
  773. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  774. responsive: [
  775. {
  776. breakpoint: 1200,
  777. settings: {
  778. slidesToShow: 5,
  779. slidesToScroll: 5,
  780. }
  781. },
  782. {
  783. breakpoint: 991,
  784. settings: {
  785. slidesToShow: 4,
  786. slidesToScroll: 4
  787. }
  788. },
  789. {
  790. breakpoint: 767,
  791. settings: {
  792. slidesToShow: 3,
  793. slidesToScroll: 1,
  794. }
  795. },
  796. {
  797. breakpoint: 575,
  798. settings: {
  799. slidesToShow: 3,
  800. slidesToScroll: 1,
  801. variableWidth: true,
  802. arrows: false,
  803. }
  804. },
  805. {
  806. breakpoint: 415,
  807. settings: {
  808. slidesToShow: 2,
  809. slidesToScroll: 1,
  810. variableWidth: true,
  811. arrows: false,
  812. }
  813. }
  814. ]
  815. });
  816. hideSlickArrow();
  817. }
  818. function renderDom(sec, data) {
  819. if (sec !== "slider-01" && sec == "slider-02") {
  820. data = data.sort((a, b) => a.order - b.order);
  821. let str = "";
  822. for (let i = 0; i < data.length; i++) {
  823. str += `
  824. <div>
  825. <section>
  826. <span class="slide-img">
  827. <a href="${locationUrl + data[i]["url"]}" target="_blank" data-ga4="By_Style">
  828. <img class="${sec}-${i + 1} slide-item img-fluid" src="${locationUrl + data[i]["image"]}" alt="${data[i]["name"]}">
  829. <h3>${data[i]["name"]}</h3>
  830. </a>
  831. </span>
  832. </section>
  833. </div>`
  834. }
  835. $(`.${sec}`).html(str);
  836. }
  837. else if (sec !== "slider-01" && sec == "slider-03") {
  838. data = data.sort((a, b) => a.order - b.order);
  839. let str = "";
  840. for (let i = 0; i < data.length; i++) {
  841. str += `
  842. <div>
  843. <section>
  844. <span class="slide-img">
  845. <a href="${locationUrl + data[i]["url"]}" target="_blank" data-ga4="By_Space">
  846. <img class="${sec}-${i + 1} slide-item img-fluid" src="${locationUrl + data[i]["image"]}" alt="${data[i]["name"]}">
  847. <h3>${data[i]["name"]}</h3>
  848. </a>
  849. </span>
  850. </section>
  851. </div>`
  852. }
  853. $(`.${sec}`).html(str);
  854. }
  855. else {
  856. data = data.sort(() => Math.random() - 0.5); // 隨機排序
  857. data = data.slice(0, 12); // 取前 12 筆
  858. let str = "";
  859. ShopProducts = [];
  860. for (let i = 0; i < data.length; i++) {
  861. let ShopProduct = `${data[i]["title"]}`;
  862. ShopProducts.push(ShopProduct);
  863. str += `
  864. <div>
  865. <section>
  866. <span class="slide-img">
  867. <a href="${data[i]["link"]}" target="_blank" data-ga4="${data[i]["title"]}">
  868. <img class="${sec}-${i + 1} slide-item img-fluid" src="${data[i]["imgUrl"]}" alt="${data[i]["title"]}">
  869. <h3>
  870. <strong>${data[i]["title"]}</strong>
  871. </h3>
  872. </a>
  873. </span>
  874. </section>
  875. </div>`
  876. }
  877. $(`.${sec}`).html(str);
  878. //ga4-banners
  879. ShopProducts.forEach((ShopProduct) => {
  880. document.querySelectorAll(`a[data-ga4="${ShopProduct}"]`).forEach((element) => {
  881. element.addEventListener('click', function () {
  882. dataLayer.push({
  883. 'event': 'ShopBanner_Click',
  884. 'product_name': ShopProduct
  885. });
  886. });
  887. });
  888. });
  889. }
  890. }
  891. // let timer;
  892. // $(window).resize(function () {
  893. // // 延遲縮放
  894. // window.clearTimeout(timer);
  895. // timer = window.setTimeout(() => {
  896. // renderTopic();
  897. // }, 100);
  898. // })
  899. // 首頁主題企劃
  900. function renderTopic() {
  901. if (result) {
  902. result.map(list => {
  903. if (list._comment === "主題企劃區") {
  904. let webData = [];
  905. let mobileData = [];
  906. list.data.filter(e => {
  907. if (e.tab === "web") {
  908. webData = e.data;
  909. } else {
  910. mobileData = e.data;
  911. }
  912. });
  913. let arr;
  914. let str = "";
  915. // 固定取手機版第一筆
  916. let linkHref = `https://m.hhh.com.tw${mobileData[0].link}`;
  917. window.innerWidth > 767 ? arr = webData : arr = mobileData;
  918. let topicLink = document.querySelector(".topic-content .more-link");
  919. topicLink.setAttribute("href", linkHref);
  920. for (let i = 0; i < arr.length; i++) {
  921. str += `
  922. <div>
  923. <section>
  924. <span class="slide-img">
  925. <a href="${locationUrl + arr[i]["link"]}" target="_blank" data-ga4="By_Topic">
  926. <div class="img-box slide-img"> <img src="${arr[i]["imgUrl"]}" alt="${arr[i]["title"]}" class="img-fluid"></div>
  927. </a>
  928. </span>
  929. <a href="${locationUrl + arr[i]["link"]}" target="_blank" data-ga4="By_Topic">
  930. <h3 class="mt-2 ellipsis-title">${arr[i]["title"]}</h3>
  931. </a>
  932. </section>
  933. </div>`;
  934. }
  935. $('.topic-slider').html(str);
  936. // 輪播設定
  937. $('.topic-slider').slick({
  938. infinite: false,
  939. slidesToShow: 4,
  940. slidesToScroll: 4,
  941. variableWidth: false,
  942. prevArrow:
  943. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  944. nextArrow:
  945. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  946. responsive: [
  947. {
  948. breakpoint: 991,
  949. settings: {
  950. slidesToShow: 2,
  951. slidesToScroll: 2,
  952. }
  953. },
  954. {
  955. breakpoint: 767,
  956. settings: {
  957. slidesToShow: 2,
  958. slidesToScroll: 1,
  959. // variableWidth: true,
  960. // arrows: false,
  961. }
  962. },
  963. {
  964. breakpoint: 575,
  965. settings: {
  966. slidesToShow: 2,
  967. slidesToScroll: 1,
  968. variableWidth: true,
  969. arrows: false,
  970. }
  971. },
  972. {
  973. breakpoint: 415,
  974. settings: {
  975. slidesToShow: 1,
  976. slidesToScroll: 1,
  977. variableWidth: true,
  978. arrows: false,
  979. }
  980. }
  981. ]
  982. });
  983. }
  984. });
  985. }
  986. }
  987. // 按鈕 hover
  988. $(function () {
  989. $('.top-card a, .center-card a')
  990. .on('mouseenter', function (e) {
  991. var parentOffset = $(this).offset(),
  992. relX = e.pageX - parentOffset.left,
  993. relY = e.pageY - parentOffset.top;
  994. $(this).find('span').css({ top: relY, left: relX })
  995. })
  996. .on('mouseout', function (e) {
  997. var parentOffset = $(this).offset(),
  998. relX = e.pageX - parentOffset.left,
  999. relY = e.pageY - parentOffset.top;
  1000. $(this).find('span').css({ top: relY, left: relX })
  1001. });
  1002. });
  1003. // 首頁廣告輪播
  1004. function renderEventAd(data) {
  1005. let adNames = [];
  1006. data.map(list => {
  1007. if (list._comment === "活動頁banners區") {
  1008. let str = "";
  1009. list.data = list.data.sort(() => Math.random() - 0.5); // 隨機排序
  1010. for (let i = 0; i < list.data.length; i++) {
  1011. let adName = `${list.data[i]["id"]}${list.data[i]["alt"]}`;
  1012. adNames.push(adName);
  1013. str += `
  1014. <div>
  1015. <a href="${list.data[i]["link"]}" target="_blank" data-ga4="${list.data[i]["id"]}${list.data[i]["alt"]}">
  1016. <img class="slide-item img-fluid" src="${list.data[i]["webp"]}" alt="${list.data[i]["alt"]}" data_id="${list.data[i]["id"]}${list.data[i]["alt"]}">
  1017. </a>
  1018. </div>`
  1019. }
  1020. $('.sub-banner-content .sub-banner-slider').html(str);
  1021. //ga4-banners
  1022. adNames.forEach((adName) => {
  1023. document.querySelectorAll(`a[data-ga4="${adName}"]`).forEach((element) => {
  1024. element.addEventListener('click', function () {
  1025. dataLayer.push({
  1026. 'event': 'Banner_Click',
  1027. 'ad_name': adName,
  1028. 'ad_location': '首頁列表'
  1029. });
  1030. });
  1031. });
  1032. });
  1033. }
  1034. });
  1035. // 輪播設定
  1036. $('.sub-banner-content .sub-banner-slider').slick({
  1037. dots: false,
  1038. infinite: true,
  1039. speed: 300,
  1040. arrows: true,
  1041. autoplay: true,
  1042. autoplaySpeed: 4000,
  1043. slidesToShow: 2,
  1044. slidesToScroll: 1,
  1045. prevArrow:
  1046. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1047. nextArrow:
  1048. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1049. responsive: [
  1050. {
  1051. breakpoint: 767,
  1052. settings: {
  1053. slidesToShow: 1,
  1054. slidesToScroll: 1,
  1055. }
  1056. },
  1057. {
  1058. breakpoint: 575,
  1059. settings: {
  1060. slidesToShow: 1,
  1061. slidesToScroll: 1,
  1062. arrows: false
  1063. }
  1064. }
  1065. ]
  1066. });
  1067. }
  1068. // 隨機對調前後順序(e.g. 5678 1234)
  1069. function randomArr(ary, num = 4) {
  1070. // 取得隨機整數
  1071. let randomVal;
  1072. (Math.random() > 0.5) ? randomVal = 1 : randomVal = 0;
  1073. let data = [...ary]; // 深拷貝
  1074. let list = [];
  1075. // index < 拆分的次數
  1076. // 如陣列長度為 8 跟 12,拆分次數即為 2 跟 3
  1077. // 例如:[8] => [4,4] or [12] => [4,4,4]
  1078. for (let index = 0; index < 1; index++) {
  1079. list.push(data.splice(num, num));
  1080. // list.push(test.splice(4, 4));
  1081. }
  1082. list = list.sort(() => Math.random() - 0.5); // 隨機排序
  1083. let finalData = [];
  1084. if (randomVal) {
  1085. finalData = data.concat(list);
  1086. } else {
  1087. finalData = list.concat(data);
  1088. }
  1089. return finalData.flat(Infinity) // 展開陣列
  1090. }
  1091. function renderDesigner(data) {
  1092. data.map(list => {
  1093. if (list._comment === "推薦設計師") {
  1094. let randomData = randomArr(list.data, 6);
  1095. let str = "";
  1096. for (let i = 0; i < randomData.length; i++) {
  1097. const item = randomData[i];
  1098. str += `
  1099. <div>
  1100. <section>
  1101. <span class="slide-img">
  1102. <a href="${locationUrl + item.link}" target="_blank" data-ga4="By_Designer">
  1103. <img class="slide-item img-fluid" src="${item.imgUrl}" alt="${item.name}|${item.designers_name}">
  1104. <span class="img-border"></span>
  1105. </a>
  1106. </span>
  1107. <a href="${locationUrl + item.link}" target="_blank" data-ga4="By_Designer">
  1108. <h3 class="ellipsis-title">
  1109. ${item.name}
  1110. </h3>
  1111. <h3 class="name">
  1112. ${item.designers_name}
  1113. <small>設計師</small>
  1114. </h3>
  1115. </a>
  1116. </section>
  1117. </div>`;
  1118. }
  1119. $('.designer-slider').html(str);
  1120. // 輪播設定
  1121. $('.designer-slider').slick({
  1122. infinite: false,
  1123. slidesToShow: 6,
  1124. slidesToScroll: 6,
  1125. variableWidth: false,
  1126. prevArrow:
  1127. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1128. nextArrow:
  1129. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1130. responsive: [
  1131. {
  1132. breakpoint: 1200,
  1133. settings: {
  1134. slidesToShow: 4,
  1135. slidesToScroll: 4,
  1136. }
  1137. },
  1138. {
  1139. breakpoint: 767,
  1140. settings: {
  1141. slidesToShow: 3,
  1142. slidesToScroll: 3,
  1143. }
  1144. },
  1145. {
  1146. breakpoint: 575,
  1147. settings: {
  1148. slidesToShow: 2,
  1149. slidesToScroll: 1,
  1150. variableWidth: true,
  1151. arrows: false,
  1152. }
  1153. },
  1154. ]
  1155. });
  1156. hideSlickArrow();
  1157. $(".designer-content h3").hover(
  1158. function () {
  1159. $(this).parent().prev().children().children('.img-border').css('opacity', '1');
  1160. }, function () {
  1161. $(this).parent().prev().children().children('.img-border').css('opacity', '0');
  1162. }
  1163. );
  1164. }
  1165. });
  1166. }
  1167. function renderTabContent(data) {
  1168. data.map(list => {
  1169. if (list._comment === "tab區塊-最夯設計, 影音實錄, 專欄文章") {
  1170. list.data.map(item => {
  1171. if (item.tab === "編輯精選") {
  1172. let randomData = randomArr(item.data);
  1173. let str = "";
  1174. let tagList = [];
  1175. for (let i = 0; i < randomData.length; i++) {
  1176. const item = randomData[i];
  1177. str += `
  1178. <div>
  1179. <section>
  1180. <span class="slide-img">
  1181. <a href="${locationUrl + item.link}" target="_blank" data-ga4="By_Editor">
  1182. <img class="slide-item img-fluid" src="${item.imgUrl}" alt="${item.title}">
  1183. </a>
  1184. </span>
  1185. <a href="${locationUrl + item.link}" target="_blank" class="title" data-ga4="By_Editor">
  1186. <h3 class="mb-0 ellipsis-title">${item.title}</h3>
  1187. </a>
  1188. <div class="tab-block tag-list-${i}"></div>
  1189. </section>
  1190. </div>`;
  1191. tagList.push(item.ctag);
  1192. }
  1193. $('.featured-slider').html(str);
  1194. // 輪播設定
  1195. $('.featured-slider').slick({
  1196. infinite: false,
  1197. slidesToShow: 4,
  1198. slidesToScroll: 4,
  1199. variableWidth: false,
  1200. prevArrow:
  1201. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1202. nextArrow:
  1203. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1204. responsive: [
  1205. {
  1206. breakpoint: 991,
  1207. settings: {
  1208. slidesToShow: 2,
  1209. slidesToScroll: 2,
  1210. }
  1211. },
  1212. {
  1213. breakpoint: 767,
  1214. settings: {
  1215. slidesToShow: 2,
  1216. slidesToScroll: 2,
  1217. // variableWidth: true,
  1218. // arrows: false,
  1219. }
  1220. },
  1221. {
  1222. breakpoint: 575,
  1223. settings: {
  1224. slidesToShow: 2,
  1225. slidesToScroll: 2,
  1226. variableWidth: true,
  1227. arrows: false,
  1228. }
  1229. },
  1230. {
  1231. breakpoint: 415,
  1232. settings: {
  1233. slidesToShow: 1,
  1234. slidesToScroll: 1,
  1235. variableWidth: true,
  1236. arrows: false,
  1237. }
  1238. }
  1239. ]
  1240. });
  1241. hideSlickArrow(); // 判斷輪播按鈕顯示
  1242. randomTag(randomData, tagList, "featured-content"); // 渲染標籤
  1243. } else if (item.tab === "最夯設計") {
  1244. let randomData = randomArr(item.data);
  1245. let str = "";
  1246. let tagList = [];
  1247. for (let i = 0; i < randomData.length; i++) {
  1248. const item = randomData[i];
  1249. str += `
  1250. <div>
  1251. <section>
  1252. <span class="slide-img">
  1253. <a href="${locationUrl + item.link}" target="_blank" data-ga4="Best_Design">
  1254. <img class="slide-item img-fluid" src="${item.imgUrl}" alt="${item.title}">
  1255. </a>
  1256. <a href="${locationUrl + item.link}" target="_blank" class="designer-item" data-ga4="Best_Design">
  1257. <img class="slide-item img-fluid" src="${item.img_designer}" alt="${item.title_designer}">
  1258. <h2>${item.title_designer}</h2>
  1259. </a>
  1260. <a href="${locationUrl + item.link}" target="_blank" class="title" data-ga4="Best_Design">
  1261. <h3 class="mb-0 ellipsis-title">${item.title}</h3>
  1262. </a>
  1263. </span>
  1264. <div class="tab-block tag-list-${i}"></div>
  1265. </section>
  1266. </div>`;
  1267. tagList.push(item.ctag);
  1268. }
  1269. $('.popular-slider').html(str);
  1270. // 輪播設定
  1271. $('.popular-slider').slick({
  1272. infinite: false,
  1273. slidesToShow: 4,
  1274. slidesToScroll: 4,
  1275. variableWidth: false,
  1276. prevArrow:
  1277. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1278. nextArrow:
  1279. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1280. responsive: [
  1281. {
  1282. breakpoint: 991,
  1283. settings: {
  1284. slidesToShow: 2,
  1285. slidesToScroll: 2,
  1286. }
  1287. },
  1288. {
  1289. breakpoint: 767,
  1290. settings: {
  1291. slidesToShow: 2,
  1292. slidesToScroll: 2,
  1293. // variableWidth: true,
  1294. // arrows: false,
  1295. }
  1296. },
  1297. {
  1298. breakpoint: 575,
  1299. settings: {
  1300. slidesToShow: 2,
  1301. slidesToScroll: 2,
  1302. variableWidth: true,
  1303. arrows: false,
  1304. }
  1305. },
  1306. {
  1307. breakpoint: 415,
  1308. settings: {
  1309. slidesToShow: 1,
  1310. slidesToScroll: 1,
  1311. variableWidth: true,
  1312. arrows: false,
  1313. }
  1314. },
  1315. ]
  1316. });
  1317. hideSlickArrow(); // 判斷輪播按鈕顯示
  1318. randomTag(randomData, tagList, "popular-content"); // 渲染標籤
  1319. } else if (item.tab === "最新影音實錄") {
  1320. let randomData = randomArr(item.data);
  1321. let str = "";
  1322. for (let i = 0; i < randomData.length; i++) {
  1323. const item = randomData[i];
  1324. // <a href="javascript:;" onclick="videoSet('${item.link}','${item.description}')" data-bs-toggle="modal" data-src="${item.link}" data-bs-target="#youtubeModal">
  1325. // <img class="slide-item img-fluid" src="${item.imgUrl}" alt="">
  1326. // </a>
  1327. str += `
  1328. <div>
  1329. <section>
  1330. <span class="slide-img">
  1331. <a href="${item.link}" target="_blank" data-ga4="Latest_Video">
  1332. <img class="slide-item img-fluid" src="${item.imgUrl}" alt="${item.description}">
  1333. <span class="play-btn">
  1334. <img class="slide-item img-fluid" src="./img/icon/material-play-circle-outline.svg" alt="">
  1335. </span>
  1336. </a>
  1337. </span>
  1338. <a href="${item.link}" target="_blank" class="title" data-ga4="Latest_Video">
  1339. <h3 class="mb-0 mt-3 ellipsis-title">${item.description}</h3>
  1340. </a>
  1341. </section>
  1342. </div>`;
  1343. }
  1344. $('.video-slider').html(str);
  1345. // 輪播設定
  1346. $('.video-slider').slick({
  1347. infinite: false,
  1348. slidesToShow: 4,
  1349. slidesToScroll: 4,
  1350. variableWidth: false,
  1351. prevArrow:
  1352. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1353. nextArrow:
  1354. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1355. responsive: [
  1356. {
  1357. breakpoint: 991,
  1358. settings: {
  1359. slidesToShow: 2,
  1360. slidesToScroll: 2,
  1361. }
  1362. },
  1363. {
  1364. breakpoint: 767,
  1365. settings: {
  1366. slidesToShow: 2,
  1367. slidesToScroll: 2,
  1368. }
  1369. },
  1370. {
  1371. breakpoint: 575,
  1372. settings: {
  1373. slidesToShow: 2,
  1374. slidesToScroll: 1,
  1375. variableWidth: true,
  1376. arrows: false,
  1377. }
  1378. },
  1379. {
  1380. breakpoint: 415,
  1381. settings: {
  1382. slidesToShow: 1,
  1383. slidesToScroll: 1,
  1384. variableWidth: true,
  1385. arrows: false,
  1386. }
  1387. }
  1388. ]
  1389. });
  1390. hideSlickArrow(); // 判斷輪播按鈕顯示
  1391. }
  1392. })
  1393. }
  1394. })
  1395. // hover 事件
  1396. $(".main-content h3").hover(
  1397. function () {
  1398. $(this).parent().parent().addClass('img-scale');
  1399. }, function () {
  1400. $(this).parent().parent().removeClass('img-scale');
  1401. }
  1402. );
  1403. $(".main-content .slide-img").hover(
  1404. function () {
  1405. $(this).parent().parent().find('h3').css('color', '#ee751b');
  1406. }, function () {
  1407. ;
  1408. $(this).parent().parent().find('h3').css('color', '#727272');
  1409. }
  1410. );
  1411. }
  1412. // 參數需帶入 (隨機排序清單, 標籤陣列, 外層 className)
  1413. function randomTag(randomData, tagList, content) {
  1414. let tagLink;
  1415. if (content === "featured-content") {
  1416. // 編輯精選
  1417. tagLink = "column";
  1418. } else {
  1419. // 最夯設計
  1420. tagLink = "case";
  1421. }
  1422. for (let index = 0; index < tagList.length; index++) {
  1423. const element = tagList[index];
  1424. randomData.map((e, i) => {
  1425. if (i === index) {
  1426. let list = [];
  1427. for (let i = 0; i < element.length; i++) {
  1428. const item = element[i];
  1429. if (item !== "") {
  1430. let tag = `
  1431. <a href=https://hhh.com.tw/search/lists/${tagLink}/${item}-keyword/" target="_blank">
  1432. <h4>${item}</h4>
  1433. </a>
  1434. `;
  1435. list.push(tag);
  1436. }
  1437. }
  1438. $(`.${content} .tag-list-${index}`).html(list);
  1439. }
  1440. })
  1441. }
  1442. }
  1443. function hideSlickArrow() {
  1444. // 隱藏輪播 disabled 按鈕,後續改為點擊判斷
  1445. $('.slick-arrow.slick-disabled').css('display', 'none');
  1446. $('.slick-arrow').click(function () {
  1447. $('.slick-arrow').css('display', 'block');
  1448. $('.slick-arrow.slick-disabled').css('display', 'none');
  1449. });
  1450. }
  1451. // 影音實錄 Modal
  1452. function videoSet(src, title) {
  1453. let url = new URL(src);
  1454. let id = url.searchParams.get('v');
  1455. $("#video").attr('src', `https://www.youtube-nocookie.com/embed/${id}`);
  1456. $("#youtubeModal h2").text(`${title}`);
  1457. }
  1458. // Back to top
  1459. $(window).scroll(function () {
  1460. if ($(this).scrollTop()) {
  1461. $('.btn-box').fadeIn();
  1462. } else {
  1463. $('.btn-box').fadeOut();
  1464. }
  1465. });
  1466. // 上方輪播
  1467. $.ajax({
  1468. method: "get",
  1469. url: "./json/data_index.json",
  1470. // url: "https://m3.hhh.com.tw:18689/genjson_new?filename=realtime.json",
  1471. dataType: "json",
  1472. }).done((data) => {
  1473. result = [...data];
  1474. renderTopCarousel(result);
  1475. console.log('result', result);
  1476. }).fail((error) => {
  1477. console.log('genjson_new error', error);
  1478. });
  1479. // 渲染頂部輪播
  1480. function renderTopCarousel(data) {
  1481. let temp = data[0]["data"];
  1482. console.log('temp', temp);
  1483. renderBullet(temp);
  1484. renderBannerStr("slider-content", temp);
  1485. let randomInt = getRandomInt(7);
  1486. let adTopup_count = []
  1487. // 新刊頭 Banner ga4 (一開始進來先送,剩下輪播送)
  1488. setTimeout(() => {
  1489. let list_Topup_Banner = document.querySelectorAll('.slider-content .slide-item');
  1490. let ad_first;
  1491. try {
  1492. ad_first = list_Topup_Banner[randomInt].getAttribute('data_id');
  1493. } catch (e) {
  1494. ad_first = '加載問題,請無視';
  1495. console.log(ad_first);
  1496. }
  1497. dataLayer.push({
  1498. 'event': 'Banner_Impression',
  1499. 'ad_name': ad_first,
  1500. 'ad_location': '新刊頭Banner'
  1501. });
  1502. adTopup_count.push(ad_first)
  1503. }, 1000);
  1504. $(".slider-content").slick({
  1505. dots: false,
  1506. infinite: true,
  1507. speed: 500,
  1508. autoplay: true,
  1509. autoplaySpeed: 3000,
  1510. slidesToScroll: 1,
  1511. arrows: true,
  1512. initialSlide: randomInt, // 起始順序
  1513. prevArrow:
  1514. '<button type="button" class="slick-prev"><i class="fas fa-chevron-left" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1515. nextArrow:
  1516. '<button type="button" class="slick-next"><i class="fas fa-chevron-right" style="font-size: 32px;color: white;transform: translateY(-10px);"></i></button>',
  1517. });
  1518. $(".bullet").removeClass("bullet-active");
  1519. $(".bullet")
  1520. .eq($(".slick-active").data("slick-index"))
  1521. .addClass("bullet-active");
  1522. $(".slider-content").on("afterChange", function (event, slick, currentSlide) {
  1523. // 輪播
  1524. $(".bullet").removeClass("bullet-active");
  1525. $(`.bullet.item-${currentSlide}`).addClass("bullet-active");
  1526. });
  1527. }
  1528. function renderBannerStr(sec, data) {
  1529. let adNamesTop = [];
  1530. let str = "";
  1531. for (let i = 0; i < data.length; i++) {
  1532. let adNameTop = `${data[i]["id"]}${data[i]["alt"]}`;
  1533. adNamesTop.push(adNameTop);
  1534. if (data[i]["Dwebp"]) {
  1535. str += `
  1536. <a href="${data[i]["link"]}" data-ga4="${data[i]["id"]}${data[i]["alt"]}">
  1537. <img class="${sec}-${i + 1} slide-item img-fluid" src="${data[i]["Dwebp"]}" data-bg="${data[i]["Dwebp"]}" alt="${data[i]["alt"]}" data_id="${data[i]["id"]}${data[i]["alt"]}">
  1538. </a>`;
  1539. } else {
  1540. str += `
  1541. <a href="${data[i]["link"]}" data-ga4="${data[i]["id"]}${data[i]["alt"]}">
  1542. <img class="${sec}-${i + 1} slide-item img-fluid" src="${data[i]["DimgUrl"]}" data-bg="${data[i]["DimgUrl"]}" alt="${data[i]["alt"]}" data_id="${data[i]["id"]}${data[i]["alt"]}">
  1543. </a>`;
  1544. }
  1545. }
  1546. $(`.${sec}`).html(str);
  1547. // ga4-banners
  1548. adNamesTop.forEach((adNameTop) => {
  1549. document.querySelectorAll(`a[data-ga4="${adNameTop}"]`).forEach((element) => {
  1550. element.addEventListener('click', function () {
  1551. dataLayer.push({
  1552. 'event': 'Banner_Click',
  1553. 'ad_name': adNameTop,
  1554. 'ad_location': '新刊頭'
  1555. });
  1556. });
  1557. });
  1558. });
  1559. }
  1560. function renderBullet(data) {
  1561. let str = "";
  1562. for (let i = 0; i < data.length; i++) {
  1563. str += `<div class="bullet item-${i}"></div>`;
  1564. }
  1565. $(".bullet-list").html(str);
  1566. }
  1567. // 範圍內取隨機整數 (0-8)
  1568. function getRandomInt(max) {
  1569. return Math.floor(Math.random() * max);
  1570. }
  1571. $(".top-carousel .close-btn").click(function () {
  1572. $(this).css("display", "none");
  1573. $(".top-carousel").addClass("banner-close");
  1574. sticky = 0;
  1575. });
  1576. // 右下按鈕
  1577. $(".gotop-btn").click(() => {
  1578. $("html, body").animate(
  1579. {
  1580. scrollTop: 0,
  1581. }, 0
  1582. );
  1583. });
  1584. // 右下按鈕滑入顯示
  1585. $(".calculator-btn").hover(function () {
  1586. $(".calculator-btn").addClass("show");
  1587. }, function () {
  1588. $(".calculator-btn").removeClass("show");
  1589. });
  1590. $(".shop-btn").hover(function () {
  1591. $(".shop-btn").addClass("show");
  1592. }, function () {
  1593. $(".shop-btn").removeClass("show");
  1594. });
  1595. // 判斷按鈕顯示 or 隱藏
  1596. $(window).scroll(function () {
  1597. if ($(this).scrollTop()) {
  1598. $('#btn-box').fadeIn();
  1599. } else {
  1600. $('#btn-box').fadeOut();
  1601. }
  1602. });
  1603. document.querySelector('button[data-ga="Go_To_Calculator"]').addEventListener('click', function () {
  1604. dataLayer.push({
  1605. 'event': 'Go_To_Calculator',
  1606. 'btn_location': 'FixedBTN'
  1607. });
  1608. });
  1609. document.querySelector('button[data-ga="Go_To_Shop"]').addEventListener('click', function () {
  1610. dataLayer.push({
  1611. 'event': 'Go_To_Shop',
  1612. 'btn_location': 'FixedBTN'
  1613. });
  1614. });
  1615. // Footer
  1616. $(".follow-list a").on({
  1617. mouseenter: function () {
  1618. // $(this).find(".media-item.before").hide();
  1619. // $(this).find(".media-item.after").show();
  1620. $(this).find(".media-item.before").css("opacity", "0");
  1621. $(this).find(".media-item.after").css("opacity", "1");
  1622. },
  1623. mouseleave: function () {
  1624. // $(this).find(".media-item.before").show();
  1625. // $(this).find(".media-item.after").hide();
  1626. $(this).find(".media-item.before").css("opacity", "1");
  1627. $(this).find(".media-item.after").css("opacity", "0");
  1628. }
  1629. });
  1630. let formData = {
  1631. email: ""
  1632. };
  1633. // 訂閱
  1634. $('.subscriber-btn, .subscriber-mb-btn').on('click', function () {
  1635. let parent = $(this).closest('.subscriber-item'); // 對應父元素
  1636. parent.find('.spinner-border').addClass('show');
  1637. let mail = parent.find('input').val();
  1638. console.log("Input value:", mail);
  1639. let regex = /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i;
  1640. let validate = regex.test(mail); // 判斷 mail 格式
  1641. if (!validate) {
  1642. parent.addClass('input-error');
  1643. parent.find('.spinner-border').removeClass('show');
  1644. parent.find('button p').text('email 格式錯誤');
  1645. } else {
  1646. parent.removeClass('input-error');
  1647. let formData = { email: mail };
  1648. let email = JSON.stringify(formData);
  1649. $.ajax({
  1650. method: "post",
  1651. url: "https://hhh.com.tw/adapter/index?http_method=POST&api_url=/third/v1/edm/subscriber",
  1652. contentType: "application/json",
  1653. data: email
  1654. }).done((data) => {
  1655. parent.find('.spinner-border').removeClass('show');
  1656. parent.find('button p').text('已完成訂閱!');
  1657. }).fail((error) => {
  1658. parent.find('.spinner-border').removeClass('show');
  1659. parent.find('button p').text('訂閱失敗,請稍後再試');
  1660. });
  1661. }
  1662. });
  1663. $('.subscriber-item input').on('focusin', function () {
  1664. console.log('focusin');
  1665. let parent = $(this).closest('.subscriber-item');
  1666. parent.addClass('input-focus');
  1667. let buttonText = parent.find('button p').text();
  1668. if (buttonText !== "訂閱") {
  1669. parent.find('button p').text('訂閱');
  1670. parent.removeClass('input-error');
  1671. }
  1672. }).on('focusout', function () {
  1673. $(this).closest('.subscriber-item').removeClass('input-focus');
  1674. });