Nickolay.info. JavaScript. Пишем информер средствами HTML и JavaScript

Написание информера - не только развлечение и дополнительный сервис для Ваших пользователей. Он еще и повышает ссылочную популярность сайта, потому что все, размещающие его у себя, вольно или невольно ставят лишнюю ссылку на Ваш сайт.

Самая естественная и правильная технология - использование PHP или другого серверного языка, выполняющего всю работу на стороне Вашего сервера. Но эта статья размещена в разделе JavaScript, и потому предназначена для тех, кто пока не постиг тайны серверного программирования или пользуется хостингом без поддержки серверных скриптов, таким как narod.ru.

Применяя только HTML и JavaScript, информер можно написать по следующему шаблону:

К сожалению, возможности классического JavaScript довольно ограничены, так что информеров, получающих данные из базы или с других серверов мы сделать не сможем. Но ведь мы и хотели обойтись, пока что, простейшими средствами.

По сути дела, JavaScript может формировать содержимое страницы в зависимости всего от нескольких факторов:

Давайте сделаем информер в виде идущих часов с датой и обеспечим подключение к нему любой нужной картинки и оформления. Все подключаемые картинки должны располагаться где-то в сети, то есть, уже иметь URL-адреса, которые и будут передаваться информеру параметрами.

Пока мы ничего не будем вводить в формы, значит, при написании кода информера необязательно передавать данные в виде имя=значение, достаточно после знака "?" в URL-адресе перечислить значения параметров, разделяя их обычным разделителем "&".

Придумаем несложный блок информера, скажем, вот такой:

Из-за изменений в адресах картинок у Яндекса, конкретно этот код информера уже не работает, но способ, описанный в статье, остаётся работающим!

Основная часть информера будет ссылкой на выбранный пользователем ресурс (у нас - Яндекс), открываемой в новом окне (параметр 1).
URL-адрес картинки, которая является ссылкой - это параметр 2. У нас это картинка Яндекса.
Параметры 3 и 4 передают ширину и высоту картинки в пикселах. Для простоты не будем пытаться узнать ее из скрипта, к тому же, у кого-то может возникнуть желание масштабировать картинку своего информера.
Внешняя таблица будет иметь настраиваемый цвет рамки - параметр 5.
При желании можно задать фоновый рисунок под датой и временем - его URL передается 6 параметром.

Вот уже и ясно, как вызывать будущий информер. Тот его вид, что показан выше, получен следующим тегом:


<iframe src="http://nickolay.info/myclock.html?http://www.ya.ru&http://ya.ru/logo.png&100&44&red&http://img.yandex.net/i/www/iconx.png" 
scrolling="no" width=102 height=74 frameborder=0 marginwidth=0 marginheight=0 
hspace=0 vspace=0></iframe>

Все атрибуты тега, расположенные после src, призваны обеспечить вид окна фрейма без полос прокрутки и лишних отступов. Ширина и высота окна iframe, думаю, может быть вычислена, исходя из ширины и высоты картинки - ведь строки отображения даты и времени занимают всегда одно и то же пространство.

Дело за малым - написать файл myclock.html, отображающий блок информера, и расположить его по адресу http://nickolay.info/myclock.html.

Прежде всего, разберемся с чтением параметров 1-6. Дадим им имена и расположим в теге <script> вместе со значениями по умолчанию:


<script type="text/javascript">
var url='http://nickolay.info';
var picture='http://nickolay.info/img/pers.gif';
var width=88;
var height=31;
var bgcolor='#009900';
var bgimage='http://nickolay.info/img/bg.gif';
//...

Метод JavaScript с именем location.search позволяет прочитать всю часть URL, включающую список параметров. Эта часть всегда начинается со знака "?" и метод возвращает ее вместе со знаком, поэтому первый символ сразу же исключим:


var count=location.search.substring(1);

Так как параметры не именованы, не будем создавать никаких дополнительных массивов, а просто разберем строку count по частям, каждый раз выделяя часть до очередного разделителя параметров "&":


if (count!='') {
 ind=count.indexOf('&');
 if (ind>-1) {
  url=count.substring(0,ind);
  count=count.substring(ind+1,count.length);
  ind=count.indexOf('&');
  if (ind>-1) {
   picture=count.substring(0,ind);
   count=count.substring(ind+1,count.length);
   ind=count.indexOf('&');
   if (ind>-1) {
    str=count.substring(0,ind);
    var w=parseInt (str);
    if ((!isNaN(w)) && (w>0)) { width=w; }
    count=count.substring(ind+1,count.length);
    ind=count.indexOf('&');
    if (ind>-1) {
     str=count.substring(0,ind);
     var h=parseInt (str);
     if ((!isNaN(h)) && (h>0)) { height=h; }
     count=count.substring(ind+1,count.length);
     ind=count.indexOf('&');
     if (ind>-1) {
      bgcolor=count.substring(0,ind);
      count=count.substring(ind+1,count.length);
      if (ind>-1) {
       bgimage=count;
      }
     }
    }
   }
  }
 }
}

Теперь все параметры получили значения, либо оставили себе значения по умолчанию, если что-то передано неверно.

Оставшаяся часть скрипта будет формировать на основе параметров вывод:


write1(); //шапка внешней таблицы с рамкой и фоновым рисунком
write2(); //шапка внутренней таблицы + картинка-ссылка   
writedate(); //вывод текущей даты
document.writeln ('<br class=clock>'); //и, через перевод строки,
writeclock();                          //вывод времени
document.writeln ('</td></tr></table></td></tr></table>');
 //закрыть обе таблицы
</script>

Теперь наполним все функции содержимым. Сначала блок для работы с датой и временем:


var clockid=new Array();
var dateid=new Array();
var i_clock=-1,d_clock=-1,thistime,thisdate;

function initTime () { //получить и сформировать время в виде ЧЧ:ММ:СС
 thistime= new Date();
 hours=thistime.getHours();
 minutes=thistime.getMinutes();
 seconds=thistime.getSeconds();
 if (eval(hours) <10) {hours="0"+hours;}
 if (eval(minutes) < 10) {minutes="0"+minutes;}
 if (eval(seconds) < 10) {seconds="0"+seconds;}
 return (hours+":"+minutes+":"+seconds);
} 

function initDate () { //получить и сформировать дату в виде ДД.ММ.ГГГГ
 thisdate = new Date();
 Day = thisdate.getDate();
 if (Day<10) Day = '0'+ Day;
 Month = thisdate.getMonth()+1;
 if (Month<10) Month = '0'+ Month;
 Year = thisdate.getFullYear();
 return (Day + "." + Month + "." + Year);
}

function writeclock() { //Вывести часы в элемент HTML с id=i_clock стилем class=clock
 i_clock++;
 if (document.all || document.getElementById || document.layers) {
  clockid[i_clock]="clock"+i_clock;
  document.write("<span class=clock id='"+
   clockid[i_clock]+"'>"+thistime+"</span>");
 }
}

function writedate() { //Вывести дату в элемент HTML с id=d_clock тем же стилем CSS
 d_clock++;
 if (document.all || document.getElementById || document.layers) {
  dateid[d_clock]="date"+d_clock;
  document.write("<span class=clock id='"+
   dateid[d_clock]+"'>"+thisdate+"</span>");
 }
}

function clockon() { //функция, вызываемая каждую секунду для обновления даты и времени
 thistime = initTime();
 thisdate = initDate(); 
 if (document.getElementById) {
  for (i=0;i<clockid.length;i++) {
   document.getElementById(clockid[i]).innerHTML=thistime;
  }
  for (i=0;i<dateid.length;i++) {
   document.getElementById(dateid[i]).innerHTML=thisdate;
  }
 }
 var timer=setTimeout("clockon()",1000);
}

Затем добавим функции для вывода шапок обеих таблиц.


function write1 () {
 document.writeln ('<table cellspacing=0 cellpadding=0 class="table" style="border-color: '+bgcolor+'; background-image: url('+bgimage+');"><tr><td align=center valign=center>');
}

function write2() {
 document.writeln ('<table border=0 cellspacing=0 cellpadding=0 width="'+width+'" height="'+height+'"><tr><td align=center valign=center>');
 document.writeln ('<a href="'+url+'" target=_blank><img src="'+picture+'" border=0></a></td></tr><tr><td align=center valign=center>');
}

Остается инициализировать текущие дату и время.


thistime = initTime ();
thisdate = initDate ();

Добавляем стилевые классы clock и table, определяющие как будут выглядеть строки даты-времени и внешняя таблица, соединяем все в один файл и получаем этот документ (новое окно). Правда, вызванный этой ссылкой без параметров, он всегда будет показывать только мой баннер - помните же, какие значения по умолчанию мы дали?

Так что теперь напишем еще один скрипт, чтоб пользователи могли создавать информеры сами себе. Заодно используем еще одно полезное свойство JavaScript - умение проверять на правильность данные форм.

Все параметры кода информера введем через форму, подготовленную специально для этой цели. Для простоты имена полей формы совпадают с показанными выше - url, picture и т. д. Текстовую область, в которую будет выводиться сгенерированный код, назовем html. Вот полный код формы:


<form name="f1">
<table width=100% cellpadding=4 cellspacing=0 border=0>
 <tr>
  <td width="50%">1. Введите URL, по которому будет выполняться переход с информера</td>
  <td width="50%"><input type=text name=url size=40 maxlength=80 class=mainoption></td>
 </tr>
 <tr>
  <td>2. Введите URL рисунка, отображаемого на информере</td>
  <td><input type=text name=picture size=40 maxlength=80 class=mainoption></td>
 </tr>
 <tr>
  <td>3. Введите нужную ширину рисунка в пикселах</td>
  <td><input type=text name=width size=3 maxlength=3 class=mainoption></td>
 </tr>
 <tr>
  <td>4. Введите нужную высоту рисунка в пикселах</td>
  <td><input type=text name=height size=3 maxlength=3 class=mainoption></td>
 </tr>
 <tr>
  <td>5. Введите имя или код цвета рамки информера (необязательно)</td>
  <td><input type=text name=bgcolor size=20 maxlength=20 class=mainoption></td>
 </tr>
 <tr>
  <td>6. Введите URL фонового рисунка информера (необязательно)</td>
  <td><input type=text name=bgimage size=40 maxlength=80 class=mainoption></td>
 </tr>
 <tr>
  <td><input type="button" class=mainoption value="Получить код" onclick="javascript:getcode()"></td>
  <td><input type="button" class=mainoption value="Очистить все" onclick="javascript:clearall()"></td>
 </tr>
 <tr>
  <td colspan=2 align=center><textarea name=html rows=10 cols=80 class=mainoption></textarea></td>
 </tr>
</table>
</form>

Кнопки button вызывают всего две функции. Начнём с более простой clearall(), очищающей все поля формы:


<script type="text/javascript">
function clearall () {
 document.f1.url.value='';
 document.f1.picture.value='';
 document.f1.width.value='';
 document.f1.height.value='';
 document.f1.bgcolor.value='';
 document.f1.bgimage.value='';
 document.f1.html.value='';
}
//...

Так как мы вводим несколько URL-адресов, нам понадобятся функции для проверки корректности адреса (correctURL) и отсечения лишних пробелов перед тем, как проверять (trim). Коды цветов принято вводить в шестнадцатеричном представлении, значит, как минимум, нужна функция, проверяющая, является ли символ шестнадцатеричной цифрой (is_hex).

Вот листинг со всеми этими служебными функциями.


function correctURL (url) {
 var template = /^(?:(?:https?|http|ftp):\/\/(?:[a-z0-9_-]{1,32}(?::[a-z0-9_-]{1,32})?@)?)?(?:(?:[a-z0-9-]{1,128}\.)+(?:com|net|org|mil|edu|arpa|ru|gov|biz|info|aero|inc|name|[a-z]{2})|(?!0)(?:(?!0[^.]|255)[0-9]{1,3}\.){3}(?!0|255)[0-9]{1,3})(?:\/[a-z0-9.,_@%&?+=\~\/-]*)?(?:#[^ \'\"&<>]*)?$/i;
 var regex = new RegExp (template);
 return (regex.test(url) ? true : false);
}

function trim(string) {
 return string.replace (/(^\s+)|(\s+$)/g, "");
}

function is_hex(c) {
 var symbols="0123456789abcdefABCDEF";
 return (symbols.indexOf(c)==-1 ? false : true);
}

Функция getcode(), выполняющая проверку введенных в форму данных, сознательно сделана максимально простой - она проверяет по очереди все 6 полей ввода и генерирует сообщение об ошибке, как только находит незаполненное или неверно заполненное поле. С URL-адресами обойтись проще всего - достаточно проверить их на корректность регулярным выражением, содержащимся в функции correctURL(). Кстати, я не уверен, что это моё старое выражение - лучшее из возможных. Поищите в Сети - и наверняка найдёте что-то ещё. Ширина и высота картинки - целые числа, поэтому getcode() пытается преобразовать содержимое полей width и height в такие числа, заодно контролируя их на соответствие произвольно установленным нижним границам размера картинки. Контроль верхних границ обеспечивается атрибутом maxlength=3. Вряд ли кому-то понадобится информер с размером картинки больше, чем 999 пикселов. Наконец, цвета можно задавать и именами, которые поддерживаются всеми популярными браузерами (в листинге ниже Вы увидите, что строчка определения массива colors получилось длинноватой, не так ли?), и 16-ричными кодами вида #RRGGBB или RRGGBB (если не знаете, что такое коды RGB, то Вы вообще зря начинали читать статью).

Если каким-то чудом все введённые пользователем данные прошли проверки корректности, функция генерирует содержимое поля html оператором


document.f1.html.value=...;

Пользователю остаётся вставить код информера в удобное место страницы. Привожу текст функции getcode():


function getcode () {
 if (correctURL(trim(document.f1.url.value))==true) {
  url=document.f1.url.value;
 }
 else {
  window.alert ('Не введен корректный адрес URL в поле 1');
  return false;
 }
 if (correctURL(trim(document.f1.picture.value))==true) {
  picture=document.f1.picture.value;
 }
 else {
  window.alert ('Не введен корректный адрес URL в поле 2');
  return false;
 }
 var w=parseInt (trim(document.f1.width.value));
 if ((isNaN(w)==true) || (w<60)) {
  window.alert ('Не введено корректное значение в поле 3 (целое, от 60 пикселов)');
  return false;
 }
 else { width=w; }
 var h=parseInt (trim(document.f1.height.value));
 if ((isNaN(h)==true) || (h<20)) {
  window.alert ('Не введено корректное значение в поле 4 (целое, от 20 пикселов)');
  return false;
 }
 else { height=h; }
 var colors = new Array (
  "Aliceblue","Antiquewhite","Aqua","Aquamarine","Azure","Beige","Bisque","Black","Blanchedalmond","Blue","Blueviolet","Brown","Burlywood","Cadetblue","Chartreuse","Chocolate","Coral","Cornflowerblue","Cornsilk","Crimson","Cyan","Darkblue","Darkcyan","Darkgoldenrod","Darkgray","Darkgreen","Darkkhaki","Darkmagenta","Darkolivegreen","Darkorange","Darkorchid","Darkred","Darksalmon","Darkseagreen","Darkslateblue","Darkslategray","Darkturquoise","Darkviolet","Deeppink","Deepskyblue","Dimgray","Dodgerblue","Firebrick","Floralwhite","Forestgreen","Fuchsia","Gainsboro","Ghostwhite","Gold","Goldenrod","Gray","Green","Greenyellow","Honeydew","Hotpink","Indianred","Indigo","Ivory","Khaki","Lavender","Lavenderblush","Lawngreen","Lemonchiffon","Lightblue","Lightcoral","Lightcyan","Lightgoldenrod","Lightgoldenrodyellow","Lightgray","Lightgreen","Lightpink","Lightsalmon","Lightseagreen","Lightskyblue","Lightslateblue","Lightslategray","Lightsteelblue","Lightyellow","Lime","Limegreen","Linen","Magenta","Maroon","Mediumaquamarine","Mediumblue","Mediumorchid","Mediumpurple","Mediumseagreen","Mediumslateblue","Mediumspringgreen","Mediumturquoise","Mediumvioletred","Midnightblue","Mintcream","Mistyrose","Moccasin","Navajowhite","Navy","Navyblue","Oldlace","Olive","Olivedrab","Orange","Orangered","Orchid","Palegoldenrod","Palegreen","Paleturquoise","Palevioletred","Papayawhip","Peachpuff","Peru","Pink","Plum","Powderblue","Purple","Red","Rosybrown","Royalblue","Saddlebrown","Salmon","Sandybrown","Seagreen","Seashell","Sienna","Silver","Skyblue","Slateblue","Slategray","Snow","Springgreen","Steelblue","Tan","Teal","Thistle","Tomato","Turquoise","Violet","Violetred","Wheat","White","Whitesmoke","Yellow","Yellowgreen"
 );
 var c= trim(document.f1.bgcolor.value).toLowerCase();
 if (c!='') { 
  var l=colors.length;
  var code=false;
  for (var i=0; i<l; i++) {
   if (colors[i].toLowerCase() == c) {
    code=true;
    break;
   }
  }
  if (code==false) {
   l=c.length;
   if (l==7) {
    if (c.substring(0,1)=='#') { c=c.substring(1,7); l=6; }
   }
   if (l==6) {
    var k=0;
    for (i=0; i<6; i++) {
     if (is_hex(c.substring(i,i+1))==true) k++;
    }
    if (k==6) { code=true; }
   }
  }
  if (code==false) {
   window.alert ('Не введены корректный код или наименование цвета в поле 5');
   return false;
  }
  else { bgcolor=c; }
 }
 bgstr=trim(document.f1.bgimage.value);
 if (bgstr!='') {
  if (correctURL(bgstr)==true) {
   bgimage=document.f1.bgimage.value;
  }
  else {
   window.alert ('Не введен корректный адрес URL в поле 6');
   return false;
  }
 }
 var w2=width+2;
 var h2=height+27;
 document.f1.html.value='<iframe src="http://nickolay.info/myclock.html?'+
  url+'&'+picture+'&'+width+'&'+height+'&'+bgcolor+'&'+bgimage+'" scrolling="no" '+
  'width='+w2+' height='+h2+' frameborder=0 marginwidth=0 '+
  'marginheight=0 hspace=0 vspace=0></iframe>';
}

и пример тега информера, сгенерированного с данными по умолчанию:


<iframe src="http://nickolay.info/myclock.html?http://nickolay.info&http://nickolay.info/img/pers.gif&88&31&009900&http://nickolay.info/img/bg.gif" scrolling="no" width=90 height=58 frameborder=0 marginwidth=0 marginheight=0 hspace=0 vspace=0></iframe>

Атрибуты ширины и высоты тега <iframe>, как можно видеть из текста функции getcode(), приняты следующими:
w2=ширина рисунка + 2 (ширина окна тега)
h2=высота рисунка + 27 (высота окна тега)

Если я с этими размерами ошибся, их нетрудно поправить. Проверено в последних Internet Explorer и Opera, работает.

Готовый скрипт формирования тега для нашего информера, конечно же, существует: вот он (новое окно). Его код отличается от разобранного лишь тем, что к названиям полей приписаны примеры ввода. Там же показан еще один информер, наугад сделанный для сайта Mail.Ru. Остаётся только дождаться, когда они его у себя установят :)

Рейтинг@Mail.ru
вверх гостевая; E-mail