<?xml version="1.0" encoding="UTF-8"?>

<Module><ModulePrefs title="Ebiquity Says..." scrolling="true" author_email="googlegadgets@dapper.net" author_affiliation="Dapper, Inc." title_url="http://www.dapper.net/dapp-howto-use.php?dappName=EbiquityBlogs&amp;from=GoogleGadget" screenshot="http://www.dapper.net/images/google-gadget-thumbnail-generator.php?type=screenshot&amp;gadgetTitle=Ebiquity%20Says...&amp;contentProvider=ebiquity.umbc.edu" thumbnail="http://www.dapper.net/images/google-gadget-thumbnail-generator.php?type=thumbnail&amp;gadgetTitle=Ebiquity%20Says...&amp;contentProvider=ebiquity.umbc.edu"></ModulePrefs>
<Content type="html"><![CDATA[
      <script src="http://www.google.com/js/nxsl.1.js" type="text/javascript"></script>
      
      <style>
        .dapperInputForm table {
          font-size:10pt;
        }
        .dapperInputForm td {
          padding-right:5px;
          text-align:right;
        }
        .dapperInputForm {
		      border-top:1px solid #c0c0c0;
				  padding:10px;
				  background:#efefef;
				}	
        .dapperInputForm .dapperInputField {
          border: 1px solid #aaaaaa;
          width:200px;
        }
        .dapperInputForm .dapperInputSubmitButton {
	      	padding:2px;
				}
        .dapperGroup {
				  border-top:1px solid #c0c0c0;
				  padding:10px;
		      margin-bottom:10px;
        }
        .dapperField {
          margin-bottom:4px;
        }
        .dapperLabel {
          font-weight:bold;
        }
        #dapperTableTemplate__MODULE_ID__ th {
        	font-size:10px;
        	color:#666666;
        	padding:2px;
        	font-weight:normal;
        	text-align:left;
        }
        #dapperTableTemplate__MODULE_ID__ td {
        	font-size:11px;
        	color:#000000;
        	padding:2px;
        }
        #dapperTableTemplate__MODULE_ID__ tr.even td {
					background-color:#eeeeee;
        }
        #dapperTableTemplate__MODULE_ID__ tr.odd td {
					background-color:#ffffff;
        }
        
        .dapperNextThumbTable td {
        	font-size:13px;
        	padding:2px;
        	vertical-align:top;
        }
        .dapperNextThumbTable .dapperLabel {
          color:#666666;
        }
        .dapperNextThumbTable .fieldSection {
        	padding-bottom:7px;
        }
        .dapperNextThumbTable .dataCell {
        	overflow:auto;
        }
        .nextPrevSection {
        	border-top: 1px dotted #999999;
        	border-bottom: 1px dotted #999999;
        	padding-top:7px;
        	padding-bottom:7px;
        }
        .nextPrevSection a {
        	color: #666666;
        	text-decoration: underline;
        }
        .nextPrevSection td {
        	font-size:13px;
        }
      </style>
      
            <div class="dapperBody" style="font-family:arial;font-size:10pt;">
      
        <!-- content provider -->
                <div style="float:right;padding-right:5px;font-size:8pt;">
          <a target="_blank" id="contentProviderLink__MODULE_ID__" href="http://ebiquity.umbc.edu/blogger/">ebiquity.umbc.edu</a>
          <img id="faviconImage__MODULE_ID__" src="" align="absmiddle" onerror="this.parentNode.removeChild(this);" />
        </div>
      
        <!-- powered by dapper -->
        <div style="margin-bottom:10px;font-size:8pt;"> 
          <img id="dapperLogo__MODULE_ID__" src="" align="absmiddle" /> powered by <a target="_top" href="http://www.dapper.net">Dapper</a>
        </div>
              
              
        <div id="outputArea__MODULE_ID__"></div>

				      </div>
      
      <script type="text/javascript">
				// adding caching for favicon img
        _gel('faviconImage'+__MODULE_ID__).src = _IG_GetImageUrl("http://ebiquity.umbc.edu/favicon.ico");
        _gel('dapperLogo'+__MODULE_ID__).src = _IG_GetImageUrl("http://www.dapper.net/images/dapper-16x16.gif");
		
				// if there's a css - use it (but the cached version		
						

        var dappXmlUrl = 'http://www.dapper.net/RunDapp?dappName=EbiquityBlogs&version=2&applyToUrl=http%3A%2F%2Febiquity.umbc.edu%2Fblogger%2F&v=1';

        function loadDappFromFormValues(form) {
          for (var e = 0; e < form.elements.length; e++) {
            var el = form.elements[e];

            if (!el.name)
              continue;

            var re = new RegExp("([?&])" + el.name + "=[^&]*", "g");
            if(re.exec(dappXmlUrl))
              dappXmlUrl = dappXmlUrl.replace(re, "$1"+el.name+"="+encodeURIComponent(el.value));
            else
              dappXmlUrl += "&"+el.name+"="+encodeURIComponent(el.value);
          }
          
          loadDapp();
        }
        
        function loadDapp() {
					          
          fetchDapp(1);
        }
        
        function storeEncryptedCredentialsAndLoadDapp(responseText) {
        	var res;
        	eval("res ="+responseText);
        
					var prefs = new _IG_Prefs();
					prefs.set('encUsername', res['username']);
					prefs.set('encPassword', res['password']);
					
					dappXmlUrl += '&username=' + _esc(res['username']) + '&password=' + _esc(res['password']) + '&encryptionAlg=1';
        	fetchDapp();
        }
        
        function fetchDapp(attemptNumber) {
					// fetch the content and update the gadget
          var div = _gel('outputArea'+__MODULE_ID__);
          
          var maxAttempts = 5;
          var attemptText = '';
          if (attemptNumber > 1)
            attemptText = ' (attempt #'+attemptNumber+')';
          
          div.innerHTML = '<div style="padding:10px;">Loading content from ebiquity.umbc.edu'+attemptText+'...</div>';
          _IG_FetchXmlContent(
          	dappXmlUrl.replace(/localhost/,'www.dapper.net'), 
          	function(responseXML) { 
          		if (responseXML) {
          			displayDapp(responseXML); 
          		}
          		else {
          			if (attemptNumber < maxAttempts) {
	          			fetchDapp(attemptNumber+1);
	          		}
	          		else {
				          div.innerHTML = '<div style="padding:10px;">Failed to load content from ebiquity.umbc.edu after '+attemptNumber+' tries...</div>';	          		
	          		}
          		}
          	}
          );
        }
        
        function generateErrorMessage(responseXML){
          var div = _gel('outputArea'+__MODULE_ID__);
          var errorMsg = responseXML.documentElement.getElementsByTagName('description');
          if ((errorMsg) && (errorMsg.length)){
            errorMsg = errorMsg[0].firstChild.nodeValue;
          } else {
            errorMsg = 'General error';
          }
          var divContent = '<div style="padding:10px;"><strong>We\'re sorry, there\'s a problem updating the Gadget content</strong><br /><br />';
          divContent += '<span style="color: #676767;">' + errorMsg + '</span></div>';
          div.innerHTML = divContent;
        }
        
        function displayDapp(responseXML) {
          // update the content provider link
          var dappResponseStatus = responseXML.documentElement.getElementsByTagName('status');
          if ((dappResponseStatus) && (dappResponseStatus.length) && (dappResponseStatus[0].firstChild.nodeValue == 'ERROR')){
            generateErrorMessage(responseXML);
            return;
          }
          
          
          var applyToUrlElements = responseXML.documentElement.getElementsByTagName('applyToUrl');
          if (applyToUrlElements && applyToUrlElements.length) {
            var applyToUrl = applyToUrlElements[0].firstChild.nodeValue;
            _gel('contentProviderLink'+__MODULE_ID__).href = applyToUrl;
            _gel('contentProviderLink'+__MODULE_ID__).innerHTML = 'ebiquity.umbc.edu';
          }
          
          var div = _gel('outputArea'+__MODULE_ID__);
          div.innerHTML = '';

          var desiredFields = {};
          desiredFields['post'] = 'post';
          
          // we have different templates, so lets proceed accordingly
          var template = 'default';
          
          if (template == 'table') {
          	displayDappTable(responseXML, div, desiredFields);
          	return;
          }
          else if (template == 'nextThumb') {
          	displayDappNextThumb(responseXML, div, desiredFields);
          	return;
          }

          // get all the groups
          var groupNodes = nxslGetElementsByAttribute('type', 'group', responseXML.documentElement);
          for (var g = 0; g < groupNodes.length; g++) {

            var groupString = '';
            for (var desiredField in desiredFields) {
              var fields = groupNodes[g].getElementsByTagName(desiredField);
              for (var f = 0; f < fields.length; f++) {
                if (fields[f].getAttribute('type') == 'field') {
                  groupString += formatField(desiredFields[desiredField], fields[f]);
                }
              }
            }
            
            if (groupString)
              div.innerHTML += '<div class="dapperGroup">'+groupString+'</div>';
            
          } // end foreach group
          
          // now we need all the fields that are not in the above groups
          for (var desiredField in desiredFields) {
            var fields = responseXML.documentElement.getElementsByTagName(desiredField);
            for (var f = 0; f < fields.length; f++) {
              if (fields[f].getAttribute('type') == 'field' && 
                  fields[f].parentNode.getAttribute('type') != 'group') {
                div.innerHTML += formatField(desiredFields[desiredField], fields[f]);
              }              
            }
          }        
          
        }
        
        
        
        // the table template
        function displayDappTable(responseXML, outputArea, desiredFields) {
        	// XXX: this template works very badly in many cases (like if one group has two values for one 
        	// field and the rest of the groups do not, or when one group have different fields than another
        	// group, etc.) - this should be fixed asap        
        
        	// gather all the grouped fields (that we want)
          var groups = [];
          var allFieldNames = {};
          var groupNodes = nxslGetElementsByAttribute('type', 'group', responseXML.documentElement);
          for (var g = 0; g < groupNodes.length; g++) {

						var group = {};
            for (var desiredField in desiredFields) {
              var fields = groupNodes[g].getElementsByTagName(desiredField);
              for (var f = 0; f < fields.length; f++) {
                if (fields[f].getAttribute('type') == 'field') {
                	if (!group[desiredFields[desiredField]])
                		group[desiredFields[desiredField]] = [];
                	group[desiredFields[desiredField]].push(fields[f]);
                	
                	allFieldNames[fields[f].getAttribute('fieldName')] = true;
                	
                }
              }
            }
            
						groups.push(group);
            
          } // end foreach group
        	
        	// XXX: gather all the ungrouped fields (that we want)
        	
        	
        	// construct the output
        	tableString = '<table id="dapperTableTemplate__MODULE_ID__" style="width:100%;" cellpadding="0" cellspacing="0">';
        	
        	// create the header row
        	tableString += '<tr>';
        	for (var fieldName in allFieldNames) {
	        	tableString += '<th>'+fieldName+'</th>';
        	}
        	tableString += '</tr>';
        	
        	var rowNum = 0;

        	// create the group rows
        	for (var g = 0; g < groups.length; g++) {
        	  tableString += '<tr class="'+(rowNum % 2 == 0 ? 'even' : 'odd')+'">';
						var group = groups[g];
        		for (var fieldName in group) {
        			for (var f = 0; f < group[fieldName].length; f++) {
	        			if (group[fieldName][f].firstChild) {
				        	tableString += '<td>'+formatField(fieldName, group[fieldName][f])+'</td>';
				        }
			        }
			      }
			      tableString += '</tr>';
			      rowNum++;
					}
        	
        	tableString += '</table>';
					outputArea.innerHTML = tableString;
					_IG_AdjustIFrameHeight();
        }


        // the "next thumbnail" template
        function displayDappNextThumb(responseXML, outputArea, desiredFields) {
        	// gather all the grouped fields (that we want)
          var groups = [];
          var groupNodes = nxslGetElementsByAttribute('type', 'group', responseXML.documentElement);
          for (var g = 0; g < groupNodes.length; g++) {

						var group = [];
	          var fieldNodes = nxslGetElementsByAttribute('type', 'field', groupNodes[g]);
	          for (var f = 0; f < fieldNodes.length; f++) {
	          	if (desiredFields[fieldNodes[f].tagName]) {
               	group.push(
               		{
               			fieldName: desiredFields[fieldNodes[f].tagName],
               		  fieldNode: fieldNodes[f]
               		}
               	);
	            }
	          }
	            
						groups.push(group);
            
          } // end foreach group
        	
        	// construct the output
        	output = '';
        	for (var g = 0; g < groups.length; g++) {
						var group = groups[g];

        		output += '<div id="dappNextThumb'+g+'-__MODULE_ID__" '+(g > 0 ? 'style="display:none;"' : '')+'>';
        		output += '<table class="dapperNextThumbTable" cellpadding="0" cellspacing="0">';
        		output += '<tr>';

						// find the first image in the group and put it here
        		for (var fieldInstanceNum = 0; fieldInstanceNum < group.length; fieldInstanceNum++) {
        			var fieldNode = group[fieldInstanceNum].fieldNode;
        			var fieldName = group[fieldInstanceNum].fieldName;
       				if (fieldNode.getAttribute('src')) {
		        		output += '<td class="imageCell">';
			        	output += '<img src="'+fieldNode.getAttribute('src')+'" />';
		        		output += '</td>';

			        	group[fieldInstanceNum] = null;
			        	break;
			        }
			      }        		
        		
        		// start the data cell
        		output += '<td>';

						var groupId = 'dataCell_'+__MODULE_ID__+'_'+g;
        		output += '<div class="dataCell" id="'+groupId+'">';
        		
        		var firstFieldNum = null;	
        		for (var fieldInstanceNum = 0; fieldInstanceNum < group.length; fieldInstanceNum++) {
        		
        			// we might have set the this field to null aove if it contained the thumbnail which
        			// we already showed on the left.
        			if (group[fieldInstanceNum] == null)
        				continue;
        			
        			var fieldNode = group[fieldInstanceNum].fieldNode;
        			var fieldName = group[fieldInstanceNum].fieldName;

		        	output += '<div class="fieldSection">'+formatField(fieldName, fieldNode)+'</div>';

        			if (firstFieldNum == null)
        				firstFieldNum = fieldInstanceNum;
			      }
			      
	        	output += '</div></td></tr></table>';

	        	
	        	if (groups.length > 1) {
				      output += '<div class="nextPrevSection">';
				      output += '<table cellpadding="0" cellspacing="0" style="width:100%;">';
				      output += '<tr>';
	
				      // show a "prev" link
			      	output += '<td>';
				      if (g > 0) {
				      	output += '<a href="#" onclick="setGroupNum_nextThumb('+(g-1)+', '+g+'); return false;">';
				      	output += '<img src="http://www.dapper.net/images/button-gg-prev.gif" style="padding-right:5px;" alt="Previous" border="0" align="absmiddle" />';
				      	output += '</a>';
				      }
			      	output += '</td>';
				      
				      // show a next link
			      	output += '<td style="text-align:right;">';
				      if (g < groups.length - 1) {
				      	output += '<a href="#" onclick="setGroupNum_nextThumb('+(g+1)+', '+g+'); return false;">';
	
				      	// we want to show the value of the first field from the next group
				      	// if it is available
				      	if (groups[g+1][firstFieldNum] && groups[g+1][firstFieldNum].fieldNode && groups[g+1][firstFieldNum].fieldNode.firstChild && groups[g+1][firstFieldNum].fieldNode.firstChild.nodeValue)
					      	output += 'Next: '+groups[g+1][firstFieldNum].fieldNode.firstChild.nodeValue;
	
				      	output += '<img src="http://www.dapper.net/images/button-gg-next.gif" style="padding-left:5px;" alt="Next" border="0" align="absmiddle" />';
				      	
				      	output += '</a>';
				      }
			      	output += '</td>';
				      
				      output += '</tr></table></div>';
				    }

	        	output += '</div>';
	        	
					}
					outputArea.innerHTML = output;
					_IG_AdjustIFrameHeight();
        	
        }
        
        function setGroupNum_nextThumb(groupNum, currentGroupNum) {
        	// we want to maintain height of the groups as we navigate, so that the
        	// navigation doesn't bounce around, so we set the height of the next group
        	// to whatever the height of this group is.
        	if (groupNum > 0) {
        		_gel('dataCell_'+__MODULE_ID__+'_'+groupNum).style.height = _gel('dataCell_'+__MODULE_ID__+'_'+currentGroupNum).clientHeight + 'px';
        	}

        	_gel('dappNextThumb'+groupNum+'-__MODULE_ID__').style.display = '';
        	_gel('dappNextThumb'+currentGroupNum+'-__MODULE_ID__').style.display = 'none';
					_IG_AdjustIFrameHeight();
        }



        // takes the name of a field and the field node itself and formats it for displayDapp
        function formatField(displayName, fieldNode) {
          var fieldValue = '';
          if (fieldNode.childNodes[0])
            fieldValue = fieldNode.childNodes[0].nodeValue;

          if (fieldNode.getAttribute('src'))
            fieldValue = '<img src="'+fieldNode.getAttribute('src')+'" border="0" />';
          
          if (fieldNode.getAttribute('href')) {
            fieldValue = '<a href="'+fieldNode.getAttribute('href')+'" target="_blank">'+
                         fieldValue+
                         '</a>';
          }

					
          if (fieldValue) {
            displayString = '<div class="dapperField">';
          
            if (fieldNode.getAttribute('fieldName'))
              displayName = fieldNode.getAttribute('fieldName');
          
                      
            displayString += fieldValue;
          
            displayString += '</div>';
          
            return displayString;
          }
          
          return '';
        }
        
        // since nsxsl's parsexml is pretty weak, this function allows us
        // to search for children with a certain attribute name and value
        function nxslGetElementsByAttribute(attributeName, attributeValue, rootNode) {

          var returnArray = new Array();
          for (var i = 0; i < rootNode.childNodes.length; i++) {
            
            if (rootNode.childNodes[i].nodeType == 1 && rootNode.childNodes[i].getAttribute(attributeName) == attributeValue)
              returnArray.push(rootNode.childNodes[i]);

            // recurse
            var subReturnArray = nxslGetElementsByAttribute(attributeName,attributeValue,rootNode.childNodes[i]);
            for (var j = 0; j < subReturnArray.length; j++) {
              returnArray.push(subReturnArray[j]);
            }
          }
          return returnArray;
        }
        
                loadDapp();
              </script>
    ]]>
</Content>
</Module>
