<%@ Page Title="Per-File Progress" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" %>
<%@ Register Assembly="AjaxUploader" Namespace="AjaxUploader.Controls" TagPrefix="au" %> 
<asp:Content ID="TitleContent" ContentPlaceHolderID="TitleContent" runat="server">Per-File Progress - AjaxUploader v5.3 Demos</asp:Content>
<asp:Content ID="HeaderContent" ContentPlaceHolderID="HeaderTitle" runat="server">Per-File Progress</asp:Content> 
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"> 
<div class="demo-card"> <div class="demo-card-header">Individual Progress Per File</div> <div class="demo-card-body"> <p class="demo-description"> Track upload progress independently for each file. Every file gets its
 own progress bar and status indicator in a custom file list.
 </p> <div class="demo-expect"><strong>What you should see:</strong> an individual bar per file, so one slow file is visible instead of being averaged into the batch.</div> <style> #fileList { margin-top: 1rem; }
 .file-item {
 display: flex; align-items: center; gap: 0.75rem;
 padding: 0.5rem 0; border-bottom: 1px solid #f3f4f6;
 }
 .file-item-name {
 flex: 1; font-size: 0.85rem; overflow: hidden;
 text-overflow: ellipsis; white-space: nowrap;
 }
 .file-item-bar {
 width: 120px; height: 8px;
 background: #e5e7eb; border-radius: 4px; overflow: hidden;
 }
 .file-item-fill {
 height: 100%; width: 0%; background: #3b82f6;
 border-radius: 4px; transition: width 0.2s;
 }
 .file-item-pct { font-size: 0.75rem; width: 40px; text-align: right; color: #6b7280; }
 </style> <div id="perFileUploader"></div> <div id="fileList"></div> <div class="code-panel"> <pre><code>onTaskStart: function(task) {
 // create a row with its own progress bar
 list.appendChild(createFileRow(task));
},
onTaskProgress: function(task, pct) {
 var row = document.getElementById('file-' + task.id);
 var safePct = clampPercent(pct);
 row.querySelector('.fill').style.width = safePct + '%';
 row.querySelector('.pct').textContent = safePct + '%';
},
onTaskComplete: function(task) {
 row.querySelector('.fill').style.background = '#10b981';
}</code></pre> </div> </div>
</div> 
</asp:Content> 
<asp:Content ID="ScriptsContent" ContentPlaceHolderID="ScriptsContent" runat="server">
<script> (function () {
 var list = document.getElementById('fileList');
 var host = document.getElementById('perFileUploader');
 function clampPercent(value) {
 var pct = Number(value);
 if (!isFinite(pct)) return 0;
 return Math.max(0, Math.min(100, Math.round(pct)));
 }
 if (!host || !window.AjaxUploader || typeof AjaxUploader.create !== 'function') return;
 AjaxUploader.create(host, {
 uploadUrl: '<%= ResolveUrl("~/ajaxupload.axd/upload") %>',
 multiple: true,
 autoUpload: true,
 onTaskStart: function (task) {
 var item = document.createElement('div');
 item.className = 'file-item';
 item.id = 'file-' + task.id;
 var name = document.createElement('span');
 name.className = 'file-item-name';
 name.textContent = task.fileName || 'File';
 var bar = document.createElement('div');
 bar.className = 'file-item-bar';
 var fill = document.createElement('div');
 fill.className = 'file-item-fill';
 var pct = document.createElement('span');
 pct.className = 'file-item-pct';
 pct.textContent = '0%';
 bar.appendChild(fill);
 item.appendChild(name);
 item.appendChild(bar);
 item.appendChild(pct);
 if (list) list.appendChild(item);
 },
 onTaskProgress: function (task, pct) {
 var item = document.getElementById('file-' + task.id);
 if (item) {
 var safePct = clampPercent(pct);
 var fill = item.querySelector('.file-item-fill');
 var pctEl = item.querySelector('.file-item-pct');
 if (fill) fill.style.width = safePct + '%';
 if (pctEl) pctEl.textContent = safePct + '%';
 }
 },
 onTaskComplete: function (task) {
 var item = document.getElementById('file-' + task.id);
 if (item) {
 var fill = item.querySelector('.file-item-fill');
 var pctEl = item.querySelector('.file-item-pct');
 if (fill) fill.style.background = '#10b981';
 if (pctEl) pctEl.textContent = 'Done';
 }
 }
 });
 })();
</script>
</asp:Content>
