/* Copyright IBM Corp. 2006 All Rights Reserved. */ /* Copyright IBM Corp. 2007 All Rights Reserved. */ var SemTagUtil = { /** * 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; // var nextConnectionId = 0; createTimeoutFunction = function (connectionId) { return function() { self.cancelRequest(connectionId); } }; this.getScriptId = function(id) { return "_JVLN_" + id; }; this.getScriptObject = function(id) { return document.getElementById(this.$_getScriptId(id)); }; // this.getNextConnectionId = function() { // return ++nextConnectionId; // }; this.cloneObject = function(obj) { var newObj = new Object(); for (i in obj) { newObj[i] = obj[i]; } return newObj; }; this.request = function(url, timeLimit, callback, srcElement, connectionId) { connectionId = connectionId.toLowerCase(); var objId = this.getScriptId(connectionId); if(callback) { openConnectionMapping[connectionId] = callback; } if (srcElement) { if(!SemTagSvc.isGecko()) requestSrcElements[connectionId] = this.cloneObject(srcElement); else requestSrcElements[connectionId] = srcElement; } var script = document.createElement("script"); script.id = objId; try { script.src = url; } catch(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 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) { callback(false, null, srcElem); } var script = this.getScriptObject(id); if(script) { document.body.removeChild(script); } } catch(e) { } } }; this.dispatch = function(id, data) { id = id.toLowerCase(); if(!id) { return; } try { // Clean up the entry var callback = openConnectionMapping[id]; var srcElem = requestSrcElements[id]; requestSrcElements[id] = null; if(callback) { openConnectionMapping[id] = null; // Call the specified callback function callback(true, data, srcElem); var script = this.getScriptObject(id); if(script) { Element_head.removeChild(script); } } } catch(e) {} }; } } // Only the methods marked with "public" are available to service implementors and others. var SemTagSvc = { debug: "false", version: "1.0", baseUrl: "http://locopo.net:9080/profiles/ibm_semanticTagServlet", service: /* Copyright IBM Corp. 2007 All Rights Reserved. */ {"entries":[ {"id":"hcard","test":"(node.className.match(/(^|\\s)vcard(\\s|$)/))","js": "http://locopo.net:9080/profiles/html/personTag?template=personTag.jsp&lang=en", "css": "http://locopo.net:9080/profiles/css/personTag.css"} ,{"id":"hgroup","test":"(node.className.match(/(^|\\s)vcomm(\\s|$)/))","js": "http://locopo.net:9080/communities/javlin/communityTag?template=community.jsp"} ]} , scripts: new Array(), css: new Array(), actionRegistry: null, refcntAttr: "semtag_refcnt", hoverIdPrefix: "semtag_hover_", hoverIdx: 0, liveElemPrefix: "semtag_live_", init: function(event) { SemTagMenu.init(); SemTagSvc.parseDom(); }, 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 (SemTagSvc.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 (SemTagSvc.debug) alert("Svc.clearEventWatch caught: " + e); } }, // public parseDom: function(event, element) { if (!element) element = document; else if (typeof element == 'string') element = document.getElementById(element); SemTagSvc.traverseDOM(element); for (k=0; k 0) { SemTagSvc.loadScript(entry.js); if (entry.css) SemTagSvc.loadCss(entry.css); if (entry.callback) entry.callback.call(this); } } }, traverseDOM: function(node) { var svcEntries = SemTagSvc.service.entries; var tagNames; var allElements = new Array(); if (typeof(microfmtTagScope) != "undefined") { tagNames = microfmtTagScope.split(','); for (var i = 0; i < tagNames.length; i++) { var elements = node.getElementsByTagName(tagNames[i]); for (var j = 0; j < elements.length; j++) { allElements.push(elements[j]); } } } else { allElements = node.getElementsByTagName("*"); } for (var i = 0; i < allElements.length; i++) { var node = allElements[i]; for (var j=0; j"; // this is bad because it's completely overriding the content of this element... var classAttrs = SemTagSvc.isGecko()? elem.getAttribute("class"): elem.className; if (classAttrs && 0 < classAttrs.length) classAttrs += " hasHover"; //NEEDSATTN decoration else classAttrs = "hasHover"; if (SemTagSvc.isGecko()) elem.setAttribute("class", classAttrs); else elem.className = classAttrs; SemTagSvc.watchEvent(elem, 'mouseover', hoverHandler, false); } } }, createHoverImage: function() { var img = document.createElement("img"); SemTagSvc.hoverIdx++; img.id = SemTagSvc.hoverIdPrefix + SemTagSvc.hoverIdx; img.className = SemTagMenu.iconName; img.setAttribute("src", SemTagSvc.baseUrl +"/images/menu_selected_hover.gif"); img.setAttribute("border", "0"); var link = document.createElement("a"); SemTagSvc.watchEvent(link,"mouseover",SemTagMenu.activateHover,false); SemTagSvc.watchEvent(link,"mouseout",SemTagMenu.deactivateHover,false); link.appendChild(img); //A11Y - caller should add 'href' for appropriate event handler return link; }, // public // event: JS 'mouseover' event object // clickHandler: JS function to be called upon click showHover: function(event, clickHandler) { SemTagMenu.showHover(event, clickHandler); }, // public // event: JS 'click' event object // items: array of 'menu item JSON' // cssClass: CSS selector for the items // header: 'header JSON' // footer: 'footer JSON' setMenuData: function(event, items, cssClass, header, footer) { SemTagMenu.setMenuData(event, items, cssClass, header, footer); }, // public getMenuItemJson: function(label, href, order, icon) { var o = order? order: 0; var i = icon? icon: ""; return {"label": label, "href": href, "order": o, "icon": i}; }, // public getMenuHeaderJson: function(markup, order) { return {"markup": markup, "order": order}; }, // public getMenuFooterJson: function(markup, order) { return {"markup": markup, "order": order}; }, getElementFromEvent: function(event) { return event.target? event.target: event.srcElement; }, // public getLiveElementFromEvent: function(event) { return SemTagMenu.findLiveElementFromEventSource(SemTagSvc.getElementFromEvent(event)); }, getEventAbsoluteX: function (e) { // find out X var x=0; if (e.pageX) x = e.pageX; else if (e.clientX) x = e.clientX + document.body.scrollLeft; return x; }, getEventAbsoluteY: function (e) { // find out Y var y=0; if (e.pageY) y = e.pageY; else if (e.clientY) y = e.clientY + document.body.scrollTop; return y; }, findPosition: function (obj) { var count=0, posX=0, posY=0; if( obj.offsetParent ) { if (obj.currentStyle) posY += obj.offsetHeight - parseInt(SemTagSvc.getStyle(obj, "paddingBottom")); else if (window.getComputedStyle) posY += obj.offsetHeight - parseInt(SemTagSvc.getStyle(obj, "padding-bottom")); while (obj != null) { posX += obj.offsetLeft; posY += obj.offsetTop; obj = obj.offsetParent; count++; } return [ posX, posY ]; } else { return [ obj.x, obj.y ]; } }, createGroupJson: function(ctx,exts) { // top-level objects in 'actionRegistry' array return {"context": ctx, "extenders": exts}; }, createActionJson: function(id,ctx,label,desc,url,order) { // elements in actionRegistry[x].extenders array //var o = SemTagSvc.parseOrder(order); var o = parseInt(order); return {"id": id, "context": ctx, "label": label, "description": desc, "url": url, "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(context) { if (!SemTagSvc.actionRegistry) { // actionRegistry buliding - run once SemTagSvc.actionRegistry = new Array(); SemTagSvc.actionRegistry[0] = SemTagSvc.createGroupJson("dummy", new Array()); var i; var actions = SemTagSvc.getNodes("com.ibm.portal.action"); while (0 < actions.length) { // prepare the Action Json var actnNode = actions.pop(); var id = SemTagSvc.getElementsByClassName("action-id",actnNode); var ctx = SemTagSvc.getElementsByClassName("action-context",actnNode); var label = SemTagSvc.getElementsByClassName("action-label",actnNode); var desc = SemTagSvc.getElementsByClassName("action-description",actnNode); var url = SemTagSvc.getElementsByClassName("action-url",actnNode); var order = SemTagSvc.getElementsByClassName("action-order",actnNode); var actn = SemTagSvc.createActionJson(id[0].innerHTML,ctx[0].innerHTML,label[0].innerHTML,desc[0].innerHTML,url[0].innerHTML,order[0].innerHTML); for (i=1; i 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 = SemTagSvc.getElementsByClassName("type", elem); var values = SemTagSvc.getElementsByClassName("value", elem); var value = ""; if (values.length < 1) value = SemTagSvc.getTextValue(elem); for (i=0;iClick here to view profile"); }, startMenu: function(out, bidi) { out.write("
"); }, writeHeader: function(out, header, bidi) { out.write(header.markup); }, startActionSection: function(out, bidi, selector) { out.write(""); //A11Y if (!selector) selector = "personMenuActions"; out.write("
"); out.write(""); out.write("
"); }, writeFooter: function(out, footer, bidi) { out.write(footer.markup); }, endMenu: function(out, bidi) { out.write("
"); }, out: function () { this.buffer = ""; this.write = function (str) { this.buffer += str; } }, activateHover: function(event) { var imgElem = SemTagSvc.getElementFromEvent(event); if (imgElem) imgElem.src = SemTagSvc.baseUrl +"/images/menu_selected_hover.gif"; SemTagMenu.setCurrentElement(SemTagMenu.findLiveElementFromEventSource(imgElem)); }, deactivateHover: function(event) { var imgElem = SemTagSvc.getElementFromEvent(event); if (imgElem) imgElem.src = SemTagSvc.baseUrl +"/images/menu_selected_hover.gif"; SemTagMenu.setCurrentElement(null); }, showHover: function(event, clickHandler) { if (SemTagMenu.staticHover) return; var tag = SemTagMenu.getMenuTag(); var elem = SemTagSvc.getElementFromEvent(event); var origRefCnt = 0; if (elem && elem != SemTagMenu.currentElem) { // new hover request SemTagMenu.clearAllSvcHandlers(tag); origRefCnt = elem.getAttribute(SemTagSvc.refcntAttr); if (origRefCnt) { SemTagMenu.setCurrentElement(elem); } else { if (SemTagSvc.debug) alert("SemTagMenu.showHover called for a DOM element with no refcnt attribute!"); SemTagMenu.setCurrentElement(null); return; } } SemTagMenu.addSvcHandler(tag, clickHandler); 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(origRefCnt); if (SemTagMenu.showing && tag.style.display != "none") return; SemTagMenu.showing = false; var out = new SemTagMenu.out(); SemTagMenu.writeHover(out, "ltr"); tag.innerHTML = out.buffer; var pos = SemTagSvc.findPosition(SemTagMenu.currentElem); SemTagMenu.show(SemTagMenu.id, event, pos[0] + SemTagMenu.hoverOffset[0], // x pos[1] + SemTagMenu.hoverOffset[1], // y SemTagMenu.hoverDimension[0], // w SemTagMenu.hoverDimension[1]); // h }, addSvcHandler: function(tag, handler) { SemTagMenu.svcHandlers.push(handler); SemTagSvc.watchEvent(tag, 'click', handler, false); }, clearAllSvcHandlers: function(tag) { while (0 < SemTagMenu.svcHandlers.length) { var handler = SemTagMenu.svcHandlers.pop(); if (handler) SemTagSvc.clearEventWatch(tag, 'click', handler, false); } }, setCurrentElement: function(elem) { SemTagMenu.currentElem = elem; SemTagMenu.setRefCount(elem? Number(elem.getAttribute(SemTagSvc.refcntAttr)): 0); 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 (SemTagSvc.debug && cnt<=0) alert("Unless this is from hide(), this is bad!"); }, setMenuData: function(event, items, cssClass, header, footer) { if (SemTagSvc.debug) window.status = "Menu.setMenuData: items.length=" + items.length; if (!SemTagMenu.staticHover && SemTagMenu.refCount < 0) { if (SemTagSvc.debug) alert("setMenuData called when refCount=" + SemTagMenu.refCount); return; } var elem = SemTagMenu.findLiveElementFromEventSource(SemTagSvc.getElementFromEvent(event)); if (!elem) { if (SemTagSvc.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... for (var i=0; i 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; } //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) { var tag = SemTagMenu.getMenuTag(); if (!tag) return false; tag.style.display="none"; SemTagMenu.showing = false; SemTagMenu.setCurrentElement(null); SemTagMenu.clearAllSvcHandlers(tag); SemTagMenu.defaultCursor(); return true; }, 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= (sumX + bufferX)) || (mouseY >= (sumY + bufferY))) return false; else return true; }, mouseout: function(event) { 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 = SemTagSvc.getElementFromEvent(event); if (srcElement.className != 'javlinHover') { menuElem = document.getElementById(SemTagMenu.id); if (!SemTagMenu.inMenu(menuElem, event)) SemTagMenu.hide(SemTagMenu.id); } }, catchEscape: function (event) { if (event.keyCode == 27) { SemTagMenu.hide(SemTagMenu.id); } }, stopEvent: function(event) { if (!event) return; if (SemTagSvc.isGecko()) { event.preventDefault(); event.stopPropagation(); } 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. } } }, startHideTimer: function(menuId) { if ( 0 < SemTagMenu.hideDelay ) { SemTagMenu.timeouts.push(window.setTimeout('SemTagMenu.endHideTimer("' + menuId + '")',SemTagMenu.hideDelay)); } }, endHideTimer: function(menuId) { menuElem = document.getElementById(menuId); SemTagMenu.hide(menuId); }, clearTimeouts: function() { for (i=0;i