Архив за Сентябрь 2008

Корзина для Интернет-магазина средствами JavaScript

Построение Интернет-магазина - это наиболее распространенная задача при построении бизнес-приложений для Интернет. В общем случае она сводится к построению каталога товаров, виртуальной корзины выбранных товаров и системы подтверждения заказа (отправка e-mail и сохранение информации о заказе в базе данных).

Учитывая, что многие Интернет-магазины предлагают лишь ограниченное число товаров (менее 100), все товары в этом случае могут быть отображены в одной большой таблице.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<html>
<title>Интернет-магазин</title>
<meta http-equiv="content-type" content="text/html; windows-1251" />
<script type="text/javascript">
var goods = new Array();
goods = [  
  ["M005","Монитор Acer AL1916CS","Описание Acer AL1916CS",6000],
  ["M006","Монитор Acer AL2216WSD","Описание Acer AL2216WSD",8900],
  ["M007","Монитор Acer AL2416WBSD","Описание Acer AL2416WBSD",15000],
  ["M009","Монитор BenQ G700","Описание BenQ G700",4800],
  ["M008","Монитор BenQ G900W","Описание BenQ G900W",5000],
  ["M003","Монитор Samsung 2043NW","Описание Samsung 2043NW",7000],
  ["M001","Монитор Samsung 740N","Описание Samsung 740N",5700],
  ["M002","Монитор Samsung 943N","Описание Samsung 943N",6430],
  ["M004","Монитор Samsung SM2232BW","Описание Samsung SM2232BW",11500],
  ["N001","Ноутбук Acer Aspire 5315","Описание Acer Aspire 5315",14500],
  ["N002","Ноутбук Acer Extensa 5220","Описание Acer Extensa 5220",15500],
  ["N003","Ноутбук Samsung R20","Описание Samsung R20",15800],
  ["N004","Ноутбук Samsung R60","Описание Samsung R60",20100],
  ["N006","Ноутбук Toshiba A210-199","Описание Toshiba A210-199",17000],
  ["N005","Ноутбук Toshiba A210-19A","Описание Toshiba A210-19A",24700],
  ["P001","Принтер EPSON PictureMate 290","Описание EPSON PictureMate 29",7300],
  ["P002","Принтер EPSON Stylus Photo R270","Описание EPSON Stylus Photo R270",3650],
  ["P003","Принтер EPSON Stylus Photo R390","Описание EPSON Stylus Photo R390",6200]
];
 
var count = goods.length;
var orders = new Array();
for( var i = 0; i < count; i++ ) orders[i] = 0;

var param = getCookie( "basket" );
for( var i = 0; i < count; i++ ) {
  pos = param.indexOf( ',' );
  if( pos == -1 ) break;
  orders[i] = parseInt( param.substring ( -1, pos ) );
  param = param.substring ( pos+1 );
}

window.onload = function() {
  var table = createTable(goods);   
  document.getElementById("shop").appendChild(table);
}
 
function updateTable()
{
  var totalGoods = 0;
  var totalCosts = 0;
  var basket = "";
  for ( var i = 0; i < count; i++ ) {
    var item = document.getElementById( "item"+i );
    var cnt = parseInt( item.value );
    if ( isNaN(cnt) || cnt < 0 ) {
      cnt = 0;
      item.value = "0";
    }
    if ( cnt > 0 )
      item.parentNode.parentNode.setAttribute("bgcolor", "lightblue");
    else
      item.parentNode.parentNode.removeAttribute("bgcolor")
    orders[i] = cnt;
    basket = basket + cnt + ",";
    totalGoods = totalGoods + cnt;
    totalCosts = totalCosts + cnt*goods[i][3];
  }
  var span = document.getElementById("totalGoods");
  var newTextNode = document.createTextNode(totalGoods);
  span.replaceChild(newTextNode, span.firstChild);
  var span = document.getElementById("totalCosts");
  var newTextNode = document.createTextNode(totalCosts);
  span.replaceChild(newTextNode, span.firstChild);
 
  setCookie("basket", basket);
}

function createTable(data) {
  var table = document.createElement("table");
  table.setAttribute("border", "1");
  table.setAttribute("cellspacing", "0");
  table.setAttribute("cellpadding", "2");
  var thead = document.createElement("thead");
  var tr = document.createElement("tr");
  tr.setAttribute("bgcolor", "lightgrey");
  var head = new Array("Код","Наименование","Описание","Стоимость","Количество");
  for (var i = 0; i < head.length; i++) {
    var th = document.createElement("th");
    var newText = document.createTextNode(head[i]);
    th.appendChild(newText);
    tr.appendChild(th);
  }
  thead.appendChild(tr);
  table.appendChild(thead);

  var totalGoods = 0;
  var totalCosts = 0.0;
 
  var tbody = document.createElement("tbody");
  for (var i = 0; i < data.length; i++) {
    var tr = document.createElement("tr");
    if ( orders[i] > 0 ) tr.setAttribute("bgcolor", "lightblue");
    for (var j=0; j < data[i].length; j++) {
      var td = document.createElement("td");
      var newText = document.createTextNode(data[i][j]);
      td.appendChild(newText);
      tr.appendChild(td);
    }
    var td = document.createElement("td");
    var newInput = document.createElement("input");
    newInput.setAttribute("type", "text");
    newInput.setAttribute("id", "item"+i);
    newInput.setAttribute("value", orders[i]);
    newInput.setAttribute("size", "3");
    newInput.onblur = updateTable;
    td.appendChild(newInput);
    tr.appendChild(td);
    tbody.appendChild(tr);

    totalGoods = totalGoods + orders[i];
    totalCosts = totalCosts + orders[i]*goods[i][3];
  }
  var tr = document.createElement("tr");
  var td = document.createElement("td");
  td.setAttribute("colspan", "3");
  td.setAttribute("align", "right");
  var textNode = document.createTextNode("Итого:");
  td.appendChild(textNode);
  tr.appendChild(td);
  var td = document.createElement("td");
  var span = document.createElement("span");
  span.setAttribute("id", "totalCosts");
  var textNode = document.createTextNode(totalCosts);
  span.appendChild(textNode);
  td.appendChild(span);
  tr.appendChild(td);
  var td = document.createElement("td");
  var span = document.createElement("span");
  span.setAttribute("id", "totalGoods");
  var textNode = document.createTextNode(totalGoods);
  span.appendChild(textNode);
  td.appendChild(span);
  tr.appendChild(td);
  tbody.appendChild(tr);

  table.appendChild(tbody);
  return table;
}

function setCookie(name,value)
{
  document.cookie = name + '=' + value;
}   

function getCookie(name)
{
  var arg = name + "=";
  startpos = document.cookie.indexOf(arg, 0);
  if (startpos == -1)
    return "";
  else
    startpos += arg.length;
  endpos = document.cookie.indexOf(';', startpos);
  if (endpos == -1) endpos = document.cookie.length;
  return document.cookie.substring(startpos, endpos);
}
</script>


</head>
<body>

<div id="shop"></div>

</body>
</html>

В приведенном выше листинге все имеющиеся товары выводятся в виде таблицы. Строка со списком количества всех заказанных товаров для всех наименований сохраняется в cookie (переменная basket).

Количество товаров содержится в переменной count. В массиве orders хранится количаство заказанных товаров соответствующего наименования. Заказанные единицы товара всех наименований перечисляются через запятую, даже если заказано нулевое количество любого товара. При построении таблицы ведется расчет общего количества заказанных товаров (переменная totalGoods) и суммарной стоимости заказанных товаров (переменная totalCosts). Финальные значения переменных totalGoods и totalCosts выводятся в последней строке таблицы.

Ссылки по теме:

Время формирования страницы

Для вычисления времени формирования страницы с требуемой точностью можно использовать функцию microtime(), которая возвращает строку вида “msec sec”, где msec - составляющая в микросекундах, а sec - время в секундах, прошедшее с 1970 года. Результат, возвращаемый функцией, может быть, к примеру, таким:

0.48023600 1076713360

Такое представление не очень удобно для вычисления разницы во времени, поэтому его необходимо преобразовать в числовой вид. Иначе говоря, строку “msec sec” необходимо преобразовать к виду “sec.msec”:

<?php
$part_time = explode(' ', microtime());
$real_time = $part_time[1].substr($part_time[0], 1);
?>

Здесь при помощи функции explode() стока, принимаемая во втором параметре, разбивается на подстроки по разделителю, передаваемому в первом параметре (в нашем случае это символ пробела).

Для получения разности между двумя числами, представленными в виде строк, можно воспользоваться функцией bcsub():

<?php
$diff_time = bcsub($stop_time, $start_time, 5);
?>

Здесь 5 - число знаков после запятой. Таким образом код, вычисляющий время генерации страницы, выглядит так:

<?php
$start_time = gettime();

// Здесь код, формирующий страницу

$stop_time = gettime();
$diff_time = bcsub($stop_time, $start_time, 5);
echo '<p>Страница сформирована за '.$diff_time.' сек.</p>';

// Вспомогательная функция
function gettime()
{
  $part_time = explode(' ', microtime());
  $real_time = $part_time[1].substr($part_time[0], 1);
  return $real_time;
}
?>