Роботландский Университет © А.А.Дуванов |
Искре-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.
![]() |