1async function initForthcoming(articleList) { 2 const container = document.querySelector('.forthcoming .content-row'); 3 if (!container || !articleList) return; 4 5 // 1. Skeleton UI 미리 ìì± (리ì¤í¸ ê°ìë§í¼) 6 articleList.forEach((item, index) => { 7 if (item.articleType) { 8 const subHeadingHtml = `<h6 class="AOPSubheading">${item.articleType}</h6>`; 9 container.insertAdjacentHTML('beforeend', subHeadingHtml); 10 } else { 11 const skeletonHtml = ` 12 <div class="articleBox card border-0" id="article-slot-${index}"> 13 <div class="row gx-3 gy-4"> 14 <div class="col-md-12"> 15 <div class="skeleton skeleton-img"></div> 16 </div> 17 <div class="col-md-12"> 18 <div class="content"> 19 <div class="skeleton skeleton-text" style="width:30%"></div> 20 <div class="skeleton skeleton-title"></div> 21 <div class="skeleton skeleton-text"></div> 22 <div class="skeleton skeleton-text" style="width:50%"></div> 23 </div> 24 </div> 25 </div> 26 </div> 27 `; 28 container.insertAdjacentHTML('beforeend', skeletonHtml); 29 } 30 }); 31 32 // ì ë ¬ì© ë¹ ë°ì¤ 미리 ì½ì (2ê°) 33 const preEmptyHtml = ` 34 <div class="articleBox card border-0 empty-box" style="visibility:hidden; height:0; margin:0!important; padding:0;"></div> 35 <div class="articleBox card border-0 empty-box" style="visibility:hidden; height:0; margin:0!important; padding:0;"></div>`; 36 container.insertAdjacentHTML('beforeend', preEmptyHtml); 37 38 // 2. ì¤í ì ëµ ë¶í 39 const PRIORITY_COUNT = 3; // 먼ì ì²ë¦¬í ê°ì 40 const priorityItems = articleList.slice(0, PRIORITY_COUNT); 41 const backgroundItems = articleList.slice(PRIORITY_COUNT); 42 43 /** 44 * A. ìì 3í¸: ë³ë ¬ ì²ë¦¬ (ì¦ì ë ëë§) 45 */ 46 const priorityPromises = priorityItems.map(async (item, index) => { 47 if (!item.doi) return null; 48 try { 49 const data = await fetchForthcomingArticleData(item.doi, item.im, item.sub); 50 updateArticleSlot(index, data); // ìë£ëë ëë¡ ì¦ì íë©´ ì ë°ì´í¸ 51 52 if (typeof checkAdditionalFiles === 'function') { 53 const articleBoxes = document.querySelectorAll('.articleBox'); 54 const targetSlot = articleBoxes[index]; // ì¬ê¸°ì ì¤ì HTMLElement를 ì¶ì¶ 55 56 if (targetSlot) { 57 // 첫 ë²ì§¸ ì¸ìë¡ ì¸ë±ì¤(ì«ì)ê° ìë ìì(Object)를 ì ë¬í©ëë¤. 58 checkAdditionalFiles(targetSlot, data); 59 } 60 } 61 } catch (err) { 62 updateArticleSlot(index, { error: true, doi: item.doi }); 63 } 64 }); 65 66 67 // ì°ì ìì ìì ì´ ëª¨ë ììë¨ (ìë£ë¥¼ 기ë¤ë¦¬ì§ ìê³ ë°±ê·¸ë¼ì´ë 루í ìì½ ê°ë¥) 68 // íì§ë§ ì´ê¸° íë©´ì ìì ì±ì ìí´ ì°ì ìì ìë£ë¥¼ 기ë¤ë¦° í ë머ì§ë¥¼ ë리ë ê²ì´ ì¢ìµëë¤. 69 await Promise.all(priorityPromises); 70 71 /** 72 * B. ë머ì§: ìì°¨ ì²ë¦¬ (íëì© ì°¨ë¡ëë¡) 73 * for...of 문ì ì¬ì©íë©´ awaitê° ê±¸ë¦´ ëë§ë¤ ë¤ì 루íë¡ ëì´ê°ê¸° ì ì ë기í©ëë¤. 74 */ 75 for (let i = 0; i < backgroundItems.length; i++) { 76 const item = backgroundItems[i]; 77 const originalIndex = i + PRIORITY_COUNT; // ì ì²´ 리ì¤í¸ììì ì¸ë±ì¤ ê³ì° 78 79 if (!item.doi) continue; 80 81 try { 82 // ì´ì ìì²ì´ ëëì¼ ë¤ì ìì²ì´ ììë¨ (ìë² ë¶í ë°©ì§ ë° ìì ë³´ì¥) 83 const data = await fetchForthcomingArticleData(item.doi, item.im, item.sub); 84 updateArticleSlot(originalIndex, data); 85 86 if (typeof checkAdditionalFiles === 'function') { 87 const articleBoxes = document.querySelectorAll('.articleBox'); 88 const targetSlot = articleBoxes[originalIndex]; // ì¬ê¸°ì ì¤ì HTMLElement를 ì¶ì¶ 89
90 if (targetSlot) { 91 // 첫 ë²ì§¸ ì¸ìë¡ ì¸ë±ì¤(ì«ì)ê° ìë ìì(Object)를 ì ë¬í©ëë¤. 92 checkAdditionalFiles(targetSlot, data); 93 } 94 } 95 } catch (err) { 96 updateArticleSlot(originalIndex, { error: true, doi: item.doi }); 97 } 98 } 99 100} 101 102// ë°ì´í°ë§ ê°ì ¸ì¤ë ìì íì± í¨ì (UI ì¡°ì ì ì¸) 103async function fetchForthcomingArticleData(doi, imInput, subsubject) { 104 const journalID = '0063JKMS'; 105 const journalAcron = 'jkms' 106 107 const urlsToTry = [ 108 `https://jkms.org/DOIx.php?id=${doi}`, 109 `https://www.jkms.org/DOIx.php?id=${doi}` 110 ]; 111 112 let response; 113 let finalUrl = ""; 114 115 // 2. ì±ê³µí ëê¹ì§ ìì°¨ì ì¼ë¡ ìëí©ëë¤. 116 for (const url of urlsToTry) { 117 try { 118 const res = await fetch(url); 119 if (res.ok) { 120 response = res; 121 finalUrl = url; 122 break; // ì±ê³µíë©´ 루í ì¢ ë£ 123 } 124 } catch (err) { 125 console.warn(`${url} ì ì ì¤í¨, ë¤ì 주ì ìë ì¤...`); 126 } 127 } 128 129 if (!response) { 130 console.error("모ë URL ì ìì ì¤í¨íìµëë¤."); 131 return; 132 } 133 134 try { 135 const htmlText = await response.text(); 136 const parser = new DOMParser(); 137 const doc = parser.parseFromString(htmlText, "text/html"); 138 139 // 기본 ë°ì´í° í ë¹ 140 let frontMeta = doc.querySelector("#article-front-meta-left")?.innerText || ""; 141 let vol = "", page = "", epub = ""; 142 143 if (frontMeta.includes('.')) { 144 vol = frontMeta.split('.')[1].trim().split(';')[1].split(':')[0]; 145 page = frontMeta.split('.')[1].trim().split(':')[1].split('-')[0]; 146 epub = frontMeta.split('.')[4].trim() 147 } 148 149 let im = imInput; 150 let imgDisplay = ""; 151 let sliderclassName = "col-md-6 col-xs-6"; 152 153 // thumbnail ê°ì ë¡ ìë³´ì´ê² íë ê²½ì° ì¶ê° 154 if (im == 'xxxx') { 155 imgDisplay = " d-none"; 156 sliderclassName = "col-md-12 col-xs-12"; 157 } else if (!im) { 158 // 1. Graphical Abstract ì²´í¬ 159 const headers = Array.from(doc.querySelectorAll('.article-section-header h2')); 160 const hasGraphicalAbstract = headers.some(h => h.innerText.toLowerCase().includes('graphical abstract')); 161 162 163 if (hasGraphicalAbstract) { 164 im = "abf001"; 165 } else { 166 // 2. Figures ì²´í¬ 167 const portletHeaders = Array.from(doc.querySelectorAll('.porlet h5')); 168 const hasFigures = portletHeaders.some(h => h.innerText.toLowerCase().includes('figures')); 169 const hasTables = portletHeaders.some(h => h.innerText.toLowerCase().includes('tables')); 170 171 if (hasFigures) { 172 im = "g001-l"; 173 } else if (hasTables) { 174 im = "i001-l"; 175 } else { 176 // ë ë¤ ìì ê²½ì° 177 im = "xxxx"; 178 imgDisplay = " d-none"; // ë¶í¸ì¤í¸ë© í´ëì¤ ëë CSS í´ëì¤ 179 sliderclassName = "col-md-12 col-xs-12"; 180 } 181 } 182 183 184 185 } 186 187 const citeButton = doc.querySelector('.CiteDialog'); 188 let author = ""; 189 const metaJournal = doc.querySelector('meta[name="citation_journal_title"]')?.getAttribute('content')?.trim(); 190 191 192 // 1. data ìì±ìì ìí¸íë í ì¤í¸ ê°ì ¸ì¤ê¸° 193 const encodedCitation = citeButton.getAttribute('data-article-citation'); 194 195 if (encodedCitation) { 196 try { 197 // 2. Base64 ëì½ë© (atob í¨ì ì¬ì©) 198 // ì¸ì½ë©ë 문ìì´ ë´ë¶ì HTML íê·¸ë í¹ì문ìê° ìì¬ ìì ì ìì¼ë¯ë¡ ì²ë¦¬ 199 const decodedText = decodeURIComponent(escape(window.atob(encodedCitation))); 200
201 // 3. ëì½ë©ë í ì¤í¸ìì 첫 ë²ì§¸ ë§ì¹¨í(.)ê¹ì§ ì르기 202 author = decodedText.split('.')[0].trim() + "."; 203 204 // 4. ì¶ì¶ë í ì¤í¸ ìì íì ì§ëª ì´ í¬í¨ëì´ ìë¤ë©´ ì´í¤ë¦ì²´ë¡ ì¹í 205 if (author.includes(metaJournal)) { 206 // í´ë¹ íì ì§ëª ë¶ë¶ë§ <i>íê·¸ë¡ ê°ì¸ê¸° 207 author = author.replace(metaJournal, `<i>${metaJournal}</i>`); 208 } 209 210 if (author === '[No authors listed].') { 211 author = ""; 212 } 213 214 } catch (e) { 215 console.error("Base64 ëì½ë© ì¤í¨:", e); 216 // ëì½ë© ì¤í¨ ì ëìì¼ë¡ ë©íë°ì´í° ì¬ì© 217 const metaAuthor = doc.querySelector('meta[name="citation_author"]')?.content; 218 author = metaAuthor ? metaAuthor + "." : "Author Unknown."; 219 } 220 } 221 222 let subject = doc.querySelector('.article-type')?.innerText; 223 224 // 1. íì´ì§ ë´ ëª¨ë <script> í그를 ê²ì¬ 225 const scripts = Array.from(doc.querySelectorAll('script')); 226 const typeScript = scripts.find(s => s.textContent.includes('document.getElementsByClassName("article-type")[0].innerHTML')); 227 228 if (typeScript) { 229 // ì ê·ííìì¼ë¡ "Research Article" ë¶ë¶ë§ ì¶ì¶ 230 // .innerHTML = "..." ëë .innerHTML = '...' íí를 모ë ì°¾ì 231 const match = typeScript.textContent.match(/\.innerHTML\s*=\s*["'](.+?)["']/); 232 if (match && match[1]) { 233 subject = match[1]; 234 } 235 } 236 237 // 본문 ííì ë°ë¼ absë§ ì°ê²°í ë ¼ë¬¸ì¸ì§ íì¸ 238 const bodyElement = doc.querySelector('#article-level-0-body'); 239 let isAbsOnly = false; 240 241 if (!bodyElement) { 242 isAbsOnly = true; 243 } else { 244 const children = bodyElement.children; 245 const hasOnlySupplementary = (children.length === 1 && children[0].id === 'supplementary-material'); 246 247 const textContent = bodyElement.innerText.trim(); 248 if (hasOnlySupplementary || textContent.length < 50) { 249 isAbsOnly = true; 250 } 251 } 252 253 let displayLink = `https://doi.org/${doi}`; 254 let displayText = displayLink; 255 256 if (isAbsOnly) { 257 epub = epub.replace('Published ', 'Posted '); 258 displayLink = finalUrl; 259 displayText = 'Abstract'; 260 } 261 262 263 // ììì© ë°ì´í° ê°ì²´ ë°í 264 return { 265 vol: vol, 266 page: page, 267 imgDisplay: imgDisplay, 268 imgSrc: `../ArticleImage/${journalID}/${journalAcron}-${vol}-${page}-${im}.jpg` || '', 269 sliderclassName: sliderclassName, 270 subject: subject, 271 subsubject: subsubject, 272 title: doc.querySelector('.article-title .content-title')?.innerHTML || '', 273 author: author, 274 history: doc.querySelector('.article-received-accepted-date')?.innerText || '', 275 epub: epub, 276 link: finalUrl, 277 doi: doi, 278 page: page, 279 displayLink: displayLink, 280 displayText: displayText 281 }; 282 } catch (e) { 283 return { title: "Error loading data", doi: doi }; 284 } 285} 286 287function updateArticleSlot(index, data) { 288 const slot = document.getElementById(`article-slot-${index}`); 289 if (!slot) return; 290 291 let articleHtml = ""; 292 293 if (data.error) { 294 // [ë¡ë ì¤í¨ ì UI] 295 articleHtml = ` 296 <div class="row gx-3 gy-3 error-box"> 297 <div class="col-12 text-center py-4"> 298 <div class="error-icon" style="font-size: 24px;">â ï¸</div> 299 <div class="error-text" style="color: #888; font-size: 13px; margin-top: 10px;"> 300 Failed to load data.<br> 301 <small><a href="https://doi.org/${data.doi}" target="_blank">${data.doi}</a></small> 302 </div> 303 </div> 304 </div> 305 `; 306 } else { 307 // [ì ì ë¡ë ì UI] 308 articleHtml = ` 309 <div class="row gx-3 gy-4"> 310 <div class="col-md-12${data.imgDisplay}"> 311 <div class="thumbnail"><img class="img-fluid myImg" src="${data.imgSrc}"/></div> 312 </div> 313 <div class="col-md-12"> 314 <div class="content"> 315 <div> 316 <div class="subject d-flex justify-content-between">${data.subject}<span class="Forthcoming">Forthcoming</span></div> 317 <div class="sub_articleType">${data.subsubject}</div> 318 </div> 319 <div class="card-text title"><a href="${data.link}">${data.title}</a></div> 320 <div class="card-text author">${data.author}</div> 321 <div class="card-text disc"> 322 <div>${data.history}</div> 323 <div>${data.epub}</div> 324 <div><a href="https://doi.org/${data.doi}">https://doi.org/${data.doi}</a></div> 325 </div> 326 <div class="card-text doi"></div> 327 <div class="card-text doi"></div> 328 </div> 329 </div> 330 </div> 331 `; 332 } 333 334 slot.innerHTML = articleHtml; 335 slot.classList.add('loaded'); 336} 337 338 339/** 340 * ì¶ê° íì¼(Author Summary, AVF) ì¡´ì¬ ì¬ë¶ ì²´í¬ ë° ë²í¼ ì½ì 341 * @param {HTMLElement} slot - í´ë¹ ë ¼ë¬¸ì articleBox ìì 342 * @param {Object} data - ë ¼ë¬¸ ë°ì´í° (vol, page/id ë± í¬í¨) 343 */ 344async function checkAdditionalFiles(slot, data) { 345 const vol = data.vol; // fetch ì vol ì 보를 ì ì¥í´ë¬ì¼ í¨ 346 const id = data.page; // í¹ì idë¡ ì¬ì©ëë ê° 347 348 if (!vol || !id) return; 349 350 const fileTypes = [ 351 { 352 name: 'Author Summary in Korean', 353 url: `https://jkms.org/src/jkms-summary/jkms-${vol}-${id}.html`,
354 containerIdx: 0 // .doi í´ëì¤ì 첫 ë²ì§¸ ìì¹ í¹ì í¹ì ìì¹ 355 }, 356 { 357 name: 'Audio-Visual File', 358 url: `https://jkms.org/src/jkms-summary-AVF/jkms-${vol}-${id}-AVF.html`, 359 containerIdx: 1 360 } 361 ]; 362 363 for (const file of fileTypes) { 364 try { 365 // HEAD ìì²ì¼ë¡ íì¼ ì¡´ì¬ ì¬ë¶ë§ ê°ë³ê² ì²´í¬ 366 const response = await fetch(file.url, { method: 'HEAD' }); 367 368 if (response.ok) { 369 const doiContainers = slot.querySelectorAll('.doi'); 370 if (doiContainers[file.containerIdx]) { 371 const btnHtml = ` 372 <span class="summary-btn"> 373 <a href="${file.url}" 374 onclick="window.open(this.href, '', 'width=760,height=450, top=630, left=590, scrollbars=yes'); return false;" 375 target="_new1"> 376 ${file.name} 377 </a> 378 </span>`; 379 380 // 기존 DOI ë´ì© ë¤ì ì¶ê°íê±°ë ë´ì©ì êµì²´ 381 doiContainers[file.containerIdx].insertAdjacentHTML('beforeend', btnHtml); 382 } 383 } else { 384 console.log(`[${id}] ${file.name} Not Found (404)`); 385 } 386 } catch (err) { 387 console.error(`Error checking file: ${file.name}`, err); 388 } 389 } 390} 391 392 393 394 395// main íì´ì§ forthcoming ë ¼ë¬¸ ì ë°ì´í¸ ê´ë ¨ 396/** 397 * ë©ì¸ íì´ì§ì©: ë¤ì¤ Forthcoming íì´ì§ë¥¼ ìííë©° 모ë ëª ë¨ ê°ì²´ë¥¼ íµí© ì¶ì¶ 398 */ 399async function syncArticleListFromForthcoming() { 400 const sliderContainer = document.querySelector('#carousel-highlight'); 401 if (!sliderContainer) return; 402 403 try { 404 // console.log("ð¡ [Slider] ë¤ì¤ íì´ì§ ëª ë¨ ìì§ ìì..."); 405 406 // --- [STEP 1] 첫 ë²ì§¸ íì´ì§ í¸ì¶ ë° ë¶ì --- 407 const firstPageUrl = 'index.php?body=forthcoming'; 408 const response = await fetch(firstPageUrl); 409 const htmlText = await response.text(); 410 411 // ê°ìì DOM ê°ì²´ë¥¼ ë§ë¤ì´ ë´ë¹ê²ì´ì ë§í¬ë¥¼ íì±í©ëë¤. 412 const parser = new DOMParser(); 413 const doc = parser.parseFromString(htmlText, 'text/html'); 414 415 // .buttonNavi a íê·¸ë¤ìì href ì¶ì¶ (ì¤ë³µ ë° íì¬íì´ì§ ì ì¸) 416 const naviLinks = Array.from(doc.querySelectorAll('.buttonNavi a')) 417 .map(a => a.getAttribute('href')) 418 .filter(href => href && href.includes('main=forthcoming') && !href.includes(firstPageUrl)); 419 420 // ê³ ì í ì¶ê° íì´ì§ 주ì 리ì¤í¸ (첫 íì´ì§ ì ì¸) 421 const additionalPages = [...new Set(naviLinks)]; 422 console.log(`ð [Slider] ì¶ê° íì´ì§ ë°ê²¬: ${additionalPages.length}ê°`); 423 424 // --- [STEP 2] ëª ë¨ ì¶ì¶ í¬í¼ í¨ì --- 425 const extractList = (text) => { 426 const listRegex = /const\s+articleList\s*=\s*(\[[\s\S]*?\]);/; 427 const match = text.match(listRegex); 428 if (match && match[1]) { 429 try { 430 const cleanStr = match[1].replace(/\/\/.*$/gm, ''); 431 return new Function(`return ${cleanStr}`)(); 432 } catch (e) { return []; } 433 } 434 return []; 435 }; 436 437 // 첫 íì´ì§ ë°ì´í° 먼ì íë³´ 438 let totalRawList = extractList(htmlText); 439 440 // --- [STEP 3] ëë¨¸ì§ íì´ì§ë¤ 'ìì°¨ì ì¼ë¡' ì½ì´ì¤ê¸° --- 441 if (additionalPages.length > 0) { 442 443 for (const url of additionalPages) { 444 try { 445 const res = await fetch(url); 446 const txt = await res.text(); 447 const pageList = extractList(txt); 448 449 // 기존 리ì¤í¸ ë¤ì ììëë¡ ë³í© 450 totalRawList = totalRawList.concat(pageList); 451 console.log(`â [Slider] íì´ì§ ë¡ë ìë£: ${url}`); 452 } catch (err) { 453 console.error(`â [Slider] ${url} ë¡ë ì¤í¨`, err); 454 } 455 } 456 } 457 458 // --- [STEP 4] ìµì¢ íí°ë§ ë° ì ë¬ --- 459 if (Array.isArray(totalRawList) && totalRawList.length > 0) { 460 const seenDoi = new Set(); 461 const finalArticleList = totalRawList.filter(item => { 462 if (item && item.doi && !seenDoi.has(item.doi)) { 463 seenDoi.add(item.doi); 464 return true; 465 } 466 return false; 467 }); 468 469 console.log(`â [Slider] íµí© ìë£ (ì´ ${finalArticleList.length}ê° ë ¼ë¬¸)`); 470 471 // ì´ì ì´ ë¦¬ì¤í¸ë íì´ì§1 -> íì´ì§2 -> íì´ì§3 ììê° ìë²½í ë³´ì¥ë©ëë¤. 472 initMainSlider(finalArticleList); 473 } 474 475 } catch (err) { 476 console.error("â [Slider] ë기í ì¤ ì¤ë¥:", err); 477 } 478} 479 480/** 481 * ë©ì¸ íì´ì§ì©: ëª ë¨ì ë°ì ì¤ì ë°ì´í°ë¥¼ íì±íê³ ì¬ë¼ì´ë를 ì´ê¸°íí¨ 482 */ 483async function initMainSlider(articleList) { 484 if (!articleList || articleList.length === 0) return; 485 486 // 1. DOIê° ìë ì¤ì ë ¼ë¬¸ë§ íí°ë§ 487 const doiItems = articleList.filter(item => item.doi); 488 const firstBatchSize = 2; // 먼ì ëì¸ ê°ì 489 490 // 1. ìì 2ê° ë°ì´í° 먼ì íì± (ìì ë³´ì¥ì ìí´ Promise.all ì¬ì©) 491 console.log("ð [Slider] íì´ë¸ë¦¬ë ë¡ë© ìì (ìì 2ê° ë³ë ¬ + ëë¨¸ì§ ì§ë ¬)"); 492 const firstBatch = doiItems.slice(0, firstBatchSize); 493 if (firstBatch.length > 0) { 494 const firstResults = await Promise.all( 495 firstBatch.map(item => fetchForthcomingArticleData(item.doi, item.im, item.sub)) 496 ); 497 498 // ìì 2ê° ì¦ì íë©´ ì¶ë ¥
499 firstResults.forEach((data, idx) => { 500 if (data && !data.error) { 501 appendMainSlider(data); 502 } 503 }); 504 } 505 506 // 2. ëë¨¸ì§ ë ¼ë¬¸ë¤ ë¡ë© (백그ë¼ì´ëìì ìì°¨ì ì¼ë¡ ì§í) 507 if (doiItems.length > firstBatchSize) { 508 console.log("ð¡ [Slider] 2ë¨ê³: ëë¨¸ì§ ë ¼ë¬¸ 백그ë¼ì´ë ë¡ë© ìì..."); 509 const remainingBatch = doiItems.slice(firstBatchSize); 510 511 // ëë¨¸ì§ í목ë¤ì íëì© ììëë¡ ì²ë¦¬íì¬ ìì 꼬ì ë°©ì§ 512 for (const item of remainingBatch) { 513 try { 514 const data = await fetchForthcomingArticleData(item.doi, item.im, item.sub); 515 if (data && !data.error) { 516 appendMainSlider(data); 517 // console.log(`â [Slider] ìì°¨ ì¶ê° ìë£: ${item.doi}`); 518 } 519 } catch (err) { 520 console.error(`â [Slider] ${item.doi} ì¶ê° ì¤í¨`, err); 521 } 522 } 523 } 524} 525 526 527 528function appendMainSlider(data) { 529 const sliderContainer = document.querySelector('#carousel-highlight .carousel-inner.test'); 530 const highlightWrapper = document.querySelector('.highlight-slider'); 531 if (!sliderContainer) return; 532 533 // íì¬ ì¬ë¼ì´ëì ìì´í ì´ íëë ìëì§ íì¸ (ìµì´ ë¡ë íë³) 534 const isFirstItem = sliderContainer.children.length === 0; 535 const activeClass = isFirstItem ? " active" : ""; 536 537 // ì¬ë¼ì´ë ìì´í ìë ID를 ë¶ì¬íì¬ íì¼ ì²´í¬ í¨ìê° íê²í í ì ìê² í©ëë¤. 538 const sliderItemId = `slider-item-${data.doi.replace(/[^a-zA-Z0-9]/g, '')}`; 539 540 const sliderHtml = ` 541 <div class="carousel-item${activeClass}" id="${sliderItemId}"> 542 <div class="articleBox card border-0"> 543 <div class="row gx-5 gy-3 justify-content-evenly"> 544 <div class="col-md-5 col-xs-6${data.imgDisplay}"> 545 <div class="thumbnail"> 546 <img class="img-fluid myImg" src="${data.imgSrc}" alt="Article Image"> 547 </div> 548 </div> 549 <div class="${data.sliderclassName}"> 550 <div class="content"> 551 <div> 552 <div class="d-flex justify-content-between">${data.subject}<span class="Forthcoming">Forthcoming</span></div> 553 <div class="sub_articleType">${data.subsubject}</div> 554 </div> 555 <div class="card-text title"><a href="${data.link}">${data.title}</a></div> 556 <div class="card-text author">${data.author}</div> 557 <div class="card-text disc"> 558 <div>${data.history}</div> 559 <div>${data.epub}</div> 560 <div><a href="https://doi.org/${data.doi}">https://doi.org/${data.doi}</a></div> 561 </div> 562 <div class="card-text doi"></div> 563 <div class="card-text doi"></div> 564 </div> 565 </div> 566 </div> 567 </div> 568 </div> 569 `; 570 571 // ììëë¡ ë§¨ ë¤ì ì½ì 572 sliderContainer.insertAdjacentHTML('beforeend', sliderHtml); 573 574 // íì¼ ì²´í¬ ì¤í 575 const currentSliderItem = document.getElementById(sliderItemId); 576 if (currentSliderItem && typeof checkAdditionalFiles === 'function') { 577 // 기존 리ì¤í¸ íì´ì§ì ëì¼íê² ììì ë°ì´í°ë¥¼ ë겨ì¤ëë¤. 578 checkAdditionalFiles(currentSliderItem, data); 579 } 580 581 // 첫 ìì´í ë¡ë ì ì¬ë¼ì´ë ì ì²´ ìì ë ¸ì¶ 582 if (isFirstItem && highlightWrapper) { 583 highlightWrapper.classList.add('loaded'); 584 } 585 586 // Bootstrap Carousel ìí ì ë°ì´í¸ 587 const carouselEl = document.querySelector('#carousel-highlight'); 588 if (carouselEl && typeof bootstrap !== 'undefined') {
589 let carousel = bootstrap.Carousel.getInstance(carouselEl); 590 if (!carousel) { 591 // ì¸ì¤í´ì¤ê° ìì¼ë©´ ìë¡ ìì± (ìë ì¬ì ìì) 592 carousel = new bootstrap.Carousel(carouselEl, { 593 interval: 5000, 594 ride: 'carousel', 595 }); 596 carousel.cycle(); 597 } else { 598 // â ï¸ ì´ë¯¸ ì¤í ì¤ì¸ ê²½ì°, ìë¡ì´ ìì´í ì ì¸ììí¤ê¸° ìí´ ì¸ë²¤í 리 ì ë°ì´í¸ 599 // Bootstrap 5ë DOM ë³í를 ê°ì§íì§ë§, ëëë¡ ëª ìì ì¸ cycle() í¸ì¶ì´ íìí©ëë¤. 600 if (isFirstItem) { 601 carousel.to(0); 602 carousel.cycle(); 603 } 604 } 605 } 606} 607
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.