Подтвердить что ты не робот

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>
4b9b3361

Ответ 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.

Чтобы получить доступ к содержимому дочернего фрейма, необходимо вызвать политику одинакового происхождения.