function FrameLocator() { };
FrameLocator.prototype.getRootLocator = function() {
return this.getRootFrame().frameLocator;
};
FrameLocator.prototype.getRootFrame = function() {
return eval(this.getPath2RootFrame());
};
FrameLocator.prototype.getFramesetLayer = function() {
/* at main screen the frameset layer is .frameset window, otherwise (in popups) the root frame is gotten */ var rootFrame = this.getRootFrame();
return rootFrame.frameset || rootFrame;
};
/**
* gets the path from the selected frame to the top frame under control of EW.
* @return path to the root frame, e.g. <i>&quot;parent.parent&quot;</i>
*/
FrameLocator.prototype.getPath2RootFrame = function() {
var chain = ["window"];
var frameobj = window;
var index = -1;
while(true) {
try {
frameobj.frameLocator;
} catch(e) {
// permission denied while accessing to frameobj.frameLocator. Stop the cycle as the selected window belongs to another domain
break;
}
if(frameobj.frameLocator) {
index = chain.length;
}
if(frameobj == frameobj.top) break;
frameobj = frameobj.parent;
chain.push("parent");
}
chain = chain.splice(0, index);
if(chain.length > 1) chain.shift();
return chain.join(".");
};
FrameLocator.prototype.getUserInfoFrame = function() {
return this.getFramesetLayer().top_info;
};
FrameLocator.prototype.getLeftPanelFrame = function() {
return this.getFramesetLayer().left_panel;
};
FrameLocator.prototype.getLeftPanelContentFrame = function() {
var leftPanelFrame = this.getLeftPanelFrame();
return leftPanelFrame ? leftPanelFrame.lp_center : null;
};
FrameLocator.prototype.getMainTabsFrame = function() {
return this.getFramesetLayer().top_tabs;
};
FrameLocator.prototype.getMainContentFrame = function() {
return this.getFramesetLayer().main_content;
};
FrameLocator.prototype.getMainHiddenFrame = function() {
return this.getRootFrame().main_hidden_frame;
};
FrameLocator.prototype.getPendingEventsFrame = function() {
return this.getRootFrame().main_pending_events_frame;
}
FrameLocator.prototype.getMessagingFrame = function() {
return this.getFramesetLayer().top_banner;
};
FrameLocator.prototype.getWindow = function() {
return window;
};
FrameLocator.prototype.display = function() {
var rootManager = Manager.getRootManager();
rootManager.expandElement(rootManager.getElement(this.getWindow().name));
};
FrameLocator.prototype.collapse = function() {
};
/**
* analyzes that frame can be overloaded with other content which cannot be unload at the moment
* @param optionalFrame window-object to analyze, can be missed. Then current frame is checked. Null passed to the method
* makes it treat like the frame is being overloaded
*/
FrameLocator.prototype.isBusy = function(optionalFrame) {
if(arguments.length > 0 && (optionalFrame == null || optionalFrame.document == null)) return false;
var busy;
try {
var busyInputs = (optionalFrame || this.getWindow()).document.getElementsByName("busy");
busy = busyInputs.length > 0 && busyInputs[0].value == "true";
} catch(e) {
busy = false;
}
return busy;
};
/**
* gets the shortest path from start frame till end one
* @param start window object from
* @param finsh window object to
* @return path from <code>start</code> to <code>finsh</code>, e.g. <i>&quot;parent.parent.main_content&quot;</i>
*/
FrameLocator.prototype.getShortPath = function(start, finsh) {
var path2start = this.getPath(start).split(".");
var path2finsh = this.getPath(finsh).split(".");
if(path2start[0] == "window") path2start.shift();
if(path2finsh[0] == "window") path2finsh.shift();
while(path2start.length > 0 && path2finsh.length > 0 && path2start[0] == path2finsh[0]) {
path2start.shift();
path2finsh.shift();
}
for(var i = 0; i < path2start.length; i++) {
path2finsh.unshift("parent");
}
if(path2finsh.length == 0) path2finsh.push("window");
return path2finsh.join(".");
};
FrameLocator.prototype.getPath = function(frameobj) {
frameobj = frameobj || this.getWindow();
var chain = [];
var rootFrame = this.getRootFrame();
while(frameobj != rootFrame) {
chain.push(frameobj.name);
frameobj = frameobj.parent;
}
if(chain.length == 0) {
chain.push("window");
}
chain.reverse();
return chain.join(".");
};
/** instance of the object is creates one per frame */ var frameLocator = new FrameLocator();
function FrameController() {
/** currently minimized frames, array of frame names */
this.minimized = []; // each array item is {"name":..,"title":...} filled out only in FrameController instance in the FRAMESET document
/** frame controller event listeners */
this.listeners = {"onminimize":[], "onrestore":[]}; // filled out only in FrameController instance in the FRAMESET document
};
/**
* hide away the panel from vision. Public.
* @param frame optional. The node of HTML FRAME element. You need to pass it when switch it being in the frameset document.
* if the method is called to minimize the current frame the argument is missing.
*/
FrameController.prototype.minimize = function(frame) {
if(arguments.length > 0) {
if(!frame) return; /* ignore it since the reference to frame is broken */
var attrName = this.getAttrName(frame);
var frameIndex = this.getFrameIndex(frame);
var frameset = this.getFrameset(frame);
var sizes = (frameset.getAttribute(attrName) || "").split(",");
var prevSize = sizes[frameIndex] || "*";
if(document.documentMode == 8 && !isNaN(prevSize)) { var offsetName = attrName == "cols" ? "offsetWidth" : "offsetHeight";
if(prevSize > frame.parentNode[offsetName]) prevSize = frame[offsetName];
}
frame.setAttribute("previousSize", prevSize);
sizes[frameIndex] = "0";
this.addMinimized(frame.name, frame.title);
frameset.setAttribute(attrName, sizes.join(","));
this.onminimize(frame.name, frame.title);
this.applyResize(frameset, null, {"verticalAlign": this.isAutoHeight(frameset), "horizontalAlign": this.isAutoWidth(frameset)});
} else {
this.getParentController().minimize(this.getFrameElement());
}
};
/**
* adds a frame item to collection of hidden frames. Private
* @param name of the HTML FRAME element
* @param title is the frame title
*/
FrameController.prototype.addMinimized = function(name, title) {
for(var i = 0; i < this.minimized.length; i++) {
if(this.minimized[i].name == name) return;
}
var newItem = new Object();
newItem.name = name;
newItem.title = title;
function sortFn(a, b) {
return a.title > b.title ? 1 : a.title < b.title ? -1 : 0
}
this.minimized.push(newItem);
this.minimized.sort(sortFn);
};
/**
* checks if the frame is currently minimized
* @param frame HTML FRAME node, required if frameController is the one initialized in the frameset document,
* otherwise it has to be missed. */
FrameController.prototype.isMinimized = function(frame) {
if(arguments.length > 0) {
for(var i = 0; i < this.minimized.length; i++)
if(this.minimized[i].name == frame.name)
return true;
return false;
} else {
return this.getParentController().isMinimized(this.getFrameElement());
}
};
/**
* removes the frame item to collection of hidden frames. Private
* @param name is the frame name
*/
FrameController.prototype.removeMinimized = function(name) {
for(var i = 0; i < this.minimized.length; i++)
if(this.minimized[i].name == name)
this.minimized.splice(i, 1);
};
/**
* switches ON the frame. Public.
* @param frame optional. The node of HTML FRAME element. You need to pass it when switch it being in the frameset document.
* if the method is called to minimize the current frame the argument is missing.
*/
FrameController.prototype.restore = function(frame) {
if(arguments.length > 0) {
var attrName = this.getAttrName(frame);
var frameIndex = this.getFrameIndex(frame);
var frameset = this.getFrameset(frame);
var sizes = (frameset.getAttribute(attrName) || "").split(",");
sizes[frameIndex] = frame.getAttribute("previousSize");
frameset.setAttribute(attrName, sizes.join(","));
this.removeMinimized(frame.name);
this.adjust(frame);
this.onrestore(frame.name, frame.title);
} else {
this.getParentController().restore(this.getFrameElement());
}
};
/**
* gets the parent FRAME/IFRAME element for this window. If parent window located at another domain this method returns null.
* @return the parent HTML FRAME/IFRAME element
*/
FrameController.prototype.getFrameElement = function() {
var fe;
try {
fe = frameElement;
} catch(e) { /* the parent document is in another domain */
fe = null;
}
return fe;
};
/**
* This private method gets controller from the EW root frame. If parent window located at another domain it returns null.
* @return controller
*/
FrameController.prototype.getParentController = function() {
var pc;
try {
pc = parent.frameController;
} catch(e) { /* the parent document is in another domain */
pc = null;
}
return pc;
};
/**
* gets the index of the frame in the collection. Private
* @param frame required. The selected HTML FRAME element
*/
FrameController.prototype.getFrameIndex = function(frame) {
var children = this.getFrameset(frame).childNodes;
var j = 0;
for(var i = 0; i < children.length; i++) {
var child = children[i];
if(child == frame) return j;
if(child.nodeName == "FRAME" || child.nodeName == "FRAMESET") {
j++;
}
}
return -1;
};
/**
* It gets an appropriate HTML FRAMESET attribute name to change frame's display. Private
 * @param frame required. The selected frame
 */
FrameController.prototype.getAttrName = function(frame) {
  return this.isVerticalLayout(frame) ? "rows" : "cols";
};

/**
 * It gets the parent HTML FRAMESET element. Private
 * @param frame required. HTML FRAMESET|FRAME child element whose parent we need
 * @return frameset parent, can be null.
 */
FrameController.prototype.getFrameset = function(frame) {
  var parentNode = frame.parentNode;
  if(parentNode) {
    if(parentNode.nodeName != "FRAMESET") throw parentNode.nodeName + " but FRAMESET is expected";
  }  
  return parentNode;
};

/**
 * analyzes that frame can be overloaded with other content which cannot be unload at the moment. Public.
 * @param frame HTML FRAME object to analyze, can be missed. Then current frame is checked. Null passed to the method
 * makes it treat like the frame is being overloaded
 */
FrameController.prototype.isBusy = function(frame) {
  var busy;
  if(arguments.length > 0) {
    if(frame == null || frame.document == null) return false;

    try {
      var busyInputs = (frame.contentDocument || frame.contentWindow.document).getElementsByName("busy");
      busy = busyInputs.length > 0 && busyInputs[0].value == "true";
    } catch(e) {
      busy = false;
    }
  } else {
    busy = this.getParentController().isBusy(this.getFrameElement());
  }
  return busy;
};

/**
 * checks if the frameset provides a vertical layout. Private
 * @param frame required. The selected frame.
 * @return true if the layout provided by the frameset is vertical or false otherwise
 */
FrameController.prototype.isVerticalLayout = function(frame) {
  var frameset = this.getFrameset(frame);
  return frameset.rows && frameset.rows.length > 0;

// gof: it doesn't work if only one child frame is not minimized
// var children = this.getFrameset(frame).childNodes;
//
// var vOffsets = [];
//
// for(var i = 0; i < children.length; i++) {
// var child = children[i];
// var nodeName = child.nodeName;
//
// if(nodeName == "FRAME" || nodeName == "FRAMESET") {
// vOffsets.push(child.offsetTop);
// }
// }
// return vOffsets.length > 1 && vOffsets[0] < vOffsets[1];
};
/**
* adjust the frame for size if needed. Public
* @param frame optional; FRAME DOM node if this method is called from the window of the frame the parameter missed
*/
FrameController.prototype.adjust = function(frame) {
if(this.isFrame(frame)) {
if(this.isMinimized(frame)) return;
var isVertical = this.isVerticalLayout(frame);
if((isVertical && this.isAutoHeight(frame)) || (!isVertical && this.isAutoWidth(frame))) {
var attrName = this.getAttrName(frame);
var frameIndex = this.getFrameIndex(frame);
var frameset = this.getFrameset(frame);
var sizes = (frameset.getAttribute(attrName) || "").split(",");
sizes[frameIndex] = (isVertical ? this.getBodyOffsetHeight(frame) : this.getBodyOffsetWidth(frame)) + "px";
frameset.setAttribute(attrName, sizes.join(","));
this.applyResize(frameset, null, {"verticalAlign": this.isAutoHeight(frameset), "horizontalAlign": this.isAutoWidth(frameset)});
}
} else {
this.getParentController().adjust(this.getFrameElement());
}
};
/**
* Propogatets resize by framesets
* @param frameset Frameset that must be resized
* @param child Size object of the child frameset who initiated parent's resize
* @param directions {verticalAlign:boolean,horizontalAlign:boolean} that sais what dimensions should be applied
*/
FrameController.prototype.applyResize = function(frameset, child, directions) {
  if (this.isAutoHeight(frameset) || this.isAutoWidth(frameset)) {
    var parentFrameset = this.getFrameset(frameset);
    if (parentFrameset == null) return;

    var frameSize = this.getSize(frameset, child);
    var dirty = false;

    if (directions.verticalAlign && this.isVerticalLayout(frameset)) {
      // Can apply resize vertically
      this.setFramesetSize(parentFrameset, "rows", this.getFrameIndex(frameset), frameSize.height);
      dirty = true;  
    }

    if (directions.horizontalAlign && !this.isVerticalLayout(frameset)) {
      // Can apply resize horizontally
      this.setFramesetSize(parentFrameset, "cols", this.getFrameIndex(frameset), frameSize.width);
      dirty = true;
    }    

    this.applyResize(parentFrameset, frameSize,
      {"verticalAlign": directions.verticalAlign && this.isAutoHeight(parentFrameset),
       "horizontalAlign": directions.horizontalAlign && this.isAutoWidth(parentFrameset)})
  }
}

/**
* Sets size for one of it's childs taht is not '*' size (todo: for all sizes)
* @param frameset Frameset to apply size
* @param attrName name of size (rows or cols)
* @param childIndex Index of child to apply
* @param size size
*/
FrameController.prototype.setFramesetSize = function(frameset, attrName, childIndex, size) {
var sizes = (frameset.getAttribute(attrName) || "").split(",");
sizes[childIndex] = sizes[childIndex] != "*" ? size + "px" : "*";
frameset.setAttribute(attrName, sizes.join(","));
}
/**
* Calculates actual size of frameset content excluding fake frames
* @param frameset Frameset to calculate
* @param except Child size object to be excluded, if any * @return size object {frameset, width, height}
*/
FrameController.prototype.getSize = function(frameset, except) {
var size = {"frameset":frameset, "width":0, "height":0};
if (this.isFrameset(frameset)) {
var childs = frameset.childNodes;
var child; for (var i=0; i<childs.length; i++) {
child = childs[i];
if(child.nodeName == "FRAME" && !this.isFake(child) && !this.isMinimized(child)) {
if (except && child == except.frameset) {
this.accumulateSize(size, except, this.isVerticalLayout(child));
} else {
this.accumulateSize(size,
// gof: Don't like this code but have no idea how to implement with onLoad not working
          this.getFrameSize(child),
          this.isVerticalLayout(child));
        }
      } else if (child.nodeName == "FRAMESET") {
        this.accumulateSize(size, this.getSize(child), this.isVerticalLayout(child));
      }
    }  
  }

  return size;
}

/**
* Returns frame content size. If it's 0, assumes that frame content was not loaded yet and uses frames absolute dimensions * @param frame
*/
FrameController.prototype.getFrameSize = function(frame) {
var result = {"width" : frame.offsetWidth, "height" : frame.offsetHeight}
if (this.isAutoWidth(frame)) {
var w = this.getBodyOffsetWidth(frame);
if (w > 0) result.width = w; }
if (this.isAutoHeight(frame)) {
var h = this.getBodyOffsetHeight(frame);
if (h > 0) result.height = h; }
return result;
}
FrameController.prototype.accumulateSize = function(size, additionalSize, isVertical) {
if (isVertical) {
size.height += additionalSize.height;
size.width = Math.max(size.width, additionalSize.width);
} else {
size.width += additionalSize.width;
size.height = Math.max(size.height, additionalSize.height);
}
}
/**
* Detects is frame fake, i.e. shoud not be counted onsize calculation * @param frame
*/
FrameController.prototype.isFake = function(frame) {
if (this.isFrame(frame)) {
return frame.getAttribute("fake") != null; }
}
/**
* Detects if passed object is FRAME one * @param frame
*/
FrameController.prototype.isFrame = function(frame) {
if(frame) {
if(frame.nodeName != "FRAME") throw "Wrong context used";
return true;
}
return false;
}
/**
* Detects if passed object is FRAMESET one * @param frame
*/
FrameController.prototype.isFrameset = function(frameset) {
if(frameset) {
if(frameset.nodeName != "FRAMESET") throw "Wrong frameset context used";
return true;
}
return false;
}
/** checks if the frame size should be adjusted on loading content */
FrameController.prototype.isAutoWidth = function(frame) { return frame.getAttribute("autowidth") != null }
/** checks if the frame size should be adjusted on loading content */
FrameController.prototype.isAutoHeight = function(frame) { return frame.getAttribute("autoheight") != null }
/** this is called only for root frame on child frame minimize event */
FrameController.prototype.onminimize = function(frameName, frameTitle) {
var listeners = this.listeners.onminimize;
for(var i = 0; i < listeners.length; i++) {
eval(listeners[i] + "(frameName, frameTitle)");
}
};
/** this is called only for root frame on child frame minimize event */
FrameController.prototype.onrestore = function(frameName, frameTitle) {
var listeners = this.listeners.onrestore;
for(var i = 0; i < listeners.length; i++) {
eval(listeners[i] + "(frameName, frameTitle)");
}
};
/** adds an event listener to the controller */
FrameController.prototype.addEventListener = function(eventName, listener) {
var lrs = this.listeners[eventName];
for(var i = 0; i < lrs.length; i++) {
if(lrs[i] == listener) return;
}
lrs.push(listener);
};
var frameController = new FrameController();
if(frameController.getFrameElement() && (frameController.isAutoWidth(frameController.getFrameElement()) || frameController.isAutoHeight(frameController.getFrameElement()))) {
try {
window.addEventListener("load", function() { frameController.adjust() }, false);
} catch(e) {
window.attachEvent("onload", function() { frameController.adjust() });
}
};
FrameController.prototype.getContentDocument = function(frame) {
return frame.contentDocument || frame.contentWindow.document;
};
FrameController.prototype.getBodyOffsetWidth = function(frame) {
var doc = this.getContentDocument(frame);
var wrapper = doc.getElementById("$wrapper");
if(wrapper) {
return wrapper.offsetWidth;
} else {
return doc.body.offsetWidth;
}
}
FrameController.prototype.getBodyOffsetHeight = function(frame) {
var doc = this.getContentDocument(frame);
var wrapper = doc.getElementById("$wrapper");
if(wrapper) {
return wrapper.offsetHeight;
} else {
var maxHeight;
var body = doc.body;
if (body == null) return 0; // not loaded yet
if(false && true) {
maxHeight = body.offsetHeight;
} else {
maxHeight = 0;
for(var i = 0; i < body.childNodes.length; i++) {
var child = body.childNodes[i];
if(child.nodeName != "#text")
maxHeight = Math.max(maxHeight, child.offsetTop + child.offsetHeight);
}
}
return maxHeight;
} };
