/* (C) Copyright IBM Corp. 2007  All Rights Reserved.                */
/**
 * This is the JS file for the common semantic tagging service
 */











 



 

var SemTagSvcPortal = {	
	debug: false,
	trace: false,
	version: "1.0",
	lang: "en_US",
	bidi: "ltr",
	tagScope: ['*'],
	baseUrl: "http://38.107.179.217/wps_semanticTag",
	service: 





{"entries":[
	 {"id":"com.ibm.portal.action","test":"(node.className.match(SemTagSvcPortal.actionRE))","js":"","classnames":[".com\\.ibm\\.portal\\.action"]}
	,{"id":"hcard","test":"(node.className.match(SemTagSvcPortal.hcardRE))","js":"/javascript/semanticTagPerson.js","classnames":[".vcard"]}
	//,{"id":"mailto","test":"(node.tagName.match(/^a$/i) && node.href.match(/^mailto:/) && !SemTagSvcPortal.getParentByClassName('vcard', node))","js":"/javascript/semanticTagPerson.js"}
	,{"id":"sametime","test":"id:hcard","js":"/javascript/semanticTagAwareness.js","classnames":[]}
	,{"id":"c2a","test":"(node.className.match(/(^|\\s)c2a:(source|target)(\\s|$)/)) ","js":"/javascript/semanticTagC2A.js","classnames":[".c2a\\:source",".c2a\\:target"]}
    //,{"id":"hcard1","test":"(node.className.match(SemTagSvcPortal.hcardRE))","js":"/javascript/ask.js",classnames:[".vcard"]}
	//,{"id":"adr","test":"(node.className.match(/(^|\\s)adr(\\s|$)/))","js":"/javascript/semanticTagAddress.js"}
	
]}
,
	scripts: new Array(),
	actionRegistry: null,
	refcntAttr: "semtag_refcnt",
	hoverIdPrefix: "semtag_hover_",
	hoverIdx: 0,
	liveElemPrefix: "semtag_live_",
	reMap: new Array(), 
	actionRE: new RegExp("(^|\\s)com\.ibm\.portal\.action(\\s|$)"),
	hcardRE: new RegExp("(^|\\s)vcard(\\s|$)"),
	specialMenuProviders: new Array(),
	parseElem: null,
	availAttribStr: "",
	ifConnUrlExists: "false",
	connUrl: "null",
	isconnServerNew:false,
	init: function(event) {
		var DELAY = 10; //SemTagUtil.isGecko? 10: 5000;
        if ( SemTagSvcPortal.debug ) console.log("inside init of SemtagSvc:");
        if ( window.ibmCfg == "undefined" ||!window.ibmCfg || ( window.ibmCfg.themeConfig.themeUniqueName != "csa2.theme") ) { // conditionally load the Portal tagging service
            if ( SemTagSvcPortal.debug ) console.log("inside init of SemtagSvc for non csa2.theme");
            SemTagSvcPortal.parseElem = SemTagSvcPortal.getElementFromEvent(event);
            window.setTimeout(SemTagSvcPortal.parseDom, DELAY);
        }else {
            if ( SemTagSvcPortal.debug ) console.log("inside init of SemtagSvc for csa2.theme");
      
			var svcEntries = SemTagSvcPortal.service.entries;
            if ( SemTagSvcPortal.debug ) console.log("In case of csa2.theme"+(svcEntries ? svcEntries.length : 0));
            for (var k=0; k<svcEntries.length; k++) {
                var entry = svcEntries[k];
                //if ( SemTagSvcPortal.debug ) console.log("Calling SemTagSvcPortal.loadScript for:"+entry.js+":"+entry.id);
              
            }
        }
        SemTagSvcPortal.setCallback("com.ibm.portal.action", SemTagSvcPortal.processActions);
        window.setTimeout(SemTagMenu.init, DELAY);
		
	},
	loadConnScript: function() {
			var scriptElem = document.createElement("script");
			var url = SemTagSvcPortal.connUrl;
			var profileUrl = url;
			//var profileUrl = "/wps_semanticTag/javascript/portalBizCard.js" ;
		    profileUrl = url + "/profiles/portalJS/portalBizCard.js" ;
			profileUrl += (profileUrl.indexOf("?")==-1)? "?": "&";
			profileUrl += "lang=" + SemTagSvcPortal.lang;
			scriptElem.src = profileUrl;
			try {
			document.body.insertBefore(scriptElem, document.body.firstChild); 
			} catch (e) {
			alert("Svc.loadConnScript caught: " + e);
			}
	}, 
	watchEvent: function(element, name, observer, useCapture) {
		try {
			if (element.addEventListener) element.addEventListener(name, observer, useCapture);
			else if (element.attachEvent) element.attachEvent('on' + name, observer);
		}
		catch (e) {
			if (SemTagSvcPortal.debug) alert("Svc.watchEvent caught: " + e);
		}
	},

	clearEventWatch: function(element, name, observer, useCapture) {
		try {
			if (element.removeEventListener) element.removeEventListener(name, observer, useCapture);
			else if (element.detachEvent) element.detachEvent('on' + name, observer);
		}
		catch (e) {
			if (SemTagSvcPortal.debug) alert("Svc.clearEventWatch caught: " + e);
		}
	},
    parseDomUsingMashupHandlerSingleNode: function (node,entryId) {
        //if ( SemTagSvcPortal.debug ) 
        if ( SemTagSvcPortal.debug ) console.log("Inside parseDomUsingMashupHandlerSingleNode :"+node+":"+entryId);
        var entry = SemTagSvcPortal.getService(entryId); 
      
		if ( !entry.nodes ) {
             entry.nodes = new Array();
        } else {
            for ( var k  = 0 ; k < entry.nodes.length ; k++) {
                entry.nodes.pop();
            }
        }
        entry.nodes.push(node);
        
        //if ( SemTagSvcPortal.debug ) 
        if ( SemTagSvcPortal.debug ) console.log("parseDomUsingMashupHandlerSingleNode entry.callback got is:"+entry.callback+":"+entry.id+":"+entry.nodes.length+":"+(entry.id == "hcard"));
        if (entry.callback) entry.callback.call(this);
		if ( entry.id == "hcard") {
			// get sametime entry and call its callback
			var entrySametime = SemTagSvcPortal.getService("sametime"); 
			if ( SemTagSvcPortal.debug ) console.log("Entry for sametime got is:"+entrySametime);
			entrySametime.callback.call(this);
		}
    },
    parseDomUsingMashupHandler: function (nodes,entryId) {
        if ( SemTagSvcPortal.debug ) console.log("Inside parseDomUsingMashupHandler :"+nodes+":"+entryId);
        var entry = SemTagSvcPortal.getService(entryId); 
      
	    if ( entryId === "com.ibm.portal.action" ) { // this is required so that action menu extensions come first time as script will be loaded during callback, only for FF
            SemTagSvcPortal.setCallback(entryId, SemTagSvcPortal.processActions);
	    }
	
		if ( !entry.nodes ) {
             entry.nodes = new Array();
        }
        for ( var len = 0 ; len < nodes.length ; len++ ){
            entry.nodes.push(nodes[len]);
        }
        
        if ( SemTagSvcPortal.debug ) console.log("parseDomUsingMashupHandler entry.callback got is:"+entry.callback+":"+entry.id+":"+entry.nodes.length+":"+(entry.id == "hcard"));
        
        if (entry.callback) entry.callback.call(this);

		try {
			var svcEntries = SemTagSvcPortal.service.entries;
			for (var k=0; k<svcEntries.length; k++) {
				var entryTemp = svcEntries[k];
				if ( SemTagSvcPortal.debug ) console.log("entryTemp.callback got is:"+entryTemp.id+":"+entryTemp.nodes+":"+entryTemp.js+":And original entry id is:"+entry.id);
				var goAhead =false;
				if ( entryTemp.id === entry.id ) continue;
				if (entryTemp.test.match(/^id:/)) {
					var svcName = entryTemp.test.substr(3);
					if ( svcName != entry.id ) continue;
					if ( SemTagSvcPortal.debug ) console.log("svcName got is:"+svcName);
					var nodes = SemTagSvcPortal.getNodes(svcName);
					if ( SemTagSvcPortal.debug ) console.log("nodes for "+svcName +" got is:"+nodes+":"+nodes.length);
					if (nodes && 0<nodes.length) {
						goAhead = true;
					}
				}
				//if (goAhead) SemTagSvcPortal.loadScript(entryTemp.js);

				//if ( SemTagSvcPortal.debug ) 
				//if ( SemTagSvcPortal.debug ) console.log("entryTemp.callback got is:"+entryTemp.id+":"+entryTemp.nodes+":"+entryTemp.callback);
				//console.log("entryTemp.callback got is:"+entryTemp.id+":"+entryTemp.nodes+":"+entryTemp.callback);
				
				if (entryTemp.callback) entryTemp.callback.call(this);
			}
		} catch (e) {
			if ( SemTagSvcPortal.debug ) console.error("Exception occured while doing match of services in SemTagSvcPortal.parseDonMashup"+e);
		}	
		
    },

	parseDom: function(/*Event*/ event, /*DomElement|String?*/ element) {
		// summary: parse DOM and search for potential live elements
		// description: 
		//
		// event: Not used in any way (defined just to allow this method to be used as a callback for an event)
		// element: Specifies the DOM node where the parse should start 'downward' (if null, 'document' is assumed, if a string is specified, it's assumed as the ID of the node, and otherwise, it is assumed as a DOM node)
        if ( SemTagSvcPortal.debug ) console.log("inside parseDom of SemtagSvc");
		if (SemTagSvcPortal.trace) SemTagUtil.log("parseDom(" + event + "," + element + ")");
		if (!element && event) element = SemTagSvcPortal.getElementFromEvent(event);
		if (!element && SemTagSvcPortal.parseElem) element = SemTagSvcPortal.parseElem;
			else if (!element) element = document;
			else if (typeof element == 'string') element = document.getElementById(element);

		var svcEntries = SemTagSvcPortal.service.entries;
		for (var j=0; j<svcEntries.length; j++) {
			var entry = svcEntries[j];
			if (!entry.nodes) entry.nodes = new Array();
				else if (element==document) while (0 < entry.nodes.length) entry.nodes.pop();
		}


		SemTagSvcPortal.traverseNodes(element);

		for (var k=0; k<svcEntries.length; k++) {
			var entry = svcEntries[k];
			var goAhead = false;
			if (0<entry.nodes.length) {
				goAhead = true;
			}
			else if (entry.test.match(/^id:/)) {
				var svcName = entry.test.substr(3);
				var nodes = SemTagSvcPortal.getNodes(svcName);
				if (nodes && 0<nodes.length) {
					goAhead = true;
				}
			}
			if (goAhead) SemTagSvcPortal.loadScript(entry.js);

            //if ( SemTagSvcPortal.debug ) 
            if ( SemTagSvcPortal.debug ) console.log("entry.callback got is:"+entry.id+":"+entry.nodes);
            
			if (entry.callback) entry.callback.call(this);
		}

		SemTagSvcPortal.parseElem = null;
	},

	traverseNodes: function(node) {
		//SemTagSvcPortal.traverse_tagscope(node);
		SemTagSvcPortal.traverse_children(node);
	},
	traverse_tagscope: function(node) {
		var svcEntries = SemTagSvcPortal.service.entries;
		var children = node.getElementsByTagName(SemTagSvcPortal.tagScope);
		for (var i = 0; i < children.length; i++) {
			var node = children[i];
			for (var j=0; j<svcEntries.length; j++) {
				var entry = svcEntries[j];
				if (!entry.nodes) entry.nodes = new Array();
				if (eval(entry.test)) entry.nodes.push(node);
			}
		}
	},
	traverse_children: function(node) {
		SemTagSvcPortal.testNode(node);

		var children = (node && node.childNodes)? node.childNodes: null;
		
		if (node && node.tagName && node.tagName=="IFRAME") {
			try {
				if (typeof ActiveXObject != "undefined") { 
					var childDoc = document.frames[node.id].document;
					if (childDoc) children = childDoc.childNodes;
					
				}
				else {  // Firefox, Safari, Opera
					if (node.contentDocument && node.contentDocument.childNodes) children = node.contentDocument.childNodes;
				}
			} catch (e) { 
			
					children = null;
			}
			if (SemTagSvcPortal.trace) SemTagUtil.log("IFRAME(id=" + node.id + ",children=" + children.length + ")");
			if (children && 0<children.length) {
				var firstTime = SemTagMenu.includeCSS(children[0].parentNode);
				if (firstTime) {
					SemTagSvcPortal.watchEvent(node, 'load', SemTagSvcPortal.parseDom, false);
					SemTagMenu.registerMenuEventHandlers(children[0].parentNode);
				}
			}
		}
		if (children==null || children=='undefined') return;
		for (var i=0; i<children.length; i++) SemTagSvcPortal.traverse_children(children[i]);
	},
	testNode: function(node) {
		if (node==null || node.className==null || node.className=='undefined' || node.tagName==null || node.tagName=='undefined') return;
		var svcEntries = SemTagSvcPortal.service.entries;
		for (var j=0; j<svcEntries.length; j++) {
			var entry = svcEntries[j];
			if (!entry.test.match(/^id:/) && eval(entry.test))  {
                if ( !node.alreadyadded ) {
                    node.alreadyadded = true;
                    entry.nodes.push(node);
                } 
            }
		}
	},

	getService: function(svcId) {
		var svcEntries = SemTagSvcPortal.service.entries;
		for (var i=0; i<svcEntries.length; i++) {
			var entry = svcEntries[i];
			if (entry.id == svcId) return entry;
		}
	},
	
	// OKOETH
    // public
    setSemanticTagValue: function(/*String*/ svcId, /*Element*/ elem, /*Object*/ value) {

		 if (! elem.semTagValues) elem.semTagValues = {};
         elem.semTagValues[svcId] = value;
    },
	
    getSemanticTagValues: function(/*Element*/ elem) {

		 return elem.semTagValues;
    },
    
	// public
	getNodes: function(/*String*/ svcId) {

		var service = SemTagSvcPortal.getService(svcId); // here service returned is entry object
        if ( SemTagSvcPortal.debug ) console.log("Inside SemTagSvcPortal.getNodes for:"+svcId);
		if (service && service.test.match(/^id:/)) service = SemTagSvcPortal.getService(service.test.substr(3));
        if ( SemTagSvcPortal.debug ) console.log("Inside SemTagSvcPortal.getNodes for:"+svcId+"and service  is:"+service);
        if ( service ) if ( SemTagSvcPortal.debug ) console.log("Inside SemTagSvcPortal.getNodes for:"+svcId+"and service.nodes  is:"+service.nodes);
		return service? service.nodes: null; 
	},
	
	// public
	setCallback: function(/*String*/ svcId, /*Function*/ callback) {

		var service = SemTagSvcPortal.getService(svcId); // this returns the entry object
        
		if (service) {
            service.callback = callback;
            if ( SemTagSvcPortal.debug ) console.log("Callback setting for :"+svcId);
            if ( SemTagSvcPortal.debug ) console.log("Callback set for :"+service.id);
        } else {
        if ( SemTagSvcPortal.debug ) console.log("Did not get service for :"+svcId);
        }
	},
	
	loadScript: function(script,dynamic) {
		if (!script || script=="") return;

		if (!SemTagSvcPortal.scripts[script]) {
			SemTagSvcPortal.scripts[script] = true;
			var scriptElem = document.createElement("script");
			//var url = script.match(/^http/)? script: SemTagSvcPortal.baseUrl + script;
			var url = script.match(/^http/)? script: "/wps_semanticTag" + script;
            //var url = "./"+script.split("/")[2];
			// pass along the language parameter
			url += (url.indexOf("?")==-1)? "?": "&";
			url += "language=" + SemTagSvcPortal.lang;
			scriptElem.src = url;
			if ( dynamic ) {
			    if ( SemTagSvcPortal.debug ) console.log("URL in LOADSCRIPT GOT IS :"+url);

			    document.body.insertBefore(scriptElem, document.body.firstChild);
		    }
			
		}
	},
	
	setSpecialMenuProvider: function(callback) {
		SemTagSvcPortal.specialMenuProviders.push(callback);
	},

	// public
	getElementsByClassName: function(/*String*/ className, /*DomElement*/ element, /*Integer*/ limitCnt, /*String[]*/ tagScope) {

		if (!element) element = document.body; // entire 'body' if not passed in
		if (!limitCnt) limit = 0; // no limit if not passed in
		if (!tagScope) tagScope = ['*']; // no scoping if not passed in

		var regexp = SemTagSvcPortal.getRegExp(className);
		if (element && element.className && element.className.match(regexp)) return new Array(element);

		var elements = new Array();
		for (var t=0; t<tagScope.length; t++) {
			var children = element.getElementsByTagName(tagScope[t]);
			for (var i=0; i<children.length; i++) {
				var child = children[i];
				if (child.className && child.className.match(regexp)) elements.push(child);
				if (0<limitCnt && limitCnt==elements.length) break;
			}
		}
		return elements;
	},

	// public
	getParentByClassName: function(/*String*/ cName, /*DomElement*/ element) {

		if (!element) return null;
		var regexp = SemTagSvcPortal.getRegExp(cName);
		if (element.className && element.className.match(regexp)) return element;
		while(element.parentNode) {
			element = element.parentNode;
			if (element.className && element.className.match(regexp)) return element;
		}
		return null;
	},

	// public
	addHover: function(/*DomElement*/ elem, /*JsFunction*/ hoverHandler, /*JsFunction*/ clickHandler, /*String*/ alttext) {

		while ( typeof SemTagMenu == undefined ) alert( "waiting..." ); //HMtest

		var refcnt = elem.getAttribute(SemTagSvcPortal.refcntAttr);
		if ( SemTagSvcPortal.debug ) console.log("Refcount got is:"+refcnt+":"+SemTagMenu.staticHover +":"+(hoverHandler !== null) +":"+clickHandler);
		if (refcnt) { // this element has already got the basic setup
			elem.setAttribute(SemTagSvcPortal.refcntAttr, parseInt(Number(refcnt)+1)); // increment the ref count

			if (SemTagMenu.staticHover) {
				var img = SemTagMenu.findHoverFromLiveElement(elem);
				if (img) {
				    SemTagSvcPortal.watchEvent(img, 'click', clickHandler, false);
                	img.setAttribute("href", "javascript:SemTagMenu.a11y()");
				}
				else if (SemTagSvcPortal.debug) alert("couldn't find the hover for this element!");
			}
			else {
			        SemTagSvcPortal.watchEvent(elem, 'mouseover', hoverHandler, false);
			}
		} else { // this element needs a new setup
			elem.setAttribute(SemTagSvcPortal.refcntAttr, "1");
			SemTagSvcPortal.hoverIdx++;
			elem.setAttribute(SemTagSvcPortal.liveElemPrefix + "id", SemTagSvcPortal.hoverIdx); //NEEDSWORK "hover" index?

			if (SemTagMenu.staticHover) {
				var img = SemTagSvcPortal.createHoverImage(alttext);
				SemTagSvcPortal.watchEvent(img, 'click', clickHandler, false);
				SemTagSvcPortal.watchEvent(img, 'keydown', SemTagMenu.a11y, false); //A11Y
				img.setAttribute("href", "javascript:void()"); //A11Y make it visibly focusable

				var sibling = elem.nextSibling;
				if (sibling) sibling.parentNode.insertBefore(img,sibling);
					else elem.parentNode.appendChild(img);

				elem.setAttribute(SemTagSvcPortal.hoverIdPrefix + "idx", parseInt(SemTagSvcPortal.hoverIdx));
				elem.id = SemTagSvcPortal.liveElemPrefix + SemTagSvcPortal.hoverIdx; //NEEDSWORK what if the element already had an id...
			}
			else { // dynamic hover == visual indicator as to where to hover
				var classAttrs = SemTagUtil.getNodeClassValue(elem);
				if (classAttrs && 0<classAttrs.length) classAttrs += " hasHover"; //NEEDSATTN decoration
					else classAttrs = "hasHover";
				SemTagUtil.setNodeClassValue(elem, classAttrs);
				SemTagSvcPortal.watchEvent(elem, 'mouseover', hoverHandler, false);
				elem.setAttribute("tabIndex", "0"); //A11Y make it not a tab stop
				SemTagSvcPortal.watchEvent(elem, 'focus', hoverHandler, false); //A11Y
				SemTagSvcPortal.watchEvent(elem, 'blur', SemTagMenu.mouseout, false); //A11Y
				elem.setAttribute("title", alttext);
			}
		}
	},

	removeHover: function(elem,hoverHandler,clickHandler) {
		var refcnt = elem.getAttribute(SemTagSvcPortal.refcntAttr);
		if (refcnt) { // this element has some hover(s)
			var newCnt = Number(refcnt)-1;
			if (newCnt<0 && SemTagSvcPortal.debug) alert("SemTagSvcPortal.removeHover called on an element with refcnt=" + refcnt);
			if (SemTagMenu.staticHover) {
				var hover = SemTagSvcPortal.getHoverElement(elem);
				SemTagSvcPortal.clearEventWatch(hover, 'click', clickHandler, false);
				if (newCnt==0) {
					hover.parentNode.removeChild(hover);
				}
			}
			else { // dynamic
				SemTagSvcPortal.clearEventWatch(elem, 'mouseover', hoverHandler, false);
				SemTagSvcPortal.clearEventWatch(elem, 'focus', hoverHandler, false); //A11Y
				elem.setAttribute(SemTagSvcPortal.refcntAttr, newCnt);
				if (newCnt==0) {
					var classAttrs = SemTagUtil.getNodeClassValue(elem);
					var newAttrs = classAttrs.replace(/hasHover/, "");
					SemTagUtil.setNodeClassValue(elem, newAttrs); //NEEDSWORK only when there is some meaningful values in it
					elem.removeAttribute(SemTagSvcPortal.refcntAttr);
					elem.removeAttribute("tabIndex"); //A11Y make it not a tab stop
				}
			}
		}
	},

	createHoverImage: function(alttext) {
		var img = document.createElement("img");
		img.id = SemTagSvcPortal.hoverIdPrefix + SemTagSvcPortal.hoverIdx;
		img.className = SemTagMenu.iconName;
		//img.setAttribute("src", SemTagSvcPortal.baseUrl +"/ui/menu_selected.gif");
		img.setAttribute("src", "/wps_semanticTag/ui/menu_selected.gif");
		img.setAttribute("border", "0");
		img.setAttribute("alt", alttext); //A11Y

		var link = document.createElement("a");
		SemTagSvcPortal.watchEvent(link,"mouseover",SemTagMenu.activateHover,false);
		SemTagSvcPortal.watchEvent(link,"mouseout",SemTagMenu.deactivateHover,false);
		link.appendChild(img); //A11Y - caller should add 'href' for appropriate event handler

		return link;
	},

	getHoverElement: function(/*DomElement*/ liveElem) { //A11Y

		if (!liveElem) return null;
		if (SemTagMenu.staticHover) {
			var idx = liveElem.getAttribute(SemTagSvcPortal.hoverIdPrefix + "idx");
			var img = document.getElementById(SemTagSvcPortal.hoverIdPrefix + idx);
			if (img) return img.parentNode;
		}
		else { // dynamic hover
			var classAttrs = SemTagUtil.getNodeClassValue(liveElem);
			if (classAttrs.match(/hasHover/)) return liveElem;
		}
		return null;
	},

	// public
	showHover: function(/*Event*/ event, /*Function*/ clickHandler, /*String*/ label) {

		SemTagMenu.showHover(event, clickHandler, label);
	},

	// public
	setMenuData: function(/*Event*/ event, /*MenuItemJson[]?*/ items, /*String?*/ cssClass, /*HeaderJson?*/ header, /*FooterJson?*/ footer) {

		SemTagMenu.setMenuData(event, items, cssClass, header, footer);
	},

	// public
	getMenuItemJson: function(/*String*/ label, /*String*/ href, /*Integer*/ order, /*String*/ icon) {

		var o = order? order: 0;
		var i = icon? icon: "";
		return {"label": label, "href": href, "order": o, "icon": i};
	},

	// public
	getMenuHeaderJson: function(/*String*/ markup, /*String*/ mimetype, /*Integer*/ order) {

		if ( mimetype != "text/html" ) return null;
		if ( markup && 0 < markup.length ) return {"markup": markup, "order": order};
		else null;
	},

	// public
	getMenuFooterJson: function(/*String*/ markup, /*String*/ mimetype, /*Integer*/ order) {

		if ( mimetype != "text/html" ) return null;
		if ( markup && 0 < markup.length ) return {"markup": markup, "order": order};
		else null;
	},

	getElementFromEvent: function(event) {
		//return event.target? event.target: event.srcElement;
		var element = event.target? event.target: event.srcElement;
		if (element == window)
		{
			element = element.document;
		}
		return element;
	},

	// public
	getLiveElementFromEvent: function(event) {
		return SemTagMenu.findLiveElementFromEventSource(SemTagSvcPortal.getElementFromEvent(event));
	},

	getEventAbsoluteX: function (e) {
		// find out X
		var x=0;
		if (e.pageX) x = e.pageX;
		else if (e.clientX) {
			if (document.body.scrollLeft > document.documentElement.scrollLeft) {
				x = e.clientX + document.body.scrollLeft;
			}
			else {
				x = e.clientX + document.documentElement.scrollLeft;
			}
		}
		return x;
	},
	
	getEventAbsoluteY: function (e) {
		// find out Y
		var y=0;
		if (e.pageY) y = e.pageY;
		else if (e.clientY) {
			if (document.body.scrollTop > document.documentElement.scrollTop) {
				y = e.clientY + document.body.scrollTop;
			}
			else {
				y = e.clientY + document.documentElement.scrollTop;
			}
		}
		return y;
	},
	
	findPosition: function (obj, rightedge) {
		var count=0, posX=0, posY=0;
		var objW = obj.offsetWidth;
		if( obj.offsetParent ) {
			if (rightedge) posX += (SemTagSvcPortal.bidi=='rtl')? 0: objW;
			posY += obj.offsetHeight;
			while (obj != null) {
				posX += obj.offsetLeft;
				posY += obj.offsetTop;
				obj = obj.offsetParent;
				count++;
			}
			return [ posX + (SemTagSvcPortal.bidi=='rtl'? objW: 0), posY ];
		} else {
			return [ obj.x + (SemTagSvcPortal.bidi=='rtl'? objW: 0), obj.y ];
		}
	},
	
	createGroupJson: function(ctx,exts) { // top-level objects in 'actionRegistry' array
		return {"context": ctx, "extenders": exts};
	},

	createActionJson: function(id,js,ctx,label,desc,showif,url,order) { // elements in actionRegistry[x].extenders array
		var i = (id && 0<id.length)? id[0].innerHTML: null;
		var j = (js && 0<js.length)? js[0].innerHTML: null;
		var c = (ctx && 0<ctx.length)? ctx[0].innerHTML: null;
		var l = (label && 0<label.length)? label[0].innerHTML: null;
		var d = (desc && 0<desc.length)? desc[0].innerHTML: null;
		var s = (showif && 0<showif.length)? showif[0].innerHTML: null;
		var u = (url && 0<url.length)? url[0].innerHTML: null;
		//var o = SemTagSvcPortal.parseOrder(order);
		var o = (order && 0<order.length)? parseInt(order[0].innerHTML): 0;
		return {"id": i, "impl": j, "context": c, "label": l, "description": d, "showif": s, "url": u, "order": o};
	},
	parseOrder: function(order) {
		if (order==null || order.length==0) return 0;
		if (order.charAt(0)=='-') return parseInt(order.substr(1)) * -1;
		else return parseInt(order);
	},

	// public
	getActions: function(/*String*/ context) {

	if (!SemTagSvcPortal.actionRegistry) SemTagSvcPortal.processActions(); // actionRegistry building - run once (usually)

		for (var i=0; i<SemTagSvcPortal.actionRegistry.length; i++) {
			if (SemTagSvcPortal.actionRegistry[i].context==context) return SemTagSvcPortal.actionRegistry[i].extenders;
		}
		return SemTagSvcPortal.actionRegistry[0].extenders; // no such extenders == 'dummy' array
	},

	processActions: function() {
	    if ( SemTagSvcPortal.debug ) console.log("inside processActions of SemtagSvcPortal");
		if (!SemTagSvcPortal.actionRegistry) {
			SemTagSvcPortal.actionRegistry = new Array();
			SemTagSvcPortal.actionRegistry[0] = SemTagSvcPortal.createGroupJson("dummy", new Array());
		}

		var i;
		var actions = SemTagSvcPortal.getNodes("com.ibm.portal.action");
        if ( SemTagSvcPortal.debug ) console.log("Nodes got for com.ibm.portal.action is:"+actions);
		while (   actions && 0 < actions.length) {
			// prepare the Action Json
			if ( SemTagSvcPortal.debug ) console.log("Inside while loop of actions");
			var actnNode = actions.pop();
			var id = SemTagSvcPortal.getElementsByClassName("action-id",actnNode);
			var impl = SemTagSvcPortal.getElementsByClassName("action-impl",actnNode);
			var ctx = SemTagSvcPortal.getElementsByClassName("action-context",actnNode);
			var label = SemTagSvcPortal.getElementsByClassName("action-label",actnNode);
			var desc = SemTagSvcPortal.getElementsByClassName("action-description",actnNode);
			var showif = SemTagSvcPortal.getElementsByClassName("action-showif",actnNode);
			var url = SemTagSvcPortal.getElementsByClassName("action-url",actnNode);
			var order = SemTagSvcPortal.getElementsByClassName("action-order",actnNode);
			var actn = SemTagSvcPortal.createActionJson(id,impl,ctx,label,desc,showif,url,order);

			for (i=1; i<SemTagSvcPortal.actionRegistry.length; i++) {
				if (SemTagSvcPortal.actionRegistry[i].context==actn.context) { // add 'actn' if there's already a matching entry in actionRegistry
					var cnt = SemTagSvcPortal.actionRegistry[i].extenders.length;
					for (var j=0; j<cnt; j++) {
						if ( actn.id == SemTagSvcPortal.actionRegistry[i].extenders[j].id ) break;
					}
					if ( j == cnt ) SemTagSvcPortal.actionRegistry[i].extenders.push( actn );
					break;
				}
			}
			if (i==SemTagSvcPortal.actionRegistry.length) { // well, this is new - let's create it
				SemTagSvcPortal.actionRegistry[i] = SemTagSvcPortal.createGroupJson(ctx[0].innerHTML, new Array());
				SemTagSvcPortal.actionRegistry[i].extenders.push( actn );
			}
            if (SemTagSvcPortal.debug) console.log("Action.impl got is:"+actn.impl);
			if (actn.impl) SemTagSvcPortal.loadScript(actn.impl,true);

		}

		for (i=0; i<SemTagSvcPortal.actionRegistry.length; i++) SemTagSvcPortal.actionRegistry[i].extenders.sort( SemTagSvcPortal.sortByOrder );
	},

	sortByOrder: function(a,b) {
		if (a.order > b.order) return 1;
		else if (a.order < b.order ) return -1;
		else return 0;
	},

	// public
	getTextValue: function(elem) {
		if (!elem) return "";
		return elem.innerHTML.replace(/<[a-zA-Z\/][^>]*>/gi,"");
	},

	// public
	getTypedValue: function(elem,defProp) {
		if (!defProp) defProp = "def"; //NEEDSATTN "def" is not a standard sub-property
		var returnElem = new Array();
		var types = SemTagSvcPortal.getElementsByClassName("type", elem);
		var values = SemTagSvcPortal.getElementsByClassName("value", elem);
		var value = "";
		if (values.length < 1) value = SemTagSvcPortal.getTextValue(elem);
		for (var i=0;i<values.length;i++) {
			value += SemTagSvcPortal.getTextValue(values[i]);
		}
		if (types.length < 1) returnElem[defProp] = value;
		else {
			for (var j=0;j<types.length;j++) {
				var typeElem = types[j];
				var type = typeElem.tagName.match(/^abbr$/i)? typeElem.getAttribute("title"): SemTagSvcPortal.getTextValue(typeElem);
				returnElem[type.toLowerCase()] = value;
			}
		}
		return returnElem;
	},

	// public
	findNameElementInHcard: function(elem) {
		if (elem.className!="vcard") elem = SemTagSvcPortal.getParentByClassName('vcard',elem);
		var nameElem = SemTagSvcPortal.getElementsByClassName("fn",elem)[0];
		if (!nameElem) {
			nameElem = SemTagSvcPortal.getElementsByClassName("n",elem)[0];
		}
		return nameElem;
	},

	// public
	getEmailFromHcard: function(elem) {
		if (!elem) return "";
		if (elem.className!="vcard") elem = SemTagSvcPortal.getParentByClassName('vcard',elem);
		var email = "";
		if (elem) {
			var mailElem = SemTagSvcPortal.getElementsByClassName("email", elem)[0];
			var tvObj = SemTagSvcPortal.getTypedValue(mailElem, "internet");
			email = tvObj.internet;
		}
		return email;
	},

	// public
	findElementByNameInHcard: function(elem,name) {
		if (elem.className!="vcard") elem = SemTagSvcPortal.getParentByClassName('vcard',elem);
		return SemTagSvcPortal.getElementsByClassName(name,elem)[0];
	},

	getRegExp: function(str) { // not so effective for performance gain...
		var regexp = SemTagSvcPortal.reMap[str];
		if (!regexp) {
			regexp = new RegExp("(^|\\s)" + str + "(\\s|$)");
			SemTagSvcPortal.reMap[str] = regexp;
		}
		return regexp;
	}
};

/* (C) Copyright IBM Corp. 2007  All Rights Reserved.                */
/**
 * This is the common JS file for menus
 */
 





// Unless specifically noted, everything in this object is private to the semantic tagging / menu generation service core
var mytest = null;
var liveNameElementId = null;
var SemTagMenu = {

	needCss: true,
	staticHover: false, 
	id: "semtagmenu",
	hideDelay: 1500, // '0' requires an explicit event to dismiss the popup
	timeouts: new Array(),
	iconName: "menu_drop_icon",
	showing: false,
	currentElem: null,
	currentHoverLabel: null,
	refCount: -1,
	a11yMode: false,

	svcHandlers: new Array(),
	items: new Array(),
	headers: new Array(),
	footers: new Array(),
    moreActionImgUrl :"/wps_semanticTag"+"/ui/ShowActions.gif",
    verticalRulerUrl :"/wps_semanticTag"+"/ui/Line_Tree.gif",
	hoverIdRE: new RegExp(SemTagSvcPortal.hoverIdPrefix),
	iconNameRE: new RegExp("(^|\\s)menu_drop_icon(\\s|$)"), //NEEDSWORK why can't you use SemTagMenu.iconName?
	sftflag:false,
	
	init: function() {
		SemTagMenu.includeCSS(document);
		//SemTagMenu.registerMenuEventHandlers(document);
	},

	includeCSS: function(node) {
		var firstTime = false;

		if (typeof(node._JAVLIN_STYLE_) == 'undefined') {
			firstTime = true;

			if (SemTagMenu.needCss) {
				var css = node.createElement('link');
				css.rel = "stylesheet";
				//css.href = SemTagSvcPortal.baseUrl + '/ui/' + (SemTagSvcPortal.bidi=='rtl'? 'styles_rtl.css': 'styles.css');
				css.href = '/wps_semanticTag'  + '/ui/' + (SemTagSvcPortal.bidi=='rtl'? 'styles_rtl.css': 'styles.css');
				css.type = "text/css";
				var head = node.getElementsByTagName('head');
				if (( head && head[0] ) )
				{
				 head[0].appendChild(css);
			}

			}

			node._JAVLIN_STYLE_ = "loaded";
		}

		return firstTime;
	},

	registerMenuEventHandlers: function(node) {
		SemTagSvcPortal.watchEvent(node, 'click', SemTagMenu.click, false);
		SemTagSvcPortal.watchEvent(node, 'keydown', SemTagMenu.catchEscape, false); // A11Y
		SemTagSvcPortal.watchEvent(node, 'keyup', SemTagMenu.catchKeyup, false);
	},

	unregisterMenuEventHandlers: function(node) {
		SemTagSvcPortal.clearEventWatch(node, 'click', SemTagMenu.click, false);
		SemTagSvcPortal.clearEventWatch(node, 'keydown', SemTagMenu.catchEscape, false); // A11Y
		SemTagSvcPortal.clearEventWatch(node, 'keyup', SemTagMenu.catchKeyup, false);
	},

	 
 
 
 
nls: {
 
"hover_label": "Click for options",
"a11y_hover": "more information",
"a11y_photo": "photo",
"a11y_close": "close",
"ally_expandImage" : "Click to hide information",
"ally_collapsedImage" : "Click to display more information",
"ally_showMore" : "Show More",
"ally_showLess" : "Show Less",
"ally_buisnessCardLabel" : "Business Card",
"ally_moreAction": "More Actions"
 
},
 
hoverDimension:[14,14],
hoverOffset:[15,-1],
menuOffset:[15,-1],
writeHover: function(out, bidi, label) {
out.write("<div class='" + SemTagMenu.iconName + "' style='cursor:pointer;'>" + label + "</div>");
},
startMenu: function(out, bidi) {
out.write("<div class='personMenu' id='personMenuID'><ul style='padding:0px;margin:0px;list-style-type:none;float:left;'title='Person card dialog' alt='Person card dialog'><li tabindex=0 onkeydown=\"SemTagMenu.catchEscape();\" onkeyup=\"SemTagMenu.catchKeyup();\"></li></ul>");
},
writeHeader: function(out, header, bidi) {
out.write("<div class='semtag_header'>" + header.markup + "</div>");
},
startActionSection: function(out, bidi, selector ,item) {
if (!selector) selector="personMenuActions";
out.write("<div id='lessItem' style='display:block'><table class='personMenuActions' id='menuItemID' dir='" + bidi + "'><tr >");
if(0 < SemTagMenu.items.length){
tempitem=SemTagMenu.items.shift();
out.write("<td style='width:10'><a href='" + tempitem.href + "' style='color:#105ec1;padding-top:5px;padding-bottom:5px;font-size:1.0em;'> " + tempitem.label + "</a></td>");
}
if(item.length >= 1){
out.write("<td style='width:1'><img src= '" + SemTagMenu.verticalRulerUrl + "' /> </td> ");
out.write("<td ><a href='#' style='color:#105ec1;padding-top:5px;padding-bottom:5px;font-size:1.0em;width:90;'onClick=\"SemTagMenu.shtest();\" onKeydown=\" if (event.keyCode==13){SemTagMenu.shtest(); }\"><label id='actionMore'>"+SemTagMenu.nls.ally_moreAction + "</label><span style='position: absolute; top: -9000px;'>Press Enter for more actions items and tab to move the focus on items</span><img style='border:none;' src='" + SemTagMenu.moreActionImgUrl + "' title='" + SemTagMenu.nls.ally_collapsedImage + " ' /></a></td>");
}
out.write("</tr></table></div>");
out.write("<div id='moreItem' style='display:none'><table id='moreActionItems' class='" + selector + "' dir='" + bidi + "'>");
while (0 < SemTagMenu.items.length) {
item=SemTagMenu.items.shift();
out.write("<tr ><td><a href='" + item.href + "'>" + item.label + "</a></td></tr>");
}
out.write("</table></div>");
},
writeFooter: function(out, footer, bidi) {
out.write("<div class='semtag_footer'>" + footer.markup + "</div>");
},
endMenu: function(out, bidi) {
out.write("<a style='width:0px; height:0px;' onblur=\"SemTagMenu.exitCard();\" onclick='return false;' href='exit from person card' title='exit from person card'></a></div>");
},


	out: function () {
		this.buffer = "";
		this.write = function (str) {
			this.buffer += str;
		}
	},

	activateHover: function(event) {
		var imgElem = SemTagSvcPortal.getElementFromEvent(event);
		if (imgElem) imgElem.src = SemTagSvcPortal.baseUrl +"/ui/menu_selected_hover.gif";
		SemTagMenu.setCurrentElement(SemTagMenu.findLiveElementFromEventSource(imgElem));
	},

	deactivateHover: function(event) {
		var imgElem = SemTagSvcPortal.getElementFromEvent(event);
		if (imgElem) imgElem.src = SemTagSvcPortal.baseUrl +"/ui/menu_selected.gif";
		//SemTagMenu.setCurrentElement(null);
	},

	showHover: function(event, clickHandler, label) {
		if (SemTagMenu.staticHover) return;

		var tag = SemTagMenu.getMenuTag();
		if (SemTagMenu.showing && tag.style.display != "none") return;

		if (SemTagSvcPortal.trace) SemTagUtil.log("Menu.showHover");

		var elem = SemTagSvcPortal.getElementFromEvent(event);
		if (SemTagSvcPortal.trace) SemTagUtil.log("currentElem=" + SemTagMenu.currentElem);
		var origRefCnt = 0;
		if (elem && elem != SemTagMenu.currentElem) { // new hover request
			SemTagMenu.clearAllSvcHandlers(tag);

			origRefCnt = elem.getAttribute(SemTagSvcPortal.refcntAttr);
			if (SemTagSvcPortal.trace) SemTagUtil.log("refcnt=" + origRefCnt);
			if (origRefCnt) {
				SemTagMenu.setCurrentElement(elem);
			}
			else {
				if (SemTagSvcPortal.debug) alert("SemTagMenu.showHover called for a DOM element with no refcnt attribute!");
				SemTagMenu.setCurrentElement(null);
				return;
			}
		}

		SemTagMenu.addSvcHandler(tag, clickHandler);

		if (label && 0<label.length) SemTagMenu.currentHoverLabel = label;

		SemTagMenu.refCount--; // decrement for this current call
		if (0 < SemTagMenu.refCount) return; // need to wait more services to call in

		// everybody called in = time to actually show hover

		SemTagMenu.setRefCount((0<origRefCnt)? origRefCnt: Number(elem.getAttribute(SemTagSvcPortal.refcntAttr)));

		SemTagMenu.showing = false;
		if (event.type=="focus") { //A11Y
			SemTagMenu.a11yMode = true;
			SemTagSvcPortal.watchEvent(elem, 'keydown', SemTagMenu.a11y, false);
		}

		var out = new SemTagMenu.out();
		var label = SemTagMenu.currentHoverLabel? SemTagMenu.currentHoverLabel: SemTagMenu.nls.hover_label;
		SemTagMenu.writeHover(out, SemTagSvcPortal.bidi, label);
    	availAttrib.retrieveAttribute();
		SemTagMenu.offScreen(tag);
		tag.innerHTML = out.buffer;
		var pos = SemTagSvcPortal.findPosition(SemTagMenu.currentElem, false);
		
		var adjustX = (SemTagSvcPortal.bidi=='rtl')? 0 - SemTagMenu.hoverOffset[0]: SemTagMenu.hoverOffset[0];
		SemTagMenu.show(SemTagMenu.id, event,
			pos[0] + adjustX, // x
			pos[1] + SemTagMenu.hoverOffset[1], // y
			tag.offsetWidth, // w
			tag.offsetHeight); // h
	},

	addSvcHandler: function(tag, handler) {
		SemTagMenu.svcHandlers.push(handler);
		SemTagSvcPortal.watchEvent(tag, 'click', handler, false);
	},

	clearAllSvcHandlers: function(tag) {
		while (0 < SemTagMenu.svcHandlers.length) {
			var handler = SemTagMenu.svcHandlers.pop();
			if (handler) SemTagSvcPortal.clearEventWatch(tag, 'click', handler, false);
		}
	},

	setCurrentElement: function(elem) {
//		if (SemTagSvcPortal.debug && elem) {
//			alert("SemTagMenu.setCurrentElement: " + elem);
//		}
		SemTagMenu.currentElem = elem;
		SemTagMenu.setRefCount(elem? Number(elem.getAttribute(SemTagSvcPortal.refcntAttr)): 0);
		SemTagMenu.currentHoverLabel = null;

		while (0 < SemTagMenu.headers.length) SemTagMenu.headers.pop();
		while (0 < SemTagMenu.items.length) SemTagMenu.items.pop();
		while (0 < SemTagMenu.footers.length) SemTagMenu.footers.pop();
	},

	setRefCount: function(cnt) {
		SemTagMenu.refCount = cnt;
		//if (SemTagSvcPortal.debug && cnt<=0) alert("Unless this is from hide(), this is bad!");
	},

	setMenuData: function(event, items, cssClass, header, footer) {
		if (SemTagSvcPortal.debug) window.status = "Menu.setMenuData: items.length=" + (items? items.length: 0);

		if (!SemTagMenu.staticHover && SemTagMenu.refCount < 0) {
			if (SemTagSvcPortal.debug) alert("setMenuData called when refCount=" + SemTagMenu.refCount);
			return;
		}

		var elem = SemTagMenu.findLiveElementFromEventSource(SemTagSvcPortal.getElementFromEvent(event));
		if (!elem) {
			if (SemTagSvcPortal.debug) alert("setMenuData called on a null live element");
			return;
		}
		if (SemTagMenu.staticHover && // need to figure out the current live element and its ref count
			(elem != SemTagMenu.currentElem || SemTagMenu.showing)) {
			SemTagMenu.setCurrentElement(elem);
		}

//		SemTagMenu.waitCursor(); // need to do this only once, but...

		if (items) for (var i=0; i<items.length; i++) SemTagMenu.items.push(items[i]);
		if (cssClass) SemTagMenu.currentMenuCss = cssClass;
		if (header) SemTagMenu.headers.push(header);
		if (footer) SemTagMenu.footers.push(footer);

		SemTagMenu.refCount--; // decrement for this current call

		if (0 < SemTagMenu.refCount) return; // need to wait more services to call in

		// everybody called in = time to actually show popup
		SemTagMenu.stopEvent(event); // eat it always - this method is called upon ENTER as well

		// but wait - we need to call 'special menu providers'
		for (var j=0; j<SemTagSvcPortal.specialMenuProviders.length; j++) {
			var callback = SemTagSvcPortal.specialMenuProviders[j];
			var specialMenus = callback.call(event, SemTagMenu.currentElem);
			if (specialMenus && 0<specialMenus.length) {
				for (var k=0; k<specialMenus.length; k++)
					SemTagMenu.items.push(specialMenus[k]);
			}
		}

		SemTagMenu.showMenu(event);
	},

	// public
	getCurrentElement: function() {
		return SemTagMenu.currentElem;
	},

	showMenu: function(event) {
		if (0 == SemTagMenu.headers.length+SemTagMenu.items.length+SemTagMenu.footers.length) {
			SemTagMenu.hide();
			return;
		}

		if (SemTagSvcPortal.trace) SemTagUtil.log("Menu.showMenu");

		SemTagMenu.items.sort(SemTagSvcPortal.sortByOrder);
		if (1 < SemTagMenu.headers.length) SemTagMenu.headers.sort(SemTagSvcPortal.sortByOrder);
		if (1 < SemTagMenu.footers.length) SemTagMenu.footers.sort(SemTagSvcPortal.sortByOrder);

		var out = new SemTagMenu.out();
		SemTagMenu.startMenu(out, SemTagSvcPortal.bidi);
		if (0 < SemTagMenu.headers.length) SemTagMenu.writeHeader(out, SemTagMenu.headers[0], SemTagSvcPortal.bidi);
		
		
		SemTagMenu.startActionSection(out, SemTagSvcPortal.bidi, SemTagMenu.currentMenuCss,SemTagMenu.items);



//		for (var i=0; i<SemTagMenu.items.length; i++) {
//			SemTagMenu.writeMenuItem(out, SemTagMenu.items[i], SemTagSvcPortal.bidi);
//		}
	//	while ( 0 < SemTagMenu.items.length ) {
	//		SemTagMenu.writeMenuItem(out, SemTagMenu.items.shift(), SemTagSvcPortal.bidi);
      // 		}
      
	//	SemTagMenu.endActionSection(out, SemTagSvcPortal.bidi);

		
	//	SemTagMenu.startActionSectionForMoreActions(out, SemTagSvcPortal.bidi, SemTagMenu.currentMenuCss);
	//	while ( 0 < SemTagMenu.items.length ) {
	  //        SemTagMenu.writeMenuItemForMoreActions(out, SemTagMenu.items.shift(), SemTagSvcPortal.bidi);
        //   }
		//SemTagMenu.endActionSectionForMoreActions(out, SemTagSvcPortal.bidi);

		
		
		
		if (0 < SemTagMenu.footers.length) SemTagMenu.writeFooter(out, SemTagMenu.footers[0], SemTagSvcPortal.bidi);
		SemTagMenu.endMenu(out, SemTagSvcPortal.bidi);

		var tag = SemTagMenu.getMenuTag();
		SemTagMenu.clearAllSvcHandlers(tag);
		SemTagMenu.offScreen(tag);
		tag.innerHTML = out.buffer;
		SemTagMenu.showing = true;

		SemTagMenu.defaultCursor();

		if (SemTagMenu.a11yMode) {
			if (SemTagUtil.isGecko) { // SemTagMenu.staticHover?
				var links = tag.getElementsByTagName("li"); //A11Y
				if (0 < links.length) links[0].focus(); //NEEDSWORK this 'focus' remains if you start using mouse to change the menu selection...
			}
			else
				tag.focus(); //A11Y works great for IE, and with dynamic hover in FF
		}
		SemTagMenu.registerMenuEventHandlers(document);

		//var event = {"target": SemTagMenu.currentElem}; // make a fake event
		var pos = SemTagSvcPortal.findPosition(SemTagMenu.currentElem, false);
		var adjustX = (SemTagSvcPortal.bidi=='rtl')? 0 - SemTagMenu.menuOffset[0]: SemTagMenu.menuOffset[0];
		SemTagMenu.show(SemTagMenu.id, event, 
			pos[0] + adjustX, // x
			pos[1] + SemTagMenu.menuOffset[1], // y
			tag.offsetWidth, // w
			tag.offsetHeight); // h
	},

	getMenuTag: function() {
		var tag = document.getElementById(SemTagMenu.id);
		if (!tag) {
			tag = document.createElement("div");
			tag.setAttribute("id", SemTagMenu.id);
			tag.style.position = "absolute";
			tag.style.display = "none";
			tag.style.zIndex = "99999";
			SemTagSvcPortal.watchEvent(tag, 'mouseout', SemTagMenu.mouseout, false);
			SemTagSvcPortal.watchEvent(tag, 'mouseover', SemTagMenu.mouseover, false);
			//document.body.appendChild(tag);
			document.body.insertBefore(tag, document.body.firstChild);
		}
		return tag;
	},

	show: function (pMenu, e, xpos, ypos, width, height) {
		if (SemTagSvcPortal.trace) SemTagUtil.log("SemTagUtil.show");
        var iframeScrollTop;  //Variables defined for scrolling defect 193500
		var iframeScrollLeft; //Variables defined for scrolling defect 193500
		// first clear all previous timeouts since we're showing new menu
		SemTagMenu.clearTimeouts();
		var ptagMenu=document.getElementById(pMenu);
		if (width == null) width=0;
		if (height == null) height=0;

		var top,left;
		if (xpos != null && ypos != null) {
			var top = ypos;
			var left = xpos - (SemTagSvcPortal.bidi=='rtl'? width: 0);
		}
		else {
			var top = SemTagSvcPortal.getEventAbsoluteY(e);
			var left = SemTagSvcPortal.getEventAbsoluteX(e);
		}

		var vSrc = SemTagMenu.currentElem;
		mytest = vSrc.parentNode;
		// find winWidth and winHeight
		var winWidth, winHeight, d=document;
		if (typeof window.innerWidth!='undefined') {
			winWidth = window.innerWidth;
			winHeight = window.innerHeight;
		} else {
			if (d.documentElement && typeof d.documentElement.clientWidth!='undefined' && d.documentElement.clientWidth!=0) {
				winWidth = d.documentElement.clientWidth
				winHeight = d.documentElement.clientHeight
			} else {
				if (d.body && typeof d.body.clientWidth!='undefined') {
					winWidth = d.body.clientWidth
					winHeight = d.body.clientHeight
				}
			}
		}
		
		var scrollX = (document.body.scrollLeft > document.documentElement.scrollLeft)? document.body.scrollLeft: document.documentElement.scrollLeft;
		
		
		

		
		if ((left + width) > (winWidth + scrollX)) {
			var howMuch = (left + width) - winWidth - scrollX;
			left -= howMuch;
		}
		var scrollY = (document.body.scrollTop > document.documentElement.scrollTop)? document.body.scrollTop: document.documentElement.scrollTop;
		

		
		if ((top + height) > (winHeight + scrollY)) {
			var howMuch = (top + height) - winHeight - scrollY;
			top -= howMuch;
		}

		if (SemTagSvcPortal.bidi=='rtl' && left < 0) left = 0;

		//NEEDSWORK ugly, ugly, ugly
		//SemTagUtil.log("before IFRAME adjust (" + left + "," + top + ")"); //HMdebug
		//SemTagUtil.log( "ownerDoc=" + vSrc.ownerDocument ); //HMdebug
		//SemTagUtil.log( "location=" + vSrc.ownerDocument.location ); //HMdebug
		var od = SemTagUtil.getOwnerDocument(vSrc);
		if (od.location != document.location) { // okay, I'm in a child page (IFRAME)...
			var f = SemTagUtil.getFrameElement(vSrc);
			if (f) {

				//fix for defect 201052,now displaying hover wrt live object
				var el =f.offsetParent;
				var x = 0, y = 0;

					while (el)
					{
					x += el.offsetLeft;
					y += el.offsetTop;
					el = el.offsetParent;
					}

					var lof =vSrc.offsetParent;

					var xx = 0, yy = 0;

					while (lof)
					{
					xx += lof.offsetLeft;
					yy += lof.offsetTop;
					lof = lof.offsetParent;
					}

				if (f.id=='wpsFLY_flyoutIFrame') { // ugly, but works
					//top += f.parentNode.offsetTop;
					//left += f.parentNode.offsetLeft;
					top =  y  + yy + vSrc.offsetHeight;
					left = x + xx + vSrc.offsetWidth ;
				}
				else {
					top += f.offsetTop;
					left += f.offsetLeft;
				}
			//Code fix for scrolling defect 193500--Start
			if(SemTagUtil.isGecko && f.id=='wpsFLY_flyoutIFrame'){
				
                  iframeScrollLeft = f.contentWindow.pageXOffset;
                  iframeScrollTop  = f.contentWindow.pageYOffset;
 				  //alert("FF-- iframeScrollLeft : "+iframeScrollLeft + "iframeScrollTop: " +iframeScrollTop);
            }
			if(!SemTagUtil.isGecko && f.id=='wpsFLY_flyoutIFrame'){
                  iframeScrollLeft = f.contentWindow.document.body.parentNode.scrollLeft;
                  iframeScrollTop  = f.contentWindow.document.body.parentNode.scrollTop;
				  //alert("IE-- iframeScrollLeft : "+iframeScrollLeft + "iframeScrollTop: " +iframeScrollTop);
		    }
					
			top -= iframeScrollTop;
            left -= iframeScrollLeft;
			//Code fix for scrolling defect 193500--End
			}
		}
		//alert("ypos=" + ypos + "\nheight=" + height + "\npageY=" + e.pageY + "\nwinHeight=" + winHeight + "\nclientY=" + e.clientY + "\ndocument.body.scrollTop=" + document.body.scrollTop + "\ndocument.documentElement.scrollTop=" + document.documentElement.scrollTop + "\ntop=" + top + "\nleft=" + left); //HMdebug
		ptagMenu.style.top = top + "px";
		ptagMenu.style.left = left  + "px";
		ptagMenu.style.display="block";
		
		SemTagMenu.startHideTimer(pMenu);
	},

	hide: function (pMenu,e) {
		SemTagMenu.unregisterMenuEventHandlers(document);

		var tag = SemTagMenu.getMenuTag();
		if (!tag) return false;

		if (SemTagSvcPortal.trace) SemTagUtil.log("Menu.hide");
		if(tag.style.display != "block")
		{
			return false;
		}
		tag.style.display="none";
		SemTagMenu.showing = false;
		// added to set focus on next element to get it working for a11y
		try{
			var nextElem = SemTagMenu.getNextEle(mytest);
   			nextElem.focus(); 		
		}catch(e)  
		{
			document.body.focus();
		}
		SemTagMenu.setCurrentElement(null);
		SemTagMenu.currentHoverLabel = null;
		SemTagMenu.clearAllSvcHandlers(tag);
		SemTagMenu.a11yMode = false;
		SemTagMenu.defaultCursor();

		return true;
	},
	getNextEle:function(ele)
	{//alert("ele : " + ele);
		var par = ele.parentNode;
		//alert("par : " + par);
		while(true){
			if(par == null || par == 'undefined')
			{
				return false;
			}else if( par.nodeName == 'BODY')
			{
				return par;
			}else
			{
				var temp = par.nextSibling;
				if(temp != null)
				{
					return temp;
				}
				par = par.parentNode;
			}
		}
		return false;
	},
	
	offScreen: function(pMenu) {
		pMenu.style.top = "-1000px";
		pMenu.style.left = "-1000px";
		pMenu.style.display="block";
	},

	findLiveElementFromEventSource: function(eventSrc) {
		if (SemTagMenu.staticHover) {
			var id = eventSrc.id;
			if (!id.match(SemTagMenu.hoverIdRE)) {
				var children = eventSrc.getElementsByTagName("img"); //NEEDSATTN
				for (var i=0; i<children.length; i++) {
					if (children[i].id && children[i].id.match(SemTagMenu.hoverIdRE)) {
						id = children[i].id;
						break;
					}
				}
			}
			if ( id && 0 < id.length ) {
				var idx = id.substr(SemTagSvcPortal.hoverIdPrefix.length);
				return document.getElementById(SemTagSvcPortal.liveElemPrefix + idx);
			}
			else return eventSrc; // this saves the "static+inline" case
		}
		else {
			var liveElem = SemTagMenu.getCurrentElement();
			return liveElem? liveElem: eventSrc;
		}
	},

	findHoverFromLiveElement: function(liveElem) {
		var idx = liveElem.getAttribute(SemTagSvcPortal.hoverIdPrefix + "idx");
		return document.getElementById(SemTagSvcPortal.hoverIdPrefix + idx);
	},

	// check to see if the mouse is in the menu during this event...optional buffer parameters
	// can be used to expand the size of the menu
	inMenu: function(menuElem,event,bufferX,bufferY) {
		if (!menuElem) return false;
		if (!SemTagMenu.showing) return false;

		if (!bufferX) bufferX = 0;
		if (!bufferY) bufferY = 0;
		var mouseX = SemTagSvcPortal.getEventAbsoluteX(event);
		var mouseY = SemTagSvcPortal.getEventAbsoluteY(event);
		var elemX = menuElem.style.left.replace(/px$/,'');
		var elemY = menuElem.style.top.replace(/px$/,'');
		// if (debug) alert("mouseX:" + mouseX + ",mouseY:" + mouseY + ";elemX:" + elemX + ",elemY:" + elemY);
		var sumX = parseInt(elemX) + parseInt(menuElem.clientWidth);
		var sumY = parseInt(elemY) + parseInt(menuElem.clientHeight);
		// for some terrible reason, in IE, if you move off the element slowly (to the top or left), 
		// the last event happens just inside the menu, which is why we need to do mouseX-1 and mouseY-1
		if ((mouseX-1 <= (elemX - bufferX)) || (mouseY-1 <= (elemY - bufferY)) ||
			(mouseX >= (sumX + bufferX)) || (mouseY >= (sumY + bufferY))) return false;
		else return true;
	},

	mouseout: function(event) {
		if (SemTagSvcPortal.trace) SemTagUtil.log("Menu.mouseout");
		if (event.type=="blur") { // current live element is losing focus
			var evtSrc = SemTagSvcPortal.getElementFromEvent(event);
			if (SemTagMenu.currentElem) {
				if (SemTagSvcPortal.trace) SemTagUtil.log("clearEventWatch");
				SemTagSvcPortal.clearEventWatch(SemTagMenu.currentElem, "keydown", SemTagMenu.a11y, false);
			}
			if (!SemTagMenu.showing) { // hover is being dismissed
				if (SemTagSvcPortal.trace) SemTagUtil.log("dismissing hover");
				if (!evtSrc.className.match(SemTagMenu.iconNameRE)) SemTagMenu.hide();
			}
			// else we don't hide the popup as we are just popping it up
		}
		else {
			var menuId = SemTagMenu.id;
			menuElem = document.getElementById(menuId);
			if (SemTagMenu.inMenu(menuElem, event)) {
			}
			else {
				SemTagMenu.startHideTimer(menuId);
			}
		}
	},
	
	mouseover: function(event) {
		// if we're over the menu, clear timeouts so it doesn't hide
		SemTagMenu.clearTimeouts();
	},
	
	click: function(event) {
		if (!event) return;

		// on document click, check to see if you are in menu, and hide if you are
		// only hide if we were not invoked by the person tag image
		var srcElement = SemTagSvcPortal.getElementFromEvent(event);
//		if (SemTagMenu.staticHover && srcElement.firstChild && srcElement.firstChild.className==SemTagMenu.iconName) return;
//		if (!srcElement.className.match(SemTagMenu.iconNameRE)) {
//			var menuElem = document.getElementById(SemTagMenu.id);
//			var headerElem = SemTagSvcPortal.getElementsByClassName("photoCard", menuElem, 1)[0]; //HMtest
//			//if (headerElem) menuElem = headerElem;
//			if (!SemTagMenu.inMenu(menuElem, event)) SemTagMenu.hide(SemTagMenu.id);
//		}
		var container = SemTagSvcPortal.getParentByClassName("semtag_header", srcElement);
		var cont2     = SemTagSvcPortal.getParentByClassName("personMenuActions",srcElement);
		if (!container && !cont2) SemTagMenu.hide(SemTagMenu.id);
	},

   catchKeyup:function(event){
	    var key1;
		var cardNameFlag = false;
		if (event) {
	       if (event.which) key1 = event.which; // Netscape, FireFox, Opera
             else key1 = event.keyCode;          // IE 
        }
		if (SemTagSvcPortal.trace) SemTagUtil.log("Menu.catchKeyup:key=" + key1);
	   
	    var classValue = document.activeElement.className;
	    if(classValue.indexOf("lotusui") > -1) cardNameFlag = true;
	    if(key1 == 16 && cardNameFlag && SemTagMenu.sftflag)SemTagMenu.exitCard();
	    SemTagMenu.sftflag = false;
	},

	catchEscape: function (event) {
		var key;
		if (event) {
	       if (event.which) key = event.which; // Netscape, FireFox, Opera
             else key = event.keyCode;          // IE 
        }
		if (SemTagSvcPortal.trace) SemTagUtil.log("Menu.catchEscape:key=" + key);
        if(key == 16) SemTagMenu.sftflag = true;
		if (key == 27) {
			var nextFocus = null;
			if (SemTagMenu.showing) { // if we are hiding the popup...
				var currElem = SemTagMenu.getCurrentElement();
				if (currElem) { //A11Y
					nextFocus = SemTagSvcPortal.getHoverElement(currElem);
				}
			}
			SemTagMenu.hide();
			if (nextFocus) nextFocus.focus();
		}
	},

	a11y: function(event) { //A11Y catch the ENTER key on hover and fake a click event
		if (event) {
			var key;
			
			if (event.which) key = event.which; // Netscape, FireFox, Opera
				else key = event.keyCode; // IE as well as Iframe in IE (people palette)

			if (SemTagSvcPortal.trace) SemTagUtil.log("Menu.a11y:key=" + key);

			if (key == 13) {
				var elem = SemTagSvcPortal.getElementFromEvent(event);
				if (elem) {
					SemTagMenu.a11yMode = true; //A11Y
					var target = (SemTagMenu.staticHover? elem: SemTagMenu.getMenuTag());
					if (SemTagUtil.isGecko) {
						var evt = document.createEvent("MouseEvents");
						evt.initEvent("click", true, true);
						SemTagUtil.fireEvent(target, evt);
					}
					else { // IE
						target.click();
					}
					SemTagMenu.stopEvent(event);
				}
			}
		}
		else { // this must be the ENTER on the 'fn' elem
			var elem = SemTagMenu.currentElem;
			if (elem) {
				SemTagMenu.a11yMode = true; //A11Y
				var target = (SemTagMenu.staticHover? elem: SemTagMenu.getMenuTag());
				if (SemTagUtil.isGecko) {
					var evt2 = document.createEvent("MouseEvents");
					evt2.initEvent("click", true, true);
					SemTagUtil.fireEvent(target, evt2);
				}
				else { // IE
					target.click();
				}
				SemTagMenu.stopEvent(evt);
			}
		}
		return true; //NEEDSWORK? does this help stop event propagation?
	},

	stopEvent: function(event)
	{
		if (!event) return;

		if (SemTagUtil.isGecko) {
			try {
				event.preventDefault();
				event.stopPropagation();
			}
			catch (e) {
				// this event object may be a fake one, and there's no stopping necessary...
			}
		}
		else {
			try {
				event.returnValue = false;
				event.cancelBubble = true;
			}
			catch (e) {
				// In IE, when Person menu sends a server request out (passing browser 
				// cache), IE will somehow manage to corrupt this click event it had sent 
				// out earlier, and it causes silent error (abort) while doing the above.
				if (SemTagSvcPortal.trace) SemTagUtil.log("stopEvent caught " + e);
			}
		}
	},

	startHideTimer: function(menuId) {
		if (0<SemTagMenu.hideDelay && !SemTagMenu.a11yMode && !SemTagSvcPortal.debug) {
			SemTagMenu.timeouts.push(window.setTimeout('SemTagMenu.endHideTimer("' + menuId + '")',SemTagMenu.hideDelay));
		}
	},
	
	endHideTimer: function(menuId) {
		if (SemTagSvcPortal.trace) SemTagUtil.log("Menu.endHideTimer");
		SemTagMenu.hide(menuId);
	},
	
	clearTimeouts: function() {
		var tos = SemTagMenu.timeouts;
		for (i=0;i<tos.length;i++) {
			window.clearTimeout(tos[i]);
		}
	},

	defaultCursor: function() {
		document.body.style.cursor = "default";
	},

	waitCursor: function() {
		document.body.style.cursor = "progress";
	},
   
	shtest:function(){
         var tempId = document.getElementById("lessItem");
		 var tempMore = document.getElementById("moreItem");
         tempId.style.display='none';
		 tempMore.style.display='block';
	},

	exitCard:function(){
    var nextFocus = null;
			if (SemTagMenu.showing) { // if we are hiding the popup...
				var currElem = SemTagMenu.getCurrentElement();
				if (currElem) { //A11Y
					nextFocus = SemTagSvcPortal.getHoverElement(currElem);
				}
			}
			SemTagMenu.hide();
			if (nextFocus) nextFocus.focus();
	}
};

/**
 * This is the common JS file for utility methods
 */




 
var SemTagUtil = {

	isGecko: (document.all? false : true),

	getNodeClassValue: function(node) {
		var rv;
		if (SemTagUtil.isGecko) {
			//NEEDSWORK? I don't know how fast this 'undefined check' executes...
			rv = (typeof(node.getAttribute)!='undefined')? node.getAttribute("class"): "";
		}
		else {
			rv = node.className;
		}
		return (typeof(rv)!='undefined' && rv!=null)? rv: "";
	},

	setNodeClassValue: function(node,value) {
		if (SemTagUtil.isGecko)
			node.setAttribute("class", value);
		else
			node.className = value;
	},

	fireEvent: function(element, event) {
		try {
			if (element.fireEvent) element.fireEvent(event);
			else if (element.dispatchEvent) element.dispatchEvent(event);
		}
		catch (e) {
			if (SemTagSvcPortal.debug) alert("Svc.fireEvent caught: " + e);
		}
	},

	getOwnerDocument: function(element) {
		if (!element) return null;

		if (SemTagUtil.isGecko) {
			return element.ownerDocument;
		}
		else {
			var tmp = element;
			while (tmp.parentNode) tmp = tmp.parentNode;
			return tmp;
		}
	},

	getFrameElement: function(element) {
		if (SemTagUtil.isGecko) {
			var oD = element.ownerDocument;
			return oD.defaultView.frameElement;
		}
		else {
			var tmp = element;
			while (tmp.parentNode) tmp = tmp.parentNode;
			return tmp.parentWindow.frameElement;
		}
	},

	getHcardAttributeValue: function(hcardAttr, srcElement) {
		switch(hcardAttr) {
			case("email"):
				return SemTagUtil.getHcardTypedAttribute(srcElement, hcardAttr, "internet");
			case("tel"):
				return SemTagUtil.getHcardTypedAttribute(srcElement, hcardAttr, "voice");
			case("adr"):
				return SemTagUtil.getHcardTypedAttribute(srcElement, hcardAttr, "intl");
		}
		var parentVcard = SemTagSvcPortal.getParentByClassName("vcard", srcElement);
		var elems = SemTagSvcPortal.getElementsByClassName(hcardAttr, parentVcard, 1);
		if (elems.length > 0 && elems[0].tagName.match(/^abbr$/i)) return elems[0].getAttribute("title");
		switch (hcardAttr) {
			case("X-person-display-inline"): // this test is done for every hCard on the page, so, do it first
				if (elems.length > 0) return true;
				else return false;
			case("fn"):
				var fn = SemTagUtil.getSinglePropertyValue(elems[0]);
				if (fn) return fn;
					else return SemTagUtil.getHcardAttributeValue("n", srcElement); // no fn, parse for n
				break;
			case("X-person-header-only"):
			case("X-person-inside-inline"):
				return (elems && 0 < elems.length);
			case("X-sametime-resolve"):
				var stResolve = elems[0];
				return (typeof(stResolve)!='undefined' && stResolve!=null);
			case("n"):
				if (elems.length > 0) {
					var nElem = elems[0];
					var fnStr = "";
					var attrs = ["honorific-prefix","given-name","additional-name","family-name","honorific-suffix"];
					for (var i=0;i<5;i++) {
						var n = SemTagUtil.getSinglePropertyValue(SemTagSvcPortal.getElementsByClassName(attrs[i], nElem, 1)[0]);
						if (n) fnStr += n + " ";
					}
					return fnStr;
				}
				// empty or no n is valid, return blank
				return "";
				break;
			case("photo"):
				var photoElem = elems[0];
				if (photoElem) return photoElem.getAttribute("src");
				else return;
				break;
			case("X-sametime-status"):
				var stStatusElem = elems[0];
				if (!stStatusElem) return "";
				var stStatusValue = stStatusElem.getAttribute("value");
				if (stStatusValue) return stStatusValue;
				else return SemTagUtil.getSinglePropertyValue(stStatusElem);
				break;
			case("street-address"):
			case("post-office-box"):
			case("extended-address"):
			case("locality"):
			case("region"):
			case("postal-code"):
			case("country-name"):
			case("title"):
			case("role"):
			case("org"):
			default:
				return SemTagUtil.getSinglePropertyValue(elems[0]);
			break;
		}
	},

	getHcardTypedAttribute: function(srcElement, hcardAttr, defSubProp) {
		var returnElem = new Object();
		var parentVcard = SemTagSvcPortal.getParentByClassName("vcard", srcElement);
		var typedElems = SemTagSvcPortal.getElementsByClassName(hcardAttr, parentVcard);
		// this means there are multiple email, adr, or tel elements
		for (var i=0; i<typedElems.length; i++) {
			var curElem = typedElems[i];
//			if (curElem.tagName.match(/^abbr$/i)) {
//				returnElem[defSubProp] = curElem.getAttribute("title");
//				continue;
//			}
			if (hcardAttr == "email" && curElem.nodeName.toLowerCase() == 'a' && curElem.href.match(/^mailto:/)) {
				// then we need to use the href value
				var queryPos = curElem.href.indexOf("?");
				if (queryPos > -1) returnElem[defSubProp] = curElem.href.slice(7,queryPos);
				else returnElem[defSubProp] = curElem.href.slice(7);
				continue;
			}
			returnElem = SemTagSvcPortal.getTypedValue(curElem, defSubProp);
		}
		return returnElem;
	},
	
	getSinglePropertyValue: function (prop) {
		if (!prop) return false;
		var returnVal = prop.innerHTML.replace(/<[a-zA-Z\/][^>]*>/gi,"");
		return returnVal;
	},

	/**
	 * Object to issue cross-domain AJAX calls.  This object uses 
	 * a dynamic script generation/removal process.  This is required due 
	 * to the security restrictions placed on XMLHttpRequest
	 */
	crossDomainRequest:	function() {
		var openConnectionMapping = new Array();
		var requestSrcElements = new Array();
		var self = this;

		createTimeoutFunction = function (connectionId) {
			return function() { self.cancelRequest(connectionId); }
		};
	
		this.getScriptId = function(id) {
			return "_JVLN_" + id;
		};
		
		this.getScriptObject = function(id)	{
			var scriptId = SemTagUtil.isGecko? this.getScriptId(id): this.$_getScriptId(id);
			return document.getElementById(scriptId);
		};
		
		this.request = function(url, timeLimit, callback, srcElement, connectionId) {
			var objId = this.getScriptId(connectionId);
			if(callback) {
				openConnectionMapping[connectionId] = callback;
			}
			if (srcElement) {
				requestSrcElements[connectionId] = srcElement;
			}
			var script = document.createElement("script");
			script.id = objId;
			try {
				script.src = url;
			}
			catch(e) {
				if (SemTagSvcPortal.debug) alert("crossDomainRequest.request: " + e);
				return false;
			}
			// Insert at the first position to avoid odd IE behavior	
			document.body.insertBefore(script, document.body.firstChild);

			if(timeLimit) {
				var self = this;
				window.setTimeout(createTimeoutFunction(connectionId), timeLimit);
			}
		};
		
		this.cancelRequest = function(id) {
			if (SemTagSvcPortal.debug) window.status = "crossDomainRequest.cancelRequest";
			// If the connection is still open, gracefully clean it up and report this to the user
			var callback = openConnectionMapping[id];
			openConnectionMapping[id] = null;
			var srcElem = requestSrcElements[id];
			requestSrcElements[id] = null;

			if(callback) {
				try {
					if(callback) {
						var evt = {"target": srcElem}; // I need a fake event
						callback.call(this, false, null, evt);
					}
					var script = this.getScriptObject(id);
					if(script) {
						document.body.removeChild(script);
					}
				}
				catch(e) {
					if (SemTagSvcPortal.trace) SemTagUtil.log("crossDomainRequest.cancelRequest caught: " + e + "(callback=" + callback + ")");
				}
			}
		};
	
		this.dispatch = function(id, data) {
			if(!id) {
				return;
			}
			try {
				// Clean up the entry
				var callback = openConnectionMapping[id];
				if (SemTagSvcPortal.debug && !callback) alert("dispatch got null callback for: " + id);
				if(callback) {
					// Call the specified callback function
					var evt = {"target": requestSrcElements[id]}; // I need a fake event
					callback.call(this, true, data, evt);

					// clean up
					openConnectionMapping[id] = null;
					requestSrcElements[id] = null;
					var script = this.getScriptObject(id);
					if(script) {
						document.body.removeChild(script);
					}
				}
			}
			catch(e) {
				if (SemTagSvcPortal.trace) SemTagUtil.log("crossDomainRequest.dispatch caught: " + e);
			}
		};
	}, 
	
	log: function(msg) {
		var logger = document.getElementById("javlin.logger"); //NEEDSATTN
		if (logger) {
			var txt = document.createTextNode(msg + "..... ");
			logger.appendChild(txt);
		}
	}
};

/*
Licensed Materials - Property of IBM
 
5724S31

Copyright IBM Corp.  2007    All Rights Reserved.

US Government Users Restricted Rights - Use, duplication or 
disclosure restricted by GSA ADP Schedule Contract with IBM 
Corp.
*/





/**
 * This is the JS file for fetching the supported attributes of PUMA
 */
var availAttrib = {

	availAttribUrl: "/wps"+"/um/secure/attributes/users",
	req: "",
	userAttributesRetrieved : false,

	retrieveAttribute: function() {

		if (availAttrib.userAttributesRetrieved)
			return;
		
		if (SemTagSvcPortal.availAttribStr != "")
			return;

		  availAttrib.req= ibm.portal.xml.getXmlHttpRequest();     
		  availAttrib.req.onreadystatechange = availAttrib.processStateChange;

		  try {

			availAttrib.req.open("GET", availAttrib.availAttribUrl, true);

		  } catch (e) {

			alert(e);

		  }

		  availAttrib.req.send(null);
          availAttrib.userAttributesRetrieved= true ;


	  },

	getAttributesFromTags: function (elm, tag, prefix) {
		 if ( typeof ActiveXObject != "undefined" ) {
		    return elm.getElementsByTagName(prefix + ":" + tag);
        }
        return elm.getElementsByTagNameNS("*", tag); 
	},

	processStateChange: function () {
		if (availAttrib.req.readyState == 4) { // Complete
		  if (availAttrib.req.status == 200) { // OK response
			var response = availAttrib.req.responseText;
		   if(response.length  > 1)	{
			var oXmlDoc=ibm.portal.xml.loadXmlString(response); 
	
/*			if (typeof ActiveXObject != "undefined") 
				var attribs = oXmlDoc.documentElement.getElementsByTagName("atom:title");
			else 
				var attribs = oXmlDoc.documentElement.getElementsByTagName("title");
*/
			var attribs = availAttrib.getAttributesFromTags(oXmlDoc.documentElement, "title", "atom");
			var i;
			for (i=1;i<attribs.length;i++)
			{
				if (( SemTagSvcPortal.availAttribStr == "" ))
				{
					if (( attribs[i].firstChild.nodeValue != null) )
					{
						SemTagSvcPortal.availAttribStr = attribs[i].firstChild.nodeValue;
					}
				}else {

					if (( attribs[i].firstChild.nodeValue != null) )
					{
						SemTagSvcPortal.availAttribStr = attribs[i].firstChild.nodeValue+","+ SemTagSvcPortal.availAttribStr;
					}
				}
			}

		  }} else {

			alert("Problem: " + availAttrib.req.statusText);

		  }
		}

	  }

};

/*
Licensed Materials - Property of IBM
 
5724S31

Copyright IBM Corp.  2007    All Rights Reserved.

US Government Users Restricted Rights - Use, duplication or 
disclosure restricted by GSA ADP Schedule Contract with IBM 
Corp.
*/

//Make sure "ibm" and "ibm.portal" objects are defined, as it's conceivable that
//another product could define an "ibm" javascript object. It also is conceivable that
//another portion of the portal product would define an "ibm.portal" object. Hopefully
//they will play nicely as well and not overwrite OUR object definitions.
if(typeof(ibm)=="undefined")ibm = {};

if(typeof(ibm.portal)=="undefined")ibm.portal = {};
if(typeof(ibm.portal.xml)=="undefined")ibm.portal.xml = {};

// The object reference for all of the functions contained in this file
//ibm.portal.xml={};  commented out for defect 193789 and added following line inplace
if(typeof(ibm.portal.xml)=="undefined")ibm.portal.xml = {};

//----------------------------------------------------------------------  General utility methods
ibm.portal.util = {};

ibm.portal.util.cloneObject = function (obj) {
 var returnObj = {};
    for (i in obj) {
        returnObj[i] = obj[i];
    }
    return returnObj;
}

//----------------------------------------------------------------------- resource utility methods
ibm.portal.resource={};
ibm.portal.resource.str = {};
ibm.portal.resource.getString = function (bundle, key) {
    s = bundle[key];
    s = (s==null)?key:s;
    if (arguments.length >= 2) {
        i = 1;
        do {
            s = s.replace("%"+i , arguments[i]);
            i = i +1;
        } while ( i < arguments.length );
     }
     return s;
}

//---------------------------------------------------------------------- xml related utility methods
/*
 * getXmlHttpRequest()
 * loadXml(sUrl) - returns oDomDoc. parses xml from the url into DOM document object.
 * loadXmlString() - returns oDomDoc. parses xml from the contents of the string into DOM document object.
 * loadXsl()
 * transform()
 */
//ibm.portal.xml = {}; Commented out for defect 193789 and added following line inplace
if(typeof(ibm.portal.xml)=="undefined")ibm.portal.xml = {};
ibm.portal.xml.ie = {};
ibm.portal.xml.gecko = {};

ibm.portal.xml.getXmlHttpRequest = function() {
	var oXml = null;
	if (typeof ActiveXObject != "undefined") {
		oXml = new ActiveXObject("Microsoft.XMLHTTP");
	} else {
		oXml = new XMLHttpRequest();
	}
  return oXml;
}

ibm.portal.xml.loadXml = function(sUrl) {
	if (typeof ActiveXObject != "undefined") 
		return ibm.portal.xml.ie.loadXml(sUrl);
	else 
		return ibm.portal.xml.gecko.loadXml(sUrl);
}

ibm.portal.xml.loadXmlString = function(sXml) {
	if (typeof ActiveXObject != "undefined") 
		return ibm.portal.xml.ie.loadXmlString(sXml);
	else 
		return ibm.portal.xml.gecko.loadXmlString(sXml);
}

ibm.portal.xml.loadXsl = function(sUrl) {
	if (typeof ActiveXObject != "undefined") 
		return ibm.portal.xml.ie.loadXsl(sUrl);
	else 
		return ibm.portal.xml.gecko.loadXsl(sUrl);
}

ibm.portal.xml.transform = function (xml, xsl, sXslMode, aXslParams, bReturnString)
{
   if (typeof ActiveXObject != "undefined") {
    return ibm.portal.xml.ie.transform(xml, xsl, sXslMode, aXslParams,bReturnString);
  }
  else 
    return ibm.portal.xml.gecko.transform(xml, xsl, sXslMode, aXslParams,bReturnString);
}

ibm.portal.xml.update = function (nodeToUpdate, xml, xsl, sXslMode, aXslParams) {
	if ( typeof ActiveXObject != "undefined" ) {
		var results = ibm.portal.xml.ie.transform(xml, xsl, sXslMode, aXslParams, true );
		//Don't really want to use innerHTML here, but seems to be the only way IE will 
		//take the update.
		ibm.portal.debug.text( "XSLT result: " + results );
		nodeToUpdate.innerHTML += results;
	}
	else {
		results = ibm.portal.xml.gecko.transform(xml,xsl,sXslMode,aXslParams, false);
		nodeToUpdate.appendChild( results.documentElement );
	}
}

//---------------------------------------------------------------------- IE xml related utility methods

ibm.portal.xml.ie.loadXml = function(sUrl) {
	var oXmlDoc = new ActiveXObject("MSXML2.DOMDocument");
	oXmlDoc.async=0;
	oXmlDoc.resolveExternals = 0;
  	if(!oXmlDoc.load(sUrl))
  	{
  		//Callers should catch this and can substitute their own error message
  		throw new Error("Error loading xml file " + sUrl);
  	}
	return oXmlDoc;

}

ibm.portal.xml.ie.loadXmlString = function(sXml) {
	var oXmlDoc = new ActiveXObject("MSXML2.DOMDocument");
	oXmlDoc.async=0;
	oXmlDoc.resolveExternals = 0;
  	if(!oXmlDoc.loadXML(sXml))
  	{
  	    //Callers should catch this and can substitute their own error message
  		throw new Error("Error loading xml string " + sXml); 
  	}
	return oXmlDoc;
}

ibm.portal.xml.ie.loadXsl = function(sUrl) {
	//we need to use MSXML2.FreeThreadedDOMDocument interface in order to support 
	//mode and parameters in XSL transformation.
	var oXslDoc = new ActiveXObject("MSXML2.FreeThreadedDOMDocument");
	oXslDoc.async=0;
	oXslDoc.resolveExternals = 0;
  	if(!oXslDoc.load(sUrl))
  	{
  		//Callers should catch this and can substitute their own error message
  		throw new Error("Error loading xsl file " + sUrl);
  	}	
	return oXslDoc;
}

ibm.portal.xml.ie.transform = function(xmlDoc, xsl, sXslMode, aXslParams,bReturnString) {
	var oXml = xmlDoc;
	var oXsl = xsl;

     try {		
		if(!oXsl.documentElement) oXsl = this.loadXsl(xsl);
	 }
	 catch(e) {
		var sMsg = e.message;
		throw new Error(""+sMsg, ""+sMsg);
	 }
	//create the xsl processor and apply the transformation
	var oXslt = new ActiveXObject("Msxml2.XSLTemplate");
	oXslt.stylesheet = oXsl;
	var oXslProc = oXslt.createProcessor();
	oXslProc.input = oXml;
	
	//set paramaters if any
	if(aXslParams) {
		for(var p in aXslParams) {
			oXslProc.addParameter(p, aXslParams[p]);
		}
	}
	if (sXslMode) oXslProc.addParameter("mode", sXslMode);
	
	if (bReturnString) {
		if(!oXslProc.transform()) {
			//Callers should catch this and can substitute their own error message
  			throw new Error("Error transforming xml doc " + oXml); 
  		}
		return oXslProc.output;
	} else {
		var oHtmlDoc = new ActiveXObject("MSXML2.DOMDocument");
		oHtmlDoc.async = 0;
		oHtmlDoc.validateOnParse = 1;
		oXml.transformNodeToObject(oXsl,oHtmlDoc);
		return oHtmlDoc;	
	}
}

//---------------------------------------------------------------------- GECKO xml related utility methods

ibm.portal.xml.gecko.loadXml = function(sUrl) {
    //var oXmlResponse = NG.ServerRequest.postRequest(sUrl);
//    if (oXmlResponse) return xmlLoadString(oXmlResponse.responseText);
//    else return null;
	var oDomDoc = document.implementation.createDocument('','',null); 
//	oDomDoc.async = 0; // this is the important part
//	oDomDoc.load(sUrl);
// to support for Safari browser
		var xhr = new XMLHttpRequest();
		xhr.open( "GET", sUrl, false );
		xhr.send( null );
		  
		if ( xhr.status == 200 ) {
			oDomDoc = xhr.responseXML;
		}
	
	return oDomDoc;
}

ibm.portal.xml.gecko.loadXmlString = function(sXml) {
    var parser = new DOMParser();
    try { oXmlDoc = parser.parseFromString(sXml, "text/xml"); }
    catch (exc) {
	    //Callers should catch this and can substitute their own error message
  		throw new Error("Error loading xml string " + sXml); 
    }
	return oXmlDoc;
}

ibm.portal.xml.gecko.loadXsl = function(sUrl) {
	//This is done through createDocument because of anchor(#) we have in portal url. 
	//Do not change the code without testing the case.
	var oDomDoc = document.implementation.createDocument('','',null); 
//	oDomDoc.async = 0; // this is the important part
//	oDomDoc.load(sUrl);
	var xhr = new XMLHttpRequest();
		xhr.open( "GET", sUrl, false );
		xhr.send( null );
		  
		if ( xhr.status == 200 ) {
			oDomDoc = xhr.responseXML;
		}
	
	return oDomDoc;
}

ibm.portal.xml.gecko.transform = function(xmlDoc, xsl, sXslMode, aXslParams,bReturnString) {
	try {
	  var xslDoc = xsl;
      if(!xslDoc.documentElement) 
      {
          alert("xslDoc is not a Document, loading it...");
          xslDoc = this.loadXsl(xsl);
      }        
      var proc = new XSLTProcessor();
      proc.importStylesheet(xslDoc); 
 
      //set parameters if any
      if(aXslParams) {
	  	for(var p in aXslParams)  {
		    proc.setParameter(null, p, aXslParams[p]);
	    }
      }
      if (sXslMode) proc.setParameter(null, "mode", sXslMode);
    
      var resultDoc = proc.transformToDocument(xmlDoc);
      if (!bReturnString) {
      	return resultDoc;
      }
      resultStr = resultDoc.documentElement.textContent;
    } 
    catch (exc)
    {
        //alert("error transforming document: "+exc)
		//Callers should catch this and can substitute their own error message
  		throw new Error("Error transforming xml doc " + exc);
	}
    return resultStr;  
}

/* This method sets the content of a layer within the HTML page
 * to the result of transforming the xml parameter by the xsl
 * parameter. The xml and xsl parameters may be of any form
 * supported by the transformXml() method. The layer parameter
 * may be either a DOM object or the name of a DOM object that
 * can be found using the findObject() method.
 */

ibm.portal.xml.setLayerContentByXml = function (layer, xml, xsl, xslparam,bReturnString) {
    var result = ibm.portal.xml.transform(xml,xsl,null,xslparam,bReturnString);
    if (layer.innerHTML) layer.innerHTML = result;
    else {
        var obj = document.getElementById(layer);
        obj.innerHTML=result;
    }
}
			   
//----------------------------------------------------------------------  temporary ajax request method 
ibm.portal.io ={};

/* Accept-Language property */
ibm.portal.io.sAcceptLanguage = "";

/*
 * Mozilla throws an exception instead of returning null when the
 * response header is not there. This is a wrapper function that
 * handles the exception and returns null if necessary.
 */
ibm.portal.io.getResponseHeader = function (oXml, sHeader) {
  var result;
  try { result = oXml.getResponseHeader(sHeader); }
  catch (exc) { result = null; }
  return result;
}

ibm.portal.io.checkForError = function (oXml) {
    var sErrMsg = null;
    var sError = ibm.portal.io.getResponseHeader(oXml, "X-IBM-REST-Error");
    if(sError)
    {
        // sArg is the string argument to be replaced in the message if needed
        // Note that RFC 822 headers must contain only US-ASCII characters.
        // non US-ASCII characters must be encoded/decoded.
        var sErrMsg = '', sArg = ibm.portal.io.getResponseHeader(oXml, "X-IBM-REST-MsgArg1");
        if (sArg)
        {
            sErrMsg = ibm.portal.resource.getString(sError, window.decodeURIComponent(sArg));
        } else {
            sErrMsg = ibm.portal.resource.getString(sError);
        }
    }
    return sErrMsg;
}

/*
 * Makes an asynchronous request, allowing the calling object to react
 * at each stage. The calling object MUST define the functions startUpdate(),
 * handleError(), and handleData().
 */
ibm.portal.io.asyncRequest = function(method, sActionUrl, sParameter, oCaller) {
    try
    {
        ibm.portal.io.setAsync(method, sActionUrl, sParameter, oCaller, true);
    } catch(e) {
        ibm.portal.io.setAsync(method, sActionUrl, sParameter, oCaller, false);
    }
}

ibm.portal.io.setAsync = function(method, sUrl, sParameter, oCaller, bfirstime) {

    var oXml = ibm.portal.xml.getXmlHttpRequest();
    oXml.open(method, sUrl, true);

    if(! bfirstime)
    {
        oXml.setRequestHeader("Accept-language", "*");
    }

    try {
        oXml.onreadystatechange = function()  {
            if (oXml.readyState == 4)
            {
                //if (NG.ServerRequest.checkSessionExpiration(oXml))
                //{
                //    return;
                //}
                    oCaller.startUpdate(); //Let the caller know the request is done
                    sError = ibm.portal.io.checkForError(oXml);

                if (sError)
                {
                        oCaller.handleError(""+ibm.portal.resource.getString(sError));
                } else {
                    var data = oXml.responseText;
                    oCaller.handleData(data);
                    }
            }
        }
        oXml.send(sParameter);
    } catch(e) {
        throw new Error("", "");
    }
}

/* Copyright IBM Corp. 2007 All Rights Reserved.                      */
/**
 * This js file is the semantic tagging service for click-to-action.  It is
 * loaded when either a "c2a:source" or a "c2a:target" node is detected on a
 * page.  
 *
 * During initialization, it does the following:
 * 
 *   - sets up a callback function to handle dom changes
 *   - sets up a callback function for adding menu items to other live objects
 *   - processes c2a:targets and builds an array of c2a target types
 *   - processes c2a:source nodes and checks for matching targets 
 *   - if a match is found, it generates UI to place a menu icon next 
 *     to the source value on the page
 *
 * When the user clicks on a menu icon, it:
 *
 *    - 
 */

 



 

var SemTagC2A = {


        // -------------------------------------------------------------
        // Constant Definitions
        // -------------------------------------------------------------
        // id for registering this service in the Live Object Framework
        serviceId:  "c2a",
        
        // source tag names
        sourceTagName:  	"c2a:source",
        typeNameTagName:   	"c2a:typename",
        valueTagName:  		"c2a:value",
        displayTagName: 	"c2a:display",
        anchorTagName:		"c2a:anchor",

        // target tag names 
        targetTagName:  	"c2a:target",
        menulabelTagName:   "c2a:action-label",
        paramTagName:   	"c2a:action-param",
        
        // namespace processing
        defaultNameSpaceStr:   "IBM_C2A_DEFAULT_NAMESPACE",
        namespaceSep: "#",
        
        // PUBLIC namespace for targets that plug into other live object services, e.g. hcard
        liveObjectNamespace: "http://www.ibm.com/xmlns/prod/websphere/portal/v6.1/livetext",
        
        

        // -------------------------------------------------------------
        // Target Definition Arrays
        // -------------------------------------------------------------

        // Optimization: 2D array (indexed by c2a:namespace and c2a:type values)
        // to quickly determine if a c2a target of given namespace and type exists
        // on page.  Prevents us from having to traverse Targets array.
        // NOTE: Index order matters, namespace is first index, type is second.
        //       eg --> a[c2a:namespaceValue,c2a:typeValue]
        targetsAvail:	null,    

        // targetNodeIDs is an object keeping all IDs of target DOM 
        // nodes which are used during menu generation time
        targetNodeIDs:		new Object(),  

        // -------------------------------------------------------------
        // Source Definition Arrays
        // -------------------------------------------------------------

        // sourceNodeIDs is an object keeping all IDs of source DOM 
        // nodes which are used during menu generation time 
        sourceNodeIDs:		new Object(),  

        // -------------------------------------------------------------
        // Current Source Values
        // -------------------------------------------------------------
        currentValue:		"",
        currentValArray:      null,
        
        // -------------------------------------------------------------
        // variables used for unique ID 
        // generation for source and target nodes
        // -------------------------------------------------------------
        IDctr:				0,
        c2aIdBaseStr: 		"IBMC2ASRVC_",
        c2aSourceIdBase: 	"IBMC2ASRVC_Source_", 
        c2aTargetIdBase:	"IBMC2ASRVC_Target_",
		
		// -------------------------------------------------------------
		// add internationalization support.
		// this will be stored in a property called 'nls' via which
		// all resource strings will be available to the service
		//
		
		 
 
 
 
nls: {
 
"c2a_click_for_actions": "Click for Actions"
 
},


        // -------------------------------------------------------------
        // Bootstrap Function
        // -------------------------------------------------------------
        init: function () {
         
           // PUBLIC
           // initialize the IBM C2A object kept in the window which is used
           // for passing the c2a values back and forth
           // initialize the respective object for all subframes as well 
           // to make them available in the window scope of the document of the subframe
           // 
           // public information will be available in:
           //   window.ibm.portal.c2a.event.value
		   if (! window.ibm) window.ibm = new Object();
           if (! window.ibm.portal) window.ibm.portal = new Object();
           window.ibm.portal.c2a = new Object();
           for (var i=0; i<parent.frames.length; i++) {
           
               // if we have control over the content of the subframe
               // we may inject the c2a value container into the DOM of the subframe
               if (SemTagC2A.canAccessFrameContent(parent.frames[i])) {
               
	               if (! parent.frames[i].ibm) parent.frames[i].ibm = new Object();
	                  if (! parent.frames[i].ibm.portal) parent.frames[i].ibm.portal = new Object();
	                  parent.frames[i].ibm.portal.c2a = new Object();
               }
                  
           }
           
           // create regular expressions for tag comparisons
           SemTagC2A.defineRegExpressions();
           
           //  set up a call back to rescan the page when the DOM changes
           SemTagSvcPortal.setCallback(SemTagC2A.serviceId,SemTagC2A.parseDOM);

           //  set up callback for add menu items to non-c2a:source live object
           SemTagSvcPortal.setSpecialMenuProvider(SemTagC2A.getSpecialC2AMenuItems);
           
           // parse the DOM for sources and targets
           SemTagC2A.parseDOM();	
           
        },

        // -------------------------------------------------------------
        // Callback Functions -- functions that the framework or browser
        // will call to handle events
        // -------------------------------------------------------------

        getSpecialC2AMenuItems:  function(elem) {
            var menuItems = null;
            // this code has to return, or it will make the menu system very slow
            try {
               var checkElem = elem;
               //  This method checks for c2a targets for objects that are marked
               //  using a microformat rather than a c2a:source.  In this case,
               //  the semantic tags themselves provide the source namespace and type.

               //  Since the elem that we are passed is always the value object,  
               //  we need to get the parent to determine what type of object this is.  
               //  Get the parent's classname and check whether we have any
               //  targets defined with namespace == classname.  If not, just return.
               var parent = elem.parentNode;

               // the "class" attribute can have multiple values
               var semTagValues = SemTagSvcPortal.getSemanticTagValues(elem);
               for (var svcId in semTagValues) {
                   var value = semTagValues[svcId];
                   if (!value) continue;
    
                   // return the c2a targets that are intended to serve for 
                   // other services? popup menus
                   menuItems = SemTagC2A.getTargetMenuItems(SemTagC2A.getSpecialC2ASourceInfo(svcId, value));
               }

            } catch (e) {
            	if (SemTagSvcPortal.trace) {
            		SemTagUtil.log("error getting special c2a menu items, exception is " + e);
            	}
            }
            return menuItems;
        },

        showHover:  function(event) {
		   SemTagSvcPortal.showHover(event, SemTagC2A.handleClick, SemTagC2A.nls.c2a_click_for_actions);
		},
		
		canAccessFrameContent: function(/*frame*/ frame) {
			var accessGranted = false;
			
			try {
				if (window.location.host == frame.location.host 
					&& window.location.protocol == frame.location.protocol) {
					
					accessGranted = true;
				}
			} catch ( err ) {
			
			}
			
			return accessGranted;			
			
		},
		
        findElementInWindowScope: function(/*String*/ elementID) {

             var element;
             element = document.getElementById(elementID);

             // if the element could not be found in the 
             // current window, one has to have a look into
             // the available subframes
             if (element == null) {
                 // walk through all frames that are in the parent
                 for (var i=0; i<parent.frames.length;i++) {
                 
                 	 if (SemTagC2A.canAccessFrameContent(parent.frames[i])) {
	                     element = frames[i].document.getElementById(elementID);
	                     if (element != null) {
	                         break;
	                     }
	                 } 
                 }
             } 
             
             return element;
        },
        
        handleClick: function (event) {
        
        
           // This function is called when the user clicks on the menu icon inserted next
           // to the c2a:value tag on the page.  Fetch node from event.
           
                         
           /*
            * clear the window.ibm.portal.c2a.event variable
            * this is not done immediately after form submission in executeMenuAction
            * as one can not guarantee that the onclick handler is executed BEFORE setting
            * the object to null. 
            * Doing it here guarantees that the variable is cleared upon next user interaction
            */                 
           if (! window.ibm) window.ibm = new Object();
           if (! window.ibm.portal) window.ibm.portal = new Object();
           window.ibm.portal.c2a = new Object();
           for (var i=0; i<parent.frames.length; i++) {
           
               // if we have control over the content of the subframe
               // we may inject the c2a value container into the DOM of the subframe
               if (SemTagC2A.canAccessFrameContent(parent.frames[i])) {
               
	               if (! parent.frames[i].ibm) parent.frames[i].ibm = new Object();
	                  if (! parent.frames[i].ibm.portal) parent.frames[i].ibm.portal = new Object();
	                  parent.frames[i].ibm.portal.c2a = new Object();
               }          
           }

           var liveNode = SemTagSvcPortal.getLiveElementFromEvent(event);
           
           // node is child c2a:value node.  Get it's parent (ie. c2a:source node).
           if (!SemTagC2A.isSource(liveNode))   {
               var sourceNode = SemTagSvcPortal.getParentByClassName(SemTagC2A.sourceTagName,liveNode);

           }
                   // now go build up menu items
           SemTagC2A.generateMenuContents(event, sourceNode);
        },

        // -------------------------------------------------------------
        // DOM Parsing functions
        // -------------------------------------------------------------
        parseDOM: function() {

            //  Split up sources and targets into separate arrays
            SemTagC2A.processDomNodes(SemTagSvcPortal.getNodes(SemTagC2A.serviceId));

            //  check all c2a sources to determine if they have matching c2a targets.  
            //  If so, add the UI to support the action menu on c2a sources
            SemTagC2A.processSources(SemTagC2A.sourceNodeIDs);

        },
        
        processDomNodes: function(newNodeList) {
           // first scan class member variable source and target arrays to see if any
           // nodes we are holding onto have been deleted from DOM.  If so, remove them from 
           // arrays to prevent ghost source and targets (i.e. ensure class data mirrors DOM).
           
           // run through array of source node ids
           for (var nodeID in SemTagC2A.sourceNodeIDs) {
           		//if (!document.getElementById(nodeID)) {
                if (! SemTagC2A.findElementInWindowScope(nodeID)) {
           			// a source node is no longer present in DOM so remove it from array
           			delete SemTagC2A.sourceNodeIDs[nodeID];
           		}
           }
           
           // run through the target node ids
           for (var nodeID in SemTagC2A.targetNodeIDs) {
           		//if (!document.getElementById(nodeID)) {
                if (! SemTagC2A.findElementInWindowScope(nodeID)) {
           			// a target node is no longer present in DOM so remove it from array
           			delete SemTagC2A.targetNodeIDs[nodeID];
           		}
           }
           
 
           // Finally, scan new list of nodes, copying sources and targets to 
           // corresponding internal source/target arrays.  NOTE: first check new nodes
           // to ensure we don't already have them in these arrays (i.e. prevent duplicates).
           
           while (newNodeList && newNodeList.length > 0) {
              var node = newNodeList.pop();
              // First check whether we already have the node in one of our arrays
              // Note: It is not sufficient to check for the common prefix as the 2 while
              // loops above might have deleted the id from our array
              var nodeIDstr = node.id;
              if (nodeIDstr != null && (SemTagC2A.exists(SemTagC2A.sourceNodeIDs, nodeIDstr) || SemTagC2A.exists(SemTagC2A.targetNodeIDs, nodeIDstr))) {
                  continue;
              }
              // now get node type and add it to appropriate member variable source/target array
              if (SemTagC2A.isSource(node)) {
                 // give it a unique ID we can use when DOM is updated to indicate we 
                 // know about this node, thus preventing duplicates in member source array
                 if (node.id == null || node.id == "") {
                     node.id = SemTagC2A.c2aSourceIdBase + SemTagC2A.IDctr;
                     SemTagC2A.IDctr++;
                 }
                 // a new source node is present in DOM so add it's ID to Sources object as property
                 SemTagC2A.sourceNodeIDs[node.id] = "true";
              }
              else if (SemTagC2A.isTarget(node)) {
                 // give it a unique ID we can use when DOM is updated to indicate we 
                 // know about this node, thus preventing duplicates in target array
                 if (node.id == null || node.id == "") {
                     node.id = SemTagC2A.c2aTargetIdBase + SemTagC2A.IDctr;
                     SemTagC2A.IDctr++;
                  }
                 // and add the node's ID to Targets object as property
                 SemTagC2A.targetNodeIDs[node.id] = "true";
              } 
           }
           // ok, we have an updated Targets array.  Now refresh the availability array we use
           // to track known targets.  Note: We don't have an avaiability array for Sources. 
           SemTagC2A.updateAvailableTargets();           
        },

		exists: function(object, property) {
			if (object[property] && object[property] == "true") {
				return true;
			}
			return false;
		},

        processSources: function(sourceIDs) {
           // iterate over c2a source nodes to add menu if necessary
           for (var sourceID in sourceIDs) {
              // fetch live DOM c2a source node
              //var sourceNode = document.getElementById(sourceID); 
              var sourceNode = SemTagC2A.findElementInWindowScope(sourceID);

                  // get the type and display fields
              var info = SemTagC2A.getSourceInfo(sourceNode);
              
              // see if there is even target avail for this source
              var hasTarget = SemTagC2A.isTargetDefined(info);
              
			  // ensure that the value node c2a:value on which the hover will be placed
			  // can be found in the info JSON parsed from the markup              
              if (info.value == null || info.value == "") {
                if (SemTagSvcPortal.trace) {
              		SemTagUtil.log("Click-to-Action error: Missing c2a:value tag");
              	}
              	break;
              }

              // get hover state since we could have previously added hover              
              var hasHover = info.anchorNode.getAttribute("hasHover");
              
              
              // If matching target was found for this source OR source has a menu display defined in
              // it ("c2a:display" tag), then source should have a menu hover.  Add hover to source's child 
              // c2a:value node (if it doesn't have one) and update hover state.
              if (hasTarget || info.display != "" ) {
                 // have we already put a hover on this node?                
                 if (hasHover == null || hasHover == "false") {  
                    // create the menu icon and insert it into the DOM after the source's c2a:value node
                    SemTagSvcPortal.addHover(info.anchorNode, SemTagC2A.showHover, SemTagC2A.handleClick);                    
                    // no support in Semantic Tag framework to track hover status so set our own an attribute.
                    info.anchorNode.setAttribute("hasHover", "true");
                 }
              }
              else  // otherwise, remove hover from c2a:value node if it exist and update hover state
              {
                 if (hasHover == "true") {
                    SemTagSvcPortal.removeHover(info.anchorNode,SemTagC2A.showHover,SemTagC2A.handleClick);
                 }
                 // now update c2a:value node's hover state
                 info.anchorNode.setAttribute("hasHover", "false");
              }
           }
        },

        // -------------------------------------------------------------
        // Utility Functions
        // -------------------------------------------------------------
        defineRegExpressions:  function() {

            // Source Tag regular expressions for comparison
            SemTagC2A.sourceRegExp = new RegExp("(^|\\s)" + 
                SemTagC2A.sourceTagName + "(\\s|$)");
            SemTagC2A.typeNameRegExp = new RegExp("(^|\\s)" + 
                SemTagC2A.typeNameTagName + "(\\s|$)");
            SemTagC2A.valueRegExp = new RegExp("(^|\\s)" + 
                SemTagC2A.valueTagName + "(\\s|$)");
            SemTagC2A.displayRegExp = new RegExp("(^|\\s)" + 
                SemTagC2A.displayTagName + "(\\s|$)");
            SemTagC2A.anchorRegExp = new RegExp("(^|\\s)" + 
            	SemTagC2A.anchorTagName + "(\\s|$)");
           
            // Target Tag regular expressions for comparison
            SemTagC2A.targetRegExp = new RegExp("(^|\\s)" + 
                SemTagC2A.targetTagName + "(\\s|$)"),
            SemTagC2A.menulabelRegExp = new RegExp("(^|\\s)" + 
                SemTagC2A.menulabelTagName + "(\\s|$)");
            SemTagC2A.paramRegExp = new RegExp("(^|\\s)" + 
                SemTagC2A.paramTagName + "(\\s|$)");
        },

        isTarget:  function(node) {
            if (node.tagName == "FORM") {
                return (SemTagUtil.getNodeClassValue(node).match(SemTagC2A.targetRegExp));
            } else {
                return false;
            }
        },

        isSource:  function(node) {
            if (node.tagName == "SPAN" || node.tagName == "DIV") {
                return (SemTagUtil.getNodeClassValue(node).match(SemTagC2A.sourceRegExp));
            } else {
                return false;
            }
        },
        
        updateAvailableTargets: function() {
           // reset target availability array
           SemTagC2A.targetsAvail = null;
           SemTagC2A.targetsAvail = new Array();
           
           for (var targetNodeID in SemTagC2A.targetNodeIDs) {
              // fetch live DOM c2a target node 
              //var parentNode = document.getElementById(targetNodeID);
              var parentNode = SemTagC2A.findElementInWindowScope(targetNodeID);
              // Find the c2a "typename" child element values.  These will
              // be used as indexes.
              var theChildNodes = parentNode.childNodes;
              var namespace = null;
              var type = null;
              for (var i=0; i < theChildNodes.length; i++) {
                 var node = theChildNodes[i];
                 var cname = SemTagUtil.getNodeClassValue(node);
                 if (cname == "") continue;
                 if (cname.match(SemTagC2A.typeNameRegExp)) {
                    var typeName = SemTagC2A.getElementValue(node);
                    var resultTypeNameParsed = SemTagC2A.parseTypeName(typeName);
                    namespace = resultTypeNameParsed.namespace;
                    type = resultTypeNameParsed.type;
                    
                    // now, use target's namespace and type values as indexes into an array
              		// to set availability.
              		if (type != null) {
                 		if (namespace == null) {
                    		// namespace is optional - it wasn't there so set default one
                    		namespace = SemTagC2A.defaultNameSpaceStr;
                 		}
                 		if (typeof(SemTagC2A.targetsAvail[namespace]) == "undefined") {
                    		SemTagC2A.targetsAvail[namespace] = new Array();
                 		}
                 		// set availability to true indicating that a target with these 
                 		// namespace and type values exists
                 		SemTagC2A.targetsAvail[namespace][type] = true;
              		}
                 }
              }
           }
        },

        parseTypeName: function(typeName) {
             var namespace = null;
             var type = null;
             var sepIdx = typeName.indexOf(SemTagC2A.namespaceSep);
             if (sepIdx < 0) {
                 namespace = SemTagC2A.defaultNameSpaceStr;
                 type = typeName;
             } else {
                 namespace = typeName.substring(0, sepIdx);
                 type = typeName.substring(sepIdx+1);
            
             }
             
             // handle the type information for typenames intended to 
             // be part of the communication between different services. 
             if (namespace == SemTagC2A.liveObjectNamespace) {
                 // handle liveobject targets that receive only a selected field of the data, e.g. hcard.email.internet
                 // the type for matching in this case would be 'hcard' whereas 'email.internet' further specifies what
                 // part of the hcard JSON is to be used 
                 var fieldSepIdx = type.indexOf('.');
                 if (fieldSepIdx > 0) {
                     var fieldSelector = type.substring(fieldSepIdx+1);
                     type = type.substring(0, fieldSepIdx);
                     return {"namespace":namespace, "type":type, "selector":fieldSelector};
                 }
             }
             
             return {"namespace":namespace, "type":type};
        },

        isTargetDefined:  function(info) {
            var retVal = false;
            
            for (var i=0; i<info.typenames.length; i++) {
            	
	            if (!info.typenames[i].namespace || info.typenames[i].namespace == "") { 
	               info.typenames[i].namespace = SemTagC2A.defaultNameSpaceStr;
	            }
	            if (typeof(SemTagC2A.targetsAvail[info.typenames[i].namespace]) != "undefined") {
	               var exists = SemTagC2A.targetsAvail[info.typenames[i].namespace][info.typenames[i].type];
	               retVal = (typeof(exists) != "undefined" && exists ? true:false);
	            }
	            
	            if (retVal == true) {
	            	return retVal;
	            }
            }
            
            return false;
        },

        isTargetSourceMatch:  function(sourceInfo, targetInfo) {

			 var sourceTypeName;
			 var targetTypeName;
             for (var i=0; i<sourceInfo.typenames.length; i++) {
             
             	 sourceTypeName = sourceInfo.typenames[i];
             	 
                 for (var j=0; j<targetInfo.typenames.length; j++) {
                 
                 	 targetTypeName = targetInfo.typenames[j];
                     //if (SemTagC2A.isTargetSourceTypenameMatch(sourceInfo.typenames[i], targetInfo.typenames[j])) {
                     //    return true;
                     //}
                     
                     if (sourceTypeName.namespace == targetTypeName.namespace) {
	                     if (sourceTypeName.namespace == SemTagC2A.liveObjectNamespace) {
	                         // need to deal with the hcard stuff specified
	                         // targetInfo selector applied to the sourceInfo value must result in not null
	                         // it would make no sense to add a menu item although the value expected
	                         // by the target action cannot be determined from the source hcard
	                         var value;
	                         if (targetTypeName.selector) {
	                             value = SemTagC2A.selectSubField(sourceInfo.value, targetInfo.selector);
	                         } else {
	                             // if no selector is defined, the full JSON is the value to be passed 
	                             value = sourceInfo.value;
	                         }
	                         if (value && value != null && value != "") {
	                             return true;
	                         } 
	                     } else {
	                         // ordinary c2a case where typematch is required
	                         if (sourceTypeName.type == targetTypeName.type) {
	                             return true;
	                         }
	                     }
             	     }
                 }
             }
             return false;
        },
	
        getElementValue: function (element) {
            var text;
            if  (SemTagUtil.getNodeClassValue(element).match(SemTagC2A.displayRegExp)) {
                text = element.innerHTML;
            } else {
                text = element.firstChild.nodeValue;
            }
            // trim off any whitespace
            return (text == null?  "" : text.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1"));
        },
        
        
        fillC2AInfo: function(node, info) {
        
        	var nodeChildren = node.childNodes;
        	for (var i=0;i<nodeChildren.length;i++) {
        		var nodeChild = nodeChildren[i];
        		var className = SemTagUtil.getNodeClassValue(nodeChild);
        		if (className == null || className=="") {
        			// any tag element not having a class needs to be investigated
        			// because it might contain c2a children
        			if (nodeChild.childNodes.length > 0) {
        				SemTagC2A.fillC2AInfo(nodeChild, info);
        			}
        		} else {
	        		if (className.match(SemTagC2A.typeNameRegExp)) {
	                    var typeName = SemTagC2A.getElementValue(nodeChild);
	                    var result = SemTagC2A.parseTypeName(typeName);
	                    
                        // add another typename to the info object
                        info.typenames.push({namespace: result.namespace, 
                                                type: result.type});
                        
                        
	                    // in case selector information has been detected for a 
	                    // source offered by a different service, this has to be 
	                    // propagated to the target menu
	                    if (result.selector) {
	                    	info.selector = result.selector;
	                    }
	                } else if (className.match(SemTagC2A.valueRegExp) && info.value=="") {
	                    info.value = SemTagC2A.getElementValue(nodeChild);
	                    
	                    // make the value node the anchor node if no anchor
	                    // has been defined yet. In case an anchor node is defined afterwards, 
	                    // it will be overwritten, if not, the value is the anchor
	                    if (! info.anchorNode || info.anchorNode == "") {
	                    	info.anchorNode = nodeChild;
	                    }
	                } else if (className.match(SemTagC2A.displayRegExp) && info.display=="") {
	                    info.display = SemTagC2A.getElementValue(nodeChild);
	                } else if (className.match(SemTagC2A.menulabelRegExp) && info.menuLabel=="") {
	                	info.menuLabel = SemTagC2A.getElementValue(nodeChild);
	                } else if (className.match(SemTagC2A.anchorRegExp)) {
	                	info.anchorNode = nodeChild;
	                } else if (! className.match(SemTagC2A.sourceRegExp) && ! className.match(SemTagC2A.targetRegExp)) {
	                	// traverse this node?s children
	                	if (nodeChild.childNodes.length > 0) {
	                		SemTagC2A.fillC2AInfo(nodeChild, info);
	                	}
	                }
	            }
        	}
        },
        
        getSpecialC2ASourceInfo: function(svcId, value) {
                                                           
        	var info = {"typenames": new Array(),
        				"value": value,
        				"display": "",
        				"anchorNode":""};
            info.typenames.push({namespace: SemTagC2A.liveObjectNamespace, 
                                                type: svcId});
                                                
            return info;
        },
        
        getSourceInfo: function (sourceNode) {
        	var info = {"typenames": new Array(),
        				"value":"",
        				"display":"",
        				"anchorNode":""}			
        	SemTagC2A.fillC2AInfo(sourceNode, info);
        	return info;
        },
        
        getTargetInfo: function(targetNode) {
        	var info = {"typenames": new Array(),
        				"menuLabel":""}				
        	SemTagC2A.fillC2AInfo(targetNode, info);		
        	return info;
        },
        	
	

        // -------------------------------------------------------------
        // Menu Item Generation functions
        // -------------------------------------------------------------
        // Get the menu display and target actions to generate the menu markup
        // for this source
        generateMenuContents: function (event, sourceNode) {

           var menuItems = null;
           var menuHdrJson = null;
                
           // retrieve child data from live DOM c2a:source node (e.g. type,value,display,etc)
           var info = SemTagC2A.getSourceInfo(sourceNode);

           // collect the menu actions
           if (SemTagC2A.isTargetDefined(info) == true) {
              menuItems = SemTagC2A.getTargetMenuItems(info);
           }

           if (info.display != "" ) {
              menuHdrJson = SemTagSvcPortal.getMenuHeaderJson(info.display, "text/html", -100);  
           }
           
           if (menuItems != null || info.display != "")
           {
              SemTagSvcPortal.setMenuData(event, menuItems, "", menuHdrJson, "");
           }
        },
        
        getTargetMenuItems:  function(sourceInfo) {
            var menuItems = new Array();
            var labelMap = new Array();
            for (var targetNodeID in SemTagC2A.targetNodeIDs) {
                // fetch live DOM c2a:target node
                //var targetNode = document.getElementById(targetNodeID);
                var targetNode = SemTagC2A.findElementInWindowScope(targetNodeID);
                // create JSON to mirror c2a:target node data and initialize
                // "namespace" member since it is optional in tag definition
                var targetInfo = SemTagC2A.getTargetInfo(targetNode);
                
                // handle label counting in case a c2a target occurs multiple times in the markup
                // which would be the case if the target portlet has been put on the page multiple times
                var label = targetInfo.menuLabel;
                var labelCounter = labelMap[label];
                if (labelCounter != null) {
                	labelMap[label] = labelCounter++;
               	} else {
               		labelMap[label] = 1;
               		labelCounter = 1;
               	}
               	if (labelCounter > 1) {
               		label += " (" + labelCounter + ")";
               	}
               	    
                // Check for a match.  If it matches, add menu items
                if (SemTagC2A.isTargetSourceMatch(sourceInfo, targetInfo) == true) {
                    menuItems.push(SemTagSvcPortal.getMenuItemJson(label,
                         "javascript:SemTagC2A.executeMenuAction(\""+ targetNodeID + "\");" ));
                }
            }

            // If there are menu items, save away the source value
            if (menuItems.length > 0)
                SemTagC2A.currentValue = sourceInfo.value;

            return menuItems;
        },
        
        

        // -------------------------------------------------------------
        // Action execution functions
        // -------------------------------------------------------------
        executeMenuAction: function(targetNodeID) {
           
          var theTarget = {};
          // fetch live DOM c2a:target node
          // var targetNode = document.getElementById(targetNodeID);
          var targetNode = SemTagC2A.findElementInWindowScope(targetNodeID);
          
          if (targetNode && targetNode.tagName == "FORM") {

              var value = SemTagC2A.currentValue;
              var targetInfo = SemTagC2A.getTargetInfo(targetNode);
              if (targetInfo.selector) {
                  value = SemTagC2A.selectSubField(value, targetInfo.selector);
              }

              var params = SemTagSvcPortal.getElementsByClassName(SemTagC2A.paramTagName, targetNode, 0, ["INPUT"]);
              for (var j=0; j<params.length; j++) {
                  // need to convert non-string objects before passing them
                  params[j].value = SemTagC2A.getStringValue(value);
              }	  
			  
              /*
               * In case there is some JS invocation which could happen either
               * by the form action attribute being set to action='javascript:doSomeAction()'
               * or by having the onSubmit handler set for the form like onSubmit='doSomeAction(this)'
               * the value to be passed to the target will be made globally available in case 
               * in the variable window.ibm.portal.c2a.event.value
               */
              // public
              window.ibm.portal.c2a.event = {value: value};
              for (var i=0; i<parent.frames.length; i++) {
              
              	  if (SemTagC2A.canAccessFrameContent(parent.frames[i])) {
	                  // as iframes may be reloaded, 
	                  // one has to reinitialize the ibm.portal.c2a.event.value
	                  // which will be available in the window object of the subframe
	                  if (! parent.frames[i].ibm) parent.frames[i].ibm = new Object();
	                     if (! parent.frames[i].ibm.portal) parent.frames[i].ibm.portal = new Object();
	                     parent.frames[i].ibm.portal.c2a = new Object();
	                  parent.frames[i].ibm.portal.c2a.event = {value: value};
	              }
              }
              
              /*
               * in case any onsubmit handler has been defined
               * for the form it needs to be triggered here as
               * it is not triggered during the node.submit() call
               */
              if (targetNode.onsubmit) {
              	if (SemTagUtil.isGecko) {
              		var eventVariable = new Object();
              		targetNode.onsubmit(eventVariable);
              	} else {
              		// IE
              		targetNode.fireEvent("onsubmit");
              	}
              }
              targetNode.submit();
               
          } else {
          	if (SemTagSvcPortal.trace) {
          		SemTagUtil.log("no target node can be found for id " + targetNodeID);
          	}
          }
        },
        
        /*
         * This method selects a sub - property for a given 
         * JSON object. The 'path' to this property is denoted by 
         * the selector parameter.
         *
         *  (x, "a.b.c") -> x.a.b.c
         */
        selectSubField:  function(obj, selector) {
             var fieldNames = selector.split('.');
             var x = obj;
             for (var i=0; i<fieldNames.length; i++) {
                 if (typeof(x) == 'object' && x[fieldNames[i]]) {
                     x = x[fieldNames[i]];
                 } else {
                 	if (SemTagSvcPortal.trace) {
                 		SemTagUtil.log("cannot select " + selector + " from " +  obj);
                 	}
                 	// if the field cannot be found, nothing should be returned
                 	x = null;
                 	break;
                 }
             }
             return x;
        },
        
        
        
        getStringValue:  function(x) {
             // if the whole value is just a string, the we do not want to put the extra JSON quotes around it
             if (typeof x == 'string') {
                 return x;
             } else {
                 return SemTagC2A.getJSON(x);
             }
        },

        getJSON:  function(x) {
            if (x == null) return "null";

            switch (typeof x) {
            case 'string': return '"'+x+'"';
            case 'number':
            case 'boolean': return String(x);
            case 'object':
                if (x instanceof Array) {
                    return SemTagC2A.getArrayJSON(x);
                } else if (x) {
                    return SemTagC2A.getObjectJSON(x);
                }
            }
        },

        getObjectJSON:  function(o) {
            var a = [];
            for (k in o) {
                if (o.hasOwnProperty(k)) {
                    a.push('"' + k + '":' + SemTagC2A.getJSON(o[k]));
                }
            }
            return '{' + a.join(',') + '}';
        },

        getArrayJSON:  function(o) {
            var a = [];
            for (var k=0; k<o.length; k++) {
                a.push(SemTagC2A.getJSON(o[k]));
            }
            return '[' + a.join(',') + ']';
        }, 
        
        // this method is necessary because the ordinary 
        // form submit is not feasible in the client side rendering mode 
        // of page builder 2. 
        // therefore the information to be submitted is extracted 
        // here and a client side portletwidget action invocation will be triggered
        triggerCSRAction: function(/* the id of this triggered c2a:target form */formID) {
        	var c2aTargetForm = SemTagC2A.findElementInWindowScope(formID);
        	
			// get the page ID
			var pageID = SemTagC2A.getC2ATargetPageID(c2aTargetForm);
			// get the portlet window ID
			var portletWindowID = SemTagC2A.getC2ATargetPortletWindowID(c2aTargetForm);
			// get the name of the communication target 
			var commTargetName = SemTagC2A.getC2ACommTargetName(c2aTargetForm);
			
			// can use currentValue from C2A service SemTagC2A.currentValue
			// for the eventing use case we only have one 
			// input field which represents the event payload 
			// to be passed into the eventing call 
			var valueSubmitted = SemTagC2A.currentValue; 
			
			var actionParameters = SemTagC2A.getTargetActionParams(c2aTargetForm);
        },
        
        // this method is necessary because the ordinary 
        // form submit is not feasible in the client side rendering mode 
        // of page builder 2. 
        // therefore the information to be submitted is extracted 
        // here and a client side portletwidget event invocation will be triggered
        triggerCSREvent: function(/* the id of this triggered c2a:target form */formID) {
        	var c2aTargetForm = SemTagC2A.findElementInWindowScope(formID);
        	
			// get the page ID
			var pageID = SemTagC2A.getC2ATargetPageID(c2aTargetForm);
			
			// get the portlet window ID
			var portletWindowID = SemTagC2A.getC2ATargetPortletWindowID(c2aTargetForm);
		
			// get the name of the communication target 
			var commTargetQName = SemTagC2A.getC2ACommTargetQName(c2aTargetForm);
			
			// can use currentValue from C2A service SemTagC2A.currentValue
			// for the eventing use case we only have one 
			// input field which represents the event payload 
			// to be passed into the eventing call 
			var valueSubmitted = SemTagC2A.currentValue;      
			
						// get the event service
			// and dispatch the event that we are reading out of the c2a form 
			var eventService = com.ibm.mashups.services.ServiceManager.getService(com.ibm.mashups.iwidget.services.EventService.SERVICE_NAME);
			eventService.fireEvent(portletWindowID, commTargetQName, valueSubmitted, "{http://www.w3.org/2001/XMLSchema}string");
			
		},
        
        getC2ATargetPageID: function(c2aTargetFormNode) {
        	var innerNodes = dojo.query('input[name="com.ibm.wps.propertybroker.standard.c2a.pageid"]', c2aTargetFormNode);
			var pageID = (innerNodes != null && innerNodes.length == 1) ? innerNodes[0].value : "undefined";
			return pageID;
        }, 
        
        getC2ATargetPortletWindowID: function(c2aTargetFormNode) {
			var innerNodes = dojo.query('input[name="com.ibm.wps.propertybroker.standard.c2a.portletwindowid"]', c2aTargetFormNode);
			var portletWindowID = (innerNodes != null && innerNodes.length == 1) ? innerNodes[0].value : "undefined";
			return portletWindowID;
        },
        
        getC2ACommTargetName: function(c2aTargetFormNode) {
        	var innerNodes = dojo.query('input[name="com.ibm.wps.propertybroker.standard.c2a.commtargetname"]', c2aTargetFormNode);
			var commTargetName = (innerNodes != null && innerNodes.length == 1) ? innerNodes[0].value : "undefined";
			return commTargetName;
        },
        
        getC2ACommTargetQName: function(c2aTargetFormNode) {
        	var innerNodes = dojo.query('input[name="com.ibm.wps.propertybroker.standard.c2a.commtargetqname"]', c2aTargetFormNode);
			var commTargetQName = (innerNodes != null && innerNodes.length == 1) ? innerNodes[0].value : "undefined";
			return commTargetQName;
        },
        
        getC2ATargetActionParams: function(c2aTargetFormNode) {
        	var innerNodes = dojo.query('input[type="text"]', c2aTargetFormNode);
			dojo.forEach(innerNodes, function(innerNode) {
				// alert("inputtext name:" + innerNode.name + " value:" + innerNode.value);
			}); 
		}
        

}

SemTagC2A.init();


/*
Licensed Materials - Property of IBM
 
5724S31

Copyright IBM Corp.  2007    All Rights Reserved.

US Government Users Restricted Rights - Use, duplication or 
disclosure restricted by GSA ADP Schedule Contract with IBM 
Corp.
*/

/**
 * This is the JS file semantic tagging with people
 */








var SemTagPerson = {

	INLINE: "X-person-display-inline",
	activeElems: new Array(),
	requestor: new SemTagUtil.crossDomainRequest(),
//	servletUrl: "http://quickr.euluc.com:80/wps_semanticTag/getPersonTag?action=ptag_menu&email=@@@EMAIL@@@",
//	reqMethod: eval("getTagFromServer"),
//	photoUrl: "http://quickr.euluc.com:80/wps_semanticTag/ui/no_photo_avail.gif",
//	servletUrl: "/wps/um/secure/users/profiles?expandRefs=true&includeAttributes=cn,businessCategory,carLicense,countryName,departmentNumber,description,displayName,employeeNumber,employeeType,facsimileTelephoneNumber,givenName,homePostalAddress,ibm-gender,ibm-generationQualifier,ibm-hobby,ibm-jobTitle,ibm-middleName,ibm-personalTitle,ibm-primaryEmail,ibm-regionalLocale,ibm-timeZone,initials,localityName,manager,mobile,o,ou,pager,postalAddress,postalCode,preferredLanguage,roomNumber,secretary,seeAlso,sn,stateOrProvinceName,street,telephoneNumber,uid&searchAttributes=@@@QUERY@@@",
	servletUrl: "/wps"+"/um/secure/users/profiles?expandRefs=true&includeAttributes=" + "@@@AVAILATTRIBUTES@@@" + "&searchAttributes=@@@QUERY@@@",
	servletUrlForObjectId: "/wps"+"/um/secure/users/profiles/" + "@@@UserObjectID@@@" + "?expandRefs=true&includeAttributes=" + "@@@AVAILATTRIBUTES@@@",
	reqMethod: eval("callUserProfileServlet"),
	//photoUrl: "/lwp/imageServlet/ImageServlet?email=@@@EMAIL@@@",
    photoUrl:"/wps"+"/um/secure/users/profiles/@@@ObjectID@@@/jpegPhoto?index=0",
	collapsedImgUrl: "/wps_semanticTag"+"/ui/imgcollapsed.gif",
	expandedImgUrl: "/wps_semanticTag"+"/ui/imgexpanded.gif",
    moreActionImgUrl :"/wps_semanticTag"+"/ui/ShowActions.gif",
    verticalRulerUrl :"/wps_semanticTag"+"/ui/Line_Tree.gif",
    profileImageUrl	:"/wps_semanticTag"+"/ui/Properties.gif",	
	showImage:false,

	init: function () {
        if (SemTagSvcPortal.trace) console.log("Inside init of SemTagPerson.init()");
		if(SemTagSvcPortal.ifConnUrlExists == "true" && SemTagSvcPortal.isconnServerNew == false) SemTagPerson.loadScript();
		if(SemTagSvcPortal.ifConnUrlExists == "true" && SemTagSvcPortal.isconnServerNew == true) SemTagSvcPortal.loadConnScript();
		SemTagSvcPortal.setCallback('hcard',SemTagPerson.hcardsAdded);
		SemTagSvcPortal.setCallback('mailto',SemTagPerson.mailtosAdded);
		SemTagPerson.processHcards(SemTagSvcPortal.getNodes('hcard'));
		SemTagPerson.processMailtos(SemTagSvcPortal.getNodes('mailto'));
		
		SemTagSvcPortal.watchEvent(window, 'load', SemTagPerson.clearInternalData, false);
	},

	loadScript: function() {
			var scriptElem = document.createElement("script");
			var url = SemTagSvcPortal.connUrl;
			url += (url.indexOf("?")==-1)? "?": "&";
			url += "lang=" + SemTagSvcPortal.lang;
			scriptElem.src = url;
			document.body.insertBefore(scriptElem, document.body.firstChild);
	},

	clearInternalData: function() {
		var leids = SemTagPerson.activeElems;
		while (0 < leids.length) {
			leids.pop();
		}
	},

	 
 
 
 
nls: {
 
"start_chat": "Chat",
"add_to_contact": "Add as Sametime Contact",
"send_email": "Send Mail",
"view_person": "Profile",
"hover_label": "Click for Person Card",
"work_location": "person.adr.locality+', '+person.adr.region+' '+person.adr.countryname",
"specify_email_if_connection": "When Portal is integrated with Connections, Connection Business Card appears only if email is specified"
 
},
 
 
 
 
getPersonResolverUrl: function(){
return "?uri=personrecord%3aTOBEREPLACED";
},
getMarkup: function(person, bidi, menuItems, selector, header, footer) {
var viewMethod="";
var email=(typeof(person.email)!='undefined' && person.email.internet)? person.email.internet: null;
if(!(SemTagSvcPortal.ifConnUrlExists == "true" && email != null)) {
if(person._profileinplace){
var onPageUId=person.uid.replace(/\\/g,"&perc5C");
viewMethod="javascript:SemTagPerson.executeJSTargetInFrame(\"javascript:doShowProfile(\\\"" + onPageUId + "\\\")\")";
}else {
viewMethod="javascript:SemTagPerson.openPersonRecord()";
}
menuItems.push(SemTagSvcPortal.getMenuItemJson(SemTagPerson.nls.view_person, viewMethod, -100));
}
if (email) menuItems.push(SemTagSvcPortal.getMenuItemJson(SemTagPerson.nls.send_email, "mailto:" + email, -90));
if (SemTagSvcPortal.debug) console.log("ST Status got in person1.jsp is:"+typeof(SemTagAwrns)!='undefined' && typeof(person.X.ststatus)!='undefined');
if (SemTagSvcPortal.debug) console.log(person.X.ststatus+":"+(person.X.ststatus=="online" || person.X.ststatus=="away"));
if (typeof(SemTagAwrns)!='undefined' && typeof(person.X.ststatus)!='undefined' && (person.X.ststatus=="online" || person.X.ststatus=="away")) {
var chatMethod="javascript:SemTagAwrns.openChat(\"" + person.X.imn + "\")";
menuItems.push(SemTagSvcPortal.getMenuItemJson(SemTagPerson.nls.add_to_contact, "javascript:SemTagPerson.addToSametimeList()", -11));
menuItems.push(SemTagSvcPortal.getMenuItemJson(SemTagPerson.nls.start_chat, chatMethod, -80));
}
var items=SemTagSvcPortal.getActions("person");
if (items) {
for (i=0; i<items.length; i++) {
var showif=items[i].showif;
var show=true;
if (showif) {
try {
var showifMethod=eval(showif);
show=showifMethod.call(null,SemTagPerson.currentPerson);
}
catch (e) {
try {
var showifMethod=eval(showif);
show=showifMethod.call(null,SemTagPerson.currentPerson);
}
catch (e2) {
show=false;
}
}
}
if (show) {
var label=items[i].label;
if (label.match(/nls\.[a-z]/)) label=eval(label);
if (!(label.indexOf("Send Instant") > -1)) {
var href=items[i].url.replace(/@@@ARGS@@@/g, "SemTagPerson.currentPerson");
menuItems.push(SemTagSvcPortal.getMenuItemJson(label, href, items[i].order));
}
}
}
}
if (!person._inline) {
if(SemTagSvcPortal.ifConnUrlExists == "true" && (SemTagSvcPortal.isconnServerNew == false) && (email != null))
{
header.write("<div class='popupPersonCard' id='businessCard'>");
header.write("</div>");
}
else
{
 
 
var stStatus="" ;
if (typeof(SemTagAwrns)!='undefined' && typeof(person.X.ststatus)!='undefined' && (person.X.ststatus=="online" || person.X.ststatus=="away"))
{
stStatus=person.X.ststatus ;
}
var imageURL=person.photo;
 
header.write("<div class ='businessCardMenu'>");
 
header.write("<span class='photoCard' id ='imageSpan'><div id='imageDiv' style='height:90px; width:90px' >");
if(SemTagPerson.showImage)  
header.write("<img id='personImg' tabindex=0 style='border:1px solid rgb(192,192,192);float:right;padding:10px ; height:50px; width:50px; background-color:white;margin-right:6px' src='" + imageURL + "' onMouseover='SemTagPerson.imgHoverIn();return false;' alt='" + person.fn + " " + SemTagMenu.nls.a11y_photo + "' title='" + person.fn + " " + SemTagMenu.nls.a11y_photo + "'/>");header.write(" <img id='personImg1' tabindex=0 style='display:none;border:1px solid rgb(192,192,192);float:right;padding:10px ; height:82px; width:82px; background-color:white;margin-right:6px' src='" + imageURL + "' onMouseout='SemTagPerson.imgHoverOut();return false;' alt='" + person.fn + " " + SemTagMenu.nls.a11y_photo + "' title='" + person.fn + " " + SemTagMenu.nls.a11y_photo + "'/></div></span>");
header.write("<div class='businessCard'><ul dir='" + bidi + "'>");
header.write("<li class='cardName' onkeydown=\"SemTagMenu.catchEscape();\" onkeyup=\"SemTagMenu.catchKeyup();\"><a href='#' style='text-Decoration:none;color:black'>" + person.fn + "</a></li>");
 
if (person.title) header.write("<li tabindex='1'><a href='#' style='text-Decoration:none;color:black'>" + person.title + "</a></li>");
 
if (person.tel && person.tel.voice) header.write("<li tabindex='1'><a href='#' style='text-Decoration:none;color:black'>" + person.tel.voice + "</a></li>");
 
if (typeof(SemTagAwrns)!='undefined' && typeof(person.X.ststatus)!='undefined' && (person.X.ststatus=="online" || person.X.ststatus=="away")){
header.write("<span id='statusIcon' style='vertical-align:text-top'><a href='#' style='text-Decoration:none;color:black'>"+ SemTagAwrns.st + stStatus + "</a></span>");}
header.write("</ul></div>");
 
header.write("<div class='showMoreDiv'>");
header.write("<span><img tabIndex=0 id='expCollapImg' src='" + SemTagPerson.collapsedImgUrl + "' title='" + SemTagMenu.nls.ally_collapsedImage + " ' onClick='SemTagPerson.imgClicked();' onKeydown='SemTagPerson.imgClicked();'/><label id='toggleLabel' class='showMoreLabel'>"+SemTagMenu.nls.ally_showMore + "</label></font></span>");
header.write("</div>");
 
header.write("<div class='businessCardExtended' id='expandedSection' style='display:none'><ul style='padding-top:5px;align:left;' dir='" + bidi + "'>");
 
if (person.email && person.email.internet) header.write("<li tabindex=0 style='padding-bottom:3px'>" + person.email.internet + "</li>");
 
if (person.adr && person.adr.streetaddress) header.write("<li tabindex=0 style='padding-bottom:3px'>" + person.adr.streetaddress + "</li>");
 
if (person.adr && person.adr.region) header.write("<li tabindex=0 style='padding-bottom:3px'>" + person.adr.region + "</li>");
 
if (person.adr && person.adr.postalcode) header.write("<li tabindex=0 style='padding-bottom:3px'>" + person.adr.postalcode + "</li>");
 
if (person.adr && person.adr.countryname) header.write("<li tabindex=0 style='padding-bottom:3px'>" + person.adr.countryname + "</li>");
 
header.write("</ul></div>");
 
header.write("</div>");
 
}
}
},
imgClicked: function(){
var image=document.getElementById("expCollapImg");
var toggleImageLabel=document.getElementById("toggleLabel");
var personDiv=document.getElementById("expandedSection");
var browser=navigator.appName;
if(browser == "Netscape")
{personDiv.style.width='240';}
else
{personDiv.style.width='378';}
if(image.src.indexOf(SemTagPerson.expandedImgUrl) > 1){
image.src=SemTagPerson.collapsedImgUrl;
image.title=SemTagMenu.nls.ally_collapsedImage ;
toggleImageLabel.innerHTML=SemTagMenu.nls.ally_showMore ;
}
else {
image.src=SemTagPerson.expandedImgUrl;
image.title= SemTagMenu.nls.ally_expandImage;
toggleImageLabel.innerHTML=SemTagMenu.nls.ally_showLess ;
}
var expandedSec=document.getElementById("expandedSection");
expandedSec.style.display=(expandedSec.style.display != 'none' ? 'none' : '');
},
imgHoverIn: function(){
var smallImage=document.getElementById("personImg");
var largeImage=document.getElementById("personImg1");
smallImage.style.display='none';
largeImage.style.display='';
},
imgHoverOut: function(){
var smallImage=document.getElementById("personImg");
var largeImage=document.getElementById("personImg1");
smallImage.style.display='';
largeImage.style.display='none';
},
 
getInlineMarkup: function (person, bidi, buffer) {
var email=person.email.internet;
buffer.write("<div class='personMenu'>");
buffer.write("<div class='photoCard'><img src='" + person.photo + "' alt=''/></div>");
buffer.write("<div class='businessCard' dir='" + bidi + "'>");
var classAttr=(person._headeronly? "class='vcard X-person-inside-inline'": "");
buffer.write("<ul " + classAttr + " dir='" + bidi + "'>");
buffer.write("<li class='cardName'><span class='fn'>" + person.fn + "</span></li>");
buffer.write("<li class='email'><span class'type' style='display:none;'>internet</span><span class='value'>" + email + "</span></li>");
if (person.title) buffer.write("<li>" + person.title + "</li>");
if (person.tel && person.tel.voice) buffer.write("<li>" + person.tel.voice + "</li>");
buffer.write("</ul>");
buffer.write("</div>");
if (person._headeronly) {
buffer.write("<div style='clear:both;'>");
}
else {
buffer.write("<div class='personMenuActions' dir='" + bidi + "' style='clear:both;'>");
buffer.write("<ul>");
buffer.write("<li><a href='NEEDSWORK" + "'>" + SemTagPerson.nls.view_person + "</a></li>");
buffer.write("<li><a href='mailto:" + email + "'>" + SemTagPerson.nls.send_email + "</a></li>");
buffer.write("<li><a href='NEEDSWORK" + "'>" + SemTagPerson.nls.add_to_contact + "</a></li>");
buffer.write("</ul>");
}
buffer.write("</div>");
buffer.write("</div>");
},
 
openPersonRecord: function() {
var person=SemTagPerson.currentPerson;
var userId=null;
if(person.uid !='undefined' && person.uid.length >0)
{
userId=person.uid;
}
else if((typeof(person.email)!='undefined' && typeof(person.email.internet)!='undefined' && 0<person.email.internet.length))
{
userId=person.email;
}
var userId2=encodeURIComponent(userId);
var userId3=encodeURIComponent(userId2);
if (SemTagSvcPortal.debug) console.log("userId3is :"+userId3+":"+SemTagPerson.currentPerson.fn+":"+SemTagPerson.getPersonResolverUrl()+":");
//window.open("/wps/poc?uri=personrecord:" + userId3, null, "height=640,width=512,resizable=yes,scrollbars=yes,status=yes,toolbar=no,menubar=no,location=no");
if (SemTagSvcPortal.debug) console.log("NEWReplaced string is:"+SemTagPerson.getPersonResolverUrl().replace("TOBEREPLACED", userId3));
window.open(SemTagPerson.getPersonResolverUrl().replace("TOBEREPLACED", userId3), null, "height=640,width=512,resizable=yes,scrollbars=yes,status=yes,toolbar=no,menubar=no,location=no");
},
addToSametimeList: function() {
var email=SemTagPerson.currentPerson.email.internet;
var fn_=encodeURIComponent(SemTagPerson.currentPerson.fn);
var fn=encodeURIComponent(fn_);
window.open("/wps/poc?uri=addtostlist:" + email + "/" + fn, null, "height=384,width=768,resizable=yes,status=yes,toolbar=no,menubar=no,location=no");
 
},

	
	out: function () {
		this.buffer = "";
		this.write = function (str) {
			this.buffer += str;
		}
	},

	processHcards: function(hcards) {
        if (SemTagSvcPortal.trace) console.log("Inside processHcards of SemTagSerson and length of hcards is:"+( hcards? hcards.length : 0 ));
		if (!hcards || hcards.length==0) return;
//		var startTime = new Date().getTime(); //HMperf
		for (var i=0; i<hcards.length; i++) {
			var hcard = hcards[i];
            var fnElem = SemTagPerson.getNameElement(hcard);
            if (!fnElem) continue;
            var email = SemTagUtil.getHcardAttributeValue("email", hcard);
            if (!email.internet) {
            	var uid = SemTagUtil.getHcardAttributeValue("uid", hcard);
            	if (!uid) continue;
            }
            var leid = fnElem.getAttribute(SemTagSvcPortal.liveElemPrefix + "id");
            if (leid && SemTagSvcPortal.ifConnUrlExists == "false") {
            	if (SemTagPerson.activeElems[leid]) continue;
            		else {
            			if (SemTagSvcPortal.trace) SemTagUtil.log("Person.leid=" + leid + " being processed again!");
            			continue; //NEEDSWORK figure out why this happens
            		}
            }
            var personEmail = SemTagSvcPortal.getElementsByClassName( "email",  hcard);
            personEmail = personEmail || null;
            if ( (personEmail == null || personEmail.length == 0) && SemTagSvcPortal.ifConnUrlExists == "true" ) {
                console.info(SemTagPerson.nls.specify_email_if_connection + "Email is for user:" + uid );
            }// end of logging info case

			if (SemTagSvcPortal.ifConnUrlExists == "true" &&  SemTagSvcPortal.isconnServerNew ) {
                if ( SemTagSvcPortal.debug ) {
                    console.log("Beofore calling lconn.profiles.bizCard.bizCard.processTag for email:"+email.internet);
                }
                //if ( lconn && lconn.profiles && lconn.profiles.bizCard && lconn.profiles.bizCard.bizCard && lconn.profiles.bizCard.bizCard.processTag ) {
                try {
                var typedElems = SemTagSvcPortal.getElementsByClassName( "userObjectId",  hcard);
				if ( SemTagSvcPortal.debug ) console.log("userObjectid element got is:"+typedElems);
                    //SemTagUtil.appendNodeClassValue(typedElems[0],"x-lconn-userid");
					if ( eval ( "window.lconn != null") == false )
					{
								SemTagPerson.processUntilAvailable(SemTagPerson.processHcards, "(window.lconn != null)", null,null,null,hcards);
					} else {
							lconn.profiles.bizCard.bizCard.processTag( fnElem);
					}
                } catch (e) {
                    console.log("Connection server is probably down please check following resource is up:"+ "null" + "/profiles/portalJS/portalBizCard.js");
                    console.log("Actual Error occured is:"+e);
                    return;
                }
			}
			
			if (SemTagPerson.isInline(hcard)) {
				var event = {"target": fnElem}; // I need an event
				SemTagPerson.requestPersonInfo(event);
			} else {
				var tmpname = SemTagSvcPortal.getTextValue(fnElem);
			    var tmpIndex = tmpname.indexOf("click");
				var alttext = tmpname.substring(0,tmpIndex) + SemTagPerson.nls.hover_label + " " + SemTagMenu.nls.a11y_hover; //A11Y
			    if (SemTagSvcPortal.ifConnUrlExists == "false" || (SemTagSvcPortal.ifConnUrlExists == "true" && SemTagSvcPortal.isconnServerNew == false ) ) {
				    if ( SemTagSvcPortal.debug ) console.log("Adding hover for old business card case or no business card");
				    SemTagSvcPortal.addHover(fnElem, SemTagPerson.showHover, SemTagPerson.showMenu, alttext);
				} else {
				    if ( SemTagSvcPortal.debug ) console.log("Inside  ifConnURLExistsnew"+SemTagSvcPortal.ifConnUrlExists+":"+ SemTagSvcPortal.isconnServerNew);
				    //SemTagSvcPortal.addHover(fnElem, null, SemTagPerson.showMenu, alttext);
					var refcnt = fnElem.getAttribute(SemTagSvcPortal.refcntAttr);
					if (refcnt) { // this element has already got the basic setup
						fnElem.setAttribute(SemTagSvcPortal.refcntAttr, parseInt(Number(refcnt)+1)); // increment the ref count
					} else { // this element needs a new setup
						fnElem.setAttribute(SemTagSvcPortal.refcntAttr, "1");
						SemTagSvcPortal.hoverIdx++;
					    fnElem.setAttribute(SemTagSvcPortal.liveElemPrefix + "id", SemTagSvcPortal.hoverIdx); //NEEDSWORK "hover" index?
					}
				}
            	leid = fnElem.getAttribute(SemTagSvcPortal.liveElemPrefix + "id");
				if ( SemTagSvcPortal.debug ) console.log("in semtagperson leid got is:"+leid);
				if (leid) SemTagPerson.activeElems[leid] = true;
			}
		}
//		var endTime = new Date().getTime(); //HMperf
//		alert("processHcards: " + (endTime-startTime)); //HMperf
	},
//looks for a test case until its true, then executes a callback
// example: lconn.core.utilities.processUntilAvailable //mycallbackFunction, "(window.myObject != null))", //parametersforCallbackFunction);
processUntilAvailable : function(callback, test, pThrowIfExhausted, pWaitBetweenTries, pMaxTries, passedInParam) 
{
if( typeof(callback) != "function" ) return; // nothing to call back,so just get out
	
// defaults
var waitBetweenTries = 500; // milliseconds
var maxTries = 20; // intervals before giving up
var throwIfExhausted = true; // throw err exhausted all tries 	
if( typeof(pWaitBetweenTries) == "number") waitBetweenTries = pWaitBetweenTries;  // override with supplied parameter
if( typeof(pMaxTries) == "number") maxTries = pMaxTries;  // override with supplied parameter
if( typeof(pThrowIfExhausted) == "boolean") throwIfExhausted = pThrowIfExhausted;  // override with supplied parameter
	 
	var intervalId = "";
	var tried = 0;
	console.log("eval(test) is :"+eval(test));
	var args = Array.prototype.slice.call(arguments);
	var callfunc = args.shift();
	var condition = args.shift();
	var throwIfExt = args.shift();
	var interval = args.shift();
	var noOfTimes = args.shift();
	if (SemTagSvcPortal.trace) console.log("shifted args length is:"+args.length+":"+args );
	if(eval(test))
	{
	// get parameter and pass to functions 
//callfunc.apply(null,Array.prototype.slice.call(args));
		if(passedInParam != null)
			callback.apply(null,Array.prototype.slice.call(args));
		else
			callback();
		return;			
	}
	if (SemTagSvcPortal.trace) console.log("inside processUntilAvailable for time :"+tried+":"+eval(test)+":"+ "clearing intervalid:"+intervalId);
	intervalId = window.setInterval(function()
	{		
		tried++;
        if (SemTagSvcPortal.trace) console.log("inside processUntilAvailable for time :"+tried+":"+eval(test)+":"+ "clearing intervalid:"+intervalId);
		if(eval(test))
		{	
			window.clearInterval(intervalId);
			if(passedInParam != null)
			    callback.apply(null,Array.prototype.slice.call(args));
			else
				callback();				
		}
		else if(tried >= maxTries)
		{
			window.clearInterval(intervalId);
			if( throwIfExhausted ) throw new Error( "processUntilAvailable: test was never met: " + test );
		}
	}, waitBetweenTries);
	
},
	
	isInline: function (hcard) {
		return SemTagUtil.getHcardAttributeValue(SemTagPerson.INLINE, hcard);
	},
	
	processMailtos: function(mailtos) {
		if (!mailtos || mailtos.length==0) return;
		while (mailtos.length > 0) {
			var mailto = mailtos.pop();
//NEEDSWORK I don't get this...why do we want to show inline for each mailto?
//			if (SemTagPerson.isInline(mailto)) {
//				//SemTagPerson.currentElem = mailto;
//				var event = {"target": mailto}; // I need an event
//				SemTagPerson.requestPersonInfo(event);
//				continue;
//			}
			SemTagSvcPortal.watchEvent(mailto, 'mouseover', SemTagPerson.tagMouseover, false);
		}
	},
	
	hcardsAdded: function(nodes) {
		if (SemTagSvcPortal.trace) SemTagUtil.log("hcardsAdded");
        if (SemTagSvcPortal.trace) console.log("INside hcardsAdded length of nodes got it:"+SemTagSvcPortal.getNodes('hcard').length+":"+nodes);
        if ( nodes && nodes.length > 0 ) {
	           SemTagPerson.processHcards(nodes); 
        } else {
            SemTagPerson.processHcards(SemTagSvcPortal.getNodes('hcard'));
        }
	},
	hcardsAdded: function() {
		if (SemTagSvcPortal.trace) SemTagUtil.log("hcardsAdded");
        if (SemTagSvcPortal.trace) console.log("INside hcardsAdded length of nodes got it:"+SemTagSvcPortal.getNodes('hcard').length);
        SemTagPerson.processHcards(SemTagSvcPortal.getNodes('hcard'));
	},
	
	mailtosAdded: function() {
		SemTagPerson.processMailtos(SemTagSvcPortal.getNodes('mailto'));
	},
	
//	loadHcardPerson: function (srcElement) {
//		var person = new Object();
//		var parentVcard = SemTagSvcPortal.getParentByClassName("vcard", srcElement);
//		var vcardElems = parentVcard.getElementsByTagName("*");
//		for (i=0; i<vcardElems.length; i++) {
//			var curElem = vcardElems[i];
//			if (curElem.className) {
//				var classes = curElem.className.split(' ');
//				for (j=0; j<classes.length; j++) {
//					var c = classes[j];
//					var attr = SemTagPerson.getHcardAttributeValue(c, parentVcard);
//					if (attr) person[c] = attr;
//				}
//			}
//		}
//		return person;
//	},

	showHover: function(event) {
		if (SemTagSvcPortal.trace) SemTagUtil.log("Person.showHover");
		var insideInline = SemTagUtil.getHcardAttributeValue("X-person-inside-inline", SemTagSvcPortal.getLiveElementFromEvent(event));
		var label = insideInline? null: SemTagPerson.nls.hover_label;
		SemTagSvcPortal.showHover(event, SemTagPerson.showMenu, label);
		return false;
	},

	showMenu: function(event) {
		if (SemTagSvcPortal.trace) SemTagUtil.log("Person.showMenu");
		SemTagMenu.waitCursor(); // I need a server roundtrip...
		SemTagMenu.stopEvent(event); //NEEDSWORK we need this when calling my servlet??
		SemTagPerson.requestPersonInfo(event);
		return false;
	},
	
	renderCard: function(person) {
		var cardHtml = new BusinessCard.out();
		BusinessCard.getMenuData(person, null, null, null, cardHtml);
		if (SemTagSvcPortal.trace) console.log("Inside renderCard"+cardHtml.buffer+":"+document.getElementById("businessCard"));
		document.getElementById("businessCard").innerHTML = cardHtml.buffer;
	},

	requestPersonInfo: function(event) {
		SemTagPerson.reqMethod.call(SemTagPerson, event);
	},

	dispatch: function (data) {
		var reqid = (data.email && data.email.internet)? data.email.internet: null;
		if (reqid) SemTagPerson.requestor.dispatch(reqid.toLowerCase(), data);
	},
	
	requestReturn: function (success, retval, event) {
		if (SemTagSvcPortal.trace) SemTagUtil.log("Person.requestReturn: " + retval + " (" + (success? "success": "fail") + ")");
		var person = success? retval: SemTagPerson.emptyPerson();
		if (person) {
			var currElem = SemTagSvcPortal.getLiveElementFromEvent(event);
			SemTagPerson.fillPersonJsonMoreFromDom(person, currElem);
			SemTagPerson.update(person, currElem, event);
		}
		else SemTagMenu.defaultCursor();
	},

	fillPersonJsonMoreFromDom: function(person, currElem) {
		if (SemTagSvcPortal.debug) window.status = "Person.fillPersonJsonMoreFromDom";

		var nameElem = SemTagSvcPortal.findNameElementInHcard(currElem);
		if (nameElem){
			var tmpname = SemTagSvcPortal.getTextValue(nameElem);
			var tmpIndex = tmpname.indexOf("click");
			if(tmpIndex>0)
			person.fn=tmpname.substring(0,tmpIndex);
			else
            person.fn=SemTagSvcPortal.getTextValue(nameElem);
        }

		var email = SemTagPerson.getElementEmail(currElem);
		if (email) person.email = {"internet": email};

		var uid = SemTagUtil.getHcardAttributeValue("uid", currElem);
		if (uid) person.uid = uid;

	    var tempObjectID = SemTagUtil.getHcardAttributeValue("userObjectId", currElem);
		
        if(person.photo){
			person.photo = person.photoURL;
			SemTagPerson.showImage= true;
		}
		else{
          SemTagPerson.showImage= false;
		}



		if (!person.tel || !person.tel.voice) {
			var telElem = SemTagSvcPortal.findElementByNameInHcard(currElem, "tel");
			if (telElem) {
				var tels = SemTagSvcPortal.getTypedValue(telElem, "voice");
				person.tel = {"voice": tels["voice"]};
			}
		}

		var addrElem = SemTagSvcPortal.findElementByNameInHcard(currElem, "adr");
		var addrJson = {};
		if (addrElem) {
			addrJson = SemTagPerson.getAddressJson(addrElem);
			person.adr = addrJson;
		}

		if (typeof(person.adr)!='undefined' && (person.adr.locality || person.adr.countryname)) {
			if (!person.X) person.X = {};
			var temp = eval(SemTagPerson.nls.work_location);
			person.X.worklocation = temp.replace(/undefined/g, "");
		}

		if (typeof(SemTagAwrns)!='undefined') {
			if (!person.X) person.X = {};
			person.X.imn = SemTagAwrns.getSametimeId(currElem);
			person.X.ststatus = nameElem.getAttribute("semtag_ststatus");
		}
	},

	emptyPerson: function() {
		return {"fn": "", "email": {"internet": ""}}; //NEEDSATTN
	},

	// you can pass in an element to place the contents in...else it ends up in the regular container
	update: function (person, currElem, event) {
		if (SemTagSvcPortal.trace) SemTagUtil.log("Person.update");
		
        SemTagPerson.currentPerson = person; // for extenders to access

		var parentVcard = SemTagSvcPortal.getParentByClassName("vcard", currElem);

		var headerOnly = SemTagUtil.getHcardAttributeValue("X-person-header-only", parentVcard);
		if (headerOnly) person._headeronly = true;
		SemTagPerson.readHcardContext(parentVcard, person);
		
        // OKOETH
        SemTagSvcPortal.setSemanticTagValue("hcard", currElem, person);
		
		if (SemTagPerson.isInline(parentVcard)) {
			var out = new SemTagPerson.out();
			SemTagPerson.getInlineMarkup(person, SemTagSvcPortal.bidi, out);
			parentVcard.innerHTML = out.buffer;
			//var dom = SemTagPerson.getInlineMarkup2(person, SemTagSvcPortal.bidi, out);
			//parentVcard.appendChild(dom);

			var classAttrs = SemTagUtil.getNodeClassValue(parentVcard);
			SemTagUtil.setNodeClassValue(parentVcard, classAttrs.replace(/vcard/, "vcard-done"));
			if (headerOnly) {
				var inner = SemTagSvcPortal.getElementsByClassName("vcard", parentVcard, 1);
				if (inner) SemTagPerson.processHcards( inner );
			}
		}
		else {
        	var menuitemJsons = new Array();
        	var cssSelector = "personMenuActions";
			var headerHtml = new SemTagPerson.out();
			var footerHtml = new SemTagPerson.out();

            SemTagPerson.getMarkup(person, SemTagSvcPortal.bidi, menuitemJsons, cssSelector, headerHtml, footerHtml);
			var email=(typeof(person.email)!='undefined' && person.email.internet)? person.email.internet: null;
				//var email="sberajaw@us.ibm.com";
			
			SemTagSvcPortal.setMenuData(event, menuitemJsons, cssSelector, SemTagSvcPortal.getMenuHeaderJson(headerHtml.buffer, "text/html", -100), SemTagSvcPortal.getMenuFooterJson(footerHtml.buffer, "text/html", -100));
			// If connections server URL is registered, the profile info(business card) is retrieved from there only.
			if (SemTagSvcPortal.trace) console.log("values are in update of semtagperson:"+SemTagSvcPortal.ifConnUrlExists+":"+(SemTagSvcPortal.isconnServerNew === false));
			if(SemTagSvcPortal.ifConnUrlExists == "true" && (SemTagSvcPortal.isconnServerNew === false) &&  email != null)
			{
					if ( eval ( "window.BusinessCard != null") == false )
					{
							SemTagPerson.processUntilAvailable(BusinessCard.getProfileInfo, "(window.BusinessCard != null)", null,null,null,true, "SemTagPerson.renderCard", email);
					} else {
				           BusinessCard.getProfileInfo(true, "SemTagPerson.renderCard", email);
					}
				
			}

			
		}
    },
	
    readHcardContext: function(elem, person) {
		var inlineDisplay = SemTagUtil.getHcardAttributeValue("X-person-inside-inline", elem);
		if (inlineDisplay) person._inline = true;

		var insideProfile = SemTagUtil.getHcardAttributeValue("X-person-inside-profile", elem);
		if (insideProfile) person._inprofile = true;

		var inPlace = SemTagUtil.getHcardAttributeValue("X-person-profile-inplace", elem);
		if (inPlace) person._profileinplace = true;
    },

	getElementEmail: function (elem) {
		if (!elem) {
			alert("getElementEmail called with: " + elem);
		}
		var email;
		var srcVcard = SemTagSvcPortal.getParentByClassName('vcard',elem);
		if (srcVcard) {
			email = SemTagUtil.getHcardAttributeValue("email", srcVcard);
			email = email.internet;
		}
		else if (elem.tagName == 'A' && elem.href.match(/^mailto:/)) {
			email = elem.href.replace(/^mailto:/,"");
		}
		return email;
	},

    getNameElement: function(elem) {
		try {
			if (elem.className!="vcard") elem = SemTagSvcPortal.getParentByClassName('vcard',elem);
			var nameElem = SemTagSvcPortal.getElementsByClassName("fn", elem, 1)[0];
			if (!nameElem) {
				nameElem = SemTagSvcPortal.getElementsByClassName("n", elem, 1)[0];
			}
			return nameElem;
		}
		catch (e) {
			if (SemTagSvcPortal.debug) alert(e);
		}
		return null;
    },

	// returns a JSON object that represents this address
	getAddressJson: function (elem) {
		var fulladr = {"postofficebox": "", "streetaddress": "", "locality": "", "region": "", "postalcode": "", "countryname": ""}
		var adrElem = elem;
		if (adrElem.className!="adr") adrElem = SemTagSvcPortal.getParentByClassName('adr',elem);
		if (adrElem) {
            var nodes = adrElem.childNodes;
            for (var i=0; i<nodes.length; i++) {
                SemTagPerson.readAddressInfo(nodes[i],fulladr);
            }
		}
		else { //NEEDSWORK
            fulladr.streetaddress = "5 Technology Park Drive";
            fulladr.locality = "Westford";
            fulladr.region = "MA";
            fulladr.postalcode = "01886";
            fulladr.countryname = "USA";
		}
		return fulladr;
	},

	// recursive method to read the 'adr' DOM structure
	readAddressInfo: function(node,addr) {
		var children = node.childNodes;
		if (children) {
			for (var i=0; i<children.length; i++) {
				SemTagPerson.readAddressInfo(children[i],addr);
			}
		}
		if (node.className!=null) {
			var cn = node.className;
			if (cn.match(/(^|\s)post-office-box(\s|$)/i)) addr.postofficebox = SemTagSvcPortal.getTextValue(node);
			else if (cn.match(/(^|\s)extenodeed-address(\s|$)/i)) addr.extenodeedaddress = SemTagSvcPortal.getTextValue(node);
			else if (cn.match(/(^|\s)street-address(\s|$)/i)) addr.streetaddress = SemTagSvcPortal.getTextValue(node);
			else if (cn.match(/(^|\s)locality(\s|$)/i)) addr.locality= SemTagSvcPortal.getTextValue(node);
			else if (cn.match(/(^|\s)region(\s|$)/i)) addr.region= SemTagSvcPortal.getTextValue(node);
			else if (cn.match(/(^|\s)postal-code(\s|$)/i)) addr.postalcode= SemTagSvcPortal.getTextValue(node);
			else if (cn.match(/(^|\s)country-name(\s|$)/i)) addr.countryname= SemTagSvcPortal.getTextValue(node);
		}
	}, 
	
	// This method tries to find a sub - object in the givent 
	// object to screen which is identified by a javascript reference 
	// string. This is walked done one by one JS identifier
    existsInObject: function(/* Object */ objectToScreen, /* String*/  jsReference) {

         var identifierChain = jsReference.split(".");

         // no ripple down the identifier chain and check 
         // whether the object is available in the 
         var nextObjectToScreen = objectToScreen;
         var foundInWindow = true;
         for (var i=0; i<identifierChain.length; i++) {

             // strip of paranthesis here if 
             // it is a method call
             var identifierPart;
             if (identifierChain[i].indexOf("(") > -1) {
                 identifierPart = identifierChain[i].substr(0, identifierChain[i].indexOf("("));
             } else {
                 identifierPart = identifierChain[i];
             }

             if (nextObjectToScreen[identifierPart]) {
                 nextObjectToScreen = nextObjectToScreen[identifierPart];
             } else {
                 foundInWindow = false;
                 break;
             }
         }

         return foundInWindow;
    } ,
    
    // This method exectues a 'javascript:' method call
    // it first tries to find the respective function in the 
    // main window and if it cannot be found there, it will
    // search for the function in a contained subframe
    executeJSTargetInFrame: function (/* String */  jsCall) {


         if (jsCall.indexOf("javascript:") > -1) {

              // get the plain identifier chain
             var plainMethodCall = jsCall.substr(("javascript:".length));

             // if the js reference cannot be found in the main 
             // window, one has to look in all iframes contained
             // in the currrent document
             var windowToExecute = window;
             if (! SemTagPerson.existsInObject(window, plainMethodCall)) {

                 // iterate over the child frames and try to 
                 // find the function object there
                 for (var i=0; i< parent.frames.length; i++) {
                     if (SemTagPerson.existsInObject(parent.frames[i], plainMethodCall)) {
                         windowToExecute = parent.frames[i];
                         break;
                     }
                 }
             } else {
                 // the function could be found in the main window
             }

             // evaluate the function call on the window/frame where
             // the function could be found
             windowToExecute.eval(jsCall);

         }  else {
             // do nothing. 
             // this call only makes sense for calling JS functions which 
             // might reside in a window/frame different then the currently 
             // executing one.
         }
	}
}

function getTagFromServer(event) { // works with the Person Servlet in cross-domain fashion
	var elem = SemTagSvcPortal.getLiveElementFromEvent(event);
	var email = SemTagPerson.getElementEmail(elem);
	if (email) {
		email = email.toLowerCase();
		var src = SemTagPerson.servletUrl.replace(/@@@EMAIL@@@/, email);
		if (SemTagSvcPortal.debug) window.status = "Person.getTagFromServer sending request for: " + email + ")";
		SemTagPerson.requestor.request(src, 6000, SemTagPerson.requestReturn, elem, email);
	}
	else {
		if (SemTagSvcPortal.debug) alert("getTagFromServer couldn't find the e-mail");
		var evt = {"target": elem}; // I need a fake event
		SemTagPerson.requestReturn(false, null, evt);
	}
}

function callUserProfileServlet(event) { // works with the User Profile Servlet of WAS/WP
	if (SemTagSvcPortal.trace) SemTagUtil.log("callUserProfileServlet");

	var userObjectId = "";
	var currElem = SemTagSvcPortal.getLiveElementFromEvent(event);
	var query = ""; {
		var email = SemTagPerson.getElementEmail(currElem);
		if (email) {
			query = "ibm-primaryEmail=" + email; //NEEDSATTN
		}
		else {
			var uid = SemTagUtil.getHcardAttributeValue("uid", currElem);
			if (uid) query = "uid=" + uid; //NEEDSATTN
		}
	}


	userObjectId = SemTagUtil.getHcardAttributeValue("userObjectId", currElem);
	if (0 < query.length) {
		var xml = null;
		try {
			if (0 < userObjectId.length)
			{
				SemTagPerson.servletUrlForObjectId = SemTagPerson.servletUrlForObjectId.replace("@@@AVAILATTRIBUTES@@@", SemTagSvcPortal.availAttribStr);
				xml = ibm.portal.xml.loadXml(SemTagPerson.servletUrlForObjectId.replace(/@@@UserObjectID@@@/, userObjectId));

			}
			else{
			SemTagPerson.servletUrl = SemTagPerson.servletUrl.replace("@@@AVAILATTRIBUTES@@@", SemTagSvcPortal.availAttribStr);
			xml = ibm.portal.xml.loadXml(SemTagPerson.servletUrl.replace(/@@@QUERY@@@/, query));
		}
		}
		catch (e) {
			if (SemTagSvcPortal.debug) alert("Person.callUserProfileServlet caught: " + e);
		}
        
		if (xml) {
			if (0 < userObjectId.length)
			{
				var xsl = ibm.portal.xml.loadXsl("/wps_semanticTag/xsl/UserAtomByIdToPersonJson.xsl");
			}
			else{ 
			    var xsl = ibm.portal.xml.loadXsl("/wps_semanticTag/xsl/UserAtomToPersonJson.xsl");
			}
			var xformed = ibm.portal.xml.transform( xml, xsl, null, null, true );
			if (SemTagSvcPortal.trace) SemTagUtil.log(xformed);

			var person = eval(xformed)[0];
			// In the following condition, || is replaced by && condition coz || was emptying the person attributes even when it has other attributes values existing but does not have fn attribute value which is not the right thing.
			//if (!person || !person.fn) person = SemTagPerson.emptyPerson();
            if (SemTagSvcPortal.trace) console.log("Person got is:"+person);            
			if (!person && !person.fn) person = SemTagPerson.emptyPerson();
            if (SemTagSvcPortal.trace) console.log("person.photo is:"+person.photo);
			SemTagPerson.fillPersonJsonMoreFromDom(person, currElem);
			SemTagPerson.update(person, currElem, event);
			return;
		}
		else if (SemTagSvcPortal.trace) SemTagUtil.log("bad XML");
	}

	// well, we are here, and that means something failed, let's popup something with the info already found in the page
	var evt = {"target": currElem}; // I need a fake event
	SemTagPerson.requestReturn(false, null, evt);
}

//function readReqIdFromJson(retval) {
//	return (retval.email && retval.email.internet)? retval.email.internet: null;
//}
//
//function noConversion(retval) {
//	return retval;
//}
//
//function readReqIdFromAtom(retval) {
//	alert("readReqIdFromAtom: " + retval); //HMdebug
//	var xml = ibm.portal.xml.loadXmlString(retval);
//	var xsl = ibm.portal.xml.loadXsl(SemTagSvcPortal.baseUrl + "/xsl/UserAtomToPersonJson.xsl");
//	var json = ibm.portal.xml.transform( xml, xsl, null, null, true );
//	return (json.email && json.email.internet)? json.email.internet: null;
//}
//
//function convertAtom(retval) {
//	//NEEDSWORK how come I have to do the XSLT twice?!
//	var xml = ibm.portal.xml.loadXmlString(retval);
//	var xsl = ibm.portal.xml.loadXsl(SemTagSvcPortal.baseUrl + "/xsl/UserAtomToPersonJson.xsl");
//	var json = ibm.portal.xml.transform( xml, xsl, null, null, true );
//	return json;
//}

/*
Licensed Materials - Property of IBM
 
5724S31

Copyright IBM Corp.  2007    All Rights Reserved.

US Government Users Restricted Rights - Use, duplication or 
disclosure restricted by GSA ADP Schedule Contract with IBM 
Corp.
*/

//Make sure "ibm" and "ibm.portal" objects are defined, as it's conceivable that
//another product could define an "ibm" javascript object. It also is conceivable that
//another portion of the portal product would define an "ibm.portal" object. Hopefully
//they will play nicely as well and not overwrite OUR object definitions.
if(typeof(ibm)=="undefined")ibm = {};

if(typeof(ibm.portal)=="undefined")ibm.portal = {};
if(typeof(ibm.portal.xml)=="undefined")ibm.portal.xml = {};

// The object reference for all of the functions contained in this file
//ibm.portal.xml={};  commented out for defect 193789 and added following line inplace
if(typeof(ibm.portal.xml)=="undefined")ibm.portal.xml = {};

//----------------------------------------------------------------------  General utility methods
ibm.portal.util = {};

ibm.portal.util.cloneObject = function (obj) {
 var returnObj = {};
    for (i in obj) {
        returnObj[i] = obj[i];
    }
    return returnObj;
}

//----------------------------------------------------------------------- resource utility methods
ibm.portal.resource={};
ibm.portal.resource.str = {};
ibm.portal.resource.getString = function (bundle, key) {
    s = bundle[key];
    s = (s==null)?key:s;
    if (arguments.length >= 2) {
        i = 1;
        do {
            s = s.replace("%"+i , arguments[i]);
            i = i +1;
        } while ( i < arguments.length );
     }
     return s;
}

//---------------------------------------------------------------------- xml related utility methods
/*
 * getXmlHttpRequest()
 * loadXml(sUrl) - returns oDomDoc. parses xml from the url into DOM document object.
 * loadXmlString() - returns oDomDoc. parses xml from the contents of the string into DOM document object.
 * loadXsl()
 * transform()
 */
//ibm.portal.xml = {}; Commented out for defect 193789 and added following line inplace
if(typeof(ibm.portal.xml)=="undefined")ibm.portal.xml = {};
ibm.portal.xml.ie = {};
ibm.portal.xml.gecko = {};

ibm.portal.xml.getXmlHttpRequest = function() {
	var oXml = null;
	if (typeof ActiveXObject != "undefined") {
		oXml = new ActiveXObject("Microsoft.XMLHTTP");
	} else {
		oXml = new XMLHttpRequest();
	}
  return oXml;
}

ibm.portal.xml.loadXml = function(sUrl) {
	if (typeof ActiveXObject != "undefined") 
		return ibm.portal.xml.ie.loadXml(sUrl);
	else 
		return ibm.portal.xml.gecko.loadXml(sUrl);
}

ibm.portal.xml.loadXmlString = function(sXml) {
	if (typeof ActiveXObject != "undefined") 
		return ibm.portal.xml.ie.loadXmlString(sXml);
	else 
		return ibm.portal.xml.gecko.loadXmlString(sXml);
}

ibm.portal.xml.loadXsl = function(sUrl) {
	if (typeof ActiveXObject != "undefined") 
		return ibm.portal.xml.ie.loadXsl(sUrl);
	else 
		return ibm.portal.xml.gecko.loadXsl(sUrl);
}

ibm.portal.xml.transform = function (xml, xsl, sXslMode, aXslParams, bReturnString)
{
   if (typeof ActiveXObject != "undefined") {
    return ibm.portal.xml.ie.transform(xml, xsl, sXslMode, aXslParams,bReturnString);
  }
  else 
    return ibm.portal.xml.gecko.transform(xml, xsl, sXslMode, aXslParams,bReturnString);
}

ibm.portal.xml.update = function (nodeToUpdate, xml, xsl, sXslMode, aXslParams) {
	if ( typeof ActiveXObject != "undefined" ) {
		var results = ibm.portal.xml.ie.transform(xml, xsl, sXslMode, aXslParams, true );
		//Don't really want to use innerHTML here, but seems to be the only way IE will 
		//take the update.
		ibm.portal.debug.text( "XSLT result: " + results );
		nodeToUpdate.innerHTML += results;
	}
	else {
		results = ibm.portal.xml.gecko.transform(xml,xsl,sXslMode,aXslParams, false);
		nodeToUpdate.appendChild( results.documentElement );
	}
}

//---------------------------------------------------------------------- IE xml related utility methods

ibm.portal.xml.ie.loadXml = function(sUrl) {
	var oXmlDoc = new ActiveXObject("MSXML2.DOMDocument");
	oXmlDoc.async=0;
	oXmlDoc.resolveExternals = 0;
  	if(!oXmlDoc.load(sUrl))
  	{
  		//Callers should catch this and can substitute their own error message
  		throw new Error("Error loading xml file " + sUrl);
  	}
	return oXmlDoc;

}

ibm.portal.xml.ie.loadXmlString = function(sXml) {
	var oXmlDoc = new ActiveXObject("MSXML2.DOMDocument");
	oXmlDoc.async=0;
	oXmlDoc.resolveExternals = 0;
  	if(!oXmlDoc.loadXML(sXml))
  	{
  	    //Callers should catch this and can substitute their own error message
  		throw new Error("Error loading xml string " + sXml); 
  	}
	return oXmlDoc;
}

ibm.portal.xml.ie.loadXsl = function(sUrl) {
	//we need to use MSXML2.FreeThreadedDOMDocument interface in order to support 
	//mode and parameters in XSL transformation.
	var oXslDoc = new ActiveXObject("MSXML2.FreeThreadedDOMDocument");
	oXslDoc.async=0;
	oXslDoc.resolveExternals = 0;
  	if(!oXslDoc.load(sUrl))
  	{
  		//Callers should catch this and can substitute their own error message
  		throw new Error("Error loading xsl file " + sUrl);
  	}	
	return oXslDoc;
}

ibm.portal.xml.ie.transform = function(xmlDoc, xsl, sXslMode, aXslParams,bReturnString) {
	var oXml = xmlDoc;
	var oXsl = xsl;

     try {		
		if(!oXsl.documentElement) oXsl = this.loadXsl(xsl);
	 }
	 catch(e) {
		var sMsg = e.message;
		throw new Error(""+sMsg, ""+sMsg);
	 }
	//create the xsl processor and apply the transformation
	var oXslt = new ActiveXObject("Msxml2.XSLTemplate");
	oXslt.stylesheet = oXsl;
	var oXslProc = oXslt.createProcessor();
	oXslProc.input = oXml;
	
	//set paramaters if any
	if(aXslParams) {
		for(var p in aXslParams) {
			oXslProc.addParameter(p, aXslParams[p]);
		}
	}
	if (sXslMode) oXslProc.addParameter("mode", sXslMode);
	
	if (bReturnString) {
		if(!oXslProc.transform()) {
			//Callers should catch this and can substitute their own error message
  			throw new Error("Error transforming xml doc " + oXml); 
  		}
		return oXslProc.output;
	} else {
		var oHtmlDoc = new ActiveXObject("MSXML2.DOMDocument");
		oHtmlDoc.async = 0;
		oHtmlDoc.validateOnParse = 1;
		oXml.transformNodeToObject(oXsl,oHtmlDoc);
		return oHtmlDoc;	
	}
}

//---------------------------------------------------------------------- GECKO xml related utility methods

ibm.portal.xml.gecko.loadXml = function(sUrl) {
    //var oXmlResponse = NG.ServerRequest.postRequest(sUrl);
//    if (oXmlResponse) return xmlLoadString(oXmlResponse.responseText);
//    else return null;
	var oDomDoc = document.implementation.createDocument('','',null); 
//	oDomDoc.async = 0; // this is the important part
//	oDomDoc.load(sUrl);
// to support for Safari browser
		var xhr = new XMLHttpRequest();
		xhr.open( "GET", sUrl, false );
		xhr.send( null );
		  
		if ( xhr.status == 200 ) {
			oDomDoc = xhr.responseXML;
		}
	
	return oDomDoc;
}

ibm.portal.xml.gecko.loadXmlString = function(sXml) {
    var parser = new DOMParser();
    try { oXmlDoc = parser.parseFromString(sXml, "text/xml"); }
    catch (exc) {
	    //Callers should catch this and can substitute their own error message
  		throw new Error("Error loading xml string " + sXml); 
    }
	return oXmlDoc;
}

ibm.portal.xml.gecko.loadXsl = function(sUrl) {
	//This is done through createDocument because of anchor(#) we have in portal url. 
	//Do not change the code without testing the case.
	var oDomDoc = document.implementation.createDocument('','',null); 
//	oDomDoc.async = 0; // this is the important part
//	oDomDoc.load(sUrl);
	var xhr = new XMLHttpRequest();
		xhr.open( "GET", sUrl, false );
		xhr.send( null );
		  
		if ( xhr.status == 200 ) {
			oDomDoc = xhr.responseXML;
		}
	
	return oDomDoc;
}

ibm.portal.xml.gecko.transform = function(xmlDoc, xsl, sXslMode, aXslParams,bReturnString) {
	try {
	  var xslDoc = xsl;
      if(!xslDoc.documentElement) 
      {
          alert("xslDoc is not a Document, loading it...");
          xslDoc = this.loadXsl(xsl);
      }        
      var proc = new XSLTProcessor();
      proc.importStylesheet(xslDoc); 
 
      //set parameters if any
      if(aXslParams) {
	  	for(var p in aXslParams)  {
		    proc.setParameter(null, p, aXslParams[p]);
	    }
      }
      if (sXslMode) proc.setParameter(null, "mode", sXslMode);
    
      var resultDoc = proc.transformToDocument(xmlDoc);
      if (!bReturnString) {
      	return resultDoc;
      }
      resultStr = resultDoc.documentElement.textContent;
    } 
    catch (exc)
    {
        //alert("error transforming document: "+exc)
		//Callers should catch this and can substitute their own error message
  		throw new Error("Error transforming xml doc " + exc);
	}
    return resultStr;  
}

/* This method sets the content of a layer within the HTML page
 * to the result of transforming the xml parameter by the xsl
 * parameter. The xml and xsl parameters may be of any form
 * supported by the transformXml() method. The layer parameter
 * may be either a DOM object or the name of a DOM object that
 * can be found using the findObject() method.
 */

ibm.portal.xml.setLayerContentByXml = function (layer, xml, xsl, xslparam,bReturnString) {
    var result = ibm.portal.xml.transform(xml,xsl,null,xslparam,bReturnString);
    if (layer.innerHTML) layer.innerHTML = result;
    else {
        var obj = document.getElementById(layer);
        obj.innerHTML=result;
    }
}
			   
//----------------------------------------------------------------------  temporary ajax request method 
ibm.portal.io ={};

/* Accept-Language property */
ibm.portal.io.sAcceptLanguage = "";

/*
 * Mozilla throws an exception instead of returning null when the
 * response header is not there. This is a wrapper function that
 * handles the exception and returns null if necessary.
 */
ibm.portal.io.getResponseHeader = function (oXml, sHeader) {
  var result;
  try { result = oXml.getResponseHeader(sHeader); }
  catch (exc) { result = null; }
  return result;
}

ibm.portal.io.checkForError = function (oXml) {
    var sErrMsg = null;
    var sError = ibm.portal.io.getResponseHeader(oXml, "X-IBM-REST-Error");
    if(sError)
    {
        // sArg is the string argument to be replaced in the message if needed
        // Note that RFC 822 headers must contain only US-ASCII characters.
        // non US-ASCII characters must be encoded/decoded.
        var sErrMsg = '', sArg = ibm.portal.io.getResponseHeader(oXml, "X-IBM-REST-MsgArg1");
        if (sArg)
        {
            sErrMsg = ibm.portal.resource.getString(sError, window.decodeURIComponent(sArg));
        } else {
            sErrMsg = ibm.portal.resource.getString(sError);
        }
    }
    return sErrMsg;
}

/*
 * Makes an asynchronous request, allowing the calling object to react
 * at each stage. The calling object MUST define the functions startUpdate(),
 * handleError(), and handleData().
 */
ibm.portal.io.asyncRequest = function(method, sActionUrl, sParameter, oCaller) {
    try
    {
        ibm.portal.io.setAsync(method, sActionUrl, sParameter, oCaller, true);
    } catch(e) {
        ibm.portal.io.setAsync(method, sActionUrl, sParameter, oCaller, false);
    }
}

ibm.portal.io.setAsync = function(method, sUrl, sParameter, oCaller, bfirstime) {

    var oXml = ibm.portal.xml.getXmlHttpRequest();
    oXml.open(method, sUrl, true);

    if(! bfirstime)
    {
        oXml.setRequestHeader("Accept-language", "*");
    }

    try {
        oXml.onreadystatechange = function()  {
            if (oXml.readyState == 4)
            {
                //if (NG.ServerRequest.checkSessionExpiration(oXml))
                //{
                //    return;
                //}
                    oCaller.startUpdate(); //Let the caller know the request is done
                    sError = ibm.portal.io.checkForError(oXml);

                if (sError)
                {
                        oCaller.handleError(""+ibm.portal.resource.getString(sError));
                } else {
                    var data = oXml.responseText;
                    oCaller.handleData(data);
                    }
            }
        }
        oXml.send(sParameter);
    } catch(e) {
        throw new Error("", "");
    }
}

SemTagPerson.init();


/*
Licensed Materials - Property of IBM
 
5724S31

Copyright IBM Corp.  2007    All Rights Reserved.

US Government Users Restricted Rights - Use, duplication or 
disclosure restricted by GSA ADP Schedule Contract with IBM 
Corp.
*/






/**
 * This is the JS file semantic tagging for awareness
 */
var SemTagAwrns = {

    SVCNAME: "sametime",
    hcards: new Array(),
	activeElems: new Array(),
    hasApplet: false,
    imIds: ["X-imn","email","uid","fn"],
    st:"",


	init: function () {
		SemTagSvcPortal.setCallback(SemTagAwrns.SVCNAME,SemTagAwrns.hcardsAdded);
		SemTagAwrns.processHcards(SemTagSvcPortal.getNodes(SemTagAwrns.SVCNAME));
	},

	hcardsAdded: function() {
		SemTagAwrns.processHcards(SemTagSvcPortal.getNodes(SemTagAwrns.SVCNAME));
	},
	
	processHcards: function(hcards) {
		if (typeof(prepareSametimeLink)=='undefined') return; // somehow stlinks.js isn't loaded...
        hcards = hcards || null;
        if ( hcards === null ) return;
		for (var i=0; i<hcards.length; i++) {
			var hcard = hcards[i];
			if (SemTagAwrns.disabled(hcard)) continue;

			SemTagAwrns.hcards.push(hcard);

			var fnElem = SemTagSvcPortal.findNameElementInHcard(hcard);
			if (SemTagSvcPortal.debug)  console.log("fnElem got is:"+fnElem);
			if (!fnElem) continue;
			var leid = fnElem.getAttribute(SemTagSvcPortal.liveElemPrefix + "id");
			if (SemTagSvcPortal.debug) console.log("leid got is:"+leid+":"+SemTagAwrns.activeElems[leid]);
			if (leid == null) continue;				
			if (leid && SemTagAwrns.activeElems[leid]) continue;
			var imId = SemTagAwrns.getSametimeId(hcard);
			var resolve = SemTagUtil.getHcardAttributeValue("X-sametime-resolve", hcard)
			 st = prepareSametimeLink(imId, "", resolve, "text:no;");
			 if (SemTagSvcPortal.debug)  console.log("ST got is:"+st);
			var status = document.createElement("span");
			//Fix for defect 200585 with multiple realm
			var od = SemTagUtil.getOwnerDocument(hcard);
			if (od.location != document.location) { //I'm in IFRAME
			var f = SemTagUtil.getFrameElement(hcard);
			if (f) {if(f.id=='wpsFLY_flyoutIFrame') continue;}}
			status.style.verticalAlign = "text-top"; //NEEDSWORK try placing the ST icon at the middle of the line...
			status.innerHTML = st;
			fnElem.parentNode.insertBefore(status,fnElem);

			if (leid) SemTagAwrns.activeElems[leid] = true;
		}
	},

	disabled: function (hcard) {
		return SemTagUtil.getHcardAttributeValue("X-no-awareness", hcard); //NEEDSATTN
	},

	getSametimeId: function(hcard) {
		var imId = null;
		for (var i=0; i<SemTagAwrns.imIds.length; i++) {
			var elem = SemTagSvcPortal.findElementByNameInHcard(hcard, SemTagAwrns.imIds[i]);
			if (elem) {
				imId = SemTagSvcPortal.getTextValue(elem);
				if (0 < imId.length) break;
			}
		}
		return imId;
	},

    updateST: function (eventArg) {
        var split = eventArg.split(";");
        var name = split[0];
        var status = split[1];
        if (SemTagSvcPortal.debug) console.log("INside updateST"+eventArg);
        for (var i=0; i < SemTagAwrns.hcards.length; i++) {
            var vc = SemTagAwrns.hcards[i];
            var watchedUser = SemTagAwrns.getSametimeId(vc);
            if ( watchedUser == name ) {
                var fnElem = SemTagSvcPortal.findNameElementInHcard(vc);
                if (fnElem) fnElem.setAttribute("semtag_ststatus", status); //NEEDSATTN
            }
        }
    },

    openChat: function(imId) {
        if (SemTagSvcPortal.debug) alert( "Opening chat with: " + imId );
       	STLinksCreateIM(imId);
    }
}

if (typeof wps_userStatusFuncs == "undefined")
	wps_userStatusFuncs = new Object();
wps_userStatusFuncs["STLinksUserStatusChanged_SA"] = 0;

if (typeof wps_loggedInFuncs == "undefined")
    wps_loggedInFuncs = new Object();
wps_loggedInFuncs["STLinksLoggedIn_SA"] = 0;

if (typeof wps_appletStartedFuncs == "undefined")
    wps_appletStartedFuncs = new Object();
wps_appletStartedFuncs["STLinksAppletStarted_SA"]=0;


function STLinksUserStatusChanged_SA(userId, displayName, status, statusMessage, groupName) {
    var val = "";
	if (SemTagSvcPortal.debug) console.log( "STLinksUserStatusChanged_SA status got is : " + userId+";"+status +":"+(typeof status));
    switch(status) {
        //case 0: val = "offline"; break;
        case 32 : val = "online"; break;
        case 64 : val = "away"; break;
        case 554 : val = "online"; break;
        case 96 : val = "away"; break;
		case 608 : val = "away"; break;
        case 128: val = "donotdisturb"; break;
        default : val = "offline"; break;
    }
    var arg = userId + ";" + val;
	if (SemTagSvcPortal.debug) console.log( "STLinksUserStatusChanged_SA status got is Final : " +arg );
    SemTagAwrns.updateST(arg);
}

function STLinksAppletStarted_SA() {
    if (SemTagSvcPortal.debug) alert( "Applet Started!" ); 
    SemTagAwrns.hasApplet = true;
}

function STLinksLoggedIn_SA(id,name) {
	if (SemTagSvcPortal.debug) alert( "Logged In: " + id + ", " + name ); 
}

SemTagAwrns.init();


var SemTagSvcConfig = null;
if ( (SemTagSvcPortal.ifConnUrlExists == "true") &&  (SemTagSvcPortal.isconnServerNew === true) )  {
//var SemTagSvcConfig = {isPortal: true, baseUrl : "null"+"/profiles", loadCssFiles  : true,isBidiRTL: false};
SemTagSvcConfig = {isPortal: true, baseUrl : SemTagSvcPortal.connUrl+"/profiles", loadCssFiles  : true,isBidiRTL: false};
}
SemTagSvcPortal.watchEvent(window, 'load', SemTagSvcPortal.init, false);
var SemTagSvc = SemTagSvcPortal; // Simply assign SemTagSvc to SemTagSvcPortal for backward compatibility. If Mashup SemTagSVc is available will be be overridden by Mashupone, Since Portal LOF is loaded first

