var CustomXsl = []; function AddCustomXsl(url) { CustomXsl.push(url); } var SKIP_MYSELF=true; // Magic constant for RefreshTabOrder and focusFirst // Focus state var FS_FOCUSED=true; // window manager is focused var FS_NOTFOCUSED=false; // window manager is not focused function ApplyInnerHTML(node, sHTML) { if(Prototype.Browser.IE) { // workaround innerHTML bug var child; while (child = node.firstChild) { node.removeChild(child); } } node.innerHTML = sHTML; } function ApplyTreeOrString(node, oSrc) { if (typeof(oSrc.documentElement) != 'undefined') { // document passed var srcNode = oSrc.documentElement; node.innerHTML=''; // clean target node (non-IE way, innerHTML is definitely safe here) if (!srcNode) return; // nothing to insert if (srcNode.localName == 'result') { // handle transformiix:result while (srcNode.childNodes.length) { // node will be unlinked from source document, so we will always append first child node.appendChild(srcNode.firstChild); } } else if (srcNode.nodeName == 'HTML') { var n; for (var i = 0; i < srcNode.childNodes.length; i++) { n = srcNode.childNodes[i]; if (n.nodeName == 'BODY') break; n = null; } if (!n) return; node.innerHTML=n.innerHTML; } else { // transformation result is a single node node.appendChild(AdoptNode(node.ownerDocument, srcNode)); } } else { ApplyInnerHTML(node, oSrc); // string } } // AWindow class var AWindow = Class.create({ initialize: function(oParams) { this.sParent_ = (oParams.sParent || ""); // parent.this() this.sLocalID_ = (oParams.sID || ""); // local name (in XML) this.sID_ = (oParams.sHTMLID || ""); // global name (in HTML) this.sendAllControls = oParams.SendAllControls; this.sInstanceID_ = (oParams.sInstanceID || ""); // identification this.sAction_ = (oParams.sInstanceID ? "Refresh" : ""); this.bInline_ = oParams.bInline; // where to insert content (control ID) this.sControlID_ = (oParams.sControlID) ? oParams.sControlID : ""; // Collection of controls this.oControls_ = {}; this.aControls_ = []; this.oHandlers_ = {}; // Collection of children instanceIDs this.oChildren = {}; // Collection of label cells this.oLabelCells = {}; GDocumentEventManager.AddTransparentControl(this.ClassName()); //if(!sParent) this.nTabBase=1; //else this.nTabBase=-1; // widget contents initialization this.sValue = oParams.sValue; if (this.sParent_) { // bug was here (oParentWin was not initialized in some cases) // mvel@ this.oParentWin = GWindowManager.GetWindow(this.sParent_); } // data if (!oParams.sParams) oParams.sParams = ""; //if (oParams.sURL && oParams.sURL.indexOf('/ahtml/')) oParams.HTMLControls = []; if (oParams.HTMLControls) { // Server-side XSLT this.sXMLSource_ = oParams.sURL; this.sParams_ = ""; this.NonXSLWindowInit(oParams.HTMLControls); return; } else if (oParams.sURL) { // we have real window var paramIdx=oParams.sURL.indexOf('?'); if(paramIdx<0) { this.sXMLSource_=oParams.sURL; this.sParams_=oParams.sParams; } else { this.sXMLSource_=oParams.sURL.substr(0, paramIdx); this.sParams_=oParams.sURL.substr(paramIdx+1)+oParams.sParams; } this.oXML_ = null; } else if (oParams.oXML) { // XML was manually generated this.sParams_ = ""; // ignore all params this.sXMLSource_ = ""; // !!! this.oXML_ = oParams.oXML; } else { // Load empty window var node=$(this.sControlID_); if (!node) return; // window already died... if(node.JSControl && typeof(node.JSControl.Die)=="function") node.JSControl.Die(); ApplyInnerHTML(node, ""); delete node.JSControl; return; } if (this.sXMLSource_) { var url = this.sXMLSource_; if (url.indexOf('/srv/') == 0 && this.sInstanceID_) url = "/act/dynamic/"; if (this.sAction_ || this.sInstanceID_) url += '/' + this.sAction_; if (this.sInstanceID_) url += '/' + this.sInstanceID_; new AjaxRequest("POST", url, this.sParams_, { onSuccess: this.LoadingCallback.bind(this), onException: this.ExceptionCallback.bind(this), timeout: oParams.timeout }); } else { this.Load(); } }, ClassName: function() { return "AWindow"; }, NonXSLWindowInit: function(controls) { for (var i = 0; i < controls.length; ++i) { var c = $(controls[i].id); this.oControls_[controls[i].id] = { node_: c }; this.aControls_.push(c); } var n = $(this.sID_); n.JSControl = this; n.writeAttribute('instanceid', this.sInstanceID_); n.writeAttribute('localid', this.sLocalID_); n.writeAttribute('eleclass', 'wnd'); GWindowManager.registerWindow(this.InstanceID(), this); if(this.oParentWin) this.oParentWin.oChildren[this.InstanceID()]=true; for (var i = 0; i < controls.length; ++i) { var id = controls[i].id; var n = $(id); if (!n) continue; var dh = n.readAttribute('defaulthandler'); if (dh) AControl.AddDefaultHandler(dh, id); var sHandlers = n.getAttribute("handle"); if (!sHandlers && controls[i].attributes && "handle" in controls[i].attributes) sHandlers = controls[i].attributes["handle"]; if(sHandlers) { var aHandlers = sHandlers.split(' '); if (!this.oControls_[id]) this.oControls_[id] = new Object(); var oCtrlInfo = this.oControls_[id]; for (var j = 0; j < aHandlers.length; ++j) { var sEventName = aHandlers[j]; if (!sEventName) continue; // put into control's map if (!oCtrlInfo.oHandlers_) oCtrlInfo.oHandlers_ = new Object(); oCtrlInfo.oHandlers_[sEventName] = ET_REGULAR; // and into global map (to register handlers this.oHandlers_[sEventName] = true; } } var n = []; for (var a in controls[i].attributes) { n.push({name: a, value: controls[i].attributes[a]}); } this.SetAttributes(id, {attributes: n}); } this.InitDefaultSubscribers(); for (var i = 0; i < controls.length; ++i) { //TODO: this can probably be reused var id = controls[i].id; var n = $(id); if (!n) continue; if (this.oControls_[id].dependsOn_) { this.Subscribe("INPUT", this.CheckDependencies.bind(this, id)); this.Subscribe("CHANGE", this.CheckDependencies.bind(this, id)); this.CheckDependencies(id); } } }, InitDefaultSubscribers: function() { //LogL("CHANGE Subscribed on: ID="+this.ID()); this.oHandlers_["CHANGE"]=true; for (var sKey in this.oHandlers_) { //LogL("GENERIC Subscribed on: "+sKey+", ID="+this.ID()); this.Subscribe(sKey, this.ServerEventHandler, this); } this.Subscribe("CHANGE", this.OnControlChange, this); this.Subscribe("WM_INIT", this.OnControlChange, this); this.Subscribe("WM_RESTORE", this.OnRestore, this); this.Subscribe("WM_REFRESH", this.OnRefresh, this); this.Subscribe("INPUT", this.OnControlChange, this); this.Subscribe("WM_POPUP", this.OnWMPopup, this); }, LoadingCallback: function(oAjaxRequest) { this.oXML_ = oAjaxRequest.XML(); this.Load(); }, Load: function() { if (!this.oXML_.documentElement) { this.SetError("AWindow::Load(): XML loading failed: No document data! "); return; } this.sLocalID_ = this.oXML_.documentElement.getAttribute("id"); this.sTitle_ = this.oXML_.documentElement.getAttribute("title"); this.sInstanceID_ = this.oXML_.documentElement.getAttribute("this"); GWindowManager.registerWindow(this.InstanceID(), this); if(this.oParentWin) this.oParentWin.oChildren[this.InstanceID()]=true; this.ProcessHTMLID(); // alert(this.oXML_.xml); var oTransformDoc = GWindowManager.Transform(this.oXML_, true); this.InitDefaultSubscribers(); GDocumentEventManager.Subscribe('KeyDown', this.ID()); // Shortcuts var ctlId = this.sControlID_; if (!this.sParent_) ctlId = GWindowManager.ID(); var node = $(ctlId); if (!node) return; // window already died... if(node.JSControl && typeof(node.JSControl.Die)=="function") node.JSControl.Die(); ApplyTreeOrString(node, oTransformDoc); this.HTML=node.select('div')[0]; this.HTML.JSControl=this; node.JSControl=this; if (this.sParent_) this.registerInParentResizer(); try { if(typeof(oTransformDoc)=="string") oTransformDoc.evalScripts(); // another IE bug workaroung else node.innerHTML.evalScripts(); } catch (err) { LogL(typeof(oTransformDoc)=="string" ? oTransformDoc : node.innerHTML); throw err; } var oRoot = this.XML().documentElement; var aElements = AXML.SelectNodes(oRoot, "/ai:wnd/ai:ele|/ai:wnd/ai:ele/ai:ele", AINS); if (!aElements) { alert("DEBUG: Bad window! No elements found! XML:\r\n"+oRoot.xml); return; } this.orderEvents(oRoot); this.ProcessEvents(oRoot, "before"); this.oShortcuts_={}; for (var i = 0; i < aElements.length; ++i) { var oNode = aElements[i]; var sID = oNode.getAttribute("id"); var sHTMLID = oNode.getAttribute("htmlid"); if (!sHTMLID) continue; // element is not referenced in layout var el = $(sHTMLID); if (el) { // this will not work on nested elements (!!!) ControlHTMLID gives wrong ID for nested elements var sControlID = this.ControlHTMLID(sID); if (!this.oControls_[sControlID]) this.oControls_[sControlID] = new Object(); //LogL("Node registered: "+sControlID); this.oControls_[sControlID].node_ = el; var dependsOn=oNode.getAttribute("dependsOn"); if (dependsOn!==null) { // attribute exists var d=dependsOn ? dependsOn.split(" ") : []; // split returns [''] on empty string for (var j=0; j < d.length; ++j) { d[j]=this.ControlHTMLID(d[j]); } // set dependsOn property for this control this.oControls_[sControlID].dependsOn_=d; this.Subscribe("INPUT", this.CheckDependencies.bind(this, sHTMLID)); this.Subscribe("CHANGE", this.CheckDependencies.bind(this, sHTMLID)); } var shortcut=oNode.getAttribute("shortcut"); if(shortcut) { if(el.JSControl) this.oShortcuts_[shortcut]=el.JSControl; else { var ctrl=el.ancestors().detect(function(n){ return n.JSControl }); if(ctrl) this.oShortcuts_[shortcut]=ctrl.JSControl; } } if(oNode.getAttribute("primary")=="yes" && el.JSControl) { this.oShortcuts_["Ctrl+#13"]=el.JSControl; } } var sClassName = oNode.getAttribute("class"); if (sClassName == "widget") { var sNewSrc = oNode.getAttribute("src"); var sValue = oNode.getAttribute("value"); if (!sValue || oNode.getAttribute("update-value")!='yes') { /*if (sValue) { LogE("Undefining VALUE, was '"+sValue+"'"); LogL("WindowID=$$"+this.ID()+"$$"); LogL("Control ID=$$"+oNode.getAttribute("id")+"$$"); LogL("Control XML="+oNode.xml); }*/ sValue=undefined; } //if (sValue) LogE("LoadingCallback: "+sValue); if (sNewSrc) { GWindowManager.CreateWindow({ sURL: sNewSrc, sParent: this.sInstanceID_, sControlID: sHTMLID, sValue: sValue, bInline: true }); } } else { this.SetAttributes(sHTMLID, oNode); } } this.UpdateLayoutElements(oRoot); this.InitChangesTracking(oRoot); // filling an array for further tabstop setting var aLay = AXML.SelectNodes(oRoot, "/ai:wnd/ai:lay//ai:ele", AINS); for (var i = 0; i < aLay.length; ++i) { var sID = aLay[i].getAttribute("id"); var sControlID = this.ControlHTMLID(sID); if(!this.oControls_[sControlID]) continue; var el=this.oControls_[sControlID].node_; if(!el) continue; el.position_ = this.aControls_.length; el.nTabBase = 0; this.aControls_.push(el); } if(this.oParentWin) { // Setup tab order of the window if (this.IsPopup) { // experimental GWindowManager.StoreActiveElement(); GWindowManager.ClearTabOrder(FS_NOTFOCUSED); this.SetTabOrder(0); } else { this.oParentWin.RefreshTabOrder(this.sControlID_); } var win=this; while(win && win.bInline_) { win=win.oParentWin; } if(win) win.focusFirst(win.HTML, SKIP_MYSELF); } // emit creation event new AEvent("WM_CREATE", { wid: this.LocalID()}, this.ID()); for (var cid in this.oControls_) { // TODO: verify this (last commented condition) if (!this.oControls_[cid] || !this.oControls_[cid].node_/* || !this.oControls_[cid].node_.JSControl*/) continue; new AEvent("INPUT", {}, this.oControls_[cid].node_.JSControl); } // initialize window as widget if (this.sValue) { var oValue=URLRestoreV(this.sValue); this.SetValue(oValue); this.sValue=undefined; } this.ProcessEvents(oRoot, "after"); this.aOrderedEvents=[]; // to remove references // We cannot post WM_INIT from window itself, because it will be captured by 'this' window // but we can use widget control of the parent window as event emitter // mvel var widgetNode=$(this.HTML.parentNode); if (widgetNode && widgetNode.JSControl==this) { new AEvent("WM_INIT", {}, widgetNode.getAttribute('id')); //LogL("Widget WM_INIT: $$"+this.ID()+"$$"); } }, OnKeyDown: function(evt) { var letter=String.fromCharCode(evt.keyCode); if(evt.keyCode>=112 && evt.keyCode<=123) letter="F"+(evt.keyCode-111); var mod=""; if(evt.ctrlKey) mod="Ctrl+"; var ctrl; if(this.oShortcuts_[mod+letter]) ctrl=this.oShortcuts_[mod+letter]; else if(this.oShortcuts_[mod+"#"+evt.keyCode]) ctrl=this.oShortcuts_[mod+"#"+evt.keyCode]; if( ctrl && typeof(ctrl.Shortcut)=="function" ) { ctrl.Shortcut(mod+"#"+evt.keyCode); return true; } }, InitChangesTracking: function(oRoot) { var sTrackChanges=oRoot.getAttribute("track-changes") || ''; if (sTrackChanges=="no") return; if (sTrackChanges.substr(0,1)=="'") { // extract control id (= action name for default handler) this.trackChangesAction=sTrackChanges.substr(1,sTrackChanges.length-2); } var aLabels=AXML.SelectNodes(oRoot, "/ai:wnd/ai:lay//ai:cell[@labelfor]", AINS); for(var i=0; i= 0 && element.style.display != 'none') { if (typeof element.activate == "function") { element.activate(); return true; } else if (typeof element.focus == "function") { element.focus(); return true; } } for (var child = element.firstChild; child; child = child.nextSibling){ if (this.focusFirst(child)) return true; } return false; }, SetAttributes: function(sHTMLID, oNode) { // LogL("AControl.SetAttributes: "+sHTMLID); var htmlNode=$(sHTMLID); if(!htmlNode || !htmlNode.JSControl) return; var jsControl=htmlNode.JSControl; var count=oNode.attributes.length; for (var i = 0; i < count; ++i) { var oAttr = oNode.attributes[i]; if (oAttr.name == "value" && jsControl.SetValue) { jsControl.SetValue(URLRestoreV(oAttr.value)); } else if (oAttr.name=="dependsOn") { var dependsOn=oAttr.value; var d=dependsOn ? dependsOn.split(" ") : []; // split returns [''] on empty string for(var j=0; j=0) return; this.ProcessEvent(this.aOrderedEvents[i], oRoot); } } else { for(var i=0; i0 ) { // child window var child=oCtrl.select('DIV[instanceid]')[0].JSControl; oCtrl.nTabBase=nTabEnd; nTabEnd=child.SetTabOrder(nTabEnd); continue; } if(oCtrl.JSControl && oCtrl.JSControl.SetTabOrder) nTabEnd=oCtrl.JSControl.SetTabOrder(nTabEnd); } if(this.oParentWin) this.oParentWin.RefreshTabOrder(this.sControlID_, SKIP_MYSELF, nTabEnd); }, Busy: function(isBusy) { if(isBusy==false) return this.Free(); if(this.HTML) this.HTML.addClassName('WidgetBusy'); this.windowBusy=true; for(var cid in this.oControls_) { var c=this.oControls_[cid]; if(c.node_ && c.node_.JSControl && c.node_.JSControl!=this && c.node_.JSControl.Busy) c.node_.JSControl.Busy(true); } }, Free: function() { if(this.HTML) this.HTML.removeClassName('WidgetBusy'); this.windowBusy=false; for(var cid in this.oControls_) { var c=this.oControls_[cid]; if(c.node_ && c.node_.JSControl && c.node_.JSControl!=this && c.node_.JSControl.Busy) c.node_.JSControl.Busy(false); } }, Refresh: function(sTimeout) { var sURL = this.sXMLSource_; if (sURL.indexOf("/srv/") == 0) sURL = "/act/dynamic/" sURL += "/Refresh/"+this.sInstanceID_; new AjaxRequest("POST", sURL, "", { onSuccess: this.UpdatingCallback.bind(this), onException: this.ExceptionCallback.bind(this), 'timeout': parseInt(sTimeout, 10) }); }, Update: function(sEventName, sData, sTimeout) { var sURL = this.sXMLSource_; if (sURL.indexOf("/srv/") == 0) sURL = "/act/dynamic/" // TODO: if window not loaded, we cannot update it... sURL += "/"+sEventName+"/"+this.sInstanceID_; new AjaxRequest("POST", sURL, sData, { onSuccess: this.UpdatingCallback.bind(this), onException: this.ExceptionCallback.bind(this), timeout: parseInt(sTimeout, 10) }); }, ExceptionCallback: function(oAjaxRequest) { this.Free(); if (window.GLoader && GLoader.CheckFatalError(oAjaxRequest.ErrorCode()) ) return; // var oXmlDomUpdate = oAjaxRequest.XML(); // if(!oXmlDomUpdate) alert("Error! Wrong Ajax response. "); alert("`Error: `" + oAjaxRequest.Error()); }, UpdatingCallback: function(oAjaxRequest) { try { // alert(oAjaxRequest.oTransport_.responseText) this.Free(); var oXmlDomUpdate = oAjaxRequest.XML(); var oDstRoot = (this.oXML_ ? this.oXML_.documentElement : null); // merge element attributes var oSrcRoot = oXmlDomUpdate.documentElement; this.ProcessID(oSrcRoot, 'update'); var sWindowInstanceID = oSrcRoot.getAttribute("this"); //LogL("Updating window $$"+this.ID()+"$$ ["+sWindowInstanceID+"]"); this.orderEvents(oSrcRoot); this.ProcessEvents(oSrcRoot, "before"); this.rememberPrevValues(); var aElements = AXML.SelectNodes(oSrcRoot, "//ai:ele[not(ancestor::ai:lay)]", AINS); if (!aElements) { alert("DEBUG: Bad window! No elements found! XML:\r\n"+oSrcRoot.xml); return; } for (var i = 0; i < aElements.length; ++i) { var oSrcNode = aElements[i]; var sID = oSrcNode.getAttribute("id"); // LogL("node found: "+sID); var oDstNode = oDstRoot ? AXML.SelectNode(oDstRoot, "//ai:ele[not(ancestor::ai:lay)][@id='" + sID + "']", AINS) : null; var sHTMLID = (oDstNode ? oDstNode : oSrcNode).getAttribute("htmlid"); if (!sHTMLID) continue; // element is not referenced in layout // LogL("node suited: "+sID); var sClassName = oDstNode ? oDstNode.getAttribute("class") : null; var isWidget=false; if (sClassName == "widget") { isWidget=true; var sNewSrc = oSrcNode.getAttribute("src"); var eW=$(sHTMLID); var sOldSrc=""; var w=(eW && eW.JSControl) ? eW.JSControl : null; if (w) { if (w instanceof DataPlaceholder) { // skip virtual widgets (bug #1504) isWidget=false; } else { sOldSrc=w.XMLSource(); var params=w.Params(); if (params) sOldSrc+='?'+params; } } if (isWidget) { this.Busy(); if (sNewSrc!=sOldSrc) { var elem = document.getElementById(sHTMLID); if (elem && elem.JSControl) new AEvent("WM_DESTROY", {}, elem.JSControl); if (sNewSrc) { GWindowManager.CreateWindow({ sURL: sNewSrc, sParent: this.InstanceID(), sControlID: sHTMLID, bCheckChanges: true }); } else { // TODO: destroy inner window } } else { // src was not changed, only set attributes if (oSrcNode.getAttribute("update-value")=='yes') { this.SetAttributes(sHTMLID, oSrcNode); } } this.Free(); } } if (!isWidget) { // regular control this.SetAttributes(sHTMLID, oSrcNode); } } this.updateModificationStatus(); this.UpdateLayoutElements(oSrcRoot); for(var cid in this.oControls_) { var c=this.oControls_[cid]; var oNode=c.node_; if(!oNode) continue; var sHTMLID=oNode.getAttribute("htmlid"); if(!sHTMLID) continue; if (!c.dependsOn_) continue; this.CheckDependencies(sHTMLID); } this.ProcessEvents(oSrcRoot, "after"); this.aOrderedEvents=[]; // clear ordered events array to remove references // ------------------------------------ Exception handling block } catch (exc) { alert("AWindow:UpdatingCallback: Exception: "+exc); } }, UpdateLayoutElements: function(xml) { var els = AXML.SelectNodes(xml, "/ai:wnd/ai:lay//*[name() != 'ele'][@id][@visibility or @style]", AINS); for (var i = 0; i < els.length; ++i) { var e = els[i]; var id = e.getAttribute('id'); var tag = e.nodeName.replace(/[^:]+:/, ''); var node; if (tag == "grid") { node = $("gridFrame_" + id + "_" + this.InstanceID()); } else { var uid = tag + "-" + id; node = $( this.ControlHTMLID(uid) ); } if (!node) continue; var st = e.getAttribute('style'); if (st !== null) { node.writeAttribute('style', st); } var visibility = e.getAttribute('visibility'); if(!visibility) continue; if(visibility != 'no') node.show(); else node.hide(); } }, CollectChangedData: function() { var oData = new Object(); for (var sKey in this.oControls_) { // enum all controls var oControl = this.oControls_[sKey]; if (oControl.bChanged_ || this.sendAllControls) { if (!oControl.node_) { LogE("CollectChangedData: Control node not found: " + sKey); continue; } var JSControl=oControl.node_.JSControl; if(!JSControl || typeof(JSControl.Value) != 'function') continue; oData[oControl.node_.readAttribute('localid')] = JSControl.Value(); } } // TODO: clear controls change state //this.oControls_ = new Object(); return oData; }, Value: function() { var res={}; for(var k in this.oControls_) { var node=this.oControls_[k].node_; if(node && node.JSControl && typeof(node.JSControl.Value)=='function') { var locid=node.readAttribute('localid'); if(locid) res[locid]=node.JSControl.Value(); } } return res; }, SetValue: function(oValue) { for(var k in this.oControls_) { var node=this.oControls_[k].node_; if (!node) continue; // strange control... var jsControl=node.JSControl; if (!jsControl) continue; // non-kosher control if (typeof(jsControl.SetValue)!='function') continue; // cannot perform SetValue for this control var locid=node.readAttribute('localid'); if (!locid) continue; // cannot get local ID, strange control if (typeof(oValue[locid]) == 'undefined') continue; // no value for this control jsControl.SetValue(oValue[locid]); //new AEvent("CHANGE", {}, jsControl); } }, OnRefresh: function() { for(var sControlID in this.oLabelCells) { var lc=this.oLabelCells[sControlID]; if($(sControlID)) lc.sValue=URLSerialize($(sControlID).JSControl.Value()); lc.bModified=false; lc.oNode.removeClassName("Modified"); } this.syncModificationStatus(); }, OnRestore: function(oEvent) { // oEvent.Stop(); this.registerInParentResizer(); }, Die: function() { for(var ch in this.oChildren) { GWindowManager.GetWindow(ch).Die(); } if(this.oParentWin) delete this.oParentWin.oChildren[this.InstanceID()]; GWindowManager.DeleteWindow(this.sInstanceID_); }, hasModifiedChildren: function() { for(var ch in this.oChildren) { var chWin=GWindowManager.GetWindow(ch); if (chWin.IsModified) return ch; var modCh=chWin.hasModifiedChildren(); if (modCh) return modCh; } return ''; }, ProcessID: function(oRoot, mode) { var aElements = AXML.SelectNodes(oRoot, "/ai:wnd/ai:ele", AINS); for (var i = 0; i < aElements.length; ++i) { var oNode = aElements[i]; if (typeof(oNode.getAttribute) == 'undefined') continue; var sLocalID = oNode.getAttribute("id"); var sID = this.sID_+'_'+sLocalID; oNode.setAttribute("htmlid", sID); if (mode=='load') this.processHandlers(oNode, sID); this.SetChildID(sID, sLocalID, oRoot, mode); } }, processHandlers: function(oNode, sID) { var sHandlers=oNode.getAttribute("handle"); if (!sHandlers) return; var aHandlers=sHandlers.split(' '); if (!this.oControls_[sID]) this.oControls_[sID]=new Object(); var oCtrlInfo=this.oControls_[sID]; for (var j=0; j= 0 ? aRets[i].substr(0, x) : aRets[i]); var rVal = (x >= 0 ? aRets[i].substr(x + 1) : aRets[i]); if (!(rVal in oValues)) continue; var id = this.sID_ + '_' + rName; var elem = document.getElementById(id); if (!elem || !elem.JSControl || !elem.JSControl.SetValue) continue; elem.JSControl.SetValue(oValues[rVal]); // we should change state before emitting events // to ensure that any server action will pass all changed controls' values rName = this.ControlHTMLID(rName); if (rName in this.oControls_){ this.oControls_[rName].bChanged_ = true; this.oControls_[rName].node_ = elem; aChanged.push(elem.JSControl); } } // we should first set all values and only then emit events for (var i=0; i < aChanged.length; ++i) { new AEvent("CHANGE", {}, aChanged[i]); } }, RegisterResizeableChild: function(sControlID) { if (!this.oResizeableChildren) this.oResizeableChildren = new Object(); this.oResizeableChildren[sControlID] = true; //LogL("Win[$$"+this.ID()+"$$]: Resizeable child registered: "+sControlID); }, OnResize: function(evt) { if (!this.HTML) { alert('OnResize: Window HTML is not initialized'); return; } var eG = AControl.GetBoundingFrame(this.HTML); // TODO: remove this popup spike if (!eG) eG = this.HTML.up('DIV.popupContents'); // no grid? try popup frame var nFullHeight = (eG ? eG.offsetHeight : document.body.clientHeight); // resize window grids //LogE("OnResize: Win[$$"+this.ID()+"$$]: Resizing window grids..."); this.ResizeGrids(nFullHeight, eG); // Resize children if (!this.oResizeableChildren) { //LogL("OnResize: No children to resize."); return; } for (var sK in this.oResizeableChildren) { var elChild = $(sK); if (elChild === null) { delete this.oResizeableChildren[sK]; //LogE("OnResize: Child $$"+sK+"$$ was garbage-collected."); continue; } var jsControl = elChild.JSControl; if (jsControl) { if (typeof(jsControl.OnResize) == 'function') { //LogL("OnResize: Win[$$"+this.ID()+"$$]: Resizing JSControl "+jsControl.ID()); jsControl.OnResize(evt); } else { LogE("Warning: Non-kosher control subscribed! No OnResize method! "+jsControl.ID()); } } else { //LogE("Child "+sK+" does not have JSControl!"); } } }, ResizeGrids: function(nFullHeight, eRoot) { var elWF = (eRoot ? eRoot : this.HTML.parentNode); // window' div or other frame //LogL("ROOT ID="+elWF.getAttribute('id')); // LogE("Win[$$"+this.ID()+"$$]: ResizeGrids... "+nFullHeight+" "+elWF.readAttribute("id")); var eBF; var aFrames=elWF.select('DIV[type="gridFrame"]'); var prevGridsH=0; for(var i=0; i2000) { // iHeight-=elWF.scrollHeight-elWF.offsetHeight; iHeight-=elWF.scrollHeight-offset-2000; eF.setStyle({"height": iHeight+'px'}); } } eF.setStyle({"height": iHeight+'px'}); this.ResizeGrids(iHeight, eF); // recurse into subframes prevGridsH+=eF.offsetHeight; } //LogL("ResizeGrids finished with level "+this.nRecurseLevel); //this.nRecurseLevel--; }, AddCustomization: function(cust) { var doc = new AXML('ai:wnd', AIURI); var lay = doc.oXML_.createElement('ai:lay'); doc.oXML_.documentElement.appendChild(lay); for (var id in cust) { var e = doc.oXML_.createElement('ai:' + (cust[id]._tag ||'ele')); e.setAttribute("id", id); for (var attr in cust[id]) { e.setAttribute(attr, String(cust[id][attr])); } lay.appendChild(e); } var oParams = { "window": this.XMLSource(), "xml": doc.oXML_.xml }; new ServerCall("/srv/WWW/WWWWorker/AddCustomization", oParams, {}); }, AddElementCustomization: function(ecust, id, tag) { var cust = {}; cust[id] = ecust; cust[id]._tag = tag; return this.AddCustomization(cust); }, // various getters/setters InstanceID: function() { return this.sInstanceID_; }, LocalID: function() { return this.sLocalID_; }, ID: function() { return this.sID_; }, // ID in HTML Title: function() { return this.sTitle_; }, // obtain child control HTML ID ControlHTMLID: function(sID) { return this.sID_ + '_' + sID.replace('.', '_'); }, Control: function(sID) { if(!this.oControls_[this.ControlHTMLID(sID)]) return undefined; return this.oControls_[this.ControlHTMLID(sID)].node_; }, // obtain parent window instance ID Parent: function() { return this.sParent_; }, XML: function() { return this.oXML_; }, XMLSource: function() { return this.sXMLSource_; }, Params: function() { return this.sParams_; } }); // static event poster AWindow.postEvent = function(oEvent) { var sControlID = oEvent.EmitterID(); var sCurrentWindowID = AControl.GetParentWindowInstanceID(sControlID); var sEventName = oEvent.Name(); //showObject(GWindowManager.GetWindow(sCurrentWindowID).oEventListeners_); // if (sEventName!='INPUT') // LogL("AWindow.postEvent: Name=$$"+sEventName+"$$, Emitter=$$"+sControlID+"$$, Parent=$$"+sCurrentWindowID+"$$"); while (sCurrentWindowID) { var oWindow = GWindowManager.GetWindow(sCurrentWindowID); var listeners = [oWindow.allevent_handlers_, oWindow.oEventListeners_[sEventName]]; var handlers = new Array(); for (var iii = 0; iii < listeners.length; ++iii){ if (listeners[iii] && listeners[iii].length) handlers.push.apply(handlers, listeners[iii]); } for (var iii = 0; iii < handlers.length; ++iii){ handlers[iii].Callback().call(handlers[iii].ThisObject(), oEvent); if (!oEvent.Propogation()) return; } // get parent window if(oWindow.Parent()==sCurrentWindowID) sCurrentWindowID=""; else sCurrentWindowID = oWindow.Parent(); } GDocumentInstance.FireEvent(oEvent); } var AWindowManager = Class.create({ initialize: function(container) { this.oWindows_ = Object(); Event.observe(window, 'resize', this.OnResize.bind(this)); // this.container = container || document.body; // if(this.container) { // this.container.writeAttribute('id', this.ID()); // this.container.JSControl=this; // } }, ID: function() { return 'WindowManager'; }, Start: function(sEntryPoint, container) { this.container = container || document.body; //delete this.container.JSControl; //this.container.removeAttribute('id'); var elWM=new Element('div', { id: this.ID() }); $(this.container).update(); this.container.appendChild(elWM); if(!sEntryPoint) { // less hardcode alert('AWindowManager::Start: No entry point defined. '); return; } this.CreateWindow({sURL: sEntryPoint}); }, Focus: function() { var eWM=$('wMain'); if (eWM && eWM.JSControl) eWM.JSControl.Focus(); }, StoreActiveElement: function() { this.activeElement=document.activeElement ? document.activeElement : null; }, ActiveElement: function() { return this.activeElement; }, Focused: function() { return this.bFocused; }, SetTabOrder: function(nTabBase) { var eWM=$('wMain'); if (eWM && eWM.JSControl) eWM.JSControl.SetTabOrder(nTabBase); this.bFocused=true; }, ClearTabOrder: function(bFocusedState) { var aTabStops=$(this.container).select('[tabindex]'); if (!aTabStops) return; for (var i=0; i 0) args = '?' + args; while (args && args.length > 0 && args[args.length - 1] == '&') { args = args.substr(0, args.length - 1); } if (Prototype.Browser.IE) { loc = window.location; if (loc.protocol.length+loc.host.length+loc.pathname.length+src.length+args.length+3>350) { // maximum buffer length is 2083 chars (non-unicode) for IE args=""; } } var upd = function() { window.location.hash = '#' + src + args; }; upd.defer(); }, XSL: function() { if (!this.oXSLDoc_) this.LoadXSL(); if (!this.oXSLDoc_) return; return this.oXSLDoc_; }, OnBeforeUnload: function(evt) { for(var win in this.oWindows_) { if(this.oWindows_[win].IsModified) { return "`There are unsaved data on the page. `"; } } } }); // Document-wide DOM event manager var DocumentEventManager = Class.create({ initialize: function() { this.oSubscribers = { 'KeyUp': [], 'KeyDown': [], 'KeyPress': [], 'KeyPressDown': [] }; this.oTransparentControls={}; $(document).observe('keyup', this.processEvent.bind(this, 'KeyUp')); $(document).observe('keydown', this.processEvent.bind(this, 'KeyDown')); $(document).observe('keypress', this.processEvent.bind(this, 'KeyPress')); BindKeyDown(document, this.processEvent.bind(this, 'KeyPressDown')); }, processEvent: function(sType, event) { if(!(event.altKey || event.ctrlKey)) { var key = event.which || event.keyCode; if(!(key>=112 && key<=123)) switch(key) { // not F1-F12 case Event.KEY_BACKSPACE: case Event.KEY_DELETE: case Event.KEY_DOWN: case Event.KEY_END: case Event.KEY_ESC: case Event.KEY_HOME: case Event.KEY_INSERT: case Event.KEY_LEFT: case Event.KEY_PAGEDOWN: case Event.KEY_PAGEUP: case Event.KEY_RETURN: case Event.KEY_RIGHT: case Event.KEY_TAB: case Event.KEY_UP: break; default: return; } } var eKD = GetKeyCode(event); var evt = Event.extend(event || window.event); var aSubscribers=this.oSubscribers[sType]; // find nearest subscriber related to var emitter=evt.element(); var newSubscribers=[]; for (var i=0; i=0; --s) { node=$(aSubscribers[s]); while(node) { if(!node.subscriberIdx) node.subscriberIdx=[]; node.subscriberIdx.push(s); node=node.parentNode; } } var subscribersQueue=[]; node=emitter; while(node && node!=root) { if(node.subscriberIdx!=undefined) { for(s=node.subscriberIdx.length-1; s>=0; --s) { var q=0; for(; q 0 && "#" == url.charAt(0)) document.location.reload(); break; } }.defer(); }, this); this.Subscribe("WM_COOKIE", function(aevent){ var name = aevent.Data().name; var data = aevent.Data().data; var path = aevent.Data().path; if(!path) path="/"; document.cookie=name+"="+data+"; path="+path+";"; }, null); this.started_ = true; } }); var LabeledGrid = Class.create({ initialize: function(htmlid) { this.id = htmlid; this.frame = $(htmlid); this.collapse = $(htmlid + '_collapse'); this.contents = $(htmlid + '_contents'); this.label = $(htmlid + '_label'); this.collapsed = false; if (this.frame && this.collapse && (this.frame.readAttribute('collapsed')=="true" || this.frame.readAttribute('collapsed')=="yes")) { this.OnCollapse(); } if (this.collapse) this.collapse.observe('click', this.OnCollapse.bind(this)); }, OnCollapse: function(evt) { if (!this.collapsed) { this.contents.hide(); this.collapse.addClassName('LabeledGridExpand'); this.label.addClassName('LabeledGridCollapsed'); this.collapsed = true; } else { this.contents.show(); this.collapse.removeClassName('LabeledGridExpand'); this.label.removeClassName('LabeledGridCollapsed'); this.collapsed = false; } // GWindowManager.OnResize(); if (evt) evt.stop(); } }); var CellResizer = Class.create({ initialize: function(htmlid) { this.id = htmlid; this.cell = $(htmlid); this.cell.JSControl = this; this.prnt = this.cell.offsetParent; this.stubleft = $(htmlid + '-rleftstub'); this.stubright = $(htmlid + '-rrightstub'); this.minWidth = String(this.cell.readAttribute('min-width') || this.MinWidthDefault || ''); this.maxWidth = String(this.cell.readAttribute('max-width') || ''); this.width = this.cell.offsetWidth; this.visible = true; var s = this.minWidth.replace(/%\s*$/, ''); if (s != this.minWidth) this.minWidthMode = '%'; this.minWidth = s.replace(/px$/, ''); var s = this.maxWidth.replace(/%\s*$/, ''); if (s != this.maxWidth) this.maxWidthMode = '%'; this.maxWidth = s.replace(/px$/, ''); var resizers = (this.cell.readAttribute('resize') || '').split(' '); for (var i = 0; i < resizers.length; ++i) { if (!resizers[i]) continue; if (resizers[i] == 'hidden') { this.visible = false; continue; } else if (resizers[i] == 'nohide') { this.nohide = true; continue; } $(htmlid + '-r' + resizers[i]).observe('mousedown', this.onMouseDown.bind(this, resizers[i])); var s = $(htmlid + '-r' + resizers[i] + 'stub'); if (s) s.observe('mousedown', this.onMouseDown.bind(this, resizers[i])); } this.cell.setStyle({width: '1px'}); this.validateWidth(); AControl.GetParentWindow(this.cell).RegisterResizeableChild( this.id ); this.dragUpHandler = this.onMouseUp.bind(this); this.dragMoveHandler = this.onMouseMove.bind(this); }, MinWidthDefault: 35, OnResize: function() { this.validateWidth(); }, validateWidth: function() { var minW = this.minWidth; var maxW = this.maxWidth; if (this.minWidthMode == '%') minW = minW * this.prnt.clientWidth / 100; if (this.maxWidthMode == '%') maxW = maxW * this.prnt.clientWidth / 100; this.visible = true; if (this.width <= minW) { this.width = minW; if (!this.nohide) this.visible = false; } else if (this.width > maxW) { this.width = maxW; } this.cell.setStyle({width: this.width + 'px' }); this.updateVisibility(); GWindowManager.OnResize(); }, updateVisibility: function() { if (this.visible) { this.cell.show(); if (this.stubleft) this.stubleft.hide(); if (this.stubright) this.stubright.hide(); } else { this.cell.hide(); if (this.stubleft) this.stubleft.show(); else if (this.stubright) this.stubright.show(); } }, onMouseUp: function(evt) { if (!evt.isLeftClick()) return; this.drag = undefined; $(document).stopObserving('mousemove', this.dragMoveHandler); $(document).stopObserving('mouseup', this.dragUpHandler); var w = AControl.GetParentWindow( this.cell ); var localId = this.cell.readAttribute('localid'); w.AddElementCustomization({ width: this.oldSize + 'px' }, localId, 'cell'); }, onMouseMove: function(evt) { var newX = evt.pointerX(); this.oldSize = this.oldSize + newX - this.dragX; if (this.drag == 'right' || this.drag == 'left') { this.width = this.oldSize; } this.validateWidth(); this.dragX = newX; }, onMouseDown: function(mode, evt) { if (!evt.isLeftClick()) return; evt.stop(); if (this.drag) return; this.oldSize = this.cell.offsetWidth; this.drag = mode; this.dragX = evt.pointerX(); $(document).observe('mouseup', this.dragUpHandler) $(document).observe('mousemove', this.dragMoveHandler); } }); //////////////////////////////////////////////////////// /// Global Definitions //////////////////////////////////////////////////////// var GWindowManager = new AWindowManager(); var GDocumentInstance = new DocumentInstance(); window.onbeforeunload = GWindowManager.OnBeforeUnload.bind(GWindowManager); if (typeof AEventHandler != "undefined") GDocumentInstance.start();