Bug 45485 - Drag&Drop скрам-карточек

git-svn-id: svn://svn.office.custis.ru/3rdparty/bugzilla.org/trunk@1253 6955db30-a419-402b-8a0d-67ecbb4d7f56
master
vfilippov 2011-04-21 22:34:13 +00:00
parent 9afd15d535
commit 96aaa3e81f
3 changed files with 771 additions and 303 deletions

View File

@ -0,0 +1,349 @@
/*
Простая JS-библиотека для организации Drag&Drop
Использование:
dragObject = new DragObject(element); // то, что тащим
dropTarget = new DropTarget(element); // то, куда тащим
Обработчики DropTarget:
* dropTarget.canAccept(DragObject) -> boolean
Вернуть true, если эта цель может принять этот DragObject
* dropTarget.onAccept(DragObject, pos = { x: int, y: int })
Объект перетаскивают на эту цель и отпускают
x, y - относительные цели координаты, в которых объект отпущен
* dropTarget.onEnter()
Объект приносят на этой цель
* dropTarget.onLeave()
Объект уносят с этой цели
* dropTarget.onMove(pos = { x: int, y: int })
Объект таскают по цели
x, y - относительные цели координаты, в которых объект находится
Обработчики DragObject:
* dragObject.onDragStart(offset = { x: int, y: int })
Объект начинают перетаскивать
x, y - относительные координаты, за которые пользователь взял объект мышкой
* dragObject.onDragMove(x, y)
Объект перетаскивают
x, y - абсолютные координаты нахождения объекта
* dragObject.onDragSuccess(DropTarget, pos = { x: int, y: int })
Объект принят целью
x, y - относительные цели координаты, в которых объект отпущен
* dragObject.onDragFail
Объект не принят ни одной целью
Соответственно, все эти обработчики можно переопределять. Так и работаем.
Можно даже унаследоваться от класса и написать обработчики прототипами:
MyDropTarget.prototype = new DropTarget();
MyDropTarget.prototype.onAccept = function(obj, pos) {...};
*/
var DragMaster = (function()
{
var dragObject;
var mouseDownAt;
var currentDropTarget;
var usePageX = (function()
{
var m = navigator.userAgent.match(/Opera.([\d\.]+)/);
var mv;
if (m && (mv = navigator.userAgent.match(/Version\/([\d\.]+)/)))
m = mv;
var sf = navigator.userAgent.match(/Safari\//) &&
!navigator.userAgent.match(/Chrome/);
if (sf || m && parseFloat(m[1]) < 10.5)
return true;
return false;
})();
function fixEvent(e)
{
// получить объект событие для IE
e = e || window.event;
// добавить pageX/pageY для IE
if (e.pageX == null && e.clientX != null)
{
var html = document.documentElement;
var body = document.body;
e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0);
e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0);
}
// правильный pageX/pageY
if (usePageX)
{
e.pX = e.pageX;
e.pY = e.pageY;
}
else
{
e.pX = e.clientX;
e.pY = e.clientY;
}
// добавить which для IE
if (!e.which && e.button)
e.which = e.button & 1 ? 1 : ( e.button & 2 ? 3 : ( e.button & 4 ? 2 : 0 ) );
return e;
};
function getOffset(elem)
{
if (elem.getBoundingClientRect)
return getOffsetRect(elem);
else
return getOffsetSum(elem);
};
function getOffsetRect(elem)
{
var box = elem.getBoundingClientRect();
var body = document.body;
var docElem = document.documentElement;
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
var clientTop = docElem.clientTop || body.clientTop || 0;
var clientLeft = docElem.clientLeft || body.clientLeft || 0;
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
return { top: Math.round(top), left: Math.round(left) };
};
function getOffsetSum(elem)
{
var top = 0, left = 0;
while(elem)
{
top = top + parseInt(elem.offsetTop);
left = left + parseInt(elem.offsetLeft);
elem = elem.offsetParent;
}
return { top: top, left: left };
};
function mouseDown(e)
{
e = fixEvent(e);
if (e.which != 1)
return;
mouseDownAt = { x: e.pageX, y: e.pageY, element: this };
addDocumentEventHandlers();
return false;
};
function mouseMove(e)
{
e = fixEvent(e);
// (1)
if (mouseDownAt)
{
if (Math.abs(mouseDownAt.x-e.pageX) < 5 &&
Math.abs(mouseDownAt.y-e.pageY) < 5)
return false;
// Начать перенос
var elem = mouseDownAt.element;
// текущий объект для переноса
dragObject = elem.dragObject;
// запомнить, с каких относительных координат начался перенос
var mouseOffset = getMouseOffset(elem, mouseDownAt.x, mouseDownAt.y);
mouseDownAt = null; // запомненное значение больше не нужно, сдвиг уже вычислен
dragObject.dragStart(mouseOffset); // начали
}
// (2)
dragObject.dragMove(e.pageX, e.pageY);
dragObject.element._moved = true;
// (3)
var newTarget = getCurrentTarget(e);
// (4)
if (currentDropTarget != newTarget)
{
if (currentDropTarget && currentDropTarget.onLeave)
currentDropTarget.onLeave();
if (newTarget && newTarget.onEnter)
newTarget.onEnter();
currentDropTarget = newTarget;
}
if (currentDropTarget && currentDropTarget.onMove)
currentDropTarget.onMove(getMouseOffset(currentDropTarget.element, e.pX, e.pY));
// (5)
return false;
};
function mouseUp(e)
{
e = fixEvent(e);
if (!dragObject) // (1)
mouseDownAt = null;
else
{
// (2)
if (currentDropTarget)
{
var pos = getMouseOffset(currentDropTarget.element, e.pX, e.pY);
currentDropTarget.accept(dragObject, pos);
dragObject.dragSuccess(currentDropTarget, pos);
}
else
dragObject.dragFail();
dragObject = null;
}
// (3)
removeDocumentEventHandlers();
};
function getMouseOffset(target, x, y)
{
var docPos = getOffset(target);
return { x: x-docPos.left, y: y-docPos.top };
};
function getCurrentTarget(e)
{
// спрятать объект, получить элемент под ним - и тут же показать опять
var x = e.pX, y = e.pY;
// чтобы не было заметно мигание - максимально снизим время от hide до show
dragObject.hide();
var elem = document.elementFromPoint(x, y);
dragObject.show();
// найти самую вложенную dropTarget
while (elem)
{
// которая может принять dragObject
if (elem.dropTarget && (!elem.dropTarget.canAccept || elem.dropTarget.canAccept(dragObject)))
return elem.dropTarget;
elem = elem.parentNode;
}
// dropTarget не нашли
return null;
};
function addDocumentEventHandlers()
{
document.onmousemove = mouseMove;
document.onmouseup = mouseUp;
document.ondragstart = document.body.onselectstart = function() { return false };
};
function removeDocumentEventHandlers()
{
document.onmousemove =
document.onmouseup =
document.ondragstart =
document.body.onselectstart = null;
};
return {
'makeDraggable': function(element)
{
element.onmousedown = mouseDown;
element.onclick = function()
{
var r = element._moved && true;
element._moved = false;
return !r;
};
}
};
}());
/* DragObject */
function DragObject(element)
{
if (!element)
return;
element.dragObject = this;
DragMaster.makeDraggable(element);
this.element = element;
}
DragObject.prototype.dragStart = function(offset)
{
var s = this.element.style;
this.rememberPosition = {
top: s.top,
left: s.left,
position: s.position,
opacity: s.opacity,
};
s.position = 'absolute';
this.mouseOffset = offset;
if (this.onDragStart)
this.onDragStart(offset);
};
DragObject.prototype.hide = function()
{
this.element.style.display = 'none';
};
DragObject.prototype.show = function()
{
this.element.style.display = '';
};
DragObject.prototype.dragMove = function(x, y)
{
this.element.style.top = y - this.mouseOffset.y + 'px';
this.element.style.left = x - this.mouseOffset.x + 'px';
if (this.onDragMove)
this.onDragMove(x, y);
};
DragObject.prototype.dragSuccess = function(dropTarget, pos)
{
this.restorePosition();
if (this.onDragSuccess)
this.onDragSuccess(dropTarget, pos);
};
DragObject.prototype.restorePosition = function()
{
var s = this.element.style;
for (var i in this.rememberPosition)
s[i] = this.rememberPosition[i];
};
DragObject.prototype.dragFail = function()
{
this.restorePosition()
if (this.onDragFail)
this.onDragFail();
};
/* DropTarget */
function DropTarget(element)
{
if (!element)
return;
element.dropTarget = this;
this.element = element;
};
DropTarget.prototype.accept = function(dragObject, pos)
{
if (this.onAccept)
this.onAccept(dragObject, pos);
if (this.onLeave)
this.onLeave();
};

View File

@ -0,0 +1,411 @@
var pressedButton;
var pasteMode = false;
var ctrl = false;
var highlitCard;
var selectedcards = {};
var cuttedcards = [];
var cuttedids = [];
function addNewCards()
{
for (var i = idlist.length-1; i >= 0; i--)
{
if (idlist[i] === '')
idlist.pop();
else
break;
}
var val = document.getElementById('addbugs').value;
var re = /(\d+)/g;
var m;
while (m = re.exec(val))
idlist.push(m[1]);
document.getElementById('idlist_value').value = idlist.join(',');
document.getElementById('scrumform').submit();
}
function addEmptyPage()
{
for (var i = 0; i < nr*nc; i++)
idlist.push('');
document.getElementById('idlist_value').value = idlist.join(',');
document.getElementById('scrumform').submit();
}
function addNewIfEnter(ev)
{
if (ev.keyCode == 10 || ev.keyCode == 13)
{
addNewCards();
return true;
}
return false;
}
function resetAll()
{
if (pressedButton)
{
buttonHandler(null, pressedButton);
pressedButton = null;
}
deselectAll();
stopPaste();
return true;
}
function deselectAll()
{
for (var i in selectedcards)
{
var e = document.getElementById('cardtd_'+i);
e.className = 'cardtd';
}
selectedcards = {};
}
function guessButton(ev)
{
exFixEvent(ev);
var t;
if (t = searchButtonTarget(ev))
return buttonHandler(ev, t);
return true;
}
function buttonHandler(ev, target)
{
if (!pressedButton)
{
pressedButton = target;
target.style.borderStyle = 'inset';
target.style.padding = '4px 2px 2px 4px';
}
else if (pressedButton == target)
{
target.style.borderStyle = 'outset';
target.style.padding = '3px';
pressedButton = null;
if (target.id == 'btn_cut')
deleteSelectedCards(true);
else if (target.id == 'btn_delete')
deleteSelectedCards(false);
else if (target.id == 'btn_paste')
pasteCards();
else if (target.id == 'btn_paste_beg')
doPasteCards(0);
return true;
}
return false;
}
function selectCard(ev, target)
{
var selectedcards_empty = 2;
for (var i in selectedcards)
{
if (i == target.id.substr(7))
selectedcards_empty = 1;
else
{
selectedcards_empty = 0;
break;
}
}
if (pasteMode)
{
doPasteCards(id_to_coord(target.id)+1);
return true;
}
else if (ctrl || selectedcards_empty)
{
if (selectedcards_empty == 1)
return true;
var issel = target.className == 'cardtd selected';
target.className = issel ? 'cardtd' : 'cardtd selected';
if (issel)
delete selectedcards[target.id.substr(7)];
else
selectedcards[target.id.substr(7)] = true;
return true;
}
return false;
}
function highlightCard(ev)
{
if (pasteMode)
{
exFixEvent(ev);
var t = searchCardTarget(ev);
t.className = 'cardtd highlight';
highlitCard = t;
}
}
function unlightCard(ev)
{
if (pasteMode)
{
exFixEvent(ev);
var t = searchCardTarget(ev);
t.className = 'cardtd';
}
}
function to_coord(i)
{
var to_k = Math.floor(i / nr / nc);
var to_i = Math.floor((i / nc) % nr);
var to_j = Math.floor(i % nc);
return [to_k, to_i, to_j];
}
function id_to_coord(id)
{
var m = /(\d+)_(\d+)_(\d+)/.exec(id.substr(7));
return (parseInt(m[1])*nr+parseInt(m[2]))*nc+parseInt(m[3]);
}
function deleteSelectedCards(cut)
{
var shift = 0;
var coord = 0;
var n = nr * nc * np;
if (cut)
{
cuttedcards = [];
cuttedids = [];
}
for (var k = 0; k < np; k++)
{
for (var i = 0; i < nr; i++)
{
for (var j = 0; j < nc; j++, coord++)
{
var s = selectedcards[k+'_'+i+'_'+j];
var e = document.getElementById('cardtd_'+k+'_'+i+'_'+j);
if (s)
{
if (cut)
{
cuttedcards.push(e.innerHTML);
cuttedids.push(idlist[coord]);
}
shift++;
}
else if (shift > 0)
{
var to = to_coord(coord-shift);
document.getElementById('cardtd_'+to[0]+'_'+to[1]+'_'+to[2]).innerHTML = e.innerHTML;
idlist[coord-shift] = idlist[coord];
}
else if (coord + shift < n)
continue;
// во всех трёх случаях - если выделена для
// удаления, если перемещена в другую, или
// если находится в конце - очищаем
e.innerHTML = emptycell;
idlist[coord] = '';
}
}
}
if (cut && cuttedids.length)
document.getElementById('cut_status').innerHTML = 'Вырезано '+cuttedids.length+' карточек.';
deselectAll();
document.getElementById('idlist_value').value = idlist.join(',');
}
function deleteAllCards()
{
idlist = [];
document.getElementById('idlist_value').value = idlist.join(',');
document.getElementById('pages').innerHTML = '';
document.getElementById('scrumform').submit();
}
function pasteCards()
{
if (!pasteMode)
{
if (!cuttedids.length)
{
alert('Сначала выделите и вырежьте какие-нибудь карточки!');
return;
}
alert('Кликните на карточку, после которой нужно вставить вырезанное, либо на кнопку "В начало".');
deselectAll();
pasteMode = true;
document.getElementById('btn_paste_beg').style.display = '';
}
}
function doPasteCards(coord)
{
stopPaste();
var nx = cuttedids.length;
if (nx <= 0)
return;
var n = nr * nc * np;
var from, to;
for (var i = n-nx-1; i >= coord; i--)
{
from = to_coord(i);
to = to_coord(i+nx);
document.getElementById('cardtd_'+to[0]+'_'+to[1]+'_'+to[2]).innerHTML =
document.getElementById('cardtd_'+from[0]+'_'+from[1]+'_'+from[2]).innerHTML;
idlist[i+nx] = idlist[i];
}
for (var i = 0; i < nx; i++)
{
to = to_coord(i+coord);
document.getElementById('cardtd_'+to[0]+'_'+to[1]+'_'+to[2]).innerHTML = cuttedcards[i];
document.getElementById('cardtd_'+to[0]+'_'+to[1]+'_'+to[2]).className = 'cardtd selected';
idlist[i+coord] = cuttedids[i];
selectedcards[to[0]+'_'+to[1]+'_'+to[2]] = true;
}
cuttedids = [];
cuttedcards = [];
document.getElementById('cut_status').innerHTML = '';
document.getElementById('idlist_value').value = idlist.join(',');
}
function stopPaste()
{
if (highlitCard)
highlitCard.className = 'cardtd';
document.getElementById('btn_paste_beg').style.display = 'none';
pasteMode = false;
}
function ctrlDown(ev)
{
if (ev.keyCode == 17)
{
ctrl = true;
return true;
}
return false;
}
function ctrlUp(ev)
{
if (ev.keyCode == 17)
{
ctrl = false;
return true;
}
return false;
}
function searchCardTarget(e)
{
var nt = e._target, i;
while (nt && (!nt.attributes ||
!(i = nt.attributes.getNamedItem('id')) ||
i.value.substr(0, 7) != 'cardtd_'))
nt = nt.parentNode;
return nt;
}
function searchButtonTarget(e)
{
var nt = e._target, i;
while (nt && (!nt.attributes ||
!(i = nt.attributes.getNamedItem('id')) ||
i.value.substr(0, 4) != 'btn_'))
nt = nt.parentNode;
return nt;
}
function mouseUpHandler(e)
{
exFixEvent(e);
var card;
if (card = searchCardTarget(e))
selectCard(e, card);
else if (card = searchButtonTarget(e))
buttonHandler(e, card);
else
resetAll();
}
var CardDragObject = function(e) { DragObject.call(this, e); };
CardDragObject.prototype = new DragObject();
CardDragObject.prototype.onDragStart = function() {
this.tmp = document.createElement('td');
this.element.style.opacity = 0.5;
this.element.parentNode.insertBefore(this.tmp, this.element);
this.element.parentNode.parentNode.parentNode.appendChild(this.element);
};
CardDragObject.prototype.onDragSuccess = function(target, pos) {
this.tmp.parentNode.insertBefore(this.element, this.tmp);
this.tmp.parentNode.removeChild(this.tmp);
var n = true;
for (var i in selectedcards)
{
n = false;
break;
}
if (n)
selectedcards[this.element.id.substr(7)] = true;
deleteSelectedCards(true);
var to = id_to_coord(target.element.id);
var w = target.element.scrollWidth;
if (pos.x < w/4 && to > 0)
to--;
else if (pos.x > w*3/4 && to+1 < np*nr*nc)
to++;
doPasteCards(to);
};
CardDragObject.prototype.onDragFail = function() {
this.tmp.parentNode.insertBefore(this.element, this.tmp);
this.tmp.parentNode.removeChild(this.tmp);
};
var CardDropTarget = function(e)
{
DropTarget.call(this, e);
this.n = id_to_coord(e.id);
};
CardDropTarget.prototype = new DropTarget();
CardDropTarget.prototype.onLeave = function()
{
this.element.style.border = '';
this.element.className = 'cardtd';
};
CardDropTarget.prototype.onMove = function(pos)
{
var w = this.element.scrollWidth;
if (pos.x < w/4 && this.n > 0)
{
this.element.style.borderLeft = '5px solid red';
this.element.className = 'cardtd';
}
else if (pos.x > w*3/4 && this.n+1 < np*nr*nc)
{
this.element.style.borderRight = '5px solid red';
this.element.className = 'cardtd';
}
else
{
this.element.style.border = '';
this.element.className = 'cardtd highlight';
}
};
var addListener = function() {
if (window.addEventListener) {
return function(el, type, fn) { el.addEventListener(type, fn, false); };
} else if (window.attachEvent) {
return function(el, type, fn) {
var f = function() { return fn.call(el, window.event); };
el.attachEvent('on'+type, f);
};
} else {
return function(el, type, fn) { element['on'+type] = fn; }
}
}();
var exFixEvent = function(ev)
{
if (!ev) var ev = window.event;
var t = ev.target;
if (!t) t = ev.srcElement;
if (t && t.nodeType == 3) t = t.parentNode; // Safari bug
ev._target = t;
// FIXME можно сюда ещё добавить фиксы из DragDrop::fixEvent
}
for (var k = 0; k < np; k++)
{
for (var i = 0; i < nr; i++)
{
for (var j = 0; j < nc; j++)
{
var e = document.getElementById('cardtd_'+k+'_'+i+'_'+j);
addListener(e, 'mouseover', highlightCard);
addListener(e, 'mouseout', unlightCard);
new CardDragObject(e);
new CardDropTarget(e);
}
}
}
addListener(document, "mousedown", guessButton);
addListener(document, "mouseup", mouseUpHandler);
addListener(document, "keydown", ctrlDown);
addListener(document.getElementById('addbugs'), "keypress", addNewIfEnter);
addListener(document, "keyup", ctrlUp);

View File

@ -6,6 +6,7 @@
<head>
<title>Печать SCRUM-карточек[% IF searchname || defaultsavename %][% ": " _ (searchname || defaultsavename) | html %][% END %]</title>
<link rel="stylesheet" type="text/css" media="print" href="skins/standard/print.css" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script language="JavaScript" type="text/javascript" src="js/yui/yahoo-dom-event.js"></script>
<style type="text/css">
.dot { border: 1px dashed black; }
@ -25,6 +26,7 @@ p { margin: 0.3em 0; }
.next { page-break-before: always; }
@media screen {
.page { margin-top: 16px; }
.cardtd { background: white; }
.cardtd.selected { background: #E0E0FF; }
.cardtd.highlight { background: #FFE0E0; }
}
@ -120,6 +122,7 @@ x
<p style="clear: both">
Выделяйте карточки Ctrl+Click. <span id="cut_status"></span>
Карточки можно перетаскивать.
</p>
<p>
@ -135,12 +138,16 @@ x
<tr>
[% FOR bug = row.bugs %][% SET coli = loop.index %]
<td class="cardtd" id="cardtd_[% pagei %]_[% rowi %]_[% coli %]">
<table class="card" cellspacing="5">
[% IF NOT bug %]
<table class="card" cellspacing="5">
<tr><td>&nbsp;</td></tr>
</table>
[% ELSIF bug.error %]
<table class="card" cellspacing="5">
<tr><td><span style="font-size: 200%">[% bug.bug_id %]</span><br />[% bug.error %]</td></tr>
</table>
[% ELSE %]
<table class="card" cellspacing="5">
<tr>
<td class="dot"><a href="show_bug.cgi?id=[% bug.bug_id %]">[% bug.bug_id | html %]</a></td>
<td class="sevpri">[% bug.bug_severity.substr(0, 3) | html %]&nbsp;[% bug.priority | html %]</td>
@ -158,8 +165,8 @@ x
[% ind.${bug.bug_id} = ind.${bug.bug_id}+1 %]
</td>
</tr>
[% END %]
</table>
[% END %]
</td>
[% END %]
</tr>
@ -170,313 +177,14 @@ x
</form>
<script language="JavaScript">
var pressedButton;
var pasteMode = false;
var ctrl = false;
var highlitCard;
var selectedcards = {};
var cuttedcards = [];
var cuttedids = [];
var emptycell = "<table class='card' cellspacing='5'><tr><td>&nbsp;</td></tr></table>";
var np = [% pages.size || "0" %];
var nr = [% t.rows || "0" %];
var nc = [% t.cols || "0" %];
var idlist = [ [% idlist_js || "" %] ];
function addNewCards()
{
for (var i = idlist.length-1; i >= 0; i--)
{
if (idlist[i] === '')
idlist.pop();
else
break;
}
var val = document.getElementById('addbugs').value;
var re = /(\d+)/g;
var m;
while (m = re.exec(val))
idlist.push(m[1]);
document.getElementById('idlist_value').value = idlist.join(',');
document.getElementById('scrumform').submit();
}
function addEmptyPage()
{
for (var i = 0; i < nr*nc; i++)
idlist.push('');
document.getElementById('idlist_value').value = idlist.join(',');
document.getElementById('scrumform').submit();
}
function addNewIfEnter(ev, target)
{
if (ev.keyCode == 10 || ev.keyCode == 13)
{
addNewCards();
return true;
}
return false;
}
function resetAll()
{
if (pressedButton)
{
buttonStyle(null, pressedButton);
pressedButton = null;
}
deselectAll();
stopPaste();
return true;
}
function deselectAll()
{
for (var i in selectedcards)
{
var e = document.getElementById('cardtd_'+i);
e.className = 'cardtd';
}
selectedcards = {};
}
function buttonStyle(ev, target)
{
if (!pressedButton)
{
pressedButton = target;
target.style.borderStyle = 'inset';
target.style.padding = '4px 2px 2px 4px';
}
else if (pressedButton == target)
{
target.style.borderStyle = 'outset';
target.style.padding = '3px';
pressedButton = null;
if (target.id == 'btn_cut')
deleteSelectedCards(true);
else if (target.id == 'btn_delete')
deleteSelectedCards(false);
else if (target.id == 'btn_paste')
pasteCards();
else if (target.id == 'btn_paste_beg')
doPasteCards(0);
return true;
}
return false;
}
function selectCard(ev, target)
{
if (pasteMode)
{
var m = /(\d+)_(\d+)_(\d+)/.exec(target.id.substr(7));
doPasteCards(parseInt(m[1])*nr*nc+parseInt(m[2])*nc+parseInt(m[3])+1);
return true;
}
else if (ctrl)
{
var issel = target.className == 'cardtd selected';
target.className = issel ? 'cardtd' : 'cardtd selected';
if (issel)
delete selectedcards[target.id.substr(7)];
else
selectedcards[target.id.substr(7)] = true;
return true;
}
return false;
}
function highlightCard(ev, target)
{
if (pasteMode)
{
target.className = 'cardtd highlight';
highlitCard = target;
}
}
function unlightCard(ev, target)
{
if (pasteMode)
target.className = 'cardtd';
}
function to_coord(i)
{
var to_k = Math.floor(i / nr / nc);
var to_i = Math.floor((i / nc) % nr);
var to_j = Math.floor(i % nc);
return [to_k, to_i, to_j];
}
function deleteSelectedCards(cut)
{
var shift = 0;
var coord = 0;
var n = nr * nc * np;
if (cut)
{
cuttedcards = [];
cuttedids = [];
}
for (var k = 0; k < np; k++)
{
for (var i = 0; i < nr; i++)
{
for (var j = 0; j < nc; j++, coord++)
{
var s = selectedcards[k+'_'+i+'_'+j];
var e = document.getElementById('cardtd_'+k+'_'+i+'_'+j);
if (s)
{
if (cut)
{
cuttedcards.push(e.innerHTML);
cuttedids.push(idlist[coord]);
}
shift++;
}
else if (shift > 0)
{
var to = to_coord(coord-shift);
document.getElementById('cardtd_'+to[0]+'_'+to[1]+'_'+to[2]).innerHTML = e.innerHTML;
idlist[coord-shift] = idlist[coord];
}
else if (coord + shift < n)
continue;
[%# во всех трёх случаях - если выделена для
# удаления, если перемещена в другую, или
# если находится в конце - очищаем %]
e.innerHTML = emptycell;
idlist[coord] = '';
}
}
}
if (cut && cuttedids.length)
document.getElementById('cut_status').innerHTML = 'Вырезано '+cuttedids.length+' карточек.';
deselectAll();
document.getElementById('idlist_value').value = idlist.join(',');
}
function deleteAllCards()
{
idlist = [];
document.getElementById('idlist_value').value = idlist.join(',');
document.getElementById('pages').innerHTML = '';
document.getElementById('scrumform').submit();
}
function pasteCards()
{
if (!pasteMode)
{
if (!cuttedids.length)
{
alert('Сначала выделите и вырежьте какие-нибудь карточки!');
return;
}
alert('Кликните на карточку, после которой нужно вставить вырезанное, либо на кнопку "В начало".');
deselectAll();
pasteMode = true;
document.getElementById('btn_paste_beg').style.display = '';
}
}
function doPasteCards(coord)
{
stopPaste();
var nx = cuttedids.length;
if (nx <= 0)
return;
var n = nr * nc * np;
var from, to;
for (var i = n-nx-1; i >= coord; i--)
{
from = to_coord(i);
to = to_coord(i+nx);
document.getElementById('cardtd_'+to[0]+'_'+to[1]+'_'+to[2]).innerHTML =
document.getElementById('cardtd_'+from[0]+'_'+from[1]+'_'+from[2]).innerHTML;
idlist[i+nx] = idlist[i];
}
for (var i = 0; i < nx; i++)
{
to = to_coord(i+coord);
document.getElementById('cardtd_'+to[0]+'_'+to[1]+'_'+to[2]).innerHTML = cuttedcards[i];
document.getElementById('cardtd_'+to[0]+'_'+to[1]+'_'+to[2]).className = 'cardtd selected';
idlist[i+coord] = cuttedids[i];
selectedcards[to[0]+'_'+to[1]+'_'+to[2]] = true;
}
cuttedids = [];
cuttedcards = [];
document.getElementById('cut_status').innerHTML = '';
document.getElementById('idlist_value').value = idlist.join(',');
}
function stopPaste()
{
if (highlitCard)
highlitCard.className = 'cardtd';
document.getElementById('btn_paste_beg').style.display = 'none';
pasteMode = false;
}
function ctrlDown(ev, target)
{
if (ev.keyCode == 17)
{
ctrl = true;
return true;
}
return false;
}
function ctrlUp(ev, target)
{
if (ev.keyCode == 17)
{
ctrl = false;
return true;
}
return false;
}
var exAttachCount = 0;
function exAttachHandler(ev, k, i, func)
{
if (!ev) var ev = window.event;
var t = ev.target;
if (!t) t = ev.srcElement;
if (t.nodeType == 3) t = t.parentNode; // Safari bug
var nt = t;
while (nt && (!nt[k] || nt[k] != i))
nt = nt.parentNode;
var st;
if (st = func(ev, nt))
{
if (ev.stopPropagation)
ev.stopPropagation();
else
ev.cancelBubble = true;
}
return !st;
}
function exAttach(element, evname, func)
{
var i = ++exAttachCount;
var k = '_exAt'+evname;
element[k] = i;
YAHOO.util.Event.addListener(element, evname, function(ev) { return exAttachHandler(ev, k, i, func); });
}
exAttach(document.getElementById('btn_delete'), "mousedown", buttonStyle);
exAttach(document.getElementById('btn_delete'), "mouseup", buttonStyle);
exAttach(document.getElementById('btn_cut'), "mousedown", buttonStyle);
exAttach(document.getElementById('btn_cut'), "mouseup", buttonStyle);
exAttach(document.getElementById('btn_paste'), "mousedown", buttonStyle);
exAttach(document.getElementById('btn_paste'), "mouseup", buttonStyle);
exAttach(document.getElementById('btn_paste_beg'), "mousedown", buttonStyle);
exAttach(document.getElementById('btn_paste_beg'), "mouseup", buttonStyle);
for (var k = 0; k < np; k++)
{
for (var i = 0; i < nr; i++)
{
for (var j = 0; j < nc; j++)
{
var e = document.getElementById('cardtd_'+k+'_'+i+'_'+j);
exAttach(e, "mouseup", selectCard);
exAttach(e, "mouseover", highlightCard);
exAttach(e, "mouseout", unlightCard);
}
}
}
exAttach(document, "mouseup", resetAll);
exAttach(document, "keydown", ctrlDown);
exAttach(document.getElementById('addbugs'), "keypress", addNewIfEnter);
exAttach(document, "keyup", ctrlUp);
</script>
<script language="JavaScript" src="extensions/custis/js/DragDrop.js"></script>
<script language="JavaScript" src="extensions/custis/js/scrumcards.js"></script>
</body>
</html>