Для того чтобы работать сразу с несколькими документами HTML, можно предоставить пользователю многооконный интерфейс, реализованный при помощи фреймов. Подробно о фреймах мы рассказали в 29 томе “Библиотеки системного программиста”. Который называется “Сервер Web своими руками”.
Для того чтобы объединить несколько документов HTML при помощи фреймов, вам нужно подготовить специальный документ HTML, в котором находится описание параметров фреймов, таких как размер и расположение.
Особенность такого документа - отсутствие на своем обычном месте области тела документа, выделенного операторами <BODY> и </BODY>. Вместо этого в файле описания фреймов располагаются операторы <FRAMESET>, </FRAMESET>, <NOFRAME> и </NOFRAME>, как это показано ниже:
<HTML> <HEAD> . . . </HEAD> <FRAMESET ROWS="Высота_строки" COLS="Ширина_колонки" onLoad="Обработчик_события" onUnload="Обработчик_события"> <FRAME SRC="Адрес_URL" NAME="Имя_фрейма"> . . . <FRAME SRC="Адрес_URL" NAME="Имя_фрейма"> <NOFRAME> <BODY> . . . </BODY> </NOFRAME> </FRAMESET> </HTML>
Параметры ROWS и COLS оператора <FRAMESET> определяют размеры фреймов и задаются в виде списка значений, разделенных запятой.
Вы можете определить обработчики событий onLoad и onUnload, получающие управление, соответственно, при загрузке содержимого в главное окно фрейма и при замене текущего документа HTML в этом окне на другой. Фактически эти обработчики относятся не к фреймам, а к окну, где эти фреймы отображаются.
Для тех браузеров, которые не могут работать с фреймами, необходимо подготовить документ HTML, расположив его тело между операторами <NOFRAME> и </NOFRAME>. В этом документе имеет смысл разместить сообщение о том, что для просмотра данной страницы Web необходимо применять более современный браузер.
Рассмотрим подробнее параметры оператора <FRAMESET>, предназначенного для определения набора фреймов.
Параметр |
Описание |
COLS |
Ширина колонки в процентах, пикселах или относительный размер |
ROWS |
Высота строки в процентах, пикселах или относительный размер |
FRAMEBORDER |
Если значение этого параметра равно 1, фреймы будут иметь трехмерную рамку, ширина которой задается в пикселах. В том случае, когда указано значение 0, рамка не создается |
BORDER |
Используется только браузером Netscape Navigator. Задает толщину рамки фрейма в пикселах |
FRAMESPACING |
С помощью этого параметра можно задать дополнительное расстояние между фреймами в пикселах |
Параметры COLS и ROWS нужны в том случае, когда фреймы, определенные в наборе, располагаются в виде таблицы. Первый из этих параметров указывает ширину колонки, а второй - высоту строки. Если фреймы располагаются в одном столбце, параметр COLS указывать не надо. Аналогично, если фреймы занимают только одну строку, не нужно указывать параметр ROWS.
Вы можете задать значения для параметров COLS и ROWS либо в процентном отношении, соответственно, к ширине и высоте окна браузера, либо в пикселах. Если вместо значения указан символ *, колонка или строка занимают всю оставшуюся часть окна.
Например, ниже указано, что высота первого фрейма равна 90 пикселам, а второй фрейм занимает всю нижнюю часть окна браузера:
<FRAMESET ROWS="90,*">
В следующем примере два фрейма, расположенные рядом, занимают, соответственно, 20% и 80% ширины окна браузера.
<FRAMESET COLS="20%,80%">
Между операторами <FRAMESET> и </FRAMESET> располагаются операторы <FRAME>, определяющие параметры отдельных фреймов. Это параметры SRC и NAME. Первый из этих параметров задает адрес URL документа HTML, который будет загружен в данный фрейм, а второй - имя фрейма, которое можно использовать в сценарии JavaScript для адресации объектов, расположенных во фрейме. Заметим, что адрес URL не должен содержать ссылки на локальные метки (anchor).
Оператор <FRAME> имеет следующие параметры:
Параметр |
Описание |
ALIGN |
Используется только для “плавающих фреймов” в браузере Microsoft Internet Explorer. Задает выравнивание фрейма или текста, расположенного рядом с фреймом. Этот параметр может принимать следующие значения: LEFT, CENTER, RIGHT, TOP, BOTTOM |
MARGINHEIGHT |
Размер отступа по вертикали от границ фрейма в пикселах |
MARGINWIDTH |
Размер отступа по горизонтали от границ фрейма в пикселах |
FRAMEBORDER |
Если значение этого параметра равно 1, фреймы будут иметь трехмерную рамку, ширина которой задается в пикселах. В том случае, когда указано значение 0, рамка не создается |
NAME |
Этот параметр задает имя фрейма, которое используется в операторе ссылки <A> для указания, в какой фрейм нужно загрузить новый документ |
NORESIZE |
Если указан этот параметр, пользователь не сможет изменять размеры фрейма, передвигая его границы мышью |
SCROLLING |
Параметр SCROLLING определяет, нужно ли создавать полосы просмотра для свертки содержимого фрейма. Для этого параметра можно указывать следующие значения: |
SRC |
Адрес URL файла с документом HTML, который загружается в окно фрейма |
С помощью сценариев JavaScript вы можете наделить фреймы возможностями, недостижимыми с применением одного лишь только языка разметки гипертекста HTML. Например, один из фреймов может содержать ссылки на документы, которые при активизации этих ссылок загружаются в окно другого фрейма. Сценарий JavaScript позволит загружать таким образом не один документ, а одновременно несколько документов в разные фреймы. Пример организации такого взаимодействия мы рассмотрим немного позже, а сейчас на конкретном примере расскажем о том, как можно передавать данные между объектами форм, расположенных в разных фреймах.
На рис. 4.1. показан внешний вид десятично-шестнадцатеричного преобразователя, выполненного на базе документов HTML с фреймами и сценарием JavaScript.
Рис. 4.1. Десятично-шестнадцатеричный преобразователь, выполненный с использованием фреймов
Верхний фрейм используется для размещения заголовка. Клавиатура преобразователя, предназначенная для ввода десятичных чисел и запуска процесса преобразования, находится в левом фрейме. Правый фрейм используется для отображения исходного десятичного числа и результата преобразования.
Вы можете вводить исходное число не только с помощью клавиатуры, но и непосредственно в поле Dec, расположенное в правом фрейме. Поле Hex заблокировано для вода при помощи обработчика события onFocus. Аналогичный прием мы использовали в шестнадцатеричном калькуляторе, исходные тексты которого были приведены в предыдущей главе.
Исходный текст файла описания фреймов представлен в листинге 4.1.
Листинг 4.1. Файл chapter4/Converter/index.html
ML> <HEAD> <TITLE>Десятично-шестнадцатеричный преобразователь</TITLE> </HEAD> <FRAMESET ROWS="85,*" FRAMEborder=0> <FRAME SCROLLING="no" NAME="title" SRC="title.html" MARGINHEIGHT="1"> <FRAMESET COLS="180,*" FRAMEborder=0> <FRAME SCROLLING="auto" NAME="toc" SRC="toc.html"> <FRAME SCROLLING="auto" NAME="mainpage" SRC="main.html"> </FRAMESET> <NOFRAME> <BODY BGCOLOR="#FFFFFF"> </BODY> </NOFRAME> </FRAMESET> </HTML>
Наш сценарий будет работать с фреймами toc и mainpage, расположенными, соответственно, в файлах с именами toc.html и main.html. В файле title.html располагается заголовок (листинг 4.2).
Листинг 4.2. Файл chapter4/Converter/title.html
<HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1251"> </HEAD> <BODY BGCOLOR="#ffffff"> <TABLE><TR><TD> <H2>Десятично-шестнадцатеричный преобразователь</H2> </TD></TR></TABLE> </BODY> </HTML>
Исходный текст документа, содержащего форму с полями Dec и Hex, представлен в листинге 4.3.
Листинг 4.3. Файл chapter4/Converter/main.html
<HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1251"> </HEAD> <BODY BGCOLOR="#FFFFFF"> <FORM NAME="Sel"> <TABLE> <TR><TD><B>Hex:</B></TD><TD><INPUT TYPE="text" NAME="hexValue" SIZE="20" onFocus="this.blur();"></TD></TR> <TR><TD><B>Dec:</B></TD><TD><INPUT TYPE="text" NAME="decValue" SIZE="20"></TD></TR> </FORM> </BODY> </HTML>
Для поля исходного десятичного числа при помощи параметра NAME мы задали имя decValue. Поле результата называется hexValue. Эти имена используются сценарием JavaScript для адресации наших полей.
Документ toc.html (листинг 4.4) содержит форму с кнопками и сценарий JavaScript.
Листинг 4.4. Файл chapter4/Converter/toc.html
<HTML> <BODY BGCOLOR="#B0FFD8"> <SCRIPT LANGUAGE="JavaScript"> <!-- var bNewNumber = true; function dec2hex(nDec) { var szHexTable="0123456789ABCDEF"; var szResult = ""; var szBuf=""; var nRem = 0; var bNegative=false; if(nDec < 0) { bNegative=true; nDec = -nDec; } nTmp=nDec; while(true) { nRem = nTmp % 16; nTmp = nTmp / 16; if(Math.floor(nTmp) < 16) break; szBuf=szHexTable.charAt(nRem); szResult = szBuf.concat(szResult); nTmp = Math.floor(nTmp); } szBuf=szHexTable.charAt(nRem); szResult = szBuf.concat(szResult); if(Math.floor(nTmp) != 0) { szBuf=szHexTable.charAt(Math.floor(nTmp)); szResult = szBuf.concat(szResult); } if(bNegative == true) return ("-" + szResult); else return szResult; } function putNumber(btn,form) { var szOld = ""; var szNew = ""; if(bNewNumber) { parent.mainpage.document.forms[0].hexValue.value = ""; parent.mainpage.document.forms[0].decValue.value = ""; bNewNumber = false; } szOld = parent.mainpage.document.forms[0].decValue.value; szNew = szOld.concat(btn.name); nCurrent = eval(szNew); parent.mainpage.document.forms[0].decValue.value = nCurrent; } function clearAll(form) { total = 0; lastOperation = "+"; parent.mainpage.document.forms[0].hexValue.value = "0"; parent.mainpage.document.forms[0].decValue.value = "0"; bNewNumber = true; } function getResult(form) { parent.mainpage.document.forms[0].hexValue.value = dec2hex(parent.mainpage.document.forms[0].decValue.value); bNewNumber = true; } // --> </SCRIPT> <FORM> <TABLE border=0 BORDERCOLOR="Black" BGCOLOR="Yellow"> <TR> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="5" VALUE=" 5 " onClick="putNumber(this,this.form);"></TD> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="6" VALUE=" 6 " onClick="putNumber(this,this.form);"></TD> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="7" VALUE=" 7 " onClick="putNumber(this,this.form);"></TD> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="8" VALUE=" 8 " onClick="putNumber(this,this.form);"></TD> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="9" VALUE=" 9 " o nClick="putNumber(this,this.form);"></TD> </TR> <TR> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="0" VALUE=" 0 " onClick="putNumber(this,this.form);"></TD> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="1" VALUE=" 1 " onClick="putNumber(this,this.form);"></TD> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="2" VALUE=" 2 " onClick="putNumber(this,this.form);"></TD> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="3" VALUE=" 3 " onClick="putNumber(this,this.form);"></TD> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="4" VALUE=" 4 " onClick="putNumber(this,this.form);"></TD> </TR> <TR> <TD ALIGN=CENTER><INPUT TYPE="button" NAME="C" VALUE=" C " onClick="clearAll(this.form);"></TD> <TD COLSPAN=4 ALIGN=CENTER><INPUT TYPE="button" NAME="=" VALUE=" to Hex " onClick="getResult(this.form);"></TD> </TR> </TABLE> </FORM> </BODY> </HTML>
Сценарий нашего десятично-шестнадцатеричного преобразователя работает аналогично сценарию шестнадцатеричного калькулятора (за исключением, конечно, того, что преобразователь не выполняет никаких арифметических действий). Главное отличие заключается в том, что теперь поля для ввода и отображения чисел располагаются в другом документе HTML, загруженном в отдельный фрейм.
Для того чтобы проинициализировать поля hexValue и decValue, мы ссылаемся на форму, расположенную внутри фрейма mainpage:
parent.mainpage.document.forms[0].hexValue.value = ""; parent.mainpage.document.forms[0].decValue.value = "";
Здесь parent ссылается на объект, который является родительским по отношению к документу HTML, содержащему сценарий. В данном случае это окно, содержащее все наши фреймы.
Для чтения содержимого поля decValue применяется аналогичная техника:
szOld = parent.mainpage.document.forms[0].decValue.value;
Функция getResult, выполняющая десятично-шестнадцатеричное преобразование, получает исходное число из поля decValue и передает его функции dec2hex . Результат преобразования, выполненного этой функцией, записывается затем в поле hexValue:
function getResult(form) { parent.mainpage.document.forms[0].hexValue.value = dec2hex(parent.mainpage.document.forms[0].decValue.value); bNewNumber = true; }
На рис. 4.2 мы показали внешний вид содержимого нашего авторского компакт-диска, первый выпуск которого появился недавно в продаже.
Рис. 4.2. Авторский компакт-диск
Информация отображается в трех фреймах. Верхний фрейм используется для заголовка, левый выполняет роль оглавления, и, наконец, правый - служит для показа содержимого. Нажимая кнопки, расположенные в левом фрейме, вы можете просматривать в правой части окна различные документы HTML.
В первом выпуске компакт-диска мы не использовали сценарии JavaScript. Сейчас мы покажем, как можно с помощью несложного сценария усовершенствовать интерфейс пользователя.
Мы будем использовать фрейм заголовка, расположенный в верхней части окна, для размещения аннотации на материал, представленный в правом фрейме.
При этом если нажать кнопку с надписью “Добро пожаловать”, в заголовке появится наш логотип, показанный на рис. 4.2. Если же нажать кнопку “Книги” или “Статьи”, заголовок будет выглядеть так, как это показано на рис. 4.3 и 4.4, соответственно.
Рис. 4.3. Просмотр информации о книгах
Рис. 4.4. Просмотр информации о статьях
В листинге 4.5 мы показали исходный текст файла описания фреймов.
Листинг 4.5. Файл chapter4/ourCD/index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> <TITLE>Авторский диск Александра Фролова и Григория Фролова</TITLE> </HEAD> <FRAMESET ROWS="85,*" FRAMEborder=0> <FRAME SCROLLING="no" NAME="title" SRC="title.html" MARGINHEIGHT="1"> <FRAMESET COLS="180,*" FRAMEborder=0> <FRAME SCROLLING="auto" NAME="toc" SRC="toc.html"> <FRAME SCROLLING="auto" NAME="mainpage" SRC="main.html"> </FRAMESET> <NOFRAME> <BODY BGCOLOR="#FFFFFF"> </BODY> </NOFRAME> </FRAMESET> </HTML>
Так же как и в предыдущем примере, здесь описаны три фрейма.
Документ заголовка, который отображается сразу после загрузки фрейма, а также после того как пользователь нажмет кнопку “Добро пожаловать”, показан в листинге 4.6.
Листинг 4.6. Файл chapter4/ourCD/title.html
<HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1251"> </HEAD> <BODY BACKGROUND="pic/FFON.GIF" BGCOLOR="#ffffff"> <P> <TABLE > <TR> <TD VALIGN=TOP><A HREF="emailus.htm" TARGET="main page"> <IMG SRC="pic/frlogo3.GIF" ALT="Александр Фролов и Григорий Фролов, технические писатели из Москвы" border=0></A> <TD VALIGN=TOP><A HREF="emailus.htm" TARGET="main page"> <IMG SRC="pic/frlogo.GIF" ALT="Александр Фролов и Григорий Фролов, технические писатели из Москвы" border=0></A> </TD></TR> </TABLE> <P> </BODY> </HTML>
Файл main.html представлен в листинге 4.7 (в сокращенном виде). Он не имеет никаких интересных особенностей.
Листинг 4.7. Файл chapter4/ourCD/main.html
<HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1251"> <TITLE>Untitled</TITLE> </HEAD> <BODY BGCOLOR="#FFFFFF"> <H2>Добро пожаловать!</H2> <P> <IMG SRC="pic/cd.GIF" ALIGN=LEFT HSPACE=5> <P> Вы приобрели первый выпуск авторского компакт-диска технических писателей Александра Фролова и Григория Фролова. . . . <P> <CENTER><A HREF="copyrihgt.htm" ><I><FONT SIZE=2> © Александр Фролов, Григорий Фролов, 1997 </FONT></I></A></CENTER> </BODY> </HTML>
Гораздо важней для нас файл toc.html. В этом файле находятся функции сценария JavaScript и ссылки на другие документы HTML. Этот файл с несущественными сокращениями показан в листинге 4.8.
Листинг 4.8. Файл chapter4/ourCD/toc.html
<HTML> <BODY BGCOLOR="#B0FFD8"> <SCRIPT LANGUAGE="JavaScript"> <!-- function loadPage(szNewURL,szTitle) { parent.mainpage.window.location.href=szNewURL; parent.title.window.location.href=szTitle; } // --> </SCRIPT> <FONT FACE="Arial, Helvetica" SIZE=1> <P> <A HREF="javascript:loadPage('main.html', 'title.html');"><IMG SRC="pic/fcd_62.GIF" border=0 ALT="Добро пожаловать"></A> <BR> <A HREF="javascript:loadPage('books/home.html', 'books/title.html');" ><IMG SRC="pic/fcd_82.GIF" border=0 ALT="Книги"></A> <BR> <A HREF="javascript:loadPage('articles/articles.html', 'articles/title.html'); "><IMG SRC="pic/fcd_102.GIF" border=0 ALT="Статьи"></A> <BR> . . . <P> </BODY> </HTML>
Функция loadPage загружает в фреймы mainpage и title документы HTML, адреса URL которых передаются ей через параметры. Для загрузки мы устанавливаем свойство location.href для окна соответствующего фрейма:
parent.mainpage.window.location.href=szNewURL; parent.title.window.location.href=szTitle;
Для вызова функции loadPage мы использовали следующую конструкцию:
<A HREF="javascript:loadPage('main.html', 'title.html');"><IMG SRC="pic/fcd_62.GIF" border=0 ALT="Добро пожаловать"></A>
Здесь в параметре HREF оператора ссылки <A> после ключевого слова javascript мы расположили строку вызова функции. Обратите внимание на использование одинарных и двойных кавычек. Так как в сценариях JavaScript вложение одинаковых кавычек недопустимо, для строк, передаваемых функции в качестве параметров, мы применили одинарные кавычки. Значение параметра HREF выделено при этом двойными кавычками.