<%@ Page Title="Full Event Log" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" %>
<%@ Register Assembly="AjaxUploader" Namespace="AjaxUploader.Controls" TagPrefix="au" %> 
<asp:Content ID="TitleContent" ContentPlaceHolderID="TitleContent" runat="server">Full Event Log - AjaxUploader v5.2 Demos</asp:Content>
<asp:Content ID="HeaderContent" ContentPlaceHolderID="HeaderTitle" runat="server">Full Event Log</asp:Content> 
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"> 
<div class="demo-card"> <div class="demo-card-header">Full Event Log with Timestamps</div> <div class="demo-card-body"> <p class="demo-description"> A comprehensive event log that captures every upload event with precise timestamps,
 event type badges, and detailed data. Useful for debugging and understanding the upload lifecycle.
 </p> <au:AjaxFileUpload ID="Uploader1" runat="server"
 AllowMultiple="true"
 ShowProgress="true" /> <div class="mt-3 d-flex justify-content-between align-items-center"> <div> <span class="badge bg-info me-1">SELECT</span> <span class="badge bg-primary me-1">START</span> <span class="badge bg-secondary me-1">PROGRESS</span> <span class="badge bg-success me-1">COMPLETE</span> <span class="badge bg-danger me-1">ERROR</span> <span class="badge bg-warning text-dark me-1">QUEUE</span> </div> <div> <button type="button" class="btn btn-outline-secondary btn-sm" id="clearFullEventLogBtn">Clear</button> <button type="button" class="btn btn-outline-primary btn-sm" id="exportFullEventLogBtn">Export</button> </div> </div> <div id="eventLog" class="mt-2 p-2 border rounded font-monospace" role="log" aria-live="polite"
 style="max-height:280px;overflow-y:auto;font-size:.78rem;background:#f8f9fa;"></div> <div id="counter" class="mt-1 text-muted small" role="status" aria-live="polite">0 events logged</div> <div class="code-panel"> <pre><code>// Attach all event handlers to build a full log
var events = [];
var uploader = AjaxUploader.getInstance('Uploader1');
uploader.on('select', function(f) { addEvent('SELECT', f.length + ' files'); });
uploader.on('taskStart', function(t) { addEvent('START', t.fileName); });
uploader.on('taskProgress', function(t) { addEvent('PROGRESS', clampPercent(t.percent) + '%'); });
uploader.on('taskComplete', function(t) { addEvent('COMPLETE', t.fileName); });
uploader.on('taskError', function(t,e) { addEvent('ERROR', e); });
uploader.on('queueRender', function(q) { addEvent('QUEUE', q.length + ' items'); });</code></pre> </div> </div>
</div> 
</asp:Content> 
<asp:Content ID="ScriptsContent" ContentPlaceHolderID="ScriptsContent" runat="server">
<script> var eventLog = document.getElementById('eventLog');
 var counter = document.getElementById('counter');
 var clearButton = document.getElementById('clearFullEventLogBtn');
 var exportButton = document.getElementById('exportFullEventLogBtn');
 var events = [];
 function clampPercent(value) {
 var pct = Number(value);
 if (!isFinite(pct)) return 0;
 return Math.max(0, Math.min(100, Math.round(pct)));
 }

 var badgeColors = {
 SELECT: 'bg-info', START: 'bg-primary', PROGRESS: 'bg-secondary',
 COMPLETE: 'bg-success', ERROR: 'bg-danger', QUEUE: 'bg-warning text-dark',
 DONE: 'bg-success'
 };

 function addEvent(type, detail) {
 if (!eventLog) return;
 var now = new Date();
 var ts = now.toLocaleTimeString() + '.' + String(now.getMilliseconds()).padStart(3, '0');
 events.push({ time: ts, type: type, detail: detail });
 var div = document.createElement('div');
 var time = document.createElement('span');
 time.className = 'text-muted';
 time.textContent = ts;
 var badge = document.createElement('span');
 badge.className = 'badge ' + (badgeColors[type] || 'bg-secondary');
 badge.style.width = '70px';
 badge.style.display = 'inline-block';
 badge.textContent = type;
 div.appendChild(time);
 div.appendChild(document.createTextNode(' '));
 div.appendChild(badge);
 div.appendChild(document.createTextNode(' ' + (detail || '')));
 eventLog.appendChild(div);
 eventLog.scrollTop = eventLog.scrollHeight;
 if (counter) counter.textContent = events.length + ' events logged';
 }

 function clearLog() {
 if (!eventLog) return;
 eventLog.textContent = '';
 events = [];
 if (counter) counter.textContent = '0 events logged';
 }

 function exportLog() {
 var text = events.map(function(e) { return e.time + '\t' + e.type + '\t' + e.detail; }).join('\n');
 var blob = new Blob([text], { type: 'text/plain' });
 var a = document.createElement('a');
 var downloadUrl = URL.createObjectURL(blob);
 a.href = downloadUrl;
 a.download = 'upload-events.txt';
 a.click();
 setTimeout(function() {
 URL.revokeObjectURL(downloadUrl);
 }, 0);
 }

 var uploader = window.AjaxUploader && AjaxUploader.getInstance ? AjaxUploader.getInstance('Uploader1') : null;
 if (uploader) {
 uploader.on('select', function(files) { addEvent('SELECT', files.length + ' file(s) selected'); });
 uploader.on('taskStart', function(task) { addEvent('START', task.fileName + ' (' + AjaxUploader.formatSize(task.total) + ')'); });
 uploader.on('taskProgress', function(task) { addEvent('PROGRESS', task.fileName + ' ' + clampPercent(task.percent) + '%'); });
 uploader.on('taskComplete', function(task) { addEvent('COMPLETE', task.fileName); });
 uploader.on('taskError', function(task, err) { addEvent('ERROR', task.fileName + ': ' + err); });
 uploader.on('queueRender', function(queue) { addEvent('QUEUE', queue.length + ' item(s)'); });
 uploader.on('complete', function() { addEvent('DONE', 'All uploads finished'); });
 }
 if (clearButton) clearButton.addEventListener('click', clearLog);
 if (exportButton) exportButton.addEventListener('click', exportLog);
</script>
</asp:Content>
