| Роботландский Университет © А.А.Дуванов |
Искре-1256 посвящается...
Мы снова на программистской кухне Ивана Сидорова.
Он товарищ открытый, секретов не держит и всегда готов поделиться своими находками за чашкой крепкого чая. Так было и встарь в славном городе Благовещенске, где сиживал он с друзьями в ЛПМ БГПИ (лаборатория прикладной математики Благовещенского пединститута).
Ах, что тогда вытворялось там, на технике, которая теперешним школьникам и не снилась! Взять хотя бы такого отечественного монстра персонального компьютеростроения как Искра-1256. Оперативной памяти аж 4 КБ! Вместо дисководов один накопитель на кассете от обычного бытового магнитофона.
Язык программирования тоже отечественный, без названия. Иван с друзьями окрестили его Дуб, за жесткую непоколебимую сущность. Представьте, имена переменных нельзя было выбирать произвольно, все они были предопределены заранее конструкторами языка. Какая-то гремучая смесь из Алгола и Ассемблера. Внешний вид программ не для слабонервных. Иван точно не помнит, но, кажется, в языке не было даже комментариев.
Тем не менее, было бы вдохновение, да интерес, да мускулистые руки посадим картофель и лопатой! А уж этого добра (интереса и вдохновения) было в ЛПМ сколько угодно. И лились рекой крепкие чаи (иногда с ложкой спирта для протирки клавиатуры), и рождались на 4 КБ удивительные вещи. Например, среда исполнителя Кукарача. В среде и сам исполнитель, и редактор программ для него, и, конечно, транслятор.
Техника теперь изменилась, Сидоров уехал из Благовещенска. Пьет он теперь чай один на своей кухне для компьютера с 256 МБ памятью и увлечен HTML, JavaScript, CSS.
Предлагаемые ниже заметки Сидорова публикуются с его согласия и посвящаются, по его настоянию, той самой Искре-1256, о которой у Ивана остались самые теплые чувства.
Заметки посвящены теме меню, которая была затронута на предыдущем уроке.
Меню нужны разные! так подумал Иван и налил первый стакан чаю.
Стандартный список HTML чем не меню? Вот вам и пример этого:
Код этого меню проще не бывает:
До того просто, что не интересно. Никакого JavaScript, CSS. Так не пойдет. Давайте создадим функцию, которая будет сама строить это меню там, где нам надо.
Пусть интерфейс функции будет таким:
menu1(
"Раздел1", "item1.htm",
"Раздел2", "item2.htm",
"Раздел3", "item3.htm"
);
|
В аргументах функции записываются название разделов и ссылки, им соответствующие, а функция строит на экране список.
Построить список динамически можно при помощи метода write объекта document. Есть только одна особенность: число аргументов функции menu1 заранее неизвестно. Но и это не беда: JavaScript для каждой нашей функции строит одноименный объект. Аргументы функции записываются в специальный массив этого объекта:
имя_функции.arguments
Внутри самой функции можно писать короче:
arguments
Длина массива, а значит, число аргументов функции, как обычно,
содержится в свойстве
// Построение списка ссылок.
// Обращение к функции:
// menu1(
// "имя раздела меню", "ссылка",
// ...
// "имя раздела меню", "ссылка",
// );
function menu1()
{
var alen = arguments.length; // Число аргументов функции.
if(alen < 1) // Функция работает,
{ // если число аргументов больше одного.
// Если число аргументов нечетно,
// последний аргумент игнорируем.
if(alen%2) alen--;
// Строим начальный тег списка.
document.write("<UL type=disc>");
// Построение списка.
for(var i=0; i<alen; i+=2)
document.write("<LI><A href="+arguments[i+1]+">"+
arguments[i]+"</A>");
document.write("</UL>"); // Строим конечный тег списка.
}
}
|
Функция menu1 не использует сложных данных и глобальных переменных, поэтому заменять ее объектом особого смысла не имеет. Меню можно отобразить следующим кодом (описание функции menu1 расположено в файле menu1.js):
Обязательно посмотрите исходный текст этого HTML-файла. Файл находится
по адресу:
Второй стакан чая Иван поднял за тег SELECT.
Без JavaScript меню вроде того, что показано ниже, интересно, но бесполезно:
Ведь надо определить, что выбрал пользователь, и в соответствии с этим что-то сделать, например, загрузить новую страницу. Но JavaScript в наших руках! Для меню на три раздела можно написать такой код:
Функция menu2_go, которая обрабатывает щелчок на кнопке Пуск, может быть такой:
function menu2_go(sel)
{
var link;
if (sel.selectedIndex==0) link="item1.htm";
else if(sel.selectedIndex==1) link="item2.htm";
else link="item3.htm";
location.href=link;
}
|
Да, но мы поставили задачу написать функцию с универсальным интерфейсом:
menu2(
"Раздел1", "item1.htm",
...
"Разделn", "itemn.htm"
);
|
Придется опять поработать с функцией write объекта document. Вот код, который сделает все, что задумано:
// Построение меню ссылок.
// Обращение к функции:
// menu2(
// "имя раздела меню", "ссылка",
// ...
// "имя раздела меню", "ссылка"
// );
//----------------------------------------
var links = new Array(); // В этот массив помещаются ссылки.
function menu2()
{
var alen = arguments.length; // Число аргументов функции
if(alen < 1) // Функция работает,
{ // если число аргументов больше одного.
// Если число аргументов нечетно,
// последний аргумент игнорируем.
if(alen%2) alen--;
document.write("<FORM><SELECT name=select size= "+alen/2+">");
// Построение позиций меню и заполнение массива ссылками.
for(var i=0; i<alen; i+=2)
{
document.write("<OPTION>"+arguments[i]+"</OPTION>");
links[i/2] = arguments[i+1];
}
document.write("</SELECT><INPUT type=button value=Пуск"+
" onclick='menu2_go(this.form.select)'></FORM>");
}
}
// Обработка щелчка на кнопке "Пуск"
function menu2_go(sel)
{
location.href= links[sel.selectedIndex];
}
|
Файл документа находится по адресу: ./sidorov/menu2.htm. Функция menu2 оформлена а качестве отдельного js-файла: ./sidorov/menu2.js.
Построенным скриптом Иван остался недоволен. Функция menu2 использует глобальный массив links. Если на одной гипертекстовой странице построить несколько таких меню, неизбежно возникнут проблемы. Ведь массив links один!
Выход прост: надо для меню построить объект, а массив links спрятать внутри. Тогда для каждого экземпляра будет создаваться своя копия этого массива.
Иван построил объект MenuSelect. Скрипт он разместил в файле menu3.js:
// Меню ссылок (объект MenuSelect).
// Использование.
// 1. Создать экземпляр объекта:
// var имя_экземпляра=MenuSelect(имя_экземпляра,
// название1,
// ссылка1, ...);
// Здесь:
// имя_экземпляра - имя созданного экземпляра;
// название1 - текст для первой строки меню;
// ссылка1 - ссылка для первой строки меню.
// 2. Настроить внешний вид меню используя свойства объекта:
// имя_экземпляра.allview = true - видны все строки меню
// имя_экземпляра.allview = false - видна одна строка меню
// (по умолчанию)
// имя_экземпляра.mark = 0 - отмеченная строка
// (по умолчанию первая)
// имя_экземпляра.textgo - текст на кнопке "Пуск"
// (по умолчанию "Пуск").
// 3. Показать меню на экране:
// имя_экземпляра.Show();
//------------------------------------------
// Описание одной строки меню (название, ccылка).
function item(name, link)
{
this.name=name; // Текст в строке меню.
this.link=link; // Ссылка, соответствующая тексту.
}
// Конструктор главного объекта.
function MenuSelect()
{
// Свойства объекта для пользователя.
this.allview = false;
this.textgo = "Пуск";
this.mark = 0;
// Методы объекта для пользователя.
this.Show = _Show;
// Внутренние переменные.
this.items = new Array(); // Массив строк меню.
this.name = arguments[0]; // Имя экземпляра объекта.
// Внутренние функции.
this.Make = _Make; // Щелчок на строке меню.
var alen = arguments.length; // Число аргументов конструктора
if(!alen%2) alen--; // должно быть нечетным.
// Заполним массив items (строки меню).
var j = 0; // Это индекс по массиву items.
for(var i=1; i<alen; i+=2)
this.items[j++] = new item(arguments[i],arguments[i+1]);
}
// Обработка нажатия кнопки Пуск.
function _Make(sel)
{
location.href = this.items[sel.selectedIndex].link;
}
// Генерация HTML-кода для построения меню на экране.
function _Show()
{
var len = this.items.length;
var str= "<FORM><SELECT name=select size="+
(this.allview ? len:1)+">";
for(var i=0; i<len; i++)
str += "<OPTION" + (i==this.mark ? " selected>" : ">") +
this.items[i].name+"</OPTION>";
str += "</SELECT><INPUT type=button value='"+this.textgo+"'"+
" onclick='"+this.name+".Make(this.form.select)'>"+
"</FORM>";
document.write(str);
}
|
Скрипт размещается в файле
Обычные кнопки
Недолго думая, Сидоров написал такую программу:
Переход к документу
Кнопочки работают хорошо, но длина у них получилась разная, что, конечно, портит дизайн.
Иван попробовал добиться одинаковой длины кнопок за счет пробелов в коротких названиях. Но идея подбирать число пробелов Ивану показалась не очень приятной, а главное, добиться одинаковой длины у всех кнопок так и не удалось ведь надписи на кнопках браузер записывает пропорциональным шрифтом, то есть, таким, у которого каждый символ имеет свою ширину.
Пытался Сидоров сменить шрифт на кнопках на моноширинный, но и это у него не получилось.
Потом он вдруг вспомнил про CSS (каскадные таблицы стилей) о которых прочитал в умной книжке, и написал такое стилевое определение:
INPUT
{
width:300px;
font-size:10pt;
}
Теперь размеры всех кнопок стали одинаковыми.
Переход к документу
Иван Сидоров сделал несколько меню на графических кнопках, которые нарисовал для него компьютерный художник Саша Мур. Саша нарисовал два экземпляра кнопок. Первый набор основной:
Второй вид кнопок, когда над ними находится курсор мыши:
Иван большой любитель порядка. Он придумал для файлов с картинками следующие имена.
Имена файлов для первого набора кнопок:
key011.gif, key021.gif, key031.gif, key041.gif, key051.gif, key061.gif, key071.gif
Имена файлов для второго набора кнопок.
key012.gif, key022.gif, key032.gif, key042.gif, key052.gif,key062.gif, key072.gif
Меню на этих кнопках получилось таким:
Для вывода такого меню на экран Иван использовал объект MenuPic:
//-- Файл menupic.js
// Меню ссылок на графических кнопках.
// (работает в Internet Explorer и Netscape Navigator)
// Использование
// -------------
// Меню представляет собой объект MenuPic. Необходимо:
// 1. Подготовить картинки кнопки и дать им имена по правилу:
// имя011.расширение - первая кнопка, курсор не над кнопкой;
// имя012.расширение - первая кнопка, курсор над кнопкой;
// ...
// Пример
// key011.gif
// key012.gif
// ...
// 2. Создать экземпляр объекта.
// var имя_экземпляра = MenuPic(
// имя_экземпляра, основа, расширение, ширина, высота,
// название1, ссылка1, ...);
// Здесь:
// имя_экземпляра - имя экземпляра объекта MenuPic
// (например, "mp");
// основа - основа имени картинок
// (например, "./pic/key");
// расширение - расширение имени картинок
// (например, "gif");
// ширина - ширина картинки (например, 43);
// высота - высота картинки (например, 43);
// название1 - alt-текст для первой кнопки
// (например, "Урок 1");
// ссылка1 - ссылка для первой кнопки
// (например, "../01.htm")
// ...
// 3. Показать меню на экране.
// имя_экземпляра.Show();
//------------------------------------------
// Описание одной строки меню.
// pic_over -ссылка на картинку под курсором.
// pic_out - ссылка на основную картинку.
// name - содержание alt-надписи кнопки.
// link - URL для перехода.
function item(pic_over, pic_out, name, link)
{
// Создали два экземпляра объекта Image.
this.pic_over = new Image();
this.pic_out = new Image();
this.pic_over.src=pic_over;
this.pic_out.src=pic_out;
this.name = name;
this.link = link;
}
// Конструктор главного объекта.
function MenuPic(name,base,ext,width,height)
{
this.name = name; // Имя экземпляра объекта.
this.width = width; // Ширина картинок.
this.height = height; // Высота картинок.
this.items = new Array(); // Массив позиций меню.
this.Show = _Show; // Метод для показа меню на экране.
this.ismenu = arguments.length > 6; // false, если
// аргументов мало.
// Заполнение массива данными
if(this.ismenu)
{
var j=0;
for(var i=5; i<arguments.length; i+=2)
{
var num = j < 9 ? "0"+eval(j+1):eval(j+1);
this.items[j++] = new item(base+num+"2."+ext,
base+num+"1."+ext,
arguments[i],
arguments[i+1]);
}
}
}
// Показать меню на экране
function _Show()
{
if(this.ismenu)
{
document.write("<NOBR>");
for(var i=0; i<this.items.length; i++)
document.write(
"<A href="+this.items[i].link+
" onmouseover=\"document.images."+this.name+i+".src='"+
this.items[i].pic_over.src+"'\""+
" onmouseout=\"document.images."+this.name+i+".src='"+
this.items[i].pic_out.src+"'\""+
"><IMG name="+this.name+i+" border=0 src="+
this.items[i].pic_out.src+
" width="+this.width+" height="+this.height+
" alt=\""+this.items[i].name+"\"></A>");
document.write("</NOBR>");
}
}
|
Функцию _Show можно упростить, если внести мышиные атрибуты внутрь тега IMG:
function _Show()
{
if(this.ismenu)
{
document.write("<NOBR>");
for(var i=0; i<this.len; i++)
document.write(
"<A href="+this.items[i].link+
"><IMG border=0 src="+this.items[i].pic_out.src+
" width="+this.width+" height="+this.height+
" alt=\""+this.items[i].name+"\""+
" onmouseover=\"this.src='"+this.items[i].pic_over.src+"'\""+
" onmouseout=\"this.src='"+this.items[i].pic_out.src+"'\""+
"></A>");
document.write("</NOBR>");
}
}
|
Замечание. Последний вариант не работает в браузерах NN ниже 6 версии. Первый вариант работает, начиная с NN3. Оба варианта нормально работают в IE, начиная с IE4.
Для показа меню можно написать такой HTML-код:
| \n'+ ' |
Переход к документу
Наконец, Сидоров решил добавить к картинкам третий набор: кнопки в момент щелчка по ним мышью. Пример использования этого меню показан здесь: ./sidorov/menu7.htm, а объект, строющий меню, расположен в файле ./sidorov/menu7.js.
|
|