<%@ Page Title="Interactive image editor" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" %> 
<asp:Content ID="TitleContent" ContentPlaceHolderID="TitleContent" runat="server">Interactive image editor - AjaxUploader v5.3 Demos</asp:Content> 
<asp:Content ID="HeaderContent" ContentPlaceHolderID="HeaderTitle" runat="server">Interactive image editor</asp:Content> 
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"> 
<div class="demo-card"> <div class="demo-card-header">Inline image editor with interactive crop</div> <div class="demo-card-body"> <p class="demo-description"> Rotate +/-90 deg, flip H/V, and interactively crop with 8 drag handles (corners + edges). Optional aspect-ratio lock, touch + mouse unified via pointer events, <kbd>Esc</kbd> to exit crop mode. Each edit is destructive: rotate -> crop yields the crop of the rotated image, not the original.
 </p> <div class="demo-expect"><strong>What you should see:</strong> the interactive editor (crop, rotate, flip) on one image before upload - the edited result is what gets sent.</div> <div class="card p-3 mt-3" style="background:#fff;border:1px solid #e2e8f0;"> <label class="form-label fw-semibold small" for="editorPicker">Pick an image</label> <div class="d-flex flex-wrap align-items-center gap-2"> <input id="editorPicker" type="file" accept="image/*" class="form-control" style="max-width:320px" /> <select id="editorAspect" class="form-select" style="max-width:200px" aria-label="Crop aspect ratio"> <option value="">Free-form crop</option> <option value="1">1:1 (square)</option> <option value="1.77777777">16:9 (widescreen)</option> <option value="1.33333333">4:3 (standard)</option> <option value="0.66666667">2:3 (portrait)</option> </select> </div> <div class="d-flex gap-2 mb-2 mt-3">
 <button type="button" class="btn btn-primary" id="startBtn_editorOutput">Start upload</button>
 <button type="button" class="btn btn-outline-secondary" id="clearBtn_editorOutput">Clear queue</button>
 </div>
 <div id="editorOutput"></div> <p class="mt-2 text-muted small mb-0">Edits happen entirely in the browser - the original file never leaves the page until you explicitly upload.</p> </div> <script> (function () {
 function init() {
 if (!window.AjaxUploader || typeof AjaxUploader.create !== 'function') return; // graceful no-op if runtime missing
 var picker = document.getElementById('editorPicker');
 var aspect = document.getElementById('editorAspect');
 var output = document.getElementById('editorOutput');
 var uploader = AjaxUploader.create(output, {
 uploadUrl: '<%= ResolveUrl("~/ajaxupload.axd/upload") %>',
 multiple: false,
 autoUpload: false
 });
 if (!picker) return;
 picker.addEventListener('change', function (e) {
 var file = e.target.files && e.target.files[0];
 if (!file) return;
 var opts = {};
 var a = parseFloat(aspect ? aspect.value : '');
 if (!isNaN(a) && a > 0) opts.aspectRatio = a;
 if (!uploader || typeof uploader.openImageEditor !== 'function') return;
 uploader.openImageEditor(file, opts).then(function (edited) {
 if (uploader && typeof uploader.addFile === 'function') {
 uploader.addFile(edited);
 }
 }).catch(function () {
 /* user cancelled */
 });
 });
 var startButton = document.getElementById('startBtn_editorOutput');
 var clearButton = document.getElementById('clearBtn_editorOutput');
 if (startButton) {
 startButton.addEventListener('click', function () {
 if (uploader && typeof uploader.upload === 'function') uploader.upload();
 });
 }
 if (clearButton) {
 clearButton.addEventListener('click', function () {
 if (uploader && typeof uploader.clear === 'function') uploader.clear();
 });
 }
 }
 if (document.readyState !== 'loading') init();
 else document.addEventListener('DOMContentLoaded', init);
 })();
 </script> <div class="alert alert-info mt-3" role="alert"> <strong>Try it:</strong> pick an image, click <strong>Crop</strong> in the editor toolbar, drag the rectangle or any of its 8 handles, then click <strong>Apply Crop</strong>. Save to add the edited file to the upload queue.
 </div> <h5 class="mt-4">JavaScript API</h5> <div class="code-panel"> 
<pre><code><span style="color:#94a3b8">// Opens the editor modal. Resolves with an edited File; rejects on cancel.</span> 
uploader.openImageEditor(file, {
 aspectRatio: 16 / 9, <span style="color:#94a3b8">// omit for free-form</span> outputType: 'image/jpeg',
 quality: 0.9
}).then(function (edited) {
 uploader.addFile(edited);
});</code></pre> </div> <h5 class="mt-4">Keyboard shortcuts</h5> <ul class="mb-3"> <li><kbd>Esc</kbd> - exit crop mode, or cancel the whole editor</li> <li>Drag corner handle - resize on two axes (<code>nw</code> / <code>ne</code> / <code>sw</code> / <code>se</code>)</li> <li>Drag edge handle - resize on one axis (<code>n</code> / <code>s</code> / <code>w</code> / <code>e</code>)</li> <li>Drag inside the box - move the crop rectangle</li> </ul> <h5 class="mt-4">Combine with the image pipeline</h5> <p>Editor output is a plain <code>File</code> - feed it through <code>imageResize</code>, <code>imageCompress</code>, or <code>watermark</code> options for a full client-side pipeline before upload.</p> </div> 
</div> 
</asp:Content> 
