Java Script, Сложность получения списка всех вложенных фреймов на странице
Здравствуйте, мне нужно получить список всех фреймов для моего GreaseMonkey script, но на самом деле я предполагаю, что это общий вопрос Javascript. Было бы здорово, если бы я смог добраться до каждого кадра, который вложен в страницу. До сих пор мне не удалось получить количество кадров, вложенных в основные рамки документа.
Страница Я имею дело с состоянием frameset, которое многоуровневое, а фреймы содержат другие фреймы. Мне удалось получить информацию о кадрах верхнего уровня основного набора фреймов документов (в коде уровень 1), но на этом уровне я получаю информацию о том, что количество кадров для этих фреймов равно 0, что неверно.
Я придумал следующий код
$(document).ready(function(){
var frames = window.frames;
var i,j;
var reportText = "level 0 > " + frames.length +"\r\n";
for (i = 0; i < frames.length; i++) {
var frames2 = frames[i].frames;
reportText += "level 1 - " + i + " > " + frames[i].name + " - " + frames2.length +"\r\n";
for (j = 0; j < frames2.length; j++) {
var frames3 = frames2[j].frames;
reportText += "level 2 - " + i + " - " + j + " > " + frames2[j].name + " - " + frames3.length +"\r\n";
}
}
alert(reportText);});
Значит уровень 0, который на самом деле является номером основного документа и уровнем 1 именами или основными фреймами документа - эти данные сообщаются правильно, но не количество кадров каждого уровень 1. И я хочу знать, если это потому, что мой код получил ошибки или, может быть, потому, что подкадры полностью не загружены.
Я попытался вызвать свой код с помощью ярлыка на клавиатуре, ведь все будет выглядеть полностью загруженным, но вот еще одна проблема, похоже, что следующий код, похоже, не работает со страницей, состоящей только из фреймов
(function(){
document.addEventListener('keydown', function(e) {
if (e.keyCode == 72 && !e.shiftKey && !e.ctrlKey && e.altKey && !e.metaKey) {
//...my previous code inside document.ready...
}
}, false);})();
Лучше всего было бы, если бы код автоматически расчесывал все кадры и подкадры, но с его текущей формой (где каждый уровень получил собственный цикл) тоже хорош.
Проблема с невозможностью использования сочетания клавиш является вторичной. Главное - получать правильные подсчеты кадров внутри фреймов основного документа и далее.
EDIT: Пример вывода и Моя тестовая страница с вложенным набором фреймов
Выход
уровень 0 > 3
уровень 1 - 0 > main1 - 0
уровень 1 - 1 > main2 - 0
уровень 1 - 2 > main3 - 0
тестовая страница с вложенным набором фреймов
frame0.htm
<!DOCTYPE html>
<html>
<frameset cols="25%,*,25%">
<frame id="frmain1" name="main1" src="frame0_1.htm">
<frame id="frmain2" name="main2" src="frame0_2.htm">
<frame id="frmain3" name="main3" src="frame0_3.htm">
</frameset>
</html>
frame0_1.htm
<!DOCTYPE html>
<html>
<frameset rows="25%,*">
<frame id="frsub11" name="sub11" src="frame0_1_1.htm">
<frame id="frsub12" name="sub12" src="frame0_1_2.htm">
</frameset>
</html>
frame0_1_1.htm
<!DOCTYPE html>
<html>
<body style="background: darkorange;">
</body>
</html>
frame0_1_2.htm
<!DOCTYPE html>
<html>
<body style="background: lightyellow;">
</body>
</html>
frame0_2.htm
<!DOCTYPE html>
<html>
<frameset rows="25%,*,25%">
<frame id="frsub21" name="sub21" src="frame0_2_1.htm">
<frame id="frsub22" name="sub22" src="frame0_2_2.htm">
<frame id="frsub23" name="sub23" src="frame0_2_3.htm">
</frameset>
</html>
frame0_2_1.htm
<!DOCTYPE html>
<html>
<body style="background: skyblue;">
</body>
</html>
frame0_2_2.htm
<!DOCTYPE html>
<html>
<body style="background: cornflowerblue;">
</body>
</html>
frame0_2_3.htm
<!DOCTYPE html>
<html>
<body style="background: slateblue;">
</body>
</html>
frame0_3.htm
<!DOCTYPE html>
<html>
<frameset rows="25%,*">
<frame id="frsub31" name="sub31" src="frame0_3_1.htm">
<frame id="frsub32" name="sub32" src="frame0_3_2.htm">
</frameset>
</html>
frame0_3_1.htm
<!DOCTYPE html>
<html>
<body style="background: darkgreen;">
</body>
</html>
frame0_3_2.htm
<!DOCTYPE html>
<html>
<body style="background: lightgreen;">
<a id="test" href="#" onclick="location.href='http://www.google.com'; return false;">testlink</a>
</body>
</html>
Ответы
Ответ 1
Проблема - это событие, на которое вы это называете. $(document).ready()
запускается при загрузке текущей DOM. Таким образом, он запускается, когда загружаются 3 основных кадра. Но в этот момент эти кадры еще не загрузили их iframes
. Изменив событие на window.onload, вы должны получить ожидаемый результат. Вот так:
$(window).load(function(){
...
или
window.onload = function(){
...
См. window.onload: https://developer.mozilla.org/en/docs/Web/API/GlobalEventHandlers/onload
Событие загрузки запускается в конце процесса загрузки документа. В этот пункт, все объекты в документе находятся в DOM, и все изображения, сценарии, ссылки и подкадры завершили загрузку.
См. https://api.jquery.com/ready/
Ответ 2
Решение рабочего кода
Используйте рекурсивную функцию и событие window
load
, например (работает в последних версиях Chrome, FireFox и Edge, не тестировало других. Возможно, работает и в IE5 +).
Используйте этот код на верхнем уровне frameset
, frame0.htm:
<!DOCTYPE HTML Frameset DTD>
<html>
<head>
<script>
window.onload = function()
{
var allFrames = [];
function recursFrames(context)
{
for(var i = 0; i < context.frames.length; i++)
{
console.log(context.frames[i].name + " -- " + context.frames[i].location.href);
allFrames.push(context.frames[i]);
recursFrames(context.frames[i]);
}
}
recursFrames(window);
console.log("Frames count: " + allFrames.length);
}
</script>
</head>
<frameset cols="25%,*,25%">
<frame id="frmain1" name="main1" src="frame0_1.htm">
<frame id="frmain2" name="main2" src="frame0_2.htm">
<frame id="frmain3" name="main3" src="frame0_3.htm">
</frameset>
</html>
Это записывает на консоль, чтобы показать вам, что происходит, но, конечно же, вы можете делать все, что хотите, с помощью этой информации. Он создает плоский список (массив) всех дочерних фреймов, но вы можете структурировать его иерархически, если хотите, или что-то еще.
Напоминание HTML 5
Вы используете HTML5 DOCTYPE
, но frameset
не поддерживается HTML5. Но браузер должен решить, когда перестать поддерживать это, и многие из них по-прежнему делают это. Я рекомендую вам прекратить использование frameset
ASAP. Используйте iframe
вместо этого, если вам нужно поведение, подобное кадру (разные окна и документы).
Ответ 3
frameset не поддерживается в html5.
Пожалуйста, просмотрите следующее демо: демонстрационный пример фреймов. Я изменил файлы htm. Идея состоит в том, чтобы прослушивать событие onload frameset и получать доступ к его содержимому после запуска события onlnoad.
Чтобы получить доступ к содержимому дочернего фрейма, необходимо вызвать политику одинакового происхождения.