Возможность перемещать объекты по экрану без ограничений и с минимальными усилиями – это, конечно, хорошо, но рано или поздно наверняка потребуется определять границы перемещения, возможность перекрытия и задавать другие ограничения. К счастью, реализация механизма «перетащил и бросил» позволяет уменьшить объем программного кода, который обычно приходится писать, чтобы наложить ограничения на возможность перемещения.
В состав модуля dojo.dnd включены три основных средства, позволяющие наложить ограничения на перемещение объектов: можно определить собственную функцию, реализующую ограничения, которая будет динамически вычислять границы допустимой области (объект constrainedMoveable), можно определить статические границы в момент создания перемещаемого объекта (объект boxConstrainedMoveable) и ограничить область перемещения рамками другого, родительского узла (объект parentConstrainedMoveable). Формат представления каждой разновидности допустимой области следует соглашениям. Ниже приводится измененная версия предыдущего примера с наклейками, где демонстрируется наложение ограничений посредством функции constrainedMoveable:
<html>
<head>
<title>Moving Around</title>
<style type="text/css">
.note {
background: #FFFFBF;
border-bottom: 1px solid black;
border-eft: 1px solid black;
border-right: 1px solid black;
width: 302px;
height: 300px;
margin : 0px;
padding : 0px;
}
.noteHandle {
border-left: 1px solid black;
border-right: 1px solid black;
border-top: 1px solid black;
cursor :pointer;
background: #FFFF8F;
width : 300px;
height: 10px;
margin : 0px;
padding : 0px;
}
.movingNote {
background : #FFFF3F;
}
#note1, #note2 {
width : 302px
}
</style>
<script
type="text/javascript"
src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js">
</script>
<script type="text/javascript">
dojo.require("dojo.dnd.Moveable");
dojo.require("dojo.dnd.move");
dojo.addOnLoad(function() {
var f1 = function() {
//вычисления, определяющие границы допустимой
//области удерживать элемент note1 не более
//чем на 50 пикселей правее и ниже узла note2
var mb2 = dojo.marginBox("note2");
b = {};
b["t"] = 0;
b["l"] = 0;
b["w"] = mb2.l + mb2.w + 50;
b["h"] = mb2.h + mb2.t + 50;
return b;
}
var m1 = new dojo.dnd.move.constrainedMoveable("note1",
{handle : "dragHandle1", constraints : f1,
within : true});
var m2 = new dojo.dnd.Moveable("note2", {handle :
"dragHandle2"});
var zIdx = 1;
dojo.connect(m1, "onMoveStart", function(mover){
dojo.style(mover.host.node, "zIndex", zIdx++);
});
dojo.connect(m2, "onMoveStart", function(mover){
dojo.style(mover.host.node, "zIndex", zIdx++);
});
});
</script>
</head>
(body)
<div id="note1">
<div id='dragHandle1' class="noteHandle"></div>
<textarea class="note">Note1</textarea>
</div>
<div id="note2">
<div id='dragHandle2' class="noteHandle"></div>
<textarea class="note">Note2</textarea>
</div>
(/body)
</html>
В этом примере для внешнего элемента div, образующего имитацию наклейки, явно была задана ширина, чтобы можно было точно определить его границы полей с помощью функции dojo.marginBox. А функция, задающая границы области, определяет такие ограничения, чтобы элемент note1 нельзя было переместить правее и ниже элемента note2 более чем на 50 пикселей.
Вариант с использованием статических границ допустимой области реализуется еще проще. Вместо функции, вычисляющей границы, нужно просто передать явные значения. Измените предыдущий пример так, чтобы превратить элемент note2 в объект boxConstrainedMoveable, как показано ниже, и посмотрите, что из этого получится:
var m2 = new dojo.dnd.move.boxConstrainedMoveable("note2",
{
handle : "dragHandle2",
box : {l : 20, t : 20, w : 500, h : 300}
});
Этот пример работает точно так же, как и прежде, за исключением того, что объект note2 нельзя переместить за определенные границы.
Наконец, подобным образом действует объект parentConstrainedMoveable: вы просто создаете перемещаемые объекты и определяете ширину и высоту родительского элемента, достаточные для обеспечения необходимого рабочего пространства. При использовании специализированного класса не придется делать никакой дополнительной работы.
Ниже приводится еще одна работающая версия нашего примера:
<!-- ... обрезано ... -->
.parent {
background: #BFECFF;
border: 10px solid lightblue;
width: 400px;
height: 700px;
padding: 10px;
margin: 10px;
}
<!-- ... обрезано ... -->
<script type="text/javascript">
dojo.require("dojo.dnd.move");
dojo.addOnLoad(function() {
new dojo.dnd.move.parentConstrainedMoveable("note1",
{
handle : "dragHandle1", area: "margin", within: true
});
new dojo.dnd.move.parentConstrainedMoveable("note2",
{
handle : "dragHandle2", area: "padding", within: true
});
});
</script>
</head>
(body)
<div class="parent" >
<div id="note1">
<div id='dragHandle1' class="noteHandle"></div>
<textarea class="note">Note1</textarea>
</div>
<div id="note2">
<div id='dragHandle2' class="noteHandle"></div>
<textarea class="note">Note2</textarea>
</div>
</div>
(/body)
</html>
Особый интерес в функции parentConstrainedMoveables представляет параметр area. Для обозначения допустимой области в пределах родительского элемента можно использовать значения "margin", "padding", "content" и "border".