/* global application object */
// classes for the application
function Application() {
this.element = null; // element being dragged
this.startX = 0;
this.startY = 0;
this.posX = 0;
this.posY = 0;
this.maxWidth = 0;
this.maxHeight = 0;
this.scale = 500.0 / 20.0; // 500 pixels divided by 20 feet
}
var application = new Application()
Application.prototype.toPixel = function( measure ) {
return measure*this.scale;
};
Application.prototype.toFeet = function( measure ) {
return measure/this.scale;
};
Application.prototype.getRoomTop = function( room ) {
var p = Application.getRoomContainer();
var t = (p.offsetHeight - this.toPixel(room.length)) / 2.0;
return t;
};
Application.prototype.getRoomLeft = function( room ) {
var p = Application.getRoomContainer();
var l = (p.offsetWidth - this.toPixel(room.width)) / 2.0;
return l;
};
Application.getRoomContainer = function() {
return document.getElementById('room' );
};
Application.getRoomNode = function() {
var c = Application.getRoomContainer();
var divs = c.getElementsByTagName('div');
if ( divs.length == 0 ) return null;
return divs[0];
};
Application.dragAction = function( evt ) {
if ( application.element == null ) {
Application.dragStop( evt )
return
}
var o = application.element
var dx = (evt.clientX-application.startX)
var dy = (evt.clientY-application.startY)
var x = (application.posX + dx)
// need to handle padding
if ( x > application.maxWidth ) x = application.maxWidth;
else if ( x < 0 ) x = 0;
var y = (application.posY + dy)
if ( y > application.maxHeight ) y = application.maxHeight;
else if ( y < 0 ) y = 0;
o.style.left = x + "px";
o.style.top = y + "px";
// update the specific movable piece
var movable = application.element.movable;
movable.top = application.toFeet( application.element.offsetTop );
movable.left = application.toFeet( application.element.offsetLeft );
//dump( movable + '\n' )
//dump( movable.left + " " + movable.top + '\n' )
};
Application.dragStop = function( evt ) {
application.element = null;
var r = application.parent;
r.removeEventListener('mousemove', Application.dragAction, true );
r.removeEventListener('mouseup', Application.dragStop, true );
evt.preventDefault();
};
Application.dragStart = function( evt ) {
application.element = evt.target;
application.startX = evt.clientX;
application.startY = evt.clientY;
application.posX = evt.target.offsetLeft;
application.posY = evt.target.offsetTop;
application.parent = evt.target.parentNode;
application.parent.addEventListener('mousemove', Application.dragAction, true );
application.parent.addEventListener('mouseup', Application.dragStop, true );
application.maxWidth = application.parent.offsetWidth - application.element.offsetWidth;
application.maxHeight = application.parent.offsetHeight - application.element.offsetHeight;
evt.preventDefault();
};
Application.updateRoomHandler = function( evt ) {
var form = evt.target.form;
var n = form.r_name.value;
var w = parseFloat( form.r_width.value);
var l = parseFloat( form.r_length.value );
var roomNode = Application.getRoomNode();
if ( !roomNode ) {
var container = Application.getRoomContainer();
var r = new Room( n, w, l );
roomNode = r.createHTML();
container.appendChild( roomNode );
r.updatePosition( roomNode );
}
else {
roomNode.room.name = n;
roomNode.room.width = w;
roomNode.room.length = l;
roomNode.room.updatePosition( roomNode );
roomNode.room.setName( roomNode );
}
}
Application.addBureauHandler = function( evt ) {
var form = evt.target.form;
var n = form.u_name.value;
var w = parseFloat( form.u_width.value);
var l = parseFloat( form.u_length.value );
var roomNode = Application.getRoomNode();
if ( roomNode ) {
var b = new Bureau( n, w, l );
var bNode = b.createHTML();
roomNode.appendChild( bNode );
}
}
Application.addBedHandler = function( evt ) {
var form = evt.target.form;
var n = form.b_name.value;
var t = form.b_type.value;
var roomNode = Application.getRoomNode();
if ( roomNode ) {
var b = new Bed( n, t );
var bNode = b.createHTML();
roomNode.appendChild( bNode );
}
}
Application.loadRoom = function() {
var p = Application.getRoomContainer();
// get rid of old room
if ( p ) {
var c = p.firstChild;
while ( c ) {
var t = c;
c = c.nextSibling;
p.removeChild( t );
}
}
// retrieve saved room from server
var req = new XMLHttpRequest();
req.open("GET","cgi-bin/loadroom.sh", true );
req.onreadystatechange = function() {
if ( req.readyState == 4) {
var root = req.responseXML.documentElement;
var room = Room.createFromXMLNode( root );
// build HTML representation of layout
var roomNode = room.createHTML();
p.appendChild( roomNode );
room.updatePosition( roomNode );
// add all the movable elements to the room
var e = root.firstChild;
while ( e ) {
if ( e.nodeName == 'bureau' ) {
var bureau = Bureau.createFromXMLNode( e );
roomNode.appendChild( bureau.createHTML() );
}
else if ( e.nodeName == 'bed' ) {
var bed = Bed.createFromXMLNode( e );
roomNode.appendChild( bed.createHTML() );
}
e = e.nextSibling;
}
}
}
req.send( null );
}
Application.saveRoom = function() {
var xmlDoc = document.implementation.createDocument("", "", null);
var roomNode = Application.getRoomNode();
if ( !roomNode ) return;
// create the XML description of the room layout
var xml = roomNode.room.toXMLNode( xmlDoc );
var divs = roomNode.getElementsByTagName( 'div' );
for( var i = 0 ; i < divs.length; i++ ) {
var m = divs[i].movable;
if ( m ) {
xml.appendChild( m.toXMLNode( xmlDoc ) );
}
}
xmlDoc.appendChild( xml );
// transmit the document
var req = new XMLHttpRequest();
req.open("POST","cgi-bin/saveroom.sh", true );
req.onreadystatechange = function() {
if ( req.readyState == 4) {
displayResult( req )
}
}
req.send( xmlDoc );
}
// extract and display the results
function displayResult( req ) {
var d = req.responseXML.documentElement
// since there is only one text value, the answer
// can be extract with textContent
var ans = d.textContent
document.getElementById('result').innerHTML = ans
}
/* ---------------------- form widget ------------------------- */
function mkShowPanelHandler( tab, panel, tabs, panels ) {
var handler = function( evt ) {
for( var i = 0, len=panels.snapshotLength; i < len; i++ ) {
var p = panels.snapshotItem( i );
var t = tabs.snapshotItem( i );
if ( p != panel ) {
p.style.display = 'none';
}
if ( t != tab ) {
t.className = ''
}
}
panel.style.display = 'block';
tab.className = 'selected'
}
tab.addEventListener("click", handler, false);
}
function initializeTabPanel( tab_panel ) {
var tabs = document.evaluate(
"div[@class='tabs']/span",
tab_panel, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
var panels = document.evaluate(
"div[@class='panel-frame']/div[@class='panel']",
tab_panel, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
// tabs.snapshotLength must equal panels.snapshotLength
for( var i = 0, len=tabs.snapshotLength; i < len; i++ ) {
var tab = tabs.snapshotItem( i );
var panel = panels.snapshotItem( i );
mkShowPanelHandler( tab, panel, tabs, panels )
}
}
/* ---------------------- end form widget ------------------------- */
/* models the moveable 'things' in the room */
// room object
function Room( name, width, length ){
this.name = name;
this.width = width;
this.length = length;
}
Room.prototype.toXMLNode = function( doc ) {
var res = doc.createElement('room');
res.setAttribute('name', this.name );
res.setAttribute('width', this.width.toString() );
res.setAttribute('length', this.length.toString() );
return res;
};
Room.createFromXMLNode = function( element ) {
var n = element.getAttribute( 'name' );
var w = parseFloat( element.getAttribute( 'width' ) );
var l = parseFloat( element.getAttribute( 'length' ) );
return new Room(n, w, l );
};
Room.prototype.createHTML = function() {
var e = document.createElement( 'div' );
var title = document.createElement('span');
title.innerHTML = this.name;
e.appendChild( title );
e.className = 'room';
e.room = this; // attach room to node
return e;
};
Room.prototype.setName = function( node ) {
var spans = node.getElementsByTagName('span' );
if ( spans.length != 0 ) {
spans[0].innerHTML = this.name;
}
};
Room.prototype.updatePosition = function( node ) {
node.style.width = application.toPixel( this.width ) + 'px';
node.style.height = application.toPixel( this.length ) + 'px';
node.style.top = application.getRoomTop( this ) + 'px';
node.style.left = application.getRoomLeft( this ) + 'px';
};
// bureau object
function Bureau( name, width, length ){
this.name = name;
this.width = width;
this.length = length;
this.top = 0;
this.left = 0;
}
Bureau.prototype.toXMLNode = function( doc ) {
var res = doc.createElement('bureau');
res.setAttribute('name', this.name );
res.setAttribute('width', this.width.toString() );
res.setAttribute('length', this.length.toString() );
res.setAttribute('top', this.top.toString() );
res.setAttribute('left', this.left.toString() );
return res;
};
Bureau.createFromXMLNode = function( element ) {
var n = element.getAttribute( 'name' );
var w = parseFloat( element.getAttribute( 'width' ) );
var l = parseFloat( element.getAttribute( 'length' ) );
var top = parseFloat( element.getAttribute( 'top' ) );
var left = parseFloat( element.getAttribute( 'left' ) );
var b = new Bureau(n, w, l );
b.top = top;
b.left = left;
return b;
};
Bureau.prototype.createHTML = function() {
var e = document.createElement( 'div' );
e.className = 'bureau';
e.style.width = application.toPixel( this.width ) + 'px';
e.style.height = application.toPixel( this.length ) + 'px';
this.updatePosition( e );
e.addEventListener("mousedown", Application.dragStart, false );
e.movable = this;
return e;
};
Bureau.prototype.updatePosition = function( node ) {
node.style.top = application.toPixel( this.top ) + 'px';
node.style.left = application.toPixel( this.left ) + 'px';
};
// bureau object
function Bed( name, size ){
this.name = name;
this.setSize(size) ;
this.top = 0;
this.left = 0;
}
Bed.prototype.setSize = function( size ) {
this.size = size;
if ( size == 'twin' ) {
this.width = 38.0 / 12.0;
this.length = 75.0 / 12.0;
}
else if ( size == 'full' || size == 'double') {
this.width = 53.0 / 12.0;
this.length = 75.0 / 12.0;
}
else if ( size == 'queen' ) {
this.width = 60.0 / 12.0;
this.length = 80.0 / 12.0;
}
else if ( size == 'king' ) {
this.width = 76.0 / 12.0;
this.length = 80.0 / 12.0;
}
}
Bed.prototype.toXMLNode = function( doc ) {
var res = doc.createElement('bed');
res.setAttribute('name', this.name );
res.setAttribute('size', this.size );
res.setAttribute('top', this.top.toString() );
res.setAttribute('left', this.left.toString() );
return res;
};
Bed.createFromXMLNode = function( element ) {
var n = element.getAttribute( 'name' );
var s = element.getAttribute( 'size' );
var top = parseFloat( element.getAttribute( 'top' ) );
var left = parseFloat( element.getAttribute( 'left' ) );
var b = new Bed( n, s );
b.top = top;
b.left = left;
return b;
};
Bed.prototype.createHTML = function() {
var e = document.createElement( 'div' );
e.className = 'bed';
e.style.width = application.toPixel( this.width ) + 'px';
e.style.height = application.toPixel( this.length ) + 'px';
e.addEventListener("mousedown", Application.dragStart, false );
this.updatePosition( e );
e.movable = this;
return e;
};
Bed.prototype.updatePosition = function( node ) {
node.style.top = application.toPixel( this.top ) + 'px';
node.style.left = application.toPixel( this.left ) + 'px';
};
function noaction(e) { return false; }
// set up the event handling
function initializeUserInterface() {
var tab_panels = document.evaluate(
"//div[@class='tab-panel']",
document, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
for ( var i = 0, len=tab_panels.snapshotLength; i < len; i++ ) {
initializeTabPanel( tab_panels.snapshotItem( i ) );
}
var u = document.getElementById( 'update-room' );
u.addEventListener('click', Application.updateRoomHandler, false );
var b = document.getElementById( 'add-bureau' );
b.addEventListener('click', Application.addBureauHandler, false )
var bed = document.getElementById( 'add-bed' );
bed.addEventListener('click', Application.addBedHandler, false )
var save = document.getElementById( 'save' );
save.addEventListener('click', Application.saveRoom, false )
var load = document.getElementById( 'load' );
load.addEventListener('click', Application.loadRoom, false )
}
// use bubble for load events, do not use capture
window.addEventListener("load", initializeUserInterface, false);