Skip to content

Instantly share code, notes, and snippets.

@jkiv
Last active December 29, 2015 23:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkiv/a0423c254cec26af1758 to your computer and use it in GitHub Desktop.
Save jkiv/a0423c254cec26af1758 to your computer and use it in GitHub Desktop.
FrameLocator

FrameLocator

Finds needle iframes in haystacks of iframes.

// Find all windows whose name matches 'foo', relative to [window]
FrameLocator.findWindowsByName(window, 'foo');
// -> array of Windows

// Find all windows whose name matches 'bar', relative to [window]
FrameLocator.findChildByName(window, 'bar');
// -> array of Windows

// Find top-most frame within same domain
FrameLocator.getSafeTop();
var FrameLocator = FrameLocator || {};
(function(module) {
var TAG_TYPE = 'iframe';
// Returns the root window that is within the same domain of the given [window_].
module.getSafeTop = function(window_) {
var child_ = window_;
var parent_ = window_;
while(true) {
try {
// Attempt to get ancestor (might be cross-domain)
parent_ = module.getParent(child_);
}
catch(e) {
// TODO catch a certain exception?
console.warn(e);
break;
}
// Have we reached the top?
if (parent_ === null || parent_ === child_) {
break;
}
// Next.
child_ = parent_;
}
return parent_;
}
// Returns all children of a given [window_].
module.getChildren = function(window_) {
var children = [];
var initialChildren = module.getImmediateChildren(window_);
initialChildren.forEach(function(child) {
// Add the immediate child
children.push(child);
// Recursively add the grand(+)children
module.getChildren(child).forEach(function(grandchild){
children.push(grandchild);
});
})
return children;
}
// Returns first level of children of a given [window_].
module.getImmediateChildren = function(window_) {
var elementCollection = window_.document.getElementsByTagName(TAG_TYPE);
var children = [];
// Map HTMLCollection items to array of window objects
for(var n = 0; n < elementCollection.length; n++) {
children.push(elementCollection.item(n).contentWindow);
}
return children;
}
// Returns the immediate parent of the [window_].
module.getParent = function(window_) {
var parent_ = window_.parent;
if (parent_ === undefined) {
parent_ = null; // use `null` over `undefined`
}
return parent_;
}
// Returns all the siblings of the [window_].
module.getSiblings = function(window_) {
var parent_ = module.getParent(window_);
if (parent_) {
return module.getImmediateChildren(parent_);
}
else {
return [];
}
}
// Returns the child of a given [name] with respect to the provided [window_]
module.findChildrenByName = function(window_, name) {
var children = module.getChildren(window_);
var name_lc = name.toLowerCase(); // make search case insensitive
var matches = [];
for(var n = 0; n < children.length; n++) {
var child = children[n];
if (child.name.toLowerCase() === name_lc) {
matches.push(child);
}
}
return matches;
}
// Returns the windows of a given [name] with respect to the safe top of given [window_].
module.findWindowsByName = function(window_, name) {
var top_ = module.getSafeTop(window_);
return module.findChildrenByName(top_, name);
}
// Enumerate tree starting from [window_] and print it out all pretty-like
module.printTree = function(window_, level) {
level = level || 0;
// Construct indentation
var indent = "";
for(var n = 0; n < level; n++) {
indent = indent + " ";
}
// Print this node
console.log(indent + (window_.name || window_.location));
// Print children recursively
var children = module.getImmediateChildren(window_);
children.forEach(function(child) {
module.printTree(child, level + 1);
});
}
})(FrameLocator);
var FrameLocator=FrameLocator||{};!function(e){var n="iframe";e.getSafeTop=function(n){for(var r=n,t=n;;){try{t=e.getParent(r)}catch(a){console.warn(a);break}if(null===t||t===r)break;r=t}return t},e.getChildren=function(n){var r=[],t=e.getImmediateChildren(n);return t.forEach(function(n){r.push(n),e.getChildren(n).forEach(function(e){r.push(e)})}),r},e.getImmediateChildren=function(e){for(var r=e.document.getElementsByTagName(n),t=[],a=0;a<r.length;a++)t.push(r.item(a).contentWindow);return t},e.getParent=function(e){var n=e.parent;return void 0===n&&(n=null),n},e.getSiblings=function(n){var r=e.getParent(n);return r?e.getImmediateChildren(r):[]},e.findChildrenByName=function(n,r){for(var t=e.getChildren(n),a=r.toLowerCase(),o=[],i=0;i<t.length;i++){var f=t[i];f.name.toLowerCase()===a&&o.push(f)}return o},e.findWindowsByName=function(n,r){var t=e.getSafeTop(n);return e.findChildrenByName(t,r)},e.printTree=function(n,r){r=r||0;for(var t="",a=0;r>a;a++)t+=" ";console.log(t+(n.name||n.location));var o=e.getImmediateChildren(n);o.forEach(function(n){e.printTree(n,r+1)})}}(FrameLocator);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment