DHTML-конструирование
Урок 9. Конюх (скрипты)

Перетаскивание элементов по экрану

Перетаскивание экранного элемента в графических системах пользователь привык выполнять так:

Если нужно перемещать по экрану, например, картинку <IMG>, то вызов собственных обработчиков событий можно вмонтировать в этот тег:

Когда перемещаемых элементов много, удобнее вызов обработчиков помещать не в тегах, а прямо в объекте document:


// Назначение обработчиков для событий,
// связанных с перетаскиванием
document.onmousedown = mouseDownEvent;
document.onmousemove = mouseMoveEvent;
document.onmouseup   = mouseUpEvent;

// Обработка захвата элемента
// --------------------------
function mouseDownEvent()
{
  ...
}

// Обработка перемещения элемента
// ------------------------------
function mouseMoveEvent()
{
  ...
}

// Обработка освобождения элемента
// -------------------------------
function mouseUpEvent()
{
  ...
}

Свойства onmousedown, onmousemove, onmouseup объекта document содержат ссылки на функции, которые обрабатывают соответствующие события. Команды:


document.onmousedown = mouseDownEvent;
document.onmousemove = mouseMoveEvent;
document.onmouseup   = mouseUpEvent;

записывают в эти свойства ссылки на функции mouseDownEvent(), mouseMoveEvent(), mouseUpEvent(), которые предстоит запрограммировать.

Пусть, например, нам нужно перемещать по экрану любую картинку (тег <IMG>). Когда пользователь “захватывает” элемент, управление передается в функцию mouseDownEvent(). Нужно проверить, что элемент действительно является картинкой, и запомнить ссылку на объект, построенный браузером для этого элемента:


// Указатель на перетаскиваемый элемент или null
var imgDragging = null;

// Обработка захвата элемента
// --------------------------
function mouseDownEvent()
{
  // Это картинка?
  if (event.srcElement.tagName == "IMG")
  {
    // Запомним указатель на объект
    imgDragging = event.srcElement;
  }
  // Перетаскивание запрещено
  else imgDragging = null;
}

На самом деле, в момент захвата элемента нужно сделать еще две вещи: запомнить координаты мышиного курсора относительно левого верхнего угла перемещаемого элемента и “приподнять” элемент над основным слоем (чтобы он перемещался “поверх” всех других элементов экрана):


// Указатель на перетаскиваемый элемент или null
var imgDragging = null;

// Положение курсора относительно элемента
// в момент начала перетаскивания
var dx;
var dy;

// Обработка захвата элемента
// --------------------------
function mouseDownEvent()
{
  // Это картинка?
  if (event.srcElement.tagName == "IMG")
  {
    // Запомним указатель на объект
    imgDragging = event.srcElement;

    // Вычислим смещения мышиного курсора
    // относительно начала перетаскиваемого элемента
    dx = event.offsetX;
    dy = event.offsetY;

    // Передвинем элемент в верхний слой
    imgDragging.style.zIndex = 1;
  }
  // Перетаскивание запрещено
  else imgDragging = null;
}

Вот теперь все подготовлено к перемещению элемента по экрану! Обработка события mousemove может быть такой:


// Обработка перемещения элемента
// ------------------------------
function mouseMoveEvent()
{
  if (imgDragging != null)
  {
    // Вычислим новые координаты элемента
    imgDragging.style.pixelLeft = event.x - dx;
    imgDragging.style.pixelTop  = event.y - dy;

    // Остановим прохождение события
    event.cancelBubble = true;
    event.returnValue = false;
  }
}

Последние две команды запрещают браузеру обрабатывать событие mousemove стандартным образом (стандартная обработка помешает работе наших кодов). Теперь осталось написать обработчик события mouseup (пользователь отпустил кнопку мыши). Код этого обработчика крайне прост: в нем устанавливается флаг запрета дальнейшего перемещения, и элемент возвращается в основной экранный слой.


// Обработка освобождения элемента
// -------------------------------
function mouseUpEvent()
{
  if (imgDragging != null)
  {
    // Вернем элемент в основной  слой
    imgDragging.style.zIndex = 0;

    // Сбросим признак перемещения
    imgDragging = null;
  }
}

Ниже представлена ссылка на документ, в котором сведены воедино все рассмотренные выше скрипты. Поработайте с ним и посмотрите его код.

Перетаскивание картинок в документе

Добавим в HTML-код примера еще одну картинку — изображение шахматной доски, не меняя при этом обслуживающие скрипты. Понятно, что третья картинка подвержена перетаскиванию по экрану, как и первые две.

Перетаскивание трех картинок

Поставим программистскую задачу — разрешить пользователю перемещать только коней. Запишем в каждом теге, кодирующего коня, атрибут id со значением horseXY, где “X” и “Y” — соответствуют координатам клетки шахматного поля, в которой конь расположен в начальный момент. Теперь легко отличить картинку, изображающую коня от других:


// Обработка захвата элемента
// --------------------------
function mouseDownEvent()
{
  // Это конь?
  if (event.srcElement.id.indexOf("horse") != -1)
  {
    // Запомним указатель на объект
    imgDragging = event.srcElement;
    // Вычислим смещения мышиного курсора
    // относительно начала перетаскиваемого элемента
    dx = event.offsetX;
    dy = event.offsetY;

    // Элемент передвинем  в верхний слой
    imgDragging.style.zIndex = 1;
  }
  // Перетаскивание запрещено
  else imgDragging = null;
}

Теперь картинка с шахматной доской перетаскиванию не подвержена:

Перетаскивание только коней

Следующий шаг — ограничить перемещение коней внутренностью шахматного поля: нужно проверять координаты мышиного курсора перед тем, как присваивать коням новые координаты:

Перетаскивание коней внутри шахматной доски

Перед тем, как “освобождать” коня от связи с курсором, нужно определить шахматную клетку, над которой “повис” конь; проверить допустимость хода и, если ход возможен, подровнять коня по центру клетки.

Модальные окна

В программе Конюх используются “всплывающие” сообщения двух типов.

Сообщения первого типа реализованы при помощи обычных картинок, которые в обычном состоянии не видны на экране (стилевое свойство visibility установлено в hidden), а в нужный момент показываются (visibility устанавливается в visible).

Сообщения второго типа показываются в так называемых модальных окнах. Модальное окно блокирует работу в основном окне до тех пор, пока не будет закрыто.

Модальное окно открывается при помощи метода showModalDialog объекта window. Формат метода:


перем=window.showModalDialog(файл,аргумент,параметры);

Здесь:

Параметры окна задаются в строке параметры в виде:


"пар1=знач1;пар2=знач2;...;парN=значN"

Вместо знака равенства можно использовать двоеточие (как в стилевых определениях). Допустимо задание следующих параметров:

параметр значение описание
dialogWidth число Ширина окна.
dialogHeight число Высота окна.
dialogTop число Вертикальная координата левого верхнего угла окна.
dialogLeft число Горизонтальная координата левого верхнего угла окна.
center yes, no, 1, 0 Выравнивать ли окно по центру экрана.
help yes, no, 1, 0 Показывать ли кнопку вызова подсказки в заголовке окна.

Модальное окно без аргументов

В первом примере покажем вызов модального окна без передачи в него аргументов. Подготовим файл 0905.htm (он будет отображаться в модальном окне):

Для вызова модального окна напишем такой код:

Можно посмотреть, что из этого получилось:

Вызов окна без передачи в него аргументов.





Модальное окно с одним аргументом

Во втором примере выведем аргумент модального окна на экран. HTML-код окна выглядит так (файл 0906.htm):

Вызов модального окна и передачу в него аргумента закодируем так:

А теперь можно посмотреть, как работают записанные коды:

Введите аргумент (он будет передан в модальное окно):





Модальное окно с несколькими аргументами

В модальное окно можно передать сколько угодно аргументов, разместив их в массиве. Подготовим код модального окна (файл 0907.htm), которое будет выводить на экран два переданных ему аргумента:

Построим испытательный стенд:

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

Введите аргументы модального окна:






Модальное окно возвращает данные

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

Получить данные из модального окна очень просто. В модальном окне нужно ссылку на них поместить в свойство window.returnValue. А в документе-родителе при вызове окна воспользоваться конструкцией ret = window.showModalDialog(...);. Переменная ret и будет содержать возвращаемые данные после закрытия модального окна. Возвращать можно одиночное значение или целый массив данных.

Давайте посмотрим, как происходит возврат настроек программы, выполненных пользователем в модальном окне программы Конюх.

Код этого модального окна (файл 0908.htm) выглядит так:

Для тестирования этого модального окна построим такой испытательный стенд:

Прочитайте приведенные выше коды и проверьте их работу, поработав на построенном стенде:

В модальное окно передаются следующие установки:

Число коней  4
 6
Перетаскивание  да
 нет

Из модального окно возвращено:





DHTML-конструирование RU 2000/2001 © А.А.Дуванов

оглавление урок 8 письмо автору об авторах