|
|
| Line 1: |
Line 1: |
| <html>
| | <div id="social-app"> |
| <div id="social-app"></div> | | <div style="text-align:center;padding:60px;color:#8e8e8e"> |
| <style>
| | <div style="font-size:48px;margin-bottom:16px">⏳</div> |
| #social-app{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;background:#fafafa;min-height:100vh;padding-bottom:40px}
| | <div>Loading Social Feed...</div> |
| #social-app *{box-sizing:border-box;margin:0;padding:0}
| | </div> |
| .sa-profile-header{background:#fff;border-bottom:1px solid #dbdbdb}
| | </div> |
| .sa-cover{height:200px;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);position:relative}
| |
| .sa-cover img{width:100%;height:100%;object-fit:cover}
| |
| .sa-cover-edit{position:absolute;bottom:12px;right:12px;background:rgba(0,0,0,.6);color:#fff;border:none;padding:8px 16px;border-radius:8px;cursor:pointer;font-size:13px}
| |
| .sa-profile-info{max-width:935px;margin:0 auto;padding:0 20px;display:flex;gap:30px;margin-top:-50px;position:relative;z-index:10}
| |
| .sa-profile-pic{width:150px;height:150px;border-radius:50%;border:4px solid #fff;background:#fff;overflow:hidden;cursor:pointer;flex-shrink:0;box-shadow:0 2px 10px rgba(0,0,0,.1)}
| |
| .sa-profile-pic img{width:100%;height:100%;object-fit:cover}
| |
| .sa-profile-pic-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;color:#fff;font-size:48px;font-weight:600}
| |
| .sa-profile-details{flex:1;padding-top:60px}
| |
| .sa-profile-top{display:flex;align-items:center;gap:20px;margin-bottom:16px;flex-wrap:wrap}
| |
| .sa-username{font-size:28px;font-weight:300}
| |
| .sa-edit-btn{background:#0095f6;color:#fff;border:none;padding:8px 24px;border-radius:8px;font-weight:600;cursor:pointer;font-size:14px}
| |
| .sa-edit-btn:hover{background:#1877f2}
| |
| .sa-stats{display:flex;gap:32px;margin-bottom:16px}
| |
| .sa-stat{text-align:center}
| |
| .sa-stat-num{font-weight:600;font-size:18px}
| |
| .sa-stat-label{color:#8e8e8e;font-size:14px}
| |
| .sa-bio{max-width:400px;line-height:1.5}
| |
| .sa-bio-name{font-weight:600}
| |
| .sa-main{max-width:935px;margin:0 auto;padding:20px}
| |
| .sa-stories{display:flex;gap:16px;padding:16px 0;overflow-x:auto;margin-bottom:20px}
| |
| .sa-story{display:flex;flex-direction:column;align-items:center;gap:8px;cursor:pointer}
| |
| .sa-story-ring{width:66px;height:66px;border-radius:50%;padding:3px;background:linear-gradient(45deg,#f09433,#e6683c,#dc2743,#cc2366,#bc1888)}
| |
| .sa-story-ring.add{background:#dbdbdb}
| |
| .sa-story-ring.seen{background:#dbdbdb}
| |
| .sa-story-inner{width:100%;height:100%;border-radius:50%;border:2px solid #fff;overflow:hidden;background:#fafafa;display:flex;align-items:center;justify-content:center}
| |
| .sa-story-inner img{width:100%;height:100%;object-fit:cover}
| |
| .sa-story-add{font-size:24px;color:#0095f6}
| |
| .sa-story-name{font-size:12px;color:#262626;max-width:66px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
| |
| .sa-composer{background:#fff;border:1px solid #dbdbdb;border-radius:12px;margin-bottom:20px}
| |
| .sa-composer-top{display:flex;gap:12px;padding:16px}
| |
| .sa-composer-avatar{width:44px;height:44px;border-radius:50%;overflow:hidden;flex-shrink:0}
| |
| .sa-composer-avatar img{width:100%;height:100%;object-fit:cover}
| |
| .sa-composer-avatar-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;color:#fff;font-size:16px;font-weight:600}
| |
| .sa-composer-input{flex:1;border:none;resize:none;font-size:16px;line-height:1.5;min-height:60px;outline:none;font-family:inherit}
| |
| .sa-composer-input::placeholder{color:#8e8e8e}
| |
| .sa-composer-preview{padding:0 16px 16px;display:none}
| |
| .sa-composer-preview.show{display:block}
| |
| .sa-composer-preview-inner{position:relative;display:inline-block}
| |
| .sa-composer-preview img,.sa-composer-preview video{max-width:100%;max-height:300px;border-radius:8px}
| |
| .sa-composer-preview-remove{position:absolute;top:8px;right:8px;width:28px;height:28px;border-radius:50%;background:rgba(0,0,0,.7);color:#fff;border:none;cursor:pointer;font-size:16px}
| |
| .sa-composer-location{padding:0 16px 12px;font-size:14px;color:#8e8e8e;display:none}
| |
| .sa-composer-location.show{display:flex;align-items:center;gap:8px}
| |
| .sa-composer-location button{background:none;border:none;cursor:pointer;font-size:14px}
| |
| .sa-composer-actions{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-top:1px solid #efefef}
| |
| .sa-composer-buttons{display:flex;gap:4px}
| |
| .sa-icon-btn{width:40px;height:40px;border:none;background:none;cursor:pointer;font-size:20px;border-radius:50%;transition:background .2s}
| |
| .sa-icon-btn:hover{background:#f0f0f0}
| |
| .sa-post-btn{background:#0095f6;color:#fff;border:none;padding:10px 24px;border-radius:8px;font-weight:600;cursor:pointer;font-size:14px}
| |
| .sa-post-btn:disabled{opacity:.3;cursor:default}
| |
| .sa-post-btn:not(:disabled):hover{background:#1877f2}
| |
| .sa-feed{display:flex;flex-direction:column;gap:20px}
| |
| .sa-post{background:#fff;border:1px solid #dbdbdb;border-radius:12px;overflow:hidden}
| |
| .sa-post-header{display:flex;align-items:center;gap:12px;padding:14px 16px}
| |
| .sa-post-avatar{width:42px;height:42px;border-radius:50%;overflow:hidden}
| |
| .sa-post-avatar img{width:100%;height:100%;object-fit:cover}
| |
| .sa-post-avatar-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;color:#fff;font-size:14px;font-weight:600}
| |
| .sa-post-user{flex:1}
| |
| .sa-post-username{font-weight:600;font-size:14px;color:#262626}
| |
| .sa-post-meta{font-size:12px;color:#8e8e8e}
| |
| .sa-post-menu{background:none;border:none;cursor:pointer;font-size:20px;color:#262626}
| |
| .sa-post-content{padding:0 16px 12px;font-size:15px;line-height:1.5;white-space:pre-wrap}
| |
| .sa-post-location{padding:0 16px 8px;font-size:13px;color:#8e8e8e}
| |
| .sa-post-media{background:#000}
| |
| .sa-post-media img{width:100%;max-height:600px;object-fit:contain}
| |
| .sa-post-media video{width:100%;max-height:600px}
| |
| .sa-post-media iframe{width:100%;height:400px;border:none}
| |
| .sa-post-actions{display:flex;gap:16px;padding:12px 16px}
| |
| .sa-post-action{background:none;border:none;cursor:pointer;font-size:24px;padding:0;transition:transform .2s}
| |
| .sa-post-action:hover{transform:scale(1.1)}
| |
| .sa-post-action.liked{color:#ed4956}
| |
| .sa-post-likes{padding:0 16px 8px;font-weight:600;font-size:14px}
| |
| .sa-post-comments-count{padding:0 16px 8px;font-size:14px;color:#8e8e8e;cursor:pointer}
| |
| .sa-post-time{padding:0 16px 12px;font-size:10px;color:#8e8e8e;text-transform:uppercase}
| |
| .sa-post-comment-form{display:flex;gap:12px;padding:12px 16px;border-top:1px solid #efefef}
| |
| .sa-post-comment-input{flex:1;border:none;font-size:14px;outline:none}
| |
| .sa-post-comment-input::placeholder{color:#8e8e8e}
| |
| .sa-post-comment-submit{background:none;border:none;color:#0095f6;font-weight:600;cursor:pointer;font-size:14px}
| |
| .sa-post-comment-submit:disabled{opacity:.3;cursor:default}
| |
| .sa-comments-section{display:none;padding:0 16px 12px;max-height:300px;overflow-y:auto}
| |
| .sa-comments-section.show{display:block}
| |
| .sa-comment{display:flex;gap:12px;margin-bottom:12px}
| |
| .sa-comment-avatar{width:32px;height:32px;border-radius:50%;overflow:hidden;flex-shrink:0}
| |
| .sa-comment-avatar img{width:100%;height:100%;object-fit:cover}
| |
| .sa-comment-avatar-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;color:#fff;font-size:10px;font-weight:600}
| |
| .sa-comment-body{flex:1}
| |
| .sa-comment-text{font-size:14px;line-height:1.4}
| |
| .sa-comment-text strong{font-weight:600}
| |
| .sa-comment-time{font-size:12px;color:#8e8e8e;margin-top:4px}
| |
| .sa-empty{text-align:center;padding:60px 20px;background:#fff;border:1px solid #dbdbdb;border-radius:12px}
| |
| .sa-empty-icon{font-size:64px;margin-bottom:16px}
| |
| .sa-empty-title{font-size:24px;font-weight:300;margin-bottom:8px}
| |
| .sa-empty-text{color:#8e8e8e}
| |
| .sa-modal{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.65);z-index:1000;align-items:center;justify-content:center;padding:20px}
| |
| .sa-modal.open{display:flex}
| |
| .sa-modal-content{background:#fff;border-radius:12px;width:100%;max-width:500px;max-height:90vh;overflow:auto}
| |
| .sa-modal-header{display:flex;align-items:center;justify-content:space-between;padding:16px;border-bottom:1px solid #dbdbdb}
| |
| .sa-modal-title{font-weight:600;font-size:16px}
| |
| .sa-modal-close{background:none;border:none;font-size:24px;cursor:pointer;padding:0;line-height:1}
| |
| .sa-modal-body{padding:20px}
| |
| .sa-tabs{display:flex;border-bottom:1px solid #dbdbdb}
| |
| .sa-tab{flex:1;padding:16px;text-align:center;cursor:pointer;font-weight:600;color:#8e8e8e;border-bottom:1px solid transparent;margin-bottom:-1px;transition:all .2s}
| |
| .sa-tab:hover{color:#262626}
| |
| .sa-tab.active{color:#262626;border-bottom-color:#262626}
| |
| .sa-tab-panel{display:none;padding:20px}
| |
| .sa-tab-panel.active{display:block}
| |
| .sa-upload-zone{border:2px dashed #dbdbdb;border-radius:8px;padding:40px;text-align:center;cursor:pointer;transition:all .2s}
| |
| .sa-upload-zone:hover{border-color:#0095f6;background:#f0f7ff}
| |
| .sa-upload-zone.dragover{border-color:#0095f6;background:#e3f2fd}
| |
| .sa-upload-zone input{display:none}
| |
| .sa-upload-icon{font-size:48px;margin-bottom:12px}
| |
| .sa-upload-text{color:#8e8e8e}
| |
| .sa-upload-text span{color:#0095f6;font-weight:600}
| |
| .sa-input{width:100%;padding:14px;border:1px solid #dbdbdb;border-radius:8px;font-size:14px;margin-bottom:12px;outline:none;transition:border-color .2s}
| |
| .sa-input:focus{border-color:#262626}
| |
| .sa-textarea{width:100%;padding:14px;border:1px solid #dbdbdb;border-radius:8px;font-size:14px;margin-bottom:12px;outline:none;resize:vertical;min-height:80px;font-family:inherit}
| |
| .sa-textarea:focus{border-color:#262626}
| |
| .sa-preview-img{width:100%;max-height:200px;object-fit:contain;border-radius:8px;margin-top:12px;display:none}
| |
| .sa-preview-img.show{display:block}
| |
| .sa-progress{height:4px;background:#dbdbdb;border-radius:2px;margin-top:12px;overflow:hidden;display:none}
| |
| .sa-progress.show{display:block}
| |
| .sa-progress-bar{height:100%;background:linear-gradient(90deg,#0095f6,#00d4ff);width:0;transition:width .3s}
| |
| .sa-btn-row{display:flex;gap:12px;margin-top:20px}
| |
| .sa-btn{flex:1;padding:14px;border:none;border-radius:8px;font-weight:600;font-size:14px;cursor:pointer;transition:all .2s}
| |
| .sa-btn-primary{background:#0095f6;color:#fff}
| |
| .sa-btn-primary:hover{background:#1877f2}
| |
| .sa-btn-secondary{background:#efefef;color:#262626}
| |
| .sa-btn-secondary:hover{background:#dbdbdb}
| |
| .sa-emoji-picker{position:absolute;bottom:50px;left:0;background:#fff;border-radius:12px;box-shadow:0 0 20px rgba(0,0,0,.15);width:320px;z-index:100;display:none}
| |
| .sa-emoji-picker.open{display:block}
| |
| .sa-emoji-header{display:flex;gap:4px;padding:12px;border-bottom:1px solid #efefef;overflow-x:auto}
| |
| .sa-emoji-cat{background:none;border:none;font-size:20px;padding:8px;cursor:pointer;border-radius:8px;opacity:.5;transition:all .2s}
| |
| .sa-emoji-cat:hover,.sa-emoji-cat.active{opacity:1;background:#efefef}
| |
| .sa-emoji-grid{display:grid;grid-template-columns:repeat(8,1fr);gap:4px;padding:12px;max-height:200px;overflow-y:auto}
| |
| .sa-emoji-btn{background:none;border:none;font-size:24px;padding:4px;cursor:pointer;border-radius:4px;transition:background .2s}
| |
| .sa-emoji-btn:hover{background:#efefef}
| |
| .sa-story-viewer{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:#1a1a1a;z-index:2000;align-items:center;justify-content:center}
| |
| .sa-story-viewer.open{display:flex}
| |
| .sa-story-viewer-content{position:relative;max-width:400px;width:100%}
| |
| .sa-story-viewer-progress{position:absolute;top:16px;left:16px;right:16px;height:2px;background:rgba(255,255,255,.3);border-radius:1px}
| |
| .sa-story-viewer-progress-bar{height:100%;background:#fff;border-radius:1px;width:0}
| |
| .sa-story-viewer-header{position:absolute;top:24px;left:16px;right:16px;display:flex;align-items:center;gap:12px;color:#fff}
| |
| .sa-story-viewer-avatar{width:32px;height:32px;border-radius:50%;overflow:hidden;border:2px solid #fff}
| |
| .sa-story-viewer-avatar img{width:100%;height:100%;object-fit:cover}
| |
| .sa-story-viewer-name{font-weight:600;font-size:14px}
| |
| .sa-story-viewer-close{position:absolute;top:16px;right:16px;background:none;border:none;color:#fff;font-size:28px;cursor:pointer;z-index:10}
| |
| .sa-story-viewer img{max-width:100%;max-height:80vh;border-radius:8px}
| |
| @media(max-width:768px){
| |
| .sa-profile-info{flex-direction:column;align-items:center;text-align:center;margin-top:-75px}
| |
| .sa-profile-pic{width:120px;height:120px}
| |
| .sa-profile-details{padding-top:16px}
| |
| .sa-stats{justify-content:center}
| |
| .sa-bio{margin:0 auto}
| |
| .sa-cover{height:150px}
| |
| }
| |
| </style>
| |
| <script>
| |
| (function(){
| |
| 'use strict';
| |
| function waitForMw(cb,max){var s=Date.now();max=max||10000;(function c(){if(window.jQuery&&window.mw&&mw.loader&&mw.config){cb(window.jQuery,window.mw);}else if(Date.now()-s<max){setTimeout(c,100);}else{document.getElementById('social-app').innerHTML='<div style="padding:40px;text-align:center">Error: MediaWiki not loaded.</div>';}})();}
| |
| waitForMw(function($,mw){mw.loader.using(['mediawiki.api','mediawiki.util']).then(function(){initApp($,mw);}).fail(function(){document.getElementById('social-app').innerHTML='<div style="padding:40px;text-align:center">Error loading modules.</div>';});});
| |
| function initApp($,mw){
| |
| var api=new mw.Api(),apiUrl=mw.util.wikiScript('api'),user=mw.config.get('wgUserName')||'Guest';
| |
| var ud={photo:localStorage.getItem('sf_photo_'+user)||'',cover:localStorage.getItem('sf_cover_'+user)||'',bio:localStorage.getItem('sf_bio_'+user)||'',name:localStorage.getItem('sf_name_'+user)||user};
| |
| var pp={image:'',video:'',location:''},uf={};
| |
| function gi(n){return(n||'?').split(/[\s_]+/).map(function(w){return(w[0]||'').toUpperCase();}).join('').substring(0,2)||'?';}
| |
| function esc(t){var d=document.createElement('div');d.textContent=t;return d.innerHTML;}
| |
| function ago(ds){var s=Math.floor((Date.now()-new Date(ds))/1000);if(s<60)return'Just now';var m=Math.floor(s/60);if(m<60)return m+'m';var h=Math.floor(m/60);if(h<24)return h+'h';return Math.floor(h/24)+'d';}
| |
| function av(pic,name,sz){if(pic)return'<img src="'+esc(pic)+'">';var c=sz==='s'?'sa-comment-avatar-placeholder':sz==='p'?'sa-post-avatar-placeholder':sz==='c'?'sa-composer-avatar-placeholder':'sa-profile-pic-placeholder';return'<div class="'+c+'">'+gi(name)+'</div>';}
| |
| function om(id){$('#'+id).addClass('open');}function cm(id){$('#'+id).removeClass('open');}
| |
| function upload(file,pre,prog){return api.getToken('csrf').then(function(tk){var ext=file.name.split('.').pop()||'jpg',fn=pre+'_'+user+'_'+Date.now()+'.'+ext,fd=new FormData();fd.append('action','upload');fd.append('filename',fn);fd.append('file',file);fd.append('token',tk);fd.append('format','json');fd.append('ignorewarnings','1');return $.ajax({url:apiUrl,type:'POST',data:fd,processData:false,contentType:false,xhr:function(){var x=$.ajaxSettings.xhr();if(x.upload&&prog)x.upload.addEventListener('progress',function(e){if(e.lengthComputable)prog(Math.round(e.loaded/e.total*100));});return x;}});}).then(function(r){if(r.upload&&r.upload.imageinfo)return r.upload.imageinfo.url;throw new Error(r.error?r.error.info:'Upload failed');});}
| |
| function build(){
| |
| var h='<div class="sa-profile-header"><div class="sa-cover" id="cover-area">'+(ud.cover?'<img src="'+esc(ud.cover)+'">':'')+'<button class="sa-cover-edit" id="edit-cover-btn">📷 Edit Cover</button></div><div class="sa-profile-info"><div class="sa-profile-pic" id="profile-pic">'+av(ud.photo,user,'')+'</div><div class="sa-profile-details"><div class="sa-profile-top"><h1 class="sa-username" id="display-name">'+esc(ud.name)+'</h1><button class="sa-edit-btn" id="edit-profile-btn">Edit Profile</button></div><div class="sa-stats"><div class="sa-stat"><div class="sa-stat-num" id="post-count">0</div><div class="sa-stat-label">posts</div></div><div class="sa-stat"><div class="sa-stat-num">0</div><div class="sa-stat-label">followers</div></div><div class="sa-stat"><div class="sa-stat-num">0</div><div class="sa-stat-label">following</div></div></div><div class="sa-bio" id="bio-display">'+(ud.bio?'<div class="sa-bio-name">'+esc(ud.name)+'</div>'+esc(ud.bio).replace(/\n/g,'<br>'):'Click Edit Profile to add a bio')+'</div></div></div></div>';
| |
| h+='<div class="sa-main"><div class="sa-stories" id="stories-container"></div><div class="sa-composer"><div class="sa-composer-top"><div class="sa-composer-avatar" id="composer-avatar">'+av(ud.photo,user,'c')+'</div><textarea class="sa-composer-input" id="post-input" placeholder="What\'s on your mind?"></textarea></div><div class="sa-composer-preview" id="post-preview"><div class="sa-composer-preview-inner"><button class="sa-composer-preview-remove" id="remove-media">×</button></div></div><div class="sa-composer-location" id="post-location">📍 <span></span><button id="remove-location">×</button></div><div class="sa-composer-actions"><div class="sa-composer-buttons" style="position:relative"><button class="sa-icon-btn" id="btn-add-photo">🖼️</button><button class="sa-icon-btn" id="btn-add-video">🎬</button><button class="sa-icon-btn" id="btn-add-location">📍</button><button class="sa-icon-btn" id="btn-add-emoji">😊</button><div class="sa-emoji-picker" id="emoji-picker"></div></div><button class="sa-post-btn" id="btn-submit-post" disabled>Post</button></div></div><div class="sa-feed" id="feed-container"></div></div>';
| |
| h+='<div class="sa-modal" id="modal-edit-profile"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Edit Profile</span><button class="sa-modal-close" data-close="modal-edit-profile">×</button></div><div class="sa-modal-body"><label style="font-weight:600;display:block;margin-bottom:8px">Display Name</label><input class="sa-input" id="input-display-name" value="'+esc(ud.name)+'"><label style="font-weight:600;display:block;margin-bottom:8px">Bio</label><textarea class="sa-textarea" id="input-bio" placeholder="Tell people about yourself...">'+esc(ud.bio)+'</textarea><div class="sa-btn-row"><button class="sa-btn sa-btn-secondary" data-close="modal-edit-profile">Cancel</button><button class="sa-btn sa-btn-primary" id="save-profile">Save</button></div></div></div></div>';
| |
| h+='<div class="sa-modal" id="modal-profile-pic"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Profile Picture</span><button class="sa-modal-close" data-close="modal-profile-pic">×</button></div><div class="sa-tabs"><div class="sa-tab active" data-panel="panel-pic-upload">Upload</div><div class="sa-tab" data-panel="panel-pic-url">URL</div></div><div class="sa-tab-panel active" id="panel-pic-upload"><div class="sa-upload-zone" id="zone-profile-pic"><input type="file" accept="image/*"><div class="sa-upload-icon">📷</div><div class="sa-upload-text">Drag photo here or <span>browse</span></div></div><div class="sa-progress" id="progress-profile-pic"><div class="sa-progress-bar"></div></div><img class="sa-preview-img" id="preview-profile-pic"></div><div class="sa-tab-panel" id="panel-pic-url"><input class="sa-input" id="input-pic-url" placeholder="Paste image URL..."><img class="sa-preview-img" id="preview-pic-url"></div><div class="sa-btn-row" style="padding:0 20px 20px"><button class="sa-btn sa-btn-secondary" data-close="modal-profile-pic">Cancel</button><button class="sa-btn sa-btn-primary" id="save-profile-pic">Save</button></div></div></div>';
| |
| h+='<div class="sa-modal" id="modal-cover"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Cover Photo</span><button class="sa-modal-close" data-close="modal-cover">×</button></div><div class="sa-tabs"><div class="sa-tab active" data-panel="panel-cover-upload">Upload</div><div class="sa-tab" data-panel="panel-cover-url">URL</div></div><div class="sa-tab-panel active" id="panel-cover-upload"><div class="sa-upload-zone" id="zone-cover"><input type="file" accept="image/*"><div class="sa-upload-icon">🖼️</div><div class="sa-upload-text">Drag photo here or <span>browse</span></div></div><div class="sa-progress" id="progress-cover"><div class="sa-progress-bar"></div></div><img class="sa-preview-img" id="preview-cover"></div><div class="sa-tab-panel" id="panel-cover-url"><input class="sa-input" id="input-cover-url" placeholder="Paste image URL..."><img class="sa-preview-img" id="preview-cover-url"></div><div class="sa-btn-row" style="padding:0 20px 20px"><button class="sa-btn sa-btn-secondary" data-close="modal-cover">Cancel</button><button class="sa-btn sa-btn-primary" id="save-cover">Save</button></div></div></div>';
| |
| h+='<div class="sa-modal" id="modal-photo"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Add Photo</span><button class="sa-modal-close" data-close="modal-photo">×</button></div><div class="sa-tabs"><div class="sa-tab active" data-panel="panel-photo-upload">Upload</div><div class="sa-tab" data-panel="panel-photo-url">URL</div></div><div class="sa-tab-panel active" id="panel-photo-upload"><div class="sa-upload-zone" id="zone-photo"><input type="file" accept="image/*"><div class="sa-upload-icon">📤</div><div class="sa-upload-text">Drag photo here or <span>browse</span></div></div><div class="sa-progress" id="progress-photo"><div class="sa-progress-bar"></div></div><img class="sa-preview-img" id="preview-photo"></div><div class="sa-tab-panel" id="panel-photo-url"><input class="sa-input" id="input-photo-url" placeholder="Paste image URL..."><img class="sa-preview-img" id="preview-photo-url"></div><div class="sa-btn-row" style="padding:0 20px 20px"><button class="sa-btn sa-btn-secondary" data-close="modal-photo">Cancel</button><button class="sa-btn sa-btn-primary" id="add-photo">Add Photo</button></div></div></div>';
| |
| h+='<div class="sa-modal" id="modal-video"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Add Video</span><button class="sa-modal-close" data-close="modal-video">×</button></div><div class="sa-tabs"><div class="sa-tab active" data-panel="panel-video-upload">Upload</div><div class="sa-tab" data-panel="panel-video-url">URL</div></div><div class="sa-tab-panel active" id="panel-video-upload"><div class="sa-upload-zone" id="zone-video"><input type="file" accept="video/*"><div class="sa-upload-icon">🎬</div><div class="sa-upload-text">Drag video here or <span>browse</span></div></div><div class="sa-progress" id="progress-video"><div class="sa-progress-bar"></div></div><video class="sa-preview-img" id="preview-video" controls style="display:none"></video></div><div class="sa-tab-panel" id="panel-video-url"><input class="sa-input" id="input-video-url" placeholder="YouTube, Vimeo, or direct video URL..."><p style="color:#8e8e8e;font-size:12px">Supports YouTube, Vimeo, and direct video links</p></div><div class="sa-btn-row" style="padding:0 20px 20px"><button class="sa-btn sa-btn-secondary" data-close="modal-video">Cancel</button><button class="sa-btn sa-btn-primary" id="add-video">Add Video</button></div></div></div>';
| |
| h+='<div class="sa-modal" id="modal-location"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Add Location</span><button class="sa-modal-close" data-close="modal-location">×</button></div><div class="sa-modal-body"><button class="sa-btn sa-btn-primary" id="detect-location" style="width:100%;margin-bottom:16px">📍 Use Current Location</button><div style="text-align:center;color:#8e8e8e;margin-bottom:16px">— or —</div><input class="sa-input" id="input-location" placeholder="Enter location manually..."><div class="sa-btn-row"><button class="sa-btn sa-btn-secondary" data-close="modal-location">Cancel</button><button class="sa-btn sa-btn-primary" id="add-location">Add</button></div></div></div></div>';
| |
| h+='<div class="sa-modal" id="modal-story"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Add to Story</span><button class="sa-modal-close" data-close="modal-story">×</button></div><div class="sa-tabs"><div class="sa-tab active" data-panel="panel-story-upload">Upload</div><div class="sa-tab" data-panel="panel-story-url">URL</div></div><div class="sa-tab-panel active" id="panel-story-upload"><div class="sa-upload-zone" id="zone-story"><input type="file" accept="image/*"><div class="sa-upload-icon">📷</div><div class="sa-upload-text">Drag photo here or <span>browse</span></div></div><div class="sa-progress" id="progress-story"><div class="sa-progress-bar"></div></div><img class="sa-preview-img" id="preview-story"></div><div class="sa-tab-panel" id="panel-story-url"><input class="sa-input" id="input-story-url" placeholder="Paste image URL..."><img class="sa-preview-img" id="preview-story-url"></div><div class="sa-btn-row" style="padding:0 20px 20px"><button class="sa-btn sa-btn-secondary" data-close="modal-story">Cancel</button><button class="sa-btn sa-btn-primary" id="add-story">Share to Story</button></div></div></div>';
| |
| h+='<div class="sa-story-viewer" id="story-viewer"><div class="sa-story-viewer-content"><div class="sa-story-viewer-progress"><div class="sa-story-viewer-progress-bar" id="sv-prog"></div></div><button class="sa-story-viewer-close" id="close-story-viewer">×</button><div class="sa-story-viewer-header"><div class="sa-story-viewer-avatar" id="story-viewer-avatar"></div><div class="sa-story-viewer-name" id="story-viewer-name"></div></div><img id="story-viewer-image" src=""></div></div>';
| |
| $('#social-app').html(h);
| |
| }
| |
| function events(){
| |
| var $a=$('#social-app');
| |
| $a.on('click','[data-close]',function(){cm($(this).data('close'));});
| |
| $a.on('click','.sa-modal',function(e){if($(e.target).hasClass('sa-modal'))cm(this.id);});
| |
| $a.on('click','.sa-tab',function(){var $t=$(this),$p=$('#'+$t.data('panel'));$t.addClass('active').siblings().removeClass('active');$p.addClass('active').siblings('.sa-tab-panel').removeClass('active');});
| |
| function suz(zid,pid,prid,fk){var $z=$('#'+zid),$i=$z.find('input'),$pv=$('#'+pid),$pr=$('#'+prid);$z.on('click',function(){$i.click();});$z.on('dragover',function(e){e.preventDefault();$(this).addClass('dragover');});$z.on('dragleave drop',function(){$(this).removeClass('dragover');});$z.on('drop',function(e){e.preventDefault();var f=e.originalEvent.dataTransfer.files;if(f.length)hf(f[0]);});$i.on('change',function(){if(this.files.length)hf(this.files[0]);});function hf(f){uf[fk]=f;if(f.type.startsWith('image/')){var r=new FileReader();r.onload=function(e){$pv.attr('src',e.target.result).addClass('show');};r.readAsDataURL(f);}else if(f.type.startsWith('video/')){$pv.attr('src',URL.createObjectURL(f)).addClass('show').show();}}return{reset:function(){uf[fk]=null;$pv.removeClass('show').hide().attr('src','');$pr.removeClass('show').find('.sa-progress-bar').css('width',0);$i.val('');},setP:function(p){$pr.addClass('show').find('.sa-progress-bar').css('width',p+'%');}};}
| |
| var upPic=suz('zone-profile-pic','preview-profile-pic','progress-profile-pic','profilePic');
| |
| var upCov=suz('zone-cover','preview-cover','progress-cover','cover');
| |
| var upPho=suz('zone-photo','preview-photo','progress-photo','photo');
| |
| var upVid=suz('zone-video','preview-video','progress-video','video');
| |
| var upSto=suz('zone-story','preview-story','progress-story','story');
| |
| $('#input-pic-url').on('input',function(){var v=$(this).val();$('#preview-pic-url').attr('src',v).toggleClass('show',!!v);});
| |
| $('#input-cover-url').on('input',function(){var v=$(this).val();$('#preview-cover-url').attr('src',v).toggleClass('show',!!v);});
| |
| $('#input-photo-url').on('input',function(){var v=$(this).val();$('#preview-photo-url').attr('src',v).toggleClass('show',!!v);});
| |
| $('#input-story-url').on('input',function(){var v=$(this).val();$('#preview-story-url').attr('src',v).toggleClass('show',!!v);});
| |
| $('#edit-profile-btn').on('click',function(){om('modal-edit-profile');});
| |
| $('#save-profile').on('click',function(){ud.name=$('#input-display-name').val().trim()||user;ud.bio=$('#input-bio').val().trim();localStorage.setItem('sf_name_'+user,ud.name);localStorage.setItem('sf_bio_'+user,ud.bio);$('#display-name').text(ud.name);$('#bio-display').html(ud.bio?'<div class="sa-bio-name">'+esc(ud.name)+'</div>'+esc(ud.bio).replace(/\n/g,'<br>'):'Click Edit Profile to add a bio');cm('modal-edit-profile');});
| |
| $('#profile-pic').on('click',function(){upPic.reset();$('#input-pic-url').val('');$('#preview-pic-url').removeClass('show');om('modal-profile-pic');});
| |
| $('#save-profile-pic').on('click',function(){var ap=$('#modal-profile-pic .sa-tab.active').data('panel');if(ap==='panel-pic-url'){var u=$('#input-pic-url').val().trim();if(u){savePic(u);}else{alert('Please enter a URL');}}else if(uf.profilePic){upload(uf.profilePic,'ProfilePic',upPic.setP).then(savePic).fail(function(e){alert('Upload error');});}else{alert('Please select an image');}});
| |
| function savePic(u){ud.photo=u;localStorage.setItem('sf_photo_'+user,u);$('#profile-pic').html(av(u,user,''));$('#composer-avatar').html(av(u,user,'c'));cm('modal-profile-pic');upPic.reset();}
| |
| $a.on('click','#edit-cover-btn',function(){upCov.reset();$('#input-cover-url').val('');$('#preview-cover-url').removeClass('show');om('modal-cover');});
| |
| $('#save-cover').on('click',function(){var ap=$('#modal-cover .sa-tab.active').data('panel');if(ap==='panel-cover-url'){var u=$('#input-cover-url').val().trim();if(u){saveCov(u);}else{alert('Please enter a URL');}}else if(uf.cover){upload(uf.cover,'Cover',upCov.setP).then(saveCov).fail(function(){alert('Upload error');});}else{alert('Please select an image');}});
| |
| function saveCov(u){ud.cover=u;localStorage.setItem('sf_cover_'+user,u);$('#cover-area').html('<img src="'+u+'"><button class="sa-cover-edit" id="edit-cover-btn">📷 Edit Cover</button>');cm('modal-cover');upCov.reset();}
| |
| $('#btn-add-photo').on('click',function(){upPho.reset();$('#input-photo-url').val('');$('#preview-photo-url').removeClass('show');om('modal-photo');});
| |
| $('#add-photo').on('click',function(){var ap=$('#modal-photo .sa-tab.active').data('panel');if(ap==='panel-photo-url'){var u=$('#input-photo-url').val().trim();if(u){setPM('image',u);cm('modal-photo');}else{alert('Please enter a URL');}}else if(uf.photo){upload(uf.photo,'Post',upPho.setP).then(function(u){setPM('image',u);cm('modal-photo');upPho.reset();}).fail(function(){alert('Upload error');});}else{alert('Please select an image');}});
| |
| $('#btn-add-video').on('click',function(){upVid.reset();$('#input-video-url').val('');om('modal-video');});
| |
| $('#add-video').on('click',function(){var ap=$('#modal-video .sa-tab.active').data('panel');if(ap==='panel-video-url'){var u=$('#input-video-url').val().trim();if(u){setPM('video',u);cm('modal-video');}else{alert('Please enter a URL');}}else if(uf.video){upload(uf.video,'Video',upVid.setP).then(function(u){setPM('video',u);cm('modal-video');upVid.reset();}).fail(function(){alert('Upload error');});}else{alert('Please select a video');}});
| |
| function setPM(t,u){pp.image='';pp.video='';pp[t]=u;var $pv=$('#post-preview'),$in=$pv.find('.sa-composer-preview-inner');if(t==='image'){$in.find('img,video').remove();$in.append('<img src="'+u+'">');}else{$in.find('img,video').remove();if(u.match(/youtube|youtu\.be/)){$in.append('<img src="https://img.youtube.com/vi/'+(u.match(/(?:v=|youtu\.be\/)([^&]+)/)||[])[1]+'/hqdefault.jpg">');}else{$in.append('<video src="'+u+'" style="max-height:200px"></video>');}}$pv.addClass('show');upd();}
| |
| $('#remove-media').on('click',function(){pp.image='';pp.video='';$('#post-preview').removeClass('show').find('img,video').remove();upd();});
| |
| $('#btn-add-location').on('click',function(){$('#input-location').val('');om('modal-location');});
| |
| $('#detect-location').on('click',function(){var $b=$(this);$b.text('Detecting...').prop('disabled',true);if(navigator.geolocation){navigator.geolocation.getCurrentPosition(function(p){$.getJSON('https://nominatim.openstreetmap.org/reverse?format=json&lat='+p.coords.latitude+'&lon='+p.coords.longitude).done(function(d){var l=(d.display_name||'').split(',').slice(0,3).join(',')||p.coords.latitude+','+p.coords.longitude;$('#input-location').val(l);$b.text('📍 Use Current Location').prop('disabled',false);}).fail(function(){$('#input-location').val(p.coords.latitude+','+p.coords.longitude);$b.text('📍 Use Current Location').prop('disabled',false);});},function(){alert('Could not get location');$b.text('📍 Use Current Location').prop('disabled',false);});}else{alert('Geolocation not supported');$b.text('📍 Use Current Location').prop('disabled',false);}});
| |
| $('#add-location').on('click',function(){var l=$('#input-location').val().trim();if(l){pp.location=l;$('#post-location').addClass('show').find('span').text(l);cm('modal-location');}else{alert('Please enter a location');}});
| |
| $('#remove-location').on('click',function(){pp.location='';$('#post-location').removeClass('show');});
| |
| var emos={'😀':['😀','😃','😄','😁','😆','😅','🤣','😂','🙂','😉','😊','😇','🥰','😍','🤩','😘'],'👋':['👋','🤚','🖐️','✋','🖖','👌','✌️','🤞','🤟','🤘','🤙','👍','👎','✊','👊','👏'],'❤️':['❤️','🧡','💛','💚','💙','💜','🖤','🤍','🤎','💔','❣️','💕','💞','💓','💗','💖'],'🐶':['🐶','🐱','🐭','🐹','🐰','🦊','🐻','🐼','🐨','🐯','🦁','🐮','🐷','🐸','🐵','🐔'],'🍎':['🍎','🍐','🍊','🍋','🍌','🍉','🍇','🍓','🍈','🍒','🍑','🥭','🍍','🥥','🥝','🍅'],'⚽':['⚽','🏀','🏈','⚾','🎾','🏐','🏉','🎱','🏓','🏸','🏒','🥊','🎿','🏄','🏊','🚴']};
| |
| var $pk=$('#emoji-picker'),ecs=Object.keys(emos);$pk.html('<div class="sa-emoji-header">'+ecs.map(function(c,i){return'<button class="sa-emoji-cat'+(i===0?' active':'')+'" data-cat="'+c+'">'+c+'</button>';}).join('')+'</div><div class="sa-emoji-grid"></div>');
| |
| function se(c){$pk.find('.sa-emoji-grid').html(emos[c].map(function(e){return'<button class="sa-emoji-btn">'+e+'</button>';}).join(''));}se(ecs[0]);
| |
| $pk.on('click','.sa-emoji-cat',function(){$(this).addClass('active').siblings().removeClass('active');se($(this).data('cat'));});
| |
| $pk.on('click','.sa-emoji-btn',function(){var em=$(this).text(),$ip=$('#post-input')[0],st=$ip.selectionStart,v=$ip.value;$ip.value=v.slice(0,st)+em+v.slice($ip.selectionEnd);$ip.selectionStart=$ip.selectionEnd=st+em.length;$ip.focus();upd();});
| |
| $('#btn-add-emoji').on('click',function(e){e.stopPropagation();$pk.toggleClass('open');});
| |
| $(document).on('click',function(e){if(!$(e.target).closest('#emoji-picker,#btn-add-emoji').length)$pk.removeClass('open');});
| |
| $('#post-input').on('input',upd);
| |
| function upd(){var h=$('#post-input').val().trim()||pp.image||pp.video;$('#btn-submit-post').prop('disabled',!h);}
| |
| $('#btn-submit-post').on('click',function(){var t=$('#post-input').val().trim();if(!t&&!pp.image&&!pp.video){alert('Please add some content');return;}var $b=$(this);$b.prop('disabled',true).text('Posting...');var p={action:'socialfeed',sfaction:'createpost',content:t||'(media)'};if(pp.image)p.image_url=pp.image;if(pp.video)p.video_url=pp.video;if(pp.location)p.location=pp.location;api.postWithToken('csrf',p).then(function(){$('#post-input').val('');pp={image:'',video:'',location:''};$('#post-preview').removeClass('show').find('img,video').remove();$('#post-location').removeClass('show');$b.prop('disabled',true).text('Post');loadP();}).fail(function(c,d){alert('Error posting: '+(d&&d.error?d.error.info:c));$b.prop('disabled',false).text('Post');});});
| |
| $a.on('click','#add-story-btn',function(){upSto.reset();$('#input-story-url').val('');$('#preview-story-url').removeClass('show');om('modal-story');});
| |
| $('#add-story').on('click',function(){var ap=$('#modal-story .sa-tab.active').data('panel');function ps(u){api.postWithToken('csrf',{action:'socialfeed',sfaction:'createstory',image_url:u}).then(function(){cm('modal-story');upSto.reset();loadS();}).fail(function(c,d){alert('Error: '+(d&&d.error?d.error.info:c));});}if(ap==='panel-story-url'){var u=$('#input-story-url').val().trim();if(u){ps(u);}else{alert('Please enter a URL');}}else if(uf.story){upload(uf.story,'Story',upSto.setP).then(ps).fail(function(){alert('Upload error');});}else{alert('Please select an image');}});
| |
| var sto;
| |
| $a.on('click','.sa-story[data-story-url]',function(){var u=$(this).data('story-url'),n=$(this).data('story-user'),p=localStorage.getItem('sf_photo_'+n)||'';$('#story-viewer-image').attr('src',u);$('#story-viewer-name').text(n);$('#story-viewer-avatar').html(av(p,n,'s'));$('#story-viewer').addClass('open');var $pb=$('#sv-prog');$pb.css('width','0');setTimeout(function(){$pb.css({width:'100%',transition:'width 5s linear'});},10);clearTimeout(sto);sto=setTimeout(function(){$('#story-viewer').removeClass('open');$pb.css({width:'0',transition:'none'});},5000);});
| |
| $('#close-story-viewer,#story-viewer').on('click',function(e){if(e.target.id==='close-story-viewer'||e.target.id==='story-viewer'){$('#story-viewer').removeClass('open');$('#sv-prog').css({width:'0',transition:'none'});clearTimeout(sto);}});
| |
| $a.on('click','.sa-post-action[data-like]',function(){var id=$(this).data('like');api.postWithToken('csrf',{action:'socialfeed',sfaction:'react',post_id:id,reaction_type:'like'}).then(loadP);});
| |
| $a.on('click','.sa-post-menu[data-delete]',function(){if(confirm('Delete this post?')){api.postWithToken('csrf',{action:'socialfeed',sfaction:'deletepost',post_id:$(this).data('delete')}).then(loadP);}});
| |
| $a.on('click','.sa-post-comments-count',function(){var id=$(this).data('post'),$s=$('#comments-'+id);if($s.hasClass('show')){$s.removeClass('show');}else{$s.addClass('show');loadC(id);}});
| |
| $a.on('keypress','.sa-post-comment-input',function(e){if(e.which===13){var $i=$(this),t=$i.val().trim(),id=$i.data('post');if(t){$i.val('').prop('disabled',true);api.postWithToken('csrf',{action:'socialfeed',sfaction:'comment',post_id:id,content:t}).then(function(){$i.prop('disabled',false);loadC(id);loadP();}).fail(function(){$i.prop('disabled',false);});}}});
| |
| }
| |
| function loadP(){api.get({action:'socialfeed',sfaction:'getposts',limit:20}).then(function(r){var ps=(r.socialfeed&&r.socialfeed.posts)||[];$('#post-count').text(ps.length);if(!ps.length){$('#feed-container').html('<div class="sa-empty"><div class="sa-empty-icon">📷</div><div class="sa-empty-title">Share Photos</div><div class="sa-empty-text">When you share photos, they will appear here.</div></div>');return;}var h=ps.map(function(p){var up=localStorage.getItem('sf_photo_'+p.username)||'',tr=0;for(var k in p.reaction_counts)tr+=p.reaction_counts[k];var m='';if(p.image_url){m='<div class="sa-post-media"><img src="'+esc(p.image_url)+'"></div>';}if(p.video_url){if(p.video_url.match(/youtube|youtu\.be/)){var vi=(p.video_url.match(/(?:v=|youtu\.be\/)([^&]+)/)||[])[1];if(vi)m='<div class="sa-post-media"><iframe src="https://www.youtube.com/embed/'+vi+'" allowfullscreen></iframe></div>';}else if(p.video_url.match(/vimeo/)){var vm=(p.video_url.match(/vimeo\.com\/(\d+)/)||[])[1];if(vm)m='<div class="sa-post-media"><iframe src="https://player.vimeo.com/video/'+vm+'" allowfullscreen></iframe></div>';}else{m='<div class="sa-post-media"><video src="'+esc(p.video_url)+'" controls></video></div>';}}var lo=p.location?'<div class="sa-post-location">📍 '+esc(p.location)+'</div>':'';var del=p.username===user?'<button class="sa-post-menu" data-delete="'+p.id+'">🗑️</button>':'';var lc=p.user_reaction==='like'?' liked':'';return'<div class="sa-post"><div class="sa-post-header"><div class="sa-post-avatar">'+av(up,p.username,'p')+'</div><div class="sa-post-user"><div class="sa-post-username">'+esc(p.username)+'</div><div class="sa-post-meta">'+ago(p.created)+'</div></div>'+del+'</div>'+(p.content&&p.content!=='(media)'?'<div class="sa-post-content">'+esc(p.content)+'</div>':'')+lo+m+'<div class="sa-post-actions"><button class="sa-post-action'+lc+'" data-like="'+p.id+'">'+(p.user_reaction==='like'?'❤️':'🤍')+'</button><button class="sa-post-action">💬</button><button class="sa-post-action">📤</button><button class="sa-post-action" style="margin-left:auto">🔖</button></div>'+(tr?'<div class="sa-post-likes">'+tr+' like'+(tr>1?'s':'')+'</div>':'')+(p.comments?'<div class="sa-post-comments-count" data-post="'+p.id+'">View all '+p.comments+' comment'+(p.comments>1?'s':'')+'</div>':'')+'<div class="sa-comments-section" id="comments-'+p.id+'"></div><div class="sa-post-time">'+ago(p.created)+'</div><div class="sa-post-comment-form"><input class="sa-post-comment-input" data-post="'+p.id+'" placeholder="Add a comment..."><button class="sa-post-comment-submit">Post</button></div></div>';}).join('');$('#feed-container').html(h);}).fail(function(){$('#feed-container').html('<div class="sa-empty"><div class="sa-empty-icon">😕</div><div class="sa-empty-title">Error Loading</div><div class="sa-empty-text">Could not load posts.</div></div>');});}
| |
| function loadC(id){api.get({action:'socialfeed',sfaction:'getcomments',post_id:id}).then(function(r){var cs=(r.socialfeed&&r.socialfeed.comments)||[];var h=cs.map(function(c){var up=localStorage.getItem('sf_photo_'+c.username)||'';return'<div class="sa-comment"><div class="sa-comment-avatar">'+av(up,c.username,'s')+'</div><div class="sa-comment-body"><div class="sa-comment-text"><strong>'+esc(c.username)+'</strong> '+esc(c.content)+'</div><div class="sa-comment-time">'+ago(c.created)+'</div></div></div>';}).join('');$('#comments-'+id).html(h||'<div style="color:#8e8e8e;font-size:14px">No comments yet</div>');});}
| |
| function loadS(){api.get({action:'socialfeed',sfaction:'getstories'}).then(function(r){var ss=(r.socialfeed&&r.socialfeed.stories)||[];var h='<div class="sa-story"><div class="sa-story-ring add"><div class="sa-story-inner" id="add-story-btn">+</div></div><div class="sa-story-name">Your story</div></div>';h+=ss.map(function(s){var up=localStorage.getItem('sf_photo_'+s.username)||'';return'<div class="sa-story" data-story-url="'+esc(s.image_url)+'" data-story-user="'+esc(s.username)+'"><div class="sa-story-ring"><div class="sa-story-inner">'+av(up,s.username,'s')+'</div></div><div class="sa-story-name">'+esc(s.username)+'</div></div>';}).join('');$('#stories-container').html(h);}).fail(function(){});}
| |
| build();events();loadP();loadS();
| |
| }
| |
| })();
| |
| </script>
| |
| </html>
| |