CURRENT PROJECTS
loading
CATEGORIES AND POSTS
loading
overset
DEVELOPMENT LOG FOR JIM PALMER
Posted 11/10/2006 in javascript


Flash and the whole R.I.A. movement has brought with it the expectation, by the end user, that they need to know what the application is doing. As an AJAX developer you understand that you can have numerous synchronous requests running at the same time - and as a conventional application developer you understand that you need a device to control the state of the application. Basically it is dangerous to have synchronous requests running at the same time in the same application initiated by the same end-user especially when each request changes the state. This issue is relatively new to the world of web-application development with the advent of AJAX.

This is a good example of why we use an "observer" pattern. Basically this is a single object that can control the state of the application. Case in point, if an end user clicks one button and an AJAX request is fired - most times we'll want to prevent the user from clicking the button again to send the same request. Not only that - but limit the end user from clicking any other buttons in the web interface that might fire another AJAX request before the first request has been returned.

There are several simple programmatic answers to controlling the state of the application - which this post is not meant to show - but there is a huge disconnect with the end user experience when all the "buttons" are disabled in the web application while the AJAX response has yet to return.

This is where I introduce a way to take any block of DHTML within the web application and essentially "turn it off" temporarily. I built a function to take a single argument - the ID of any table/div/span/etc that should be displayed as unusable.

In the example below, I show a simple html table-based layout showing that a specific table-cell can be "turned off" temporarily. And here's the straight HTML for reference.
<script>

	var stateNode;

	function offState(rootCell) {

		var tallyLeft = document.getElementById(rootCell).offsetLeft;
		var tallyTop = document.getElementById(rootCell).offsetTop;
		if (document.getElementById(rootCell).offsetParent) {
			var rootNodeFound = false;
			var offsetStart = document.getElementById(rootCell).offsetParent;
			while (!rootNodeFound) {
				tallyLeft += offsetStart.offsetLeft;
				tallyTop += offsetStart.offsetTop;
				if (offsetStart.offsetParent)
					offsetStart = offsetStart.offsetParent;
				else
					rootNodeFound = true;
			}
		}

		var shadow = document.createElement('div');
		shadow.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=90)';
		shadow.style.MozOpacity = 0.85;
		shadow.setAttribute('id', 'shadow_' + rootCell);
		shadow.style.position = 'absolute';
		shadow.style.left = tallyLeft + 'px';
		shadow.style.top = tallyTop + 'px';
		shadow.style.width = document.getElementById(rootCell).offsetWidth.toString() + 'px';
		shadow.style.height = document.getElementById(rootCell).offsetHeight.toString() + 'px';
		shadow.style.background = '#FFFFFF';
		document.body.appendChild(shadow);

		var shadowMessage = document.createElement('div');
		shadowMessage.setAttribute('id', 'shadowMessage');
		shadowMessage.style.position = 'absolute';
		shadowMessage.innerHTML =
			'<table>' +
				'<tr>' +
					'<td valign=middle style="color:#006699;">' +
						'PLEASE WAIT' +
					'</td>' +
					'<td valign=middle>' +
						'<object type="application/x-shockwave-flash" data="throbber-bars1.swf" width="40" height="40">' +
							'<param name="movie" value="throbber-bars1.swf" />' +
							'<param name="BGCOLOR" value="#ffffff" />' +
							'<param name="wmode" value="transparent" />' +
						'</object>' +
					'</td>' +
				'</tr>' +
			'</table>';
		shadow.appendChild(shadowMessage);
		shadowMessage.style.left = ((shadowMessage.offsetParent.offsetWidth / 2) - (shadowMessage.offsetWidth / 2)).toString() + 'px';
		shadowMessage.style.top = ((shadowMessage.offsetParent.offsetHeight / 2) - (shadowMessage.offsetHeight / 2)).toString() + 'px';

		stateNode = 'shadow_' + rootCell;

	}

	function onState () {
		document.getElementById(stateNode).parentNode.removeChild(document.getElementById(stateNode));
	}
</script>

<body marginwidth=0 marginheight=0 topmargin=0 leftmargin=0 rightmargin=0>

	<table cellpadding=0 cellspacing=0 border=0 width="100%">

		<tr>
			<td style="background:#006699; color:#FFFFFF; padding:5px; font-family:Tahoma; font-size:10pt;" align=center width="100%">
				Header
				<input type=button value="start" style="background:#E3E3E3; color:#000000; border:2px outset #E3E3E3; font-family:Tahoma; font-size:8pt;" onClick="offState('dynContainer'); return true;">
				<input type=button value="stop " style="background:#E3E3E3; color:#000000; border:2px outset #E3E3E3; font-family:Tahoma; font-size:8pt;" onClick="onState(); return true;">

			</td>
		</tr>

		<tr>
			<td id="dynContainer" style="padding:10px;">

				<table cellpadding=0 cellspacing=0 border=0 width="100%">
					<tr>
						<td colspan=3 style="background:#006699; color:#FFFFFF; padding:5px; font-family:Tahoma; font-size:8pt;">
							Dynamic Table
						</td>

					</tr>

					<tr>
						<td style="background:#E3E3E3; color:#000000; padding:5px; font-family:Tahoma; font-size:8pt; border-bottom:1px solid #FFFFFF;" align=left width="100%">
							<nobr>First Product Name</nobr>
						</td>
						<td style="background:#E3E3E3; color:#000000; padding:5px; font-family:Tahoma; font-size:8pt; border-bottom:1px solid #FFFFFF;" align=right>
							<nobr>$100.00</nobr>

						</td>
						<td style="background:#E3E3E3; color:#000000; padding:5px; border-bottom:1px solid #FFFFFF;">
							<nobr><a href="javascript:alert('remove product');">delete</a></nobr>
						</td>
					</tr>

					<tr>
						<td style="background:#E3E3E3; color:#000000; padding:5px; font-family:Tahoma; font-size:8pt; border-bottom:1px solid #FFFFFF;" align=left width="100%">
							<nobr>Second Product Name</nobr>

						</td>
						<td style="background:#E3E3E3; color:#000000; padding:5px; font-family:Tahoma; font-size:8pt; border-bottom:1px solid #FFFFFF;" align=right>
							<nobr>$200.00</nobr>
						</td>
						<td style="background:#E3E3E3; color:#000000; padding:5px; border-bottom:1px solid #FFFFFF;">
							<nobr><a href="javascript:alert('remove product');">delete</a></nobr>
						</td>
					</tr>

					<tr>
						<td style="background:#E3E3E3; color:#000000; padding:5px; font-family:Tahoma; font-size:8pt; border-bottom:1px solid #FFFFFF;" align=left width="100%">
							<nobr>Third Product Name</nobr>
						</td>
						<td style="background:#E3E3E3; color:#000000; padding:5px; font-family:Tahoma; font-size:8pt; border-bottom:1px solid #FFFFFF;" align=right>
							<nobr>$300.00</nobr>
						</td>

						<td style="background:#E3E3E3; color:#000000; padding:5px; border-bottom:1px solid #FFFFFF;">
							<nobr><a href="javascript:alert('remove product');">delete</a></nobr>
						</td>
					</tr>

					<tr>
						<td style="background:#E3E3E3; color:#000000; padding:5px; font-family:Tahoma; font-size:8pt; border-bottom:1px solid #FFFFFF;" align=left width="100%">
							<nobr>Fourth Product Name</nobr>

						</td>
						<td style="background:#E3E3E3; color:#000000; padding:5px; font-family:Tahoma; font-size:8pt; border-bottom:1px solid #FFFFFF;" align=right>
							<nobr>$400.00</nobr>
						</td>
						<td style="background:#E3E3E3; color:#000000; padding:5px; border-bottom:1px solid #FFFFFF;">
							<nobr><a href="javascript:alert('remove product');">delete</a></nobr>
						</td>
					</tr>

				</table>

			</td>
		</tr>

		<tr>
			<td style="background:#006699; color:#FFFFFF; padding:5px; font-family:Tahoma; font-size:10pt;" align=center width="100%">
				Footer
				<input type=button value="start" style="background:#E3E3E3; color:#000000; border:2px outset #E3E3E3; font-family:Tahoma; font-size:8pt;" onClick="offState('dynContainer'); return true;">
				<input type=button value="stop " style="background:#E3E3E3; color:#000000; border:2px outset #E3E3E3; font-family:Tahoma; font-size:8pt;" onClick="onState(); return true;">

			</td>
		</tr>

	</table>

</body>
comments
loading
new comment
NAME
EMAIL ME ON UPDATES
EMAIL (hidden)
URL
MESSAGE TAGS ALLOWED: <code> <a> <pre class="code [tab4|tabX|inline|bash]"> <br>
PREVIEW COMMENT
TURING TEST
gravatar