function Point(x, y) { this.x = x; this.y = y; } function Size(w, h) { this.w = w; this.h = h; } function Rect(x, y, w, h) { this.x = x; this.y = y; this.w = w; this.h = h; } var box_rect = new Rect(0, 0, 111, 143); // the initial position of the crop box var max_size = new Size(800, 600); // the size of the original pic (and therefore the maximum size of the crop box) var min_size = new Size(55.5, 71.5); // the minimum size of the cropped image var aspect_ratio = box_rect.w / box_rect.h; // the aspect ratio of the crop box // some configurables ... var border_width = 1; // the width of the crop box border // some globals var target = null; var client_start = new Point(0, 0); // where the mouse starts dragging var box = null; var area = null; domOnLoad(function() { box = document.getElementById('crop_box'); area = document.getElementById('crop_area'); // these style assigns shouldn't be necessary, but if we don't all the style properties (left/top etc.) are null?!? box.style.left = box_rect.x + "px"; box.style.top = box_rect.y + "px"; box.style.width = box_rect.w + "px"; box.style.height = box_rect.h + "px"; box.onmousedown = OnMouseDown; }); function GetDelta(e, pt) { if (!e) e = window.event; return new Point(e.clientX - pt.x, e.clientY - pt.y); } function OnMouseDown(e) { target = (window.event) ? window.event.srcElement : e.target; area.onmousemove = OnMouseMove; area.onmouseup = EndDrag; client_start = GetDelta(e, new Point(0, 0)); box_rect = new Rect(parseInt(box.style.left), parseInt(box.style.top), parseInt(box.style.width), parseInt(box.style.height)); cancelBubble(e); // prevent the text selection } function EndDrag() { target = null; area.onmousemove = null; area.onmouseup = null; } function bound_value(min_value, preferred, max_value) { return Math.max(min_value, Math.min(preferred, max_value)); } function do_size(rect, delta, left_locked, top_locked) { if (left_locked) { rect.w = bound_value(min_size.w, box_rect.w + delta.x, max_size.w - box_rect.x - 1); } else { rect.x = bound_value(0, box_rect.x + delta.x, box_rect.x + box_rect.w - min_size.w); rect.w = box_rect.w + box_rect.x - rect.x; } if(top_locked) { rect.h = bound_value(min_size.h, box_rect.h + delta.y, max_size.h - box_rect.y - 1); } else { rect.y = bound_value(0, box_rect.y + delta.y, box_rect.y + box_rect.h - min_size.h); rect.h = box_rect.h + box_rect.y - rect.y; } // fix the aspect ratio var diff = rect.w - rect.h * aspect_ratio; if (diff > 0) { rect.w -= diff; if (!left_locked) rect.x += diff; } else { diff /= -aspect_ratio; // the change was in terms of the width, adjust for height / y pos rect.h -= diff; if (!top_locked) rect.y += diff; } } var drag_functions = new Array(); drag_functions['crop_box'] = function(rect, delta) { rect.x = bound_value(0, box_rect.x + delta.x, max_size.w - box_rect.w - 1); rect.y = bound_value(0, box_rect.y + delta.y, max_size.h - box_rect.h - 1); } drag_functions['crop_gripper_se'] = function(rect, delta) { do_size(rect, delta, true, true); } drag_functions['crop_gripper_ne'] = function(rect, delta) { do_size(rect, delta, true, false); } drag_functions['crop_gripper_sw'] = function(rect, delta) { do_size(rect, delta, false, true); } drag_functions['crop_gripper_nw'] = function(rect, delta) { do_size(rect, delta, false, false); } function OnMouseMove(e) { var button = (e ? e.which : window.event.button) > 0 ? 1 : 0; if (button == 0) { // did we miss a mouse up? (maybe because the cursor went outside the div - mouseout doesn't work reliably - so we catch it here instead) EndDrag(); } else if (target && drag_functions[target.id]) { var rect = new Rect(box_rect.x, box_rect.y, box_rect.w, box_rect.h); drag_functions[target.id](rect, GetDelta(e, client_start)); box.style.backgroundPosition = "-" + (rect.x + border_width) + "px" + " " + "-" + (rect.y + border_width) + "px"; box.style.left = rect.x + "px"; box.style.top = rect.y + "px"; box.style.width = rect.w + "px"; box.style.height = rect.h + "px"; document.getElementById("crop_submit").href = "submit.html?x=" + Math.round(rect.x) + "&y=" + Math.round(rect.y) + "&cx=" + Math.round(rect.w) + "&cy=" + Math.round(rect.h); } cancelBubble(e); // prevent the text selection }