PageSourceSearch

https://www.moneyplants.in/academy/academy.1782991374.js

js moneyplants.in collected 2026-10-03 20:08:59 UTC 13,573 bytes, 86 lines download raw bytes

1document.addEventListener('DOMContentLoaded',function(){const basePath=window.MONEYPLANTS_BASE_PATH||'';const API_BASE_URL=basePath+'academy/api.php';const LOGO_PATH=window.MONEYPLANTS_LOGO_PATH||'assets/img/logo.png';const PLACEHOLDER_PATH=window.MONEYPLANTS_BLOG_PLACEHOLDER_PATH||'assets/img/blog/blog-placeholder.webp';const preloader=document.getElementById('preloader');const postsContainer=document.getElementById('blog-posts-container');const paginationContainer=document.getElementById('blog-pagination-container');const searchForm=document.getElementById('blog-search-form');const searchInput=document.getElementById('blog-search-input');const postDetailContentArea=document.getElementById('blog-detail-content-area');const blogDetailTitleEl=document.getElementById('blog-detail-page-title');const blogDetailDescriptionEl=document.getElementById('blog-detail-description');function escapeHtml(unsafe){if(unsafe===null||typeof unsafe==='undefined')return'';return unsafe.toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}
2function showPreloader(){if(preloader)preloader.style.display='flex'}
3function hidePreloader(){if(preloader)preloader.style.display='none'}
4function getYouTubeVideoID(url){if(!url)return null;const regExp=/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;const match=url.match(regExp);return(match&&match[2].length===11)?match[2]:null}
5function setMetaTags(title,description){document.title=title?`${escapeHtml(title)} - MoneyPlants.in Blog`:"MoneyPlants.in Blog";const metaDesc=document.querySelector('meta[name="description"]');if(metaDesc){metaDesc.setAttribute('content',escapeHtml(description).substring(0,300))}}
6function displayPosts(data){if(!postsContainer)return;postsContainer.innerHTML='';if(!data.posts||data.posts.length===0){postsContainer.innerHTML=`
7                <div class="col-12 text-center py-5">
8                    <div class="mb-3"><i class="bi bi-search" style="font-size: 2rem; color: #ccc;"></i></div>
9                    <h4 class="text-muted">No posts found.</h4>
10                    <p>We couldn't find any articles matching your search. Try different keywords.</p>
11                    ${searchInput && searchInput.value ? '<button id="btn-reset-search" class="btn btn-outline-primary mt-2 btn-sm">Clear Search</button>' : ''}
12                </div>`;const resetBtn=document.getElementById('btn-reset-search');if(resetBtn){resetBtn.addEventListener('click',()=>{if(searchInput)searchInput.value='';updateUrlAndFetch(1,'')})}
13if(paginationContainer)paginationContainer.innerHTML='';hidePreloader();return}
14data.posts.forEach(post=>{const postElement=document.createElement('div');postElement.className='col';let postDate='Recently';if(post.date){const dateObj=new Date(post.date);if(!isNaN(dateObj.getTime())){postDate=dateObj.toLocaleDateString('en-US',{year:'numeric',month:'long',day:'numeric'})}}
15const authorName=escapeHtml(post.Author||'MoneyPlants Team');const postTitle=escapeHtml(post.title||'Untitled Post');const authorIconPath=post.AuthorIcon?escapeHtml(post.AuthorIcon):LOGO_PATH;let mediaPreviewHTML='';if(post.Image){mediaPreviewHTML=`<img src="${escapeHtml(post.Image)}" alt="${postTitle}" onerror="this.onerror=null;this.src='${PLACEHOLDER_PATH}';">`}else if(post.YouTube){const videoId=getYouTubeVideoID(post.YouTube);mediaPreviewHTML=videoId?`<img src="https://i.ytimg.com/vi/${videoId}/hqdefault.jpg" alt="${postTitle}">`:`<img src="${PLACEHOLDER_PATH}" alt="${postTitle}">`}else{mediaPreviewHTML=`<img src="${PLACEHOLDER_PATH}" alt="${postTitle}">`}
16let descriptionPreview=post.description?escapeHtml(post.description):'Click to read more...';if(descriptionPreview.length>120){descriptionPreview=descriptionPreview.substring(0,120)+'...'}
17const tagsArray=Array.isArray(post.tags)?post.tags:(post.tags?String(post.tags).split(','):[]);const tagsString=tagsArray.length>0&&tagsArray[0].trim()!==""?escapeHtml(tagsArray[0].trim()):'General';postElement.innerHTML=`
18                <article>
19                    <div class="post-img">
20                        ${mediaPreviewHTML}
21                    </div>
22                    <div class="post-content">
23                        <div class="post-meta mb-2 d-flex justify-content-between align-items-center">
24                             <span class="post-category">${tagsString}</span>
25                             <time class="post-date text-muted small">${postDate}</time>
26                        </div>
27                        <h2 class="title h5 mb-2">
28                            <a href="blog-details.php?slug=${escapeHtml(post.slug)}" class="stretched-link">${postTitle}</a>
29                        </h2>
30                        <p class="mb-0 text-muted small">${descriptionPreview}</p>
31                    </div>
32                </article>
33            `;postsContainer.appendChild(postElement)});renderPagination(data.current_page,data.total_pages,searchInput?searchInput.value.trim():'');hidePreloader()}
34function renderPagination(currentPage,totalPages,currentQuery){if(!paginationContainer)return;paginationContainer.innerHTML='';if(totalPages<=1)return;const createPageLink=(page,iconOrText)=>{const li=document.createElement('li');if(page===currentPage)li.className='active';const a=document.createElement('a');a.href='#';a.innerHTML=iconOrText;a.addEventListener('click',(e)=>{e.preventDefault();if(page!==currentPage){updateUrlAndFetch(page,currentQuery)}});li.appendChild(a);return li};if(currentPage>1){paginationContainer.appendChild(createPageLink(currentPage-1,'<i class="bi bi-chevron-left"></i>'))}
35const startPage=Math.max(1,currentPage-1);const endPage=Math.min(totalPages,currentPage+1);if(startPage>1){paginationContainer.appendChild(createPageLink(1,1));if(startPage>2){const dots=document.createElement('li');dots.innerHTML='<a href="#" onclick="return false;">...</a>';paginationContainer.appendChild(dots)}}
36for(let i=startPage;i<=endPage;i++){paginationContainer.appendChild(createPageLink(i,i))}
37if(endPage<totalPages){if(endPage<totalPages-1){const dots=document.createElement('li');dots.innerHTML='<a href="#" onclick="return false;">...</a>';paginationContainer.appendChild(dots)}
38paginationContainer.appendChild(createPageLink(totalPages,totalPages))}
39if(currentPage<totalPages){paginationContainer.appendChild(createPageLink(currentPage+1,'<i class="bi bi-chevron-right"></i>'))}}
40function fetchBlogPosts(page=1,query=''){showPreloader();let url=`${API_BASE_URL}?action=list_posts&page=${page}&per_page=12`;if(query){url=`${API_BASE_URL}?action=search_posts&query=${encodeURIComponent(query)}&page=${page}&per_page=12`}
41fetch(url).then(response=>{if(!response.ok)throw new Error('Network response was not ok');return response.json()}).then(data=>{if(data.error)throw new Error(data.error);displayPosts(data)}).catch(error=>{console.error('Error fetching posts:',error);if(postsContainer)postsContainer.innerHTML='<div class="col-12 text-center text-danger py-5"><h4>Could not load posts.</h4><p>Please check your connection.</p></div>';hidePreloader()})}
42function updateUrlAndFetch(page,query){const newUrl=`${window.location.pathname}?query=${encodeURIComponent(query)}&page=${page}`;window.history.pushState({page:page,query:query},'',newUrl);fetchBlogPosts(page,query);const searchSection=document.querySelector('.blog-search-container');if(searchSection){const topPos=searchSection.getBoundingClientRect().top+window.scrollY-120;window.scrollTo({top:topPos,behavior:'smooth'})}else{window.scrollTo({top:0,behavior:'smooth'})}}
43function displayPostDetail(post){if(!postDetailContentArea)return;const postTitle=escapeHtml(post.title);let postDate='Recently';if(post.date){const dateObj=new Date(post.date);if(!isNaN(dateObj.getTime())){postDate=dateObj.toLocaleDateString('en-US',{year:'numeric',month:'long',day:'numeric'})}}
44const authorName=escapeHtml(post.Author||'MoneyPlants Team');const authorIconPath=post.AuthorIcon?escapeHtml(post.AuthorIcon):LOGO_PATH;const authorBio=post.author_bio?escapeHtml(post.author_bio):'We help simplify accounting for Mandi merchants.';setMetaTags(postTitle,escapeHtml(post.description));if(blogDetailTitleEl){const titleStr=post.title||'';blogDetailTitleEl.textContent=titleStr;if(titleStr.length>80){blogDetailTitleEl.style.fontSize='clamp(1.4rem, 3.2vw, 2.0rem)';blogDetailTitleEl.style.lineHeight='1.3'}else if(titleStr.length>50){blogDetailTitleEl.style.fontSize='clamp(1.7rem, 3.8vw, 2.3rem)';blogDetailTitleEl.style.lineHeight='1.3'}else{blogDetailTitleEl.style.fontSize='';blogDetailTitleEl.style.lineHeight=''}}
45if(blogDetailDescriptionEl){const descStr=post.description||'';blogDetailDescriptionEl.textContent=descStr;if(descStr.length>180){blogDetailDescriptionEl.style.fontSize='0.95rem';blogDetailDescriptionEl.classList.remove('fs-5')}else if(descStr.length>120){blogDetailDescriptionEl.style.fontSize='1.05rem';blogDetailDescriptionEl.classList.remove('fs-5')}else{blogDetailDescriptionEl.style.fontSize='';blogDetailDescriptionEl.classList.add('fs-5')}}
46let mediaFullHTML='';if(post.Image){mediaFullHTML=`<img src="${escapeHtml(post.Image)}" alt="${postTitle}" onerror="this.onerror=null;this.src='${PLACEHOLDER_PATH}';">`}else if(post.YouTube){const videoId=getYouTubeVideoID(post.YouTube);mediaFullHTML=videoId?`<div class="ratio ratio-16x9"><iframe src="https://www.youtube.com/embed/${videoId}" title="YouTube video player" frameborder="0" allowfullscreen></iframe></div>`:`<img src="${PLACEHOLDER_PATH}" alt="${postTitle}">`}else{mediaFullHTML=`<img src="${PLACEHOLDER_PATH}" alt="${postTitle}">`}
47const tagsArray=Array.isArray(post.tags)?post.tags:(post.tags?String(post.tags).split(','):[]);let tagsHTML='';tagsArray.forEach(tag=>{const t=tag.trim();if(t)tagsHTML+=`<a href="blog.php?query=${encodeURIComponent(t)}">${escapeHtml(t)}
47</a>`});postDetailContentArea.innerHTML=`
48            <article class="article">
49                <div class="entry-media-full mb-4" id="post-media-full">
50                    ${mediaFullHTML}
51                </div>
52                
53                <h2 class="title">${postTitle}</h2>
54                
55                <div class="content mt-3">
56                    ${post.content}
57                </div>
58                
59                <div class="meta-bottom">
60                  <i class="bi bi-tags"></i>
61                  <ul class="tags">
62                    <li>${tagsHTML || '<a href="blog.php">Article</a>'}</li>
63                  </ul>
64                </div>
65            </article>
66            
67            <section class="blog-author mt-4">
68               <div class="author-container">
69                  <img src="${authorIconPath}" alt="${authorName}" onerror="this.onerror=null;this.src='${LOGO_PATH}';">
70                  <div>
71                    <h4>${authorName}</h4>
72                    <div class="social-links">
73                      <a href="https://wa.me/918279111008" target="_blank" rel="noopener noreferrer"><i class="bi bi-whatsapp"></i></a>
74                      <a href="https://www.instagram.com/moneyplants.in" target="_blank" rel="noopener noreferrer"><i class="bi bi-instagram"></i></a>
75                      <a href="https://www.youtube.com/@MoneyPlants-in" target="_blank" rel="noopener noreferrer"><i class="bi bi-youtube"></i></a>
76                      <a href="https://www.facebook.com/people/Moneyplants/61590477064064/" target="_blank" rel="noopener noreferrer"><i class="bi bi-facebook"></i></a>
77                    </div>
78                    <p>${authorBio}</p>
79                  </div>
80               </div>
81            </section>
82        `;hidePreloader()}
83function fetchPostDetail(slug){showPreloader();fetch(`${API_BASE_URL}?action=get_post&slug=${slug}`).then(response=>response.json()).then(data=>{if(data.error)throw new Error(data.error);displayPostDetail(data)}).catch(error=>{console.error('Error fetching post:',error);if(postDetailContentArea)postDetailContentArea.innerHTML=`<div class="alert alert-danger text-center"><strong>Error:</strong> Post not found or removed. <br><a href="blog.php" class="btn btn-outline-danger mt-2">Return to Blog</a></div>`;hidePreloader()})}
84function initFaq(){const faqItems=document.querySelectorAll('.faq-item');if(!faqItems.length)return;faqItems.forEach(faqItem=>{if(!faqItem.dataset.faqInitialized){faqItem.dataset.faqInitialized="true";faqItem.addEventListener('click',(e)=>{if(e.target.closest('.faq-content')){return}
85faqItem.classList.toggle('faq-active')})}})}
86initFaq();if(postsContainer){const urlParams=new URLSearchParams(window.location.search);const queryFromUrl=urlParams.get('query')||'';const pageFromUrl=parseInt(urlParams.get('page'),10)||1;if(searchInput)searchInput.value=queryFromUrl;fetchBlogPosts(pageFromUrl,queryFromUrl);window.addEventListener('popstate',function(event){const state=event.state;if(state){if(searchInput)searchInput.value=state.query||'';fetchBlogPosts(state.page,state.query)}else{fetchBlogPosts(1,'')}});if(searchForm){searchForm.addEventListener('submit',function(e){e.preventDefault();const q=searchInput.value.trim();updateUrlAndFetch(1,q)})}}else if(postDetailContentArea){const slug=new URLSearchParams(window.location.search).get('slug');const ssrContentExists=postDetailContentArea.querySelector('.post-content-body');if(slug&&!ssrContentExists){fetchPostDetail(slug)}else if(!slug){postDetailContentArea.innerHTML='<div class="alert alert-warning text-center">No post specified. <a href="blog.php">Go back to Blog</a></div>';hidePreloader()}else{hidePreloader()}}else{hidePreloader()}})

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.