1function loadPageDataHanhTrinh(page) { 2 $.ajax({ 3 url: "/service/api/article/list", 4 dataType: "jsonp", 5 jsonp: "jsonCallback", 6 data: { 7 scUnitMapId: $("#site_id").html(), 8 saArticleCateId: "8a10ed229a2f4095019aa07d75ad6684", 9 first: 0, 10 pageSize: 52, 11 }, 12 success: function (res) { 13 if (res && res.response) { 14 const container = $(".milestones-swiper .swiper-wrapper"); 15 16 // Clear existing content if needed 17 container.empty(); 18 let first = ""; 19 // Loop through each item in the response 20 res.response.forEach((item, index) => { 21 // Featured item (first one) 22 23 first += ` 24 <div class="swiper-slide" data-year="${item.subTitle 25 }" data-title="${item.title}" data-content='${JSON.stringify( 26 item.lead || "" 27 )}' data-img="${item.avatarApp}"> 28 <div 29 class="group transition-all duration-300 mx-auto rounded-xl shadow-lg bg-white border border-gray-100 w-[80%] md:w-88 min-h-[320px] sm:min-h-[460px] md:min-h-88 2xl:w-96 2xl:min-h-96 flex flex-col" 30 > 31 <div 32 class="relative w-full aspect-[16/9] rounded-t-xl overflow-hidden" 33 > 34 <img 35 alt="NÄm ${item.subTitle}" 36 class="object-cover" 37 sizes="100vw" 38 src="${item.avatarApp}" 39 style=" 40 position: absolute; 41 height: 100%; 42 width: 100%; 43 inset: 0px; 44 color: transparent; 45 " 46 /> 47 </div> 48 <div 49 class="h-1 w-full bg-gradient-to-r from-blue-600 to-sky-400" 50 ></div> 51 <div class="flex-1 px-6 pt-4 pb-6 flex flex-col"> 52 <span class="font-medium text-gray-500 mb-1" 53 > ${item.subTitle.includes("/") 54 ? item.subTitle 55 : "NÄm " + item.subTitle 56 }</span 57 ><span 58 class="font-medium text-lg text-gray-800 line-clamp-2 md:line-clamp-4" 59 >${item.title}</span 60 > 61 </div> 62 <div 63 data-index="${index}" 64 class="btn-detail flex item-center px-6 !pb-4 text-blue-600 cursor-pointer hover:opacity-80"><span class="text-lg font-medium mr-[2px]">Chi tiết</span><svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-up-right" aria-hidden="true"><path d="M7 7h10v10"></path><path d="M7 17 17 7"></path></svg></div> 65 </div> 66 </div> 67 68 `; 69 }); 70 71 container.append(first); 72 73 // ===== 1. Thu tháºÂp text ÃâÃ¡Â»Æ tạo timeline ===== 74 var mainSlides = document.querySelectorAll( 75 ".main-swiper .swiper-slide" 76 ); 77 var timelineWrapper = document.querySelector( 78 ".timeline-swiper .swiper-wrapper" 79 ); 80 81 // tạo slide timeline tðáng ứng 82 mainSlides.forEach((slide) => { 83 var year = slide.dataset.year || slide.innerText.trim(); 84 var el = document.createElement("div"); 85 el.classList.add("swiper-slide"); 86 if (year.includes("/")) { 87 el.textContent = year; 88 } else { 89 el.textContent = "NÄm " + year; 90 } 91 timelineWrapper.appendChild(el); 92 }); 93 94 // ===== 2. Khởi tạo timeline swiper ===== 95 var timelineSwiper = new Swiper(".timeline-swiper", { 96 slidesPerView: 8, 97 centeredSlides: false, 98 slidesPerGroup: 1, 99 breakpoints: { 100 360: { 101 slidesPerView: 2, 102 }, 103 768: { 104 slidesPerView: 8, 105 }, 106 }, 107 }); 108 109 // ===== 3. Khởi tạo main swiper vÄ link thumbs ===== 110 var mainSwiper = new Swiper(".main-swiper", { 111 slidesPerView: 1, 112 centeredSlides: true, 113 spaceBetween: 20, 114 initialSlide: 1, 115 loop: false, 116 breakpoints: { 117 768: { 118 slidesPerView: 3, 119 }, 120 }, 121 navigation: { 122 nextEl: "#cac-moc-phat-trien .btn-next", 123 prevEl: "#cac-moc-phat-trien .btn-prev", 124 }, 125 }); 126 127 // ===== 1. Update indicator and scroll timeline if needed ===== 128 function updateIndicator(activeIndex) { 129 130 // Scroll timeline if out of view 131 var firstVisible = timelineSwiper.activeIndex; 132 var notChangePosition = false; 133 var lastVisible = 134 firstVisible + timelineSwiper.params.slidesPerView - 1; 135 136 var changeHide = null; 137 if (activeIndex > lastVisible) { 138 const rest = activeIndex - lastVisible 139 140 timelineSwiper.slideTo(firstVisible + rest); 141 notChangePosition = true; 142 changeHide = 1222.5; 143 } else if (activeIndex < firstVisible) { 144 const rest = firstVisible - activeIndex 145 timelineSwiper.slideTo(firstVisible - rest); 146 notChangePosition = true; 147 changeHide = 81.5; 148 149 150 } 151 152 var indicator = document.querySelector(".indicator"); 153 var timelineSlides = timelineSwiper.slides; 154 var activeSlide = timelineSlides[activeIndex]; 155 console.log("activeSlide",activeSlide) 156 157 if (!activeSlide) return; 158 159 console.log("activeIndex",activeIndex) 160 updateActiveTimeline(activeIndex); 161 162 // Move indicator 163 var rect = activeSlide.getBoundingClientRect(); 164 var wrapperRect = document 165 .querySelector(".timeline-wrapper") 166 .getBoundingClientRect(); 167 168 var x = rect.left + rect.width / 2 - wrapperRect.left; 169 if(changeHide != null) { 170 indicator.style.transform = `translateX(${changeHide - 12}px)`; 171 changeHide = null; 172 } 173 if (!notChangePosition) { 174 indicator.style.transform = `translateX(${x - 12}px)`; 175 } 176 } 177 178 // ===== 2. Sync from mainSwiper to timeline ===== 179 mainSwiper.on("slideChange", function () { 180 var activeIndex = mainSwiper.activeIndex; 181 updateIndicator(activeIndex); 182 }); 183 184 // ===== 3. Sync from timeline click to mainSwiper ===== 185 timelineSwiper.on("click", function (swiper, e) { 186 var clickedIndex = swiper.clickedIndex; 187 if (clickedIndex === undefined) return; 188 mainSwiper.slideTo(clickedIndex); 189 updateIndicator(clickedIndex); 190 }); 191 192 // ===== 4. Initial indicator ===== 193 setTimeout(() => updateIndicator(mainSwiper.activeIndex), 300); 194 } 195 }, 196 error: function (err) { 197 console.log("err", err); 198 }, 199 }); 200} 201if ($("#cac-moc-phat-trien").length > 0) { 202 loadPageDataHanhTrinh(); 203} 204 205// === CLICK CHI TIẾT === 206$(document).on("click", ".btn-detail", function () { 207 const slide = $(this).closest(".swiper-slide"); 208 209 const year = slide.data("year") + ""; 210 const title = slide.data("title"); 211 const img = slide.data("img"); 212 const content = slide.data("content") || ""; 213 214 // GÄ¡n vÄ o popup 215 if (year.includes("/")) { 216 $("#popupYear").text(year); 217 } else { 218 $("#popupYear").text("NÄm " + year); 219 } 220 $("#popupTitle").text(title); 221 $("#popupImg").attr("src", img); 222 223 try { 224 $("#popupContent").html(JSON.parse(content)); 225 } catch (e) { 226 $("#popupContent").html(content); 227 } 228 229 $("#popupHanhTrinh").removeClass("hidden"); 230}); 231 232$(document).on("click", "#closePopupHanhTrinh", function () { 233 $("#popupHanhTrinh").addClass("hidden"); 234}); 235$(document).on("click", "#popupHanhTrinh", function (e) { 236 if (e.target.id === "popupHanhTrinh") { 237 $("#popupHanhTrinh").addClass("hidden"); 238 } 239}); 240 241$(document).on("click", ".btn-songphuong", function () { 242 243 244 const title = $("#songphuong .title").html(); 245 const img = $("#songphuong .img").html(); 246 const content = $("#songphuong .content").html(); 247 248 // GÄ¡n vÄ o popup 249 250 $("#popupYear").text(title); 251 $("#popupImg").attr("src", img); 252 253 try { 254 $("#popupContent").html(JSON.parse(content)); 255 } catch (e) { 256 $("#popupContent").html(content); 257 } 258 259 $("#popupHanhTrinh").removeClass("hidden"); 260}); 261 262$(document).on("click", ".btn-daphuong", function () { 263 264 265 const title = $("#daphuong .title").html(); 266 const img = $("#daphuong .img").html(); 267 const content = $("#daphuong .content").html(); 268 269 // GÄ¡n vÄ o popup 270 271 $("#popupYear").text(title); 272 $("#popupImg").attr("src", img); 273 274 try { 275 $("#popupContent").html(JSON.parse(content)); 276 } catch (e) { 277 $("#popupContent").html(content); 278 } 279 280 $("#popupHanhTrinh").removeClass("hidden"); 281}); 282 283$(document).on("click", "#closePopupHanhTrinh", function () { 284 $("#popupHanhTrinh").addClass("hidden"); 285}); 286$(document).on("click", "#popupHanhTrinh", function (e) { 287 if (e.target.id === "popupHanhTrinh") { 288 $("#popupHanhTrinh").addClass("hidden"); 289 } 290}); 291 292function updateActiveTimeline(index) { 293 const slides = document.querySelectorAll(".timeline-swiper .swiper-slide"); 294
295 slides.forEach((s, i) => { 296 if (i === index) { 297 s.classList.add( 298 "!text-blue-600", 299 "cursor-pointer", 300 "transition", 301 "text-blue-600", 302 "!font-bold", 303 "timeline-active" 304 ); 305 } else { 306 s.classList.remove( 307 "!text-blue-600", 308 "cursor-pointer", 309 "transition", 310 "text-blue-600", 311 "!font-bold", 312 "timeline-active" 313 ); 314 } 315 }); 316}
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.