(function(){
var A2HS_AUTO = !!(window.dnA2hsCfg&&window.dnA2hsCfg.auto);
var ua=navigator.userAgent||'';
var isIOS=/iPad|iPhone|iPod/.test(ua)&&!window.MSStream;
var isAndroid=/Android/.test(ua);
var inappPatterns={
'kakao':/KAKAOTALK/i,
'facebook':/FBAN|FBAV|FB_IAB/i,
'instagram': /Instagram/i,
'naver':/NAVER\(inapp/i,
'band':/BAND\//i,
'line':/\bLine\//i,
'daum':/DaumApps|DaumDevice/i,
'kakaostory':/KAKAOSTORY/i,
'everytime': /everytime/i,
'zalo':/Zalo/i
};
function detectInapp(){
for (var k in inappPatterns){
if(inappPatterns[k].test(ua)) return k;
}
return null;
}
function inappLabel(k){
return {
kakao:'카카오톡', facebook:'페이스북', instagram:'인스타그램',
naver:'네이버', band:'밴드', line:'라인', daum:'다음',
kakaostory:'카카오스토리', everytime:'에브리타임', zalo:'Zalo'
}[k]||'인앱';
}
var modal=document.getElementById('dn-a2hs-modal');
if(!modal) return;
var body=modal.querySelector('.dn-a2hs-body');
var okBtn=modal.querySelector('.dn-a2hs-ok');
var xBtn=modal.querySelector('.dn-a2hs-close');
var deferredPrompt=(window.__dnBIP||null);
var btnsContainer=modal.querySelector('.dn-a2hs-btns');
function openModal(html){
body.innerHTML=html;
modal.classList.add('show');
}
function closeModal(){ modal.classList.remove('show'); }
okBtn.addEventListener('click', closeModal);
xBtn.addEventListener('click', closeModal);
modal.addEventListener('click', function(e){ if(e.target===modal) closeModal(); });
var MIN_INSTALLING_MS=15000;
var INSTALL_FALLBACK_MS=18000;
var PROGRESS_R=40;
var PROGRESS_CIRC=2 * Math.PI * PROGRESS_R;
var installMinDelayTimer=null;
var installFallbackTimer=null;
var installProgressTimer=null;
var isInstallingShown=false;
var installEventReceived=false;
var installMinElapsed=false;
function showInstallingModal(){
isInstallingShown=true;
installEventReceived=false;
installMinElapsed=false;
body.innerHTML =
'<div class="dn-a2hs-progress" aria-hidden="true">' +
'  <svg viewBox="0 0 100 100">' +
'    <circle class="dn-a2hs-pg-bg" cx="50" cy="50" r="' + PROGRESS_R + '"/>' +
'    <circle class="dn-a2hs-pg-fg" cx="50" cy="50" r="' + PROGRESS_R + '" ' +
'      stroke-dasharray="' + PROGRESS_CIRC + '" stroke-dashoffset="' + PROGRESS_CIRC + '"/>' +
'  </svg>' +
'  <div class="dn-a2hs-pct">0%</div>' +
'</div>' +
'<p style="font-size:14.5px;color:#1a3a6c;font-weight:600;margin-bottom:6px">📥 설치 중...</p>' +
'<p style="font-size:12.5px;color:#666">홈 화면에 아이콘을 추가하고 있습니다.<br>잠시만 기다려주세요.</p>';
btnsContainer.innerHTML =
'<button type="button" class="dn-a2hs-btn" style="background:#eef0f4;color:#555" disabled>닫기</button>' +
'<button type="button" class="dn-a2hs-btn dn-a2hs-ok" disabled>앱으로 보기</button>';
modal.classList.add('show');
var start=Date.now();
var fg=body.querySelector('.dn-a2hs-pg-fg');
var pct=body.querySelector('.dn-a2hs-pct');
installProgressTimer=setInterval(function(){
var elapsed=Date.now() - start;
var p=Math.min(1, elapsed / MIN_INSTALLING_MS);
if(fg)  fg.setAttribute('stroke-dashoffset', String(PROGRESS_CIRC * (1 - p)));
if(pct) pct.textContent=Math.round(p * 100) + '%';
if(p >=1){ clearInterval(installProgressTimer); installProgressTimer=null; }}, 100);
installMinDelayTimer=setTimeout(function(){
installMinElapsed=true;
if(installEventReceived) showPostInstallModal();
}, MIN_INSTALLING_MS);
installFallbackTimer=setTimeout(function(){
if(isInstallingShown) showPostInstallModal();
}, INSTALL_FALLBACK_MS);
}
function showPostInstallModal(){
if(installMinDelayTimer){ clearTimeout(installMinDelayTimer); installMinDelayTimer=null; }
if(installFallbackTimer){ clearTimeout(installFallbackTimer); installFallbackTimer=null; }
if(installProgressTimer){ clearInterval(installProgressTimer); installProgressTimer=null; }
isInstallingShown=false;
body.innerHTML =
'<p style="font-size:14.5px;color:#1a3a6c;font-weight:600;margin-bottom:10px">✅ 설치 완료!</p>' +
'<p>주소창 없는 <b>앱 전용 화면</b>으로 더 깔끔하게 볼 수 있습니다.<br>지금 앱으로 여시겠습니까?</p>' +
'<div class="dn-a2hs-steps" style="margin-top:2px">📌 <b>홈 화면</b>에 아이콘이 안 보이나요?<br>앱 목록(앱 서랍)에서 <b>한상데일리뉴스</b> 아이콘을 <b>길게 눌러</b> <b>&ldquo;홈 화면에 추가&rdquo;</b> 를 선택하세요. (홈 화면이 꽉 찼으면 자동으로 다음 화면에 추가됩니다)</div>';
btnsContainer.innerHTML =
'<button type="button" class="dn-a2hs-btn" id="dn-a2hs-later" style="background:#eef0f4;color:#555">닫기</button>' +
'<button type="button" class="dn-a2hs-btn dn-a2hs-ok">앱으로 보기</button>';
modal.querySelector('#dn-a2hs-later').addEventListener('click', closeModal);
modal.querySelector('.dn-a2hs-ok').addEventListener('click', function(){
try { window.open(location.origin + '/', '_blank'); } catch(e){}
showAppOpenedModal();
});
modal.classList.add('show');
}
function showAppOpenedModal(){
body.innerHTML =
'<p style="font-size:14.5px;color:#1a3a6c;font-weight:600;margin-bottom:10px">📱 앱이 열렸습니다</p>' +
'<p>홈 화면의 <b>한상데일리뉴스</b> 아이콘으로 앱이 실행되었습니다.<br>이 브라우저 탭은 닫으셔도 됩니다.</p>';
btnsContainer.innerHTML='<button type="button" class="dn-a2hs-btn dn-a2hs-ok">확인</button>';
modal.querySelector('.dn-a2hs-ok').addEventListener('click', closeModal);
}
function markInstalled(){
installEventReceived=true;
if(!isInstallingShown){ showPostInstallModal(); return; }
if(installMinElapsed) showPostInstallModal();
}
window.addEventListener('beforeinstallprompt', function(e){
e.preventDefault();
deferredPrompt=e;
window.__dnBIP=e;
});
window.addEventListener('appinstalled', markInstalled);
function isStandalone(){
return (window.matchMedia&&window.matchMedia('(display-mode: standalone)').matches)
|| window.navigator.standalone===true;
}
window.dnAddToHomeScreen=function(){
if(!deferredPrompt&&window.__dnBIP) deferredPrompt=window.__dnBIP;
if(isStandalone()){
openModal('<p>이미 홈 화면에 추가된 앱으로 실행중입니다.</p>');
return;
}
var inapp=detectInapp();
if(inapp){
openInAppRedirectGuide(inapp);
return;
}
if(isAndroid&&deferredPrompt){
try {
deferredPrompt.prompt();
deferredPrompt.userChoice.then(function(choice){
if(choice&&choice.outcome==='accepted'){
showInstallingModal();   // "설치 중..." 15초 진행률 표시 → appinstalled 대기
}
deferredPrompt=null;
});
} catch(e){
openAndroidManualGuide();
}
return;
}
if(isIOS){
if(isIOSSafari()) openIOSGuide();
else               openIOSNonSafariGuide();
}else if(isAndroid){
openAndroidManualGuide();
}else{
openDesktopGuide();
}};
function openInAppRedirectGuide(inapp){
var name=inappLabel(inapp);
var href=location.href;
if(isAndroid){
body.innerHTML =
'<p><b>' + name + '</b> 브라우저에서는 홈 화면에 추가를 지원하지 않습니다.<br>' +
'<b>크롬</b> 등 외부 브라우저에서 열어주세요.</p>' +
'<div class="dn-a2hs-steps">' +
'1. 아래 <b>&ldquo;크롬으로 열기&rdquo;</b> 버튼 터치<br>' +
'2. 크롬에서 열리면 이 메뉴의 <b>&ldquo;홈 화면에 추가&rdquo;</b> 를 다시 눌러주세요' +
'</div>';
var btnsEl=modal.querySelector('.dn-a2hs-btns');
btnsEl.innerHTML =
'<button type="button" class="dn-a2hs-btn" id="dn-a2hs-chrome" style="background:#eef0f4;color:#555">닫기</button>' +
'<button type="button" class="dn-a2hs-btn dn-a2hs-ok">크롬으로 열기</button>';
modal.classList.add('show');
modal.querySelector('#dn-a2hs-chrome').addEventListener('click', closeModal);
modal.querySelector('.dn-a2hs-ok').addEventListener('click', function(){
var clean=href.split('#')[0];
var targetUrl=clean + (clean.indexOf('?')===-1 ? '?':'&') + 'a2hs_reset=1';
var url=targetUrl.replace(/^https?:\/\//, '');
var intent='i
+ 'S.browser_fallback_url=' + encodeURIComponent(targetUrl) + ';end';
try { location.href=intent; } catch(e){}});
}else if(isIOS){
body.innerHTML =
'<p><b>' + name + '</b> 브라우저에서는 홈 화면에 추가를 지원하지 않습니다.<br>' +
'<b>Safari</b> 에서 열어주세요.</p>' +
'<div class="dn-a2hs-steps">' +
'1. 아래 <b>&ldquo;주소 복사&rdquo;</b> 버튼 터치<br>' +
'2. <b>Safari</b> 앱 실행<br>' +
'3. 주소창에 붙여넣기 후 이동<br>' +
'4. Safari 에서 이 메뉴의 <b>&ldquo;홈 화면에 추가&rdquo;</b> 를 다시 눌러주세요' +
'</div>';
var btnsEl2=modal.querySelector('.dn-a2hs-btns');
btnsEl2.innerHTML =
'<button type="button" class="dn-a2hs-btn" id="dn-a2hs-close2" style="background:#eef0f4;color:#555">닫기</button>' +
'<button type="button" class="dn-a2hs-btn dn-a2hs-ok">주소 복사</button>';
modal.classList.add('show');
modal.querySelector('#dn-a2hs-close2').addEventListener('click', closeModal);
modal.querySelector('.dn-a2hs-ok').addEventListener('click', function(){
copyToClipboard(href);
body.innerHTML =
'<p>✅ 주소가 복사되었습니다.<br>이제 <b>Safari</b> 앱을 열고 주소창에 붙여넣기 해주세요.</p>' +
'<div class="dn-a2hs-steps" style="word-break:break-all;font-size:11.5px;color:#666">' + href + '</div>';
modal.querySelector('.dn-a2hs-btns').innerHTML =
'<button type="button" class="dn-a2hs-btn dn-a2hs-ok">확인</button>';
modal.querySelector('.dn-a2hs-ok').addEventListener('click', closeModal);
});
}else{
openModal('<p><b>' + name + '</b> 브라우저에서는 홈 화면에 추가를 지원하지 않습니다.<br>외부 브라우저에서 열어주세요.</p>');
}}
function copyToClipboard(text){
try {
if(navigator.clipboard&&navigator.clipboard.writeText){
navigator.clipboard.writeText(text);
return;
}} catch(e){}
var ta=document.createElement('textarea');
ta.value=text; ta.style.position='fixed'; ta.style.opacity='0';
document.body.appendChild(ta); ta.select();
try { document.execCommand ('copy'); } catch(e){}
document.body.removeChild(ta);
}
function isIOSSafari(){
return isIOS&&/Safari/.test(ua)
&& !/CriOS|FxiOS|EdgiOS|OPiOS|Whale|NAVER|DaumApps|KAKAOTALK|\bLine\/|FBAN|FBAV|FB_IAB|Instagram|Zalo/i.test(ua);
}
function iosShareIcon(sz){
sz=sz||22;
return '<svg width="' + sz + '" height="' + sz + '" viewBox="0 0 24 24" fill="none" stroke="#007aff" '
+ 'stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:middle">'
+ '<path d="M12 3v12"/><path d="M8 7l4-4 4 4"/>'
+ '<path d="M6 11H5a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-7a1 1 0 0 0-1-1h-1"/></svg>';
}
function openIOSGuide(){
body.innerHTML =
'<p><b>Safari</b> 의 <b>공유 버튼</b> 을 눌러 홈 화면에 추가하세요.</p>' +
'<div style="display:flex;align-items:center;justify-content:center;gap:10px;background:#f0f6ff;border:1px solid #d6e6ff;border-radius:12px;padding:12px;margin:2px 0 12px">' +
'<span style="width:42px;height:42px;border-radius:11px;background:#fff;box-shadow:0 1px 5px rgba(0,0,0,.14);display:inline-flex;align-items:center;justify-content:center">' + iosShareIcon(24) + '</span>' +
'<span style="font-size:12.5px;color:#007aff;font-weight:700">이 공유 아이콘을<br>찾으세요</span>' +
'</div>' +
'<div class="dn-a2hs-steps">' +
'<b>1.</b> Safari 화면 <b>하단</b>(구형 아이폰은 상단)의 <b>공유</b> 버튼 ' + iosShareIcon(15) + ' 탭<br>' +
'<b>2.</b> 목록을 아래로 내려 <b>&ldquo;홈 화면에 추가&rdquo;</b> 탭<br>' +
'<b>3.</b> 오른쪽 위 <b>&ldquo;추가&rdquo;</b> 탭 → 완료!' +
'</div>' +
'<p style="font-size:11.5px;color:#888;margin:0">※ 아이폰은 <b>Safari</b> 에서만 홈 화면 추가가 됩니다.</p>';
var btnsEl=modal.querySelector('.dn-a2hs-btns');
btnsEl.innerHTML='<button type="button" class="dn-a2hs-btn dn-a2hs-ok">확인</button>';
btnsEl.querySelector('.dn-a2hs-ok').addEventListener('click', closeModal);
modal.classList.add('show');
}
function openIOSNonSafariGuide(){
var href=location.href;
body.innerHTML =
'<p>이 브라우저에서는 홈 화면 추가가 <b>안 됩니다</b>.<br>아이폰은 <b>Safari</b> 브라우저에서만 가능합니다.</p>' +
'<div class="dn-a2hs-steps">' +
'<b>1.</b> 아래 <b>&ldquo;주소 복사&rdquo;</b> 탭<br>' +
'<b>2.</b> <b>Safari</b> 앱 실행 → 주소창에 붙여넣기<br>' +
'<b>3.</b> Safari 에서 이 메뉴의 <b>&ldquo;홈 화면 바로가기&rdquo;</b> 를 다시 탭' +
'</div>';
var btnsEl=modal.querySelector('.dn-a2hs-btns');
btnsEl.innerHTML =
'<button type="button" class="dn-a2hs-btn" id="dn-a2hs-ios-close" style="background:#eef0f4;color:#555">닫기</button>' +
'<button type="button" class="dn-a2hs-btn dn-a2hs-ok">주소 복사</button>';
modal.classList.add('show');
modal.querySelector('#dn-a2hs-ios-close').addEventListener('click', closeModal);
modal.querySelector('.dn-a2hs-ok').addEventListener('click', function(){
copyToClipboard(href);
body.innerHTML =
'<p>✅ 주소가 복사되었습니다.<br>이제 <b>Safari</b> 앱을 열고 주소창에 붙여넣기 하세요.</p>' +
'<div class="dn-a2hs-steps" style="word-break:break-all;font-size:11.5px;color:#666">' + href + '</div>';
modal.querySelector('.dn-a2hs-btns').innerHTML =
'<button type="button" class="dn-a2hs-btn dn-a2hs-ok">확인</button>';
modal.querySelector('.dn-a2hs-ok').addEventListener('click', closeModal);
});
}
function openAndroidManualGuide(){
openModal(
'<p>크롬 메뉴에서 직접 홈 화면에 추가할 수 있습니다.</p>' +
'<div class="dn-a2hs-steps">' +
'1. 주소창 오른쪽 <b>&vellip; (메뉴)</b> 터치<br>' +
'2. <b>&ldquo;홈 화면에 추가&rdquo;</b> 또는 <b>&ldquo;앱 설치&rdquo;</b> 선택<br>' +
'3. <b>&ldquo;추가&rdquo;</b> 또는 <b>&ldquo;설치&rdquo;</b> 터치' +
'</div>'
);
}
function openDesktopGuide(){
openModal('<p>모바일 기기(스마트폰)에서 이 페이지에 접속한 뒤 이 버튼을 눌러주세요.</p>');
}
document.addEventListener('click', function(e){
if(!e.target||!e.target.closest) return;
var t=e.target.closest('.a2hs-trigger, a[href="#add-to-homescreen"], a[href$="#add-to-homescreen"]');
if(!t) return;
e.preventDefault();
window.dnAddToHomeScreen();
}, true);
(function autoBanner(){
if(!A2HS_AUTO) return;
var banner=document.getElementById('dn-a2hs-banner');
if(!banner) return;
var DKEY='dn_a2hs_banner_dismiss', DDAYS=1;
if(/a2hs_reset=1/.test(location.search)||location.hash==='#a2hs-reset'){
try {
localStorage.removeItem(DKEY);
localStorage.removeItem('dn_a2hs_was_installed');
sessionStorage.removeItem('dn_a2hs_shown_session');
} catch(e){}}
function dismissed(){
try { var t=parseInt(localStorage.getItem(DKEY)||'0',10); return t&&(Date.now()-t) < DDAYS*86400000; } catch(e){ return false; }}
function hide(){ banner.classList.remove('show'); }
var SKEY='dn_a2hs_shown_session';
function show(){
if(isStandalone()||window.__dnInstalled) return;
if(dismissed()) return;
try { if(sessionStorage.getItem(SKEY)==='1') return; } catch(e){}
try { sessionStorage.setItem(SKEY, '1'); } catch(e){}
banner.classList.add('show');
}
function dismiss(){ hide(); try { localStorage.setItem(DKEY, String(Date.now())); } catch(e){}}
banner.querySelector('.dn-a2hs-bn-add').addEventListener('click', function(){ hide(); window.dnAddToHomeScreen(); });
banner.querySelector('.dn-a2hs-bn-x').addEventListener('click', dismiss);
var laterBtn=banner.querySelector('.dn-a2hs-bn-later');
if(laterBtn) laterBtn.addEventListener('click', dismiss);
banner.addEventListener('click', function(e){ if(e.target===banner) dismiss(); });
if(isStandalone()) return;
var inapp=detectInapp();
if(inapp){
if(dismissed()) return;
try { if(sessionStorage.getItem(SKEY)==='1') return; sessionStorage.setItem(SKEY, '1'); } catch(e){}
setTimeout(function(){ if(detectInapp()&&!isStandalone()) openInAppRedirectGuide(inapp); }, 1200);
return;
}
function waitAndShow(force){
var start=Date.now();
(function w(){
if(deferredPrompt||window.__dnBIP){ setTimeout(show, 800); return; }
if(Date.now()-start > 3000){ if(force) show(); return; }
setTimeout(w, 200);
})();
}
if(isAndroid){
var WKEY='dn_a2hs_was_installed';
if(navigator.getInstalledRelatedApps){
navigator.getInstalledRelatedApps().then(function(apps){
if(apps&&apps.length > 0){
try { localStorage.setItem(WKEY, '1'); } catch(e){}}else if(localStorage.getItem(WKEY)==='1'){
try {
localStorage.removeItem(WKEY);
localStorage.removeItem(DKEY);
sessionStorage.removeItem(SKEY);
} catch(e){}}
}).catch(function(){});
}
waitAndShow(true);
}else if(isIOS){
var isSafari=/Safari/.test(ua)&&!/CriOS|FxiOS|EdgiOS|OPiOS/.test(ua);
if(isSafari) setTimeout(show, 1500);
}})();
(function autoTriggerFromHash(){
if(!A2HS_AUTO) return;
if(location.hash!=='#add-to-homescreen') return;
if(detectInapp()) return;
if(isStandalone()){ history.replaceState(null, '', location.pathname + location.search); return; }
history.replaceState(null, '', location.pathname + location.search);
function go(){
try { window.dnAddToHomeScreen(); } catch(e){}}
function waitForPrompt(maxMs){
var start=Date.now();
(function check(){
if(deferredPrompt||window.__dnBIP){ go(); return; }
if(Date.now() - start >=maxMs){ go(); return; }
setTimeout(check, 150);
})();
}
if(document.readyState==='complete'||document.readyState==='interactive'){
setTimeout(function(){ waitForPrompt(2500); }, 300);
}else{
window.addEventListener('DOMContentLoaded', function(){
setTimeout(function(){ waitForPrompt(2500); }, 300);
});
}})();
})();