4umi.com/web/javascript/clip

Adam clipped

Beautiful Javascript

Featured is a detail of the ceiling in the Sistine Chapel, ‘The Creation of Man’ by Michelangelo Buonarroti, 1508-1512.

The Sistine Chapel measures 40.93 meters deep by 13.41 meters wide, or 40 by 130 feet, i.e. the same dimensions as the Temple of Solomon in Jerusalem. It was built by Pope Sixtus IV between 1475 and 1483, and was named after him. His nephew, Pope Julius II, commissioned Michelangelo Buonarroti to repaint the ceiling. The artist signed the contract on 8 May 1508. And after only four years, the work was unveiled on 31 October 1512.

The frame

document.images.adam.style.clip =
 'rect( )';

This page features a clipped .jpg image of a part of the enormous painting by the great master. The image is 750 pixels wide and 385 pixels high, but with four borders on each side the visible area can be reduced to reveal only a section and so highlight a detail. The borders can be dragged up, down and across, with a little Javascript that manipulates the clip style property of the <img> element. The current value is constantly displayed in the form on the right, assembled from the current positions of all four borders, and opting for the special value of auto where possible, using some equally special regular expressions. A new value can also be entered by overwriting it in the form, the clip will update as you type.

The thickness or size of the border lines, their weight, can be selected in the list labeled ‘Line’. Some suggestions for aesthetical or otherwise meaningful clips are made in the ‘Clips’ list, the current clip can be added by choosing the ‘New’ option, to save and retrieve at a later stage. Build your own slideshow.

The style

Style on the world wide web not necessarily leads to beauty (to put it mildly), every aspect must be balanced with every other property in the end.

.rest { z-index:2; background-color:#ccc0d0; position:absolute; margin:0; border:0; }
.drag { z-index:3; background-color:red; }
#t, #b { left:10px; width:810px; height:4px; font-size:1px; cursor:n-resize; }
#l, #r { top:370px; height:445px; width:4px; cursor:e-resize; }
#adam { position:absolute; left: 40px; top:400px; display:none; }

The script

May the script serve as a demonstration of the ambiguity of all framed images. There is nothing, but only detail.

var adam, rect, t, r, b, l, ob, p, d = window.document;

function init() {
 adam = d.images.adam;
 rect = d.forms.f.elements.rect;
 t = d.getElementById( 't' );
 r = d.getElementById( 'r' );
 b = d.getElementById( 'b' );
 l = d.getElementById( 'l' );
 rect.onkeyup = update;
 rect.onmouseup = update;
 t.onmousedown = downy;
 r.onmousedown = downx;
 b.onmousedown = downy;
 l.onmousedown = downx;
 adam.style.display='block';
 ps( d.forms.f.elements.line.value );
};

function update( u ) { u = u || rect.value;
 if( u!==rect.value ) { rect.value = u; }
 if( /^(\s+(auto|\d+(\.\d+)?[a-z]{2}\s*,?)){4}\s*$/.test( ' ' + u ) ) {
   adam.style.clip = 'rect(' + u  + ')';
 }else{
   adam.style.clip = 'rect(auto)';
 }
 u = u.split(/\s/);
 var ax = adam.offsetLeft, ay = adam.offsetTop;
 t.style.top = ay + ( pa( u[0] ) || 0 ) - p - 1 + 'px';
 r.style.left = ax + ( pa( u[1] ) || ( pa( u[1] )<1 ? 0 : adam.width ) ) + 1 + 'px';
 b.style.top = ay + ( pa( u[2] ) || ( pa( u[2] )<1 ? 0 : adam.height ) ) + 1 + 'px';
 l.style.left = ax + ( pa( u[3] ) || 0 ) - p - 1 + 'px';
 return false;
}

function pa( s ) { return parseInt( s, 10 ); }

function mx(e) { e = e || window.event || {}; return 'number'===typeof e.clientX ? e.clientX : e.x; }
function my(e) { e = e || window.event || {}; return 'number'===typeof e.clientY ? e.clientY : e.y; }

function downx(e) { d.onmousemove = movex; move( this, e ); }
function downy(e) { d.onmousemove = movey; move( this, e ); }

function movex(e) { ob.style.left = Math.max( 0, mx(e) - ob.oX ) + 'px'; moved(); }
function movey(e) { ob.style.top = Math.max( 0, my(e) - ob.oY ) + 'px'; moved(); }

function move( o, e ) {
 ob = o;
 ob.oY = my( e ) - o.offsetTop;
 ob.oX = mx( e ) - o.offsetLeft;
 ob.className += ' drag';
 d.onmouseup = up;
 d.onselectstart = function() { return false; };
}

function moved() {
 var ax = adam.offsetLeft, ay = adam.offsetTop, aw=adam.width, ah=adam.height,
  tt = t.offsetTop - ay + 1 + p,
  tr = r.offsetLeft - ax - 1,
  tb = b.offsetTop - ay - 1,
  tl = l.offsetLeft - ax + 1 + p,
  s = [
   Math.max( 0, Math.min( tt, tb ) ),
   Math.min( aw, Math.max( tr, tl ) ),
   Math.min( ah, Math.max( tt, tb ) ),
   Math.max( 0, Math.min( tr, tl ) ) ].join( 'px ' ) + 'px';
 s = s.replace( new RegExp( '^(\\w+) ' + aw + 'px', '' ), '$1 auto' );
 s = s.replace( new RegExp( ' ' + ah + 'px (\\w+)$', '' ), ' auto $1' );
 s = s.replace( /^0px|\b0px$/g, 'auto' );
 s = s.replace( /^(auto)( \1){3}$/, '$1' );
 update( s );
}

function up() {
 ob.className = 'rest';
 ob = null;
 d.onmousemove = null;
 d.onmouseup = null;
 d.onselectstart = null;
}

function ps( n ) { 
 p = pa( n );
 n = p + 'px';
 d.forms.f.elements.line.value = n;
 t.style.height = n;
 r.style.width = n;
 b.style.height = n;
 l.style.width = n;
 update();
}

function clips( o ) {
 var s = o.options[o.selectedIndex].value;
 if( s==='new' ) { o = o.options;
  var n = window.prompt( 'Save this clip as...', 'Clip ' + o.length );
  if( n ) {
   o[ o.length ] = new Option( n, rect.value, false, true );
  }
 } else { update( s ); }
}

init();

The HTML

If the style and script are kept in external files, the source code of the page itself may remain relatively short:

<div><img src="/image/art/michelangelo/Adam.jpg"
 alt=" &quot; Creation of Adam &quot; &#13; Michelangelo, Sistine Chapel "
 width="750" height="385"
 id="adam"/></div>
<div class="rest" id="t" title="Top"></div>
<div class="rest" id="b" title="Bottom"></div>
<div class="rest" id="l" title="Left"></div>
<div class="rest" id="r" title="Right"></div>

The image and the <div> elements that are the borders are all positioned absolutely, and all near the top of the page. However, they appear in the source after this paragraph.

 " Creation of Adam " 
 Michelangelo, Sistine Chapel

This last paragraph follows the relevant elements in the source order. What more can we say?