Разработка Web 2.0 приложений с помощью PHP и DHTML, Часть 2: Создание HTML элементов на лету, используя JavaScript

В первой части серии статей "Разработка Web 2.0 приложений с помощью PHP и DHTML" мы показали, как построить PHP приложения с такими элементами пользовательского интерфейса, как панели, прокрутки и всплывающие меню и окна, используя JavaScript, каскадные листы стилей (Cascading Style Sheets - CSS) и HTML. Во второй части мы рассмотрим графические приемы, которые используются в JavaScript для создания новых элементов HTML на лету.

Джек Геррингтон, старший программист, "Code Generation Network"

Джек Геррингтон (Jack Herrington) работает старшим программистом, и его стаж составляет более 20 лет. Он является автором трех книг: Code Generation in Action, Podcasting Hacks и скоро выйдет в свет новая книга PHP Hacks. Он также является автором более 30 статей.



09.05.2006

В первой части мы показали, как перемещать, прятать и отображать содержимое web-страницы. Но как создавать новые документы HTML на лету? Как графически изображать данные и использовать те же функции? На рисунке 1 показана диаграмма мирового уровня безграмотности (данные предоставлены Юнеско; см. Ресурсы).

Рисунок 1. Уровень мировой безграмотности по годам
Уровень мировой безграмотности по годам

Это не самая занимательная информация, зато ободряющая. А если вам захочется посмотреть уровень безграмотности в одной Европе? Все просто: в выпадающем меню выберите Европу.

Рисунок 2. Уровень безграмотности в Европе по годам
Уровень безграмотности в Европе по годам

На этой диаграмме видно, что уровень безграмотности в Европе намного ниже мирового. В листинге 1 показан код, который выводит эту динамическую диаграмму.

Листинг 1. Код гистограммы
<html>
<head>
<title>Bar Graph Example</title>
<script>
var years = [ 1970, 1980, 1990, 1995, 2000, 2005, 2010, 2015 ];

var rates = [];
rates[ 'World' ] = [ 36.6, 30.3, 24.7, 22.4,
  20.3, 18.3, 16.5, 15.0 ];
rates[ 'Africa' ] = [ 72.4, 62.4, 51.2, 45.6,
  40.2, 35.2, 30.8, 26.8 ];
rates[ 'America' ] = [ 14.8, 11.6, 9.0, 7.9,
  6.9, 6.0, 5.3, 4.6 ];
rates[ 'Asia' ] = [ 48.5, 38.7, 30.2, 27.2,
  24.4, 21.8, 19.6, 17.7 ];
rates[ 'Europe' ] = [ 6.4, 4.3, 2.8, 2.2, 1.8,
  1.4, 1.1, 0.8 ];
rates[ 'Oceania' ] = [ 11.1, 8.7, 7.1, 6.6,
  6.1, 5.6, 5.3, 5.0 ];

function plot( region )
{
  var html = "";
  html += "<table width='100%' cellspacing='0' cellpadding='1'>";
  for( var year in years )
  {
    var val = Math.round( rates[region][year] );
    html += "<tr>";
    html += "<td width='8%'>"+years[year]+"</td>";
    html += "<td width='1%' class='bar-start'></td>";
    html += "<td width='92%'>";
    html += "<table width='100%' cellspacing='0' ";
	html += "cellpadding='0'><tr>";
    html += "<td width='"+val+"%' class='bar-on'>";
	html += "&nbsp;</td>";
    html += "<td width='"+(100-val);
	html += "%' class='bar-off'>&nbsp;</td>";
    html += "</tr></table></td>";
    html += "<td width='1%' class='bar-start'></td>";
    html += "</tr>";
  }
  html += "</table>";
  document.getElementById( "graph" ).innerHTML = html;
}
</script>
<style>
body { font-family: arial, verdana, sans serif; }
.bar-on { background: blue; }
.bar-off { background: white; }
.bar-start { width:1px; background: black; }
#graph { width: 600px; }
</style>
</head>
<body onload="plot('World')">
Region:
<select onchange="plot(this.options[this.selectedIndex].value)">
<option value="World">World</option>
<option value="Africa">Africa</option>
<option value="America">America</option>
<option value="Asia">Asia</option>
<option value="Europe">Europe</option>
<option value="Oceania">Oceania</option>
</select><br/><br/>
Rates of illiteracy (larger is worse):<br/><br/>
<div id="graph">
</div>
</body>
</html>

Начнем с пустого тега <div> и значением ID - "graph". Атрибут onload тега <body> сообщает браузеру вызвать функцию plot, когда загружается страница. С функции plot начинается все самое интересное.

Сначала функция создает пустую строку. Затем она строит диаграмму, добавляя в строку теги <table>, <tr> и <td>. Далее функция добавляет атрибут innerHTML к тегу graph <div>, и создается новый документ HTML.

Сам по себе граф - это таблица с четырьмя колонками: годы, маленькая вертикальная полоска, полосы диаграммы и еще одна вертикальная полоска. Внутри каждой строки в колонке полос есть еще одна таблица. Эта внутренняя таблица имеет две ячейки: синяя и белая. Процент безграмотности составляет длину синий полоски, а длина белой получается, если мы из 100 вычтем исходные проценты. В результате получим простую гистограмму в HTML без рисунков.

Выпадающее меню региона управляется атрибутом onchange, который вызывается каждый раз, когда выбран новый объект. И тогда запускается метод plot с выбранным текущем значением и диаграмма обновляется.

Это очень совместимый код. Использование атрибута innerHTML, который может заменяться такими методами DOM, как createElement и appendChild, совместимо со всеми современными браузерами.

Гистограммы на PHP

Чтобы использовать PHP для гистограмм, мы рассмотрим в этой статье, как выбирать данные из кода PHP с сервера и интегрировать их в динамический HTML (DHTML) JavaScript. Код на PHP для гистограммы показан в листинге 2.

Листинг 2. Код на PHP для гистограммы
<?php
$years = array( 1970, 1980, 1990, 1995, 2000, 2005, 2010, 2015 );
$countries = array();
$countries[ "World" ] = array( 36.6, 30.3, 24.7, 22.4,
  20.3, 18.3, 16.5, 15.0 );
$countries[ "Africa" ] = array( 72.4, 62.4, 51.2, 45.6,
  40.2, 35.2, 30.8, 26.8 );
$countries[ "America" ] = array( 14.8, 11.6, 9.0, 7.9,
  6.9, 6.0, 5.3, 4.6 );
$countries[ "Asia" ] = array( 48.5, 38.7, 30.2, 27.2,
  24.4, 21.8, 19.6, 17.7 );
$countries[ "Europe" ] = array( 6.4, 4.3, 2.8, 2.2,
  1.8, 1.4, 1.1, 0.8 );
$countries[ "Oceania" ] = array( 11.1, 8.7, 7.1, 6.6,
  6.1, 5.6, 5.3, 5.0 );
?>
<html>
<head>
<title>Bar Graph Example</title>
<script>
var years = [ <?php echo( join( ",", $years ) ); ?> ];

var rates = [];
<?php
foreach( $countries as $name => $values ) {
?>
rates[ '<?php echo($name) ?>' ] = [
  <?php echo( join( ",", $values ) ); ?> ];
<?php } ?>

function plot( region )
{
  var html = "";
  html += "<table width='100%' cellspacing='0' cellpadding='1'>";
  for( var year in years )
  {
    var val = Math.round( rates[region][year] );
    html += "<tr>";
    html += "<td width='8%'>"+years[year]+"</td>";
    html += "<td width='1%' class='bar-start'></td>";
    html += "<td width='92%'>";
    html += "<table width='100%' cellspacing='0' cellpadding='0'><tr>";
    html += "<td width='"+val+"%' class='bar-on'>&nbsp;</td>";
    html += "<td width='"+(100-val)+"%' class='bar-off'>&nbsp;</td>";
    html += "</tr></table></td>";
    html += "<td width='1%' class='bar-start'></td>";
    html += "</tr>";
  }
  html += "</table>";
  document.getElementById( "graph" ).innerHTML = html;
}
</script>
<style>
body { font-family: arial, verdana, sans serif; }
.bar-on { background: blue; }
.bar-off { background: white; }
.bar-start { width:1px; background: black; }
#graph { width: 600px; }
</style>
</head>
<body onload="plot('World')">
Region: <select onchange="plot(this.options[this.selectedIndex].value)">
<?php
foreach( $countries as $name => $values ) {
?>
<option value="<?php echo($name) ?>"><?php echo($name) ?></option>
<?php } ?>
</select><br/><br/>
Rates of illiteracy (larger is worse):<br/><br/>
<div id="graph">
</div>
</body>
</html>

В начале файла расположены массивы years и countries, в них перечислены годы и список стран с уровнем безграмотности. Теперь PHP создает три DHTML кода. Первый заполняет массив years в JavaScript, второй заполняет rates, а третий устанавливает соответствие между тегом <select> и названиями стран.


Точечный график

Создание новых документов HTML на лету - основа DHTML. Как вариант можно создать строку и установить теги HTML для внутренних элементов на странице. Этот пример показывает второй метод, использующий в качестве примера точечный график. На рисунке 3 показан график простого уравнения.

Рисунок 3. График нескольких периодов синуса
График нескольких периодов синуса

Вы можете изменить уравнение и нажать кнопку Try It!, чтобы обновить график, как показано на рисунке 4.

Рисунок 4. График немного измененного уравнения
График немного измененного уравнения

И всё это не обращаясь к PHP-серверу. Этот пример вообще не использует сервер - вы просто создаете новый HTML-файл и начинаете писать HTML код. Код для графика показан в листинге 3.

Листинг 3. Код для точечного графика
<html>
<head>
<title>Dynamic Graphing Example</title>
<style type="text/css">
body { font-family: arial, verdana, sans serif; }
#graphdiv {
  height:500px; width:500px;
  border:1px solid black;
  position:relative;
}
</style>
<script>
function drawgraph()
{
  var g = document.getElementById( "graphdiv" );
  var eq = document.getElementById( "eq" ).value;

  var dx = [];
  var dy = [];

  var sx = 10000;
  var ex = -10000;
  var sy = 10000;
  var ey = -10000;

  for( var i = 0; i < 100; i++ )
  {
    var x = i / 100;
    var y = eval( eq );
    if ( y > ey ) ey = y;
    if ( y < sy ) sy = y;
    if ( x > ex ) ex = x;
    if ( x < sx ) sx = x;
    dx.push( x );
    dy.push( y );
  }

  var gwidth = 500;
  var gheight = 500;
  var imgwidth = 100;
  var imgheight = 100;

  var fx = (gwidth-(imgwidth/2))/(ex-sx);
  var fy = ((gheight-(imgheight/2))/2)/(ey-sy);

  g.innerHTML = "";
  for( i = 0; i < dx.length; i++ )
  {
    var x = ( dx[i] * fx );
    var y = ((gheight-(imgheight/2))/2)+(dy[i]*fy);
    var img = document.createElement( "img" );
    img.src = "ball.gif";
    img.style.position = "absolute";
    img.style.top = y+"px";
    img.style.left = x+"px";
    g.appendChild( img );
  }
}
</script>
</head>
<body onload="drawgraph()">
Equation:
<input type="text" id="eq" value="Math.sin(x*32)" />
<button onclick="drawgraph()">Try It!</button>
<br/><br/>
<div id="graphdiv">
</div>
</body>
</html>

Основная часть кода содержится в функции JavaScript drawgraph. Эта функция создает два массива чисел - один для значений x, второй для значений y. Значения оси x пробегают от 0 до 1; а значения оси y получаются вычислением уравнения для заданного значения x.

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

Чтобы подключить рисунки к графику, мы воспользуемся новой техникой: Используем переменную document.createElement для создания тега <img>, затем применяем appendChild, чтобы добавить только что созданный объект img к объекту графика. Применяя эту технику удобнее устанавливать значения атрибута innerHTML, используя строку, потому что код удобнее читать и сохранять - и вам не надо беспокоиться о проблеме кодировки строки.

Техника использования createElement совместима со спецификациями World Wide Web Consortium (W3C) Document Object Model (DOM) (Объектная модель документов) и является лучшим способом динамического создания элементов HTML.


Точечные графики на PHP

Пример точечного графика замкнутый. PHP код покрывает точечный график как компонент. Код для компонента показан в листинге 4.

Листинг 4. Код точенчного графика на PHP
<?php
function graph_header()
{
?>
<style type="text/css">
body { font-family: arial, verdana, sans serif; }
#graphdiv {
  height:500px; width:500px;
  border:1px solid black;
  position:relative;
}
</style>
<script>
function drawgraph()
{
  var g = document.getElementById( "graphdiv" );
  var eq = document.getElementById( "eq" ).value;

  var dx = [];
  var dy = [];

  var sx = 10000;
  var ex = -10000;
  var sy = 10000;
  var ey = -10000;

  for( var i = 0; i < 100; i++ )
  {
    var x = i / 100;
    var y = eval( eq );
    if ( y > ey ) ey = y;
    if ( y < sy ) sy = y;
    if ( x > ex ) ex = x;
    if ( x < sx ) sx = x;
    dx.push( x );
    dy.push( y );
  }

  var gwidth = 500;
  var gheight = 500;
  var imgwidth = 100;
  var imgheight = 100;

  var fx = (gwidth-(imgwidth/2))/(ex-sx);
  var fy = ((gheight- (imgheight/2))/2)/(ey-sy);

  g.innerHTML = "";
  for( i = 0; i < dx.length; i++ )
  {
    var x = ( dx[i] * fx );
    var y = ((gheight-(imgheight/2))/2)+(dy[i]*fy);
    var img = document.createElement( "img" );
    img.src = "ball.gif";
    img.style.position = "absolute";
    img.style.top = y+"px";
    img.style.left = x+"px";
    g.appendChild( img );
  }
}
</script>
<?php
}

function graph_place()
{
?>
</head>
<div id="graphdiv">
</div>
<?php
}
?>

Этот код определяет две функции: graph_header и graph_place. Функция graph_header должна вызываться в заголовке документа, а graph_place будет вызвана там, где вы захотите расположить график. В листинге 5 показан код для обновленной страницы с графиком.

Листинг 5. Обновленный код на PHP для графика
<?php
require_once( "graph_component.php" );
?>
<html>
<head>
<title>Dynamic Graphing Example</title>
<?php graph_header(); ?>
</head>
<body onload="drawgraph()">
Equation:
<input type="text" id="eq" value="Math.sin(x*32)" />
<button onclick="drawgraph()">Try It!</button>
<br/><br/>
<?php graph_place(); ?>
</body>
</html>

Это намного проще первоначального варианта страницы. Вы включаете код для компонента. Затем вызываете функцию graph_header, чтобы добавить JavaScript и CSS. Наконец, вызываете функцию graph_place там, где хотите разместить граф на странице.


Как далеко может зайти DHTML?

Совсем не сложно получить картинку в мощном и простом коде на JavaScript. Но теперь вопрос не в том, как мало можно завернуть в конверт, а в том, как далеко его можно протолкнуть. Карты Google (см. Ресурсы) - это отличный пример приложения на DHTML, которое не только полезно на сайте, но также может быть интегрировано в любую интернет-страницу, как небольшой JavaScript. Но Google на этом не остановился: он создал почту Gmail (см. Ресурсы), где активно использует DHTML для создания простого в обращении почтового клиента прямо в браузере. (Возможно, вам не удастся так далеко продвинуть вашу программу на JavaScript, но приятно посмотреть, что может получиться, если бы у вас было время.)

Каждый программист на DHTML должен посмотреть такую технологию, как Asynchronous JavaScript and XML (Ajax). Ajax добавляет возможность браузерам отодвинуть интернет-запросы на задний план. Это значит, что ваше приложение на DHTML может вызывать приложение на PHP, не требуя обновление страницы. Страница может использовать эти данных для обновления представленной информации - и все это не покидая уютной страницы, на которую зашел пользователь. (см. Ресурсы для ссылок на статьи и руководства по Ajax.)


Заключение

Предыдущая статья этой серии "Разработка Web 2.0 приложений с помощью PHP и DHTML" начиналась с модного слова Web 2.0. Другое модное выражение - расширенные клиентские приложения (rich client applications). Оба они означают классные web-приложения. Существует множество технологий для создания расширенных интренет-приложений (rich Internet applications). Laszlo и MXML намного упростили создание Flash, а Microsoft® взял несколько идей от Vista. Но DHTML пытается создавать расширенные интренет-приложения, потому что вы сможете создавать их с помощью технологий, которые уже освоили, как например, PHP.

В этой статье показаны несколько методов обогатить ваш опыт простыми CSS и JavaScript. Вы можете сделать то же самое с приложениями, над которыми сейчас работаете - просто откройте тег <script> и наслаждайтесь.

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source
ArticleID=164831
ArticleTitle=Разработка Web 2.0 приложений с помощью PHP и DHTML, Часть 2: Создание HTML элементов на лету, используя JavaScript
publish-date=05092006