Вход

Просмотр полной версии : Uncaught TypeError: Cannot call method 'getElementById' of undefined


Socgamer
10.01.2012, 12:53
Здравствуйте, дорогие прогеры!

Случилась такая ситуация: Есть некая ссылка, которая закрывать / скрывает один див по нажатию на ссылку. В IE все корректно работает, в мозилле и хроме работает только в одном направлении то есть - только скрывает див. По умолчанию див открыт.

p.s. смотрел откладчик Хрома, пишет следующее:
Uncaught TypeError: Cannot call method 'getElementById' of undefined

Сам код:

<td><nobr><a class="normal" href="#" onclick="ChangeTree(); return false;"><img id="chek" src="http://is/pict/skrmenu.GIF" align='left' /><span id="checktext"></span></nobr></a></td>


<script>
var TreeShow = true;
var OptsShow = false;
var TreeOn = "&nbsp;&nbsp;";//Показать меню
var TreeOf = "&nbsp;&nbsp;"; //Скрыть меню

function ChangeTree()
{
if (TreeShow) {
chek.src = "http://is/pict/pokmenu.GIF";
checktext.innerHTML = TreeOn;
hidemenu();
} else {
chek.src = "http://is/pict/skrmenu.GIF";
checktext.innerHTML = TreeOf;
showmenu();
}
TreeShow = !TreeShow;
}
</script>



// метод показа дерева навигации
function showmenu() {
top.document.getElementsByTagName("frameset")[1].cols=frame_cols;
top.document.getElementById("outterframe").frameBorder = "no";
top.document.getElementById("outterframe").document.getElementById("frames2").frameBorder = "no";
top.document.getElementById("outterframe").document.getElementById("frames2").Border=5;
top.document.getElementById("outterframe").document.getElementById("frames2").frameSpacing=5;
top.frames['mainWindow'].focus(); // передаем фокус основному окну
}

// метод скрытия дерева навигации
function hidemenu() {
frame_cols=top.document.getElementsByTagName("frameset")[1].cols;
top.document.getElementsByTagName("frameset")[1].cols="2,*";
top.document.getElementById("outterframe").document.getElementById("frames2").frameBorder = "no";
top.document.getElementById("outterframe").document.getElementById("frames2").Border=0;
top.document.getElementById("outterframe").document.getElementById("frames2").frameSpacing=0;
// top.document.getElementById("outterframe").document.getElementById("frames2").style.visibility = 'hidden';
top.frames['mainWindow'].focus(); // передаем фокус основному окну
}



Заранее, всем откликнувшимся спасибо!

poorking
10.01.2012, 14:00
Подсказка. Свойство document находится в объекте window, у элементов фреймов оно называется contentWindow.

iframe.contentWindow.document

PS не делайте выборки одни и те же несколько раз подряд, нашли элемент, сохранили ссылку и пользуйтесь, да и вообще

Socgamer
10.01.2012, 14:12
poorking, пожалуйста ткните как это сделать, совсем туплю с фреймами...

:thanks: *низкий вам поклон*

poorking
10.01.2012, 14:16
Если я правильно понял что #outterframe это собсна фрейм

top.document.getElementById("outterframe").contentWindow.document.getElementById("frames2")

Судя по всему вы в окне ходите взять фрейм и внутри него найти другой фрейм. Да вы не торопитесь, сайт этот прочитайте: статьи, учебник ))

Socgamer
10.01.2012, 14:20
poorking, х) правильно понимаете )

Я не тороплюсь... :) На сайте я сижу не первый раз, просто регистрироваться было когда лень сейчас же возникла острая необходимость... Спасибо!

Socgamer
10.01.2012, 14:33
Хм не работает выше указанный код, теперь и в IE не робит)

// метод показа дерева навигации
function showmenu() {
top.document.getElementsByTagName("frameset")[1].cols=frame_cols;
top.document.getElementById("outterframe").frameBorder = "YES";
top.document.getElementById("outterframe").contentWindow.document.getElementById("frames2").frameBorder = "no";
top.document.getElementById("outterframe").contentWindow.document.getElementById("frames2").Border=0;
top.document.getElementById("outterframe").contentWindow.document.getElementById("frames2").frameSpacing=0;
top.frames['mainWindow'].focus(); // передаем фокус основному окну
}

// метод скрытия дерева навигации
function hidemenu() {
frame_cols=top.document.getElementsByTagName("frameset")[1].cols;
top.document.getElementsByTagName("frameset")[1].cols="2,*";
top.document.getElementById("outterframe").document.getElementById("frames2").frameBorder = "no";
top.document.getElementById("outterframe").document.getElementById("frames2").Border=0;
top.document.getElementById("outterframe").document.getElementById("frames2").frameSpacing=0;
// top.document.getElementById("outterframe").document.getElementById("frames2").style.visibility = 'hidden';
top.frames['mainWindow'].focus(); // передаем фокус основному окну
}

poorking
10.01.2012, 14:52
Ну много ж чего быть может, вы отладчиком пользоваться учитесь
Uncaught TypeError: Cannot call method 'getElementById' of undefined - значит что объект, в контексте которого вы вызываете метод "getElementById" есть undefined, может документ фрейма еще не прогружен, может еще что, вы б рабочий пример сделали тут, виднее было б, к тому же в методе hidemenu вы все равно ищете document прямо в элементе фрейма. Посмотрите на результат top.document.getElementById("outterframe"). В отладчике же можно посмотреть в любую переменную. К тому же в методе hidemenu вы все равно ищете document не в window а в самом элементе. И сделайте наконец

var outterFrame = top.document.getElementById("outterframe"), innerFrame = outterFrame.contentWindow.document.getElementById("frames2")

Так ваш код и гибче и производительнее и читабельнее и удобнее для отладки будет. И проследите чтобы на момент поиска одного фрейма в другом, тот другой загрузился, если нет уверенности этом, то повесьте на outterFrame.contentWindow слушатель onload, а в его обработчике уже и делайте выборку #frame2

Socgamer
11.01.2012, 11:08
poorking, спасибо! Увы, сюда рабочий вариант кинуть не могу... из-за того что там тьма файлов и адреса придется ставить относительные и не думаю что некоторые файлы я буду в состоянии исправить... Извините.

Итак, вот что я сделал:

// метод показа дерева навигации
function showmenu() {
top.document.getElementsByTagName("frameset")[1].cols=frame_cols;

top.frames['mainWindow'].focus(); // передаем фокус основному окну
}

// метод скрытия дерева навигации
function hidemenu() {
frame_cols=top.document.getElementsByTagName("frameset")[1].cols;
top.document.getElementsByTagName("frameset")[1].cols="2,*";

top.frames['mainWindow'].focus(); // передаем фокус основному окну
}

в итоге скрыть / открыть работает отлично в Chrome, IE 8, Mozilla. Однако Опера (у меня стоит версия 10.01) не работает. По умолчанию фрейм открыт, по нажатию как и положено он прячется (скрывается), но более не открывается. По сути отчасти вернулась проблема...

Как же я благодарен вам профессор - poorking, спасибо :thanks: ! Узнал кое что новое и искренне надеюсь мы с вами добьем эту "казявку"! ^__^

poorking
11.01.2012, 12:07
А где остальной код? где вы проверяете ширину колонки фрейма с меню? Как в первом посте мудрите? смотрите на первый символ значения аттрибута cols фреймсета, если он равен "2" (как я понял это значение ширины "скрытого фрейма"), то скрыт, иначе открыт
var toggleMenu = (function () {

// Ширина фрейма меню
var MENU_WIDTH = 200;

// Статическая ссылка на фреймсет
var frame = top.document.getElementsByTagName("frameset")[0];

return function toggleMenu() {

var colsValue = frameset.getAttribute(cols);
frameset.setAttribute("cols", ( (colsValue && colsValue.clarAt(0) === "0") ? MENU_WIDTH : "0" ) + ",*")
}

}());

Например, даже не тестил, потом, повесьте на вашу кнопку на клик этот обработчик. И вообще обосновано ли использование фреймсета?

Socgamer
11.01.2012, 12:50
ткните пальцем пожалуйста...

poorking
11.01.2012, 13:25
// У вас есть кнопка. На кнопке, на событии click висит обработчик-функция,
// когда вы кликаете по кнопке, функция запускается

// Создаем анонимную функцию и тут же ее вызываем,
// чтобы замкнуть внутри некоторые данные, а эта анонимная функция уже вернет нашу
// функцию обработчик, которую мы сохраним в ссылке под именем toggleMenu
// которую мы и будем в итоге использовать
var toggleMenu = (function () {

// Ширина фрейма меню. Я предположил что она заранее известна
var DEFAULT_MENU_WIDTH = 200; // или любое другое значение в пикселах

// Ширина фрейма, когда меню скрыто
var HIDDEN_MENU_WIDTH = 0; // или любое друго значение

// Статическая ссылка на фреймсет, чтобы не делать
// выборку каждый раз, получаем ее сразу
var frame = top.document.getElementsByTagName("frameset")[0]; // или другая выборка, по id например

// Это сама функция, которую возвращает наша анинимная функция
return function () {

// Получаем значение атрибута cols фреймсета, раз вы выбрали
// такой путь скрытия меню, то по значению этого атрибута мы узнаем,
// скрыто или открыто меню.
var colsValue = frameset.getAttribute(cols);

// Если значение атрибута имеется и первый его символ равен 0,
// то значит, что ширина левогог фрейма равна нулю, значит "меню скрыто"
if ( colsValue && colsValue.clarAt(0) ) {

// Значит надо его показать

// Получаем новое значение атрибута cols из нашщей "константы" DEFAULT_MENU_WIDTH,
// а значение ширины второго фрейма - все оставшееся пространство(*)
colsValue = MENU_WIDTH + ", *";

// Устанавливаем новое значение атрибута cols
frameset.setAttribute("cols", colsValue);

} else {

// Если меню не скрыто, то оно открыто (O_O)

// Получаем новое значение
colsValue = HEDDEN_MENU_WIDTH + ", *";

// Устанавливаем
frameset.setAttribute("cols", colsValue)
}
}

// Итого, по клике на кнопку "Скрыть/развернуть меню",
// наш обработчик события click сам определил, скрыто меню или нет, и выбрал нужное действие
}());

// Теперь просто нужно повесить эту функцию обработчиком на событие click

Поподробнее расписал, но сделал вывод что знаний по предмету у вас нет, все равно все кончится тем, что вы пойдете читать учебник на этом сайте, если, конечно, заинтересутесь