Project

General

Profile

Bug #862 » WTreeView.js

DQ Qin, 06/20/2011 05:12 PM

 
/*
* Copyright (C) 2010 Emweb bvba, Kessel-Lo, Belgium.
*
* See the LICENSE file for terms of use.
*/

/* Note: this is at the same time valid JavaScript and C++. */

WT_DECLARE_WT_MEMBER
(1, JavaScriptConstructor, "WTreeView",
function(APP, el, contentsContainer, headerContainer, rowHeaderCount) {
jQuery.data(el, 'obj', this);

var contents = contentsContainer.firstChild;
var headers = headerContainer.firstChild;

var self = this;
var WT = APP.WT;

/** @const */ var EnsureVisible = 0;
/** @const */ var PositionAtTop = 1;
/** @const */ var PositionAtBottom = 2;
/** @const */ var PositionAtCenter = 3;

function getItem(event) {
var columnId = -1, nodeId = null, selected = false,
drop = false, ele = null;

var t = WT.target(event);

while (t) {
if (t.className.indexOf('c1 rh') == 0) {
if (columnId == -1)
columnId = 0;
} else if (t.className.indexOf('Wt-tv-c') == 0) {
if (t.className.indexOf('Wt-tv-c') == 0)
columnId = t.className.split(' ')[0].substring(7) * 1;
else if (columnId == -1)
columnId = 0;
if (t.getAttribute('drop') === 'true')
drop = true;
ele = t;
} else if (t.className == 'Wt-tv-node') {
nodeId = t.id;
break;
}
if (t.className === 'Wt-selected')
selected = true;
t = t.parentNode;
if (WT.hasTag(t, 'BODY'))
break;
}

return { columnId: columnId, nodeId: nodeId, selected: selected,
drop: drop, el: ele };
};

this.click = function(obj, event) {
var item = getItem(event);
if (item.columnId != -1) {
APP.emit(el, { name: 'itemEvent', eventObject: obj, event: event },
item.nodeId, item.columnId, 'clicked', '', '');
}
};

this.dblClick = function(obj, event) {
var item = getItem(event);
if (item.columnId != -1) {
APP.emit(el, { name: 'itemEvent', eventObject: obj, event: event },
item.nodeId, item.columnId, 'dblclicked', '', '');
}
};

this.mouseDown = function(obj, event) {
WT.capture(null);
var item = getItem(event);
if (item.columnId != -1) {
APP.emit(el, { name: 'itemEvent', eventObject: obj, event: event },
item.nodeId, item.columnId, 'mousedown', '', '');
if (el.getAttribute('drag') === 'true' && item.selected)
APP._p_.dragStart(el, event);
}
};

this.mouseUp = function(obj, event) {
var item = getItem(event);
if (item.columnId != -1) {
APP.emit(el, { name: 'itemEvent', eventObject: obj, event: event },
item.nodeId, item.columnId, 'mouseup', '', '');
}
};

this.resizeHandleMDown = function(obj, event) {
var parent = obj.parentNode.parentNode,
c = parent.className.split(' ')[0];

if (c) {
var r = WT.getCssRule('#' + el.id + ' .' + c),
cw = WT.pxself(r, 'width'),
minDelta = -cw,
maxDelta = 10000,
rtl = $(document.body).hasClass('Wt-rtl');

if (rtl) {
var tmp = minDelta;
minDelta = -maxDelta;
maxDelta = -tmp;
}

new WT.SizeHandle(WT, 'h', obj.offsetWidth, el.firstChild.offsetHeight,
minDelta, maxDelta, 'Wt-hsh',
function (delta) {
var newWidth = cw + (rtl ? -delta : delta),
columnId = c.substring(7) * 1;
r.style.width = newWidth + 'px';
self.adjustColumns();
APP.emit(el, 'columnResized', columnId,
parseInt(newWidth));
}, obj, el, event, -2, -1);
}
};

/*
* this adjusts invariants that take into account column resizes
*
* c0w is set as soon as possible.
*
* if (!column1 fixed):
* 1) width('Wt-headerdiv') = sum(column widths)
* 2) width('float: right') = sum(column(-1) widths)
* 3) width(table parent) = width('Wt-headerdiv')
* else
* 4) width('Wt-rowc') = sum(column(-1) widths)
*/
var adjustScheduled = false;

/*
* sometimes autoJavaScript() will run before adjustColumns()
* we should schedule the autoJavaScript() after first calling adjustColumns(). --DQ Qin
*/
var adjustColumnsDone = false;
var adjustColumnsFirstTime = true;

this.adjustColumns = function() {
if (adjustScheduled)
return;

adjustScheduled = true;

setTimeout(function() {
adjustScheduled = false;

var t = contents.firstChild, // table parent
hc = headers.firstChild, // Wt-tv-row
allw_1=0, allw=0,
c0id = headers.lastChild.className.split(' ')[0],
c0r = WT.getCssRule('#' + el.id + ' .' + c0id);

if (rowHeaderCount)
hc = hc.firstChild; // Wt-tv-rowc

if (WT.isHidden(el) || (headers.offsetWidth - hc.offsetWidth < 8))
return;

for (var i=0, length=hc.childNodes.length; i < length; ++i) {
if (hc.childNodes[i].className) { // IE may have only a text node
var cl = hc.childNodes[i].className.split(' ')[0],
r = WT.getCssRule('#' + el.id + ' .' + cl);

if (r.style.display == 'none')
continue;

// 7 = 2 * 3px (padding) + 1px border
allw_1 += WT.pxself(r, 'width') + 7;
}
}

if (!rowHeaderCount)
if (!c0r.style.width) // first resize and c0 width not set
c0r.style.width = (headers.offsetWidth - hc.offsetWidth - 8) + 'px';
else
$(el).find('.Wt-headerdiv .' + c0id).css('width', c0r.style.width);

allw = allw_1 + WT.pxself(c0r, 'width') + (WT.isIE6 ? 10 : 8);

if (!rowHeaderCount) {
headers.style.width = t.style.width = allw + 'px';
hc.style.width = allw_1 + 'px';
} else {
var r = WT.getCssRule('#' + el.id + ' .Wt-tv-rowc');
r.style.width = allw_1 + 'px';

//.Wt-tv-row should also be changed, otherwise right float divs will be "hidden" --DQ Qin
var r1 = WT.getCssRule('#' + el.id + ' .Wt-tv-row');
r1.style.width = allw_1 + 'px';

if (WT.isIE) {
setTimeout(function() {
$(el).find('.Wt-tv-rowc')
.css('width', allw_1 + 'px')
.css('width', '');
$(el).find('.Wt-tv-row')
.css('width', allw_1 + 'px')
.css('width', '');
}, 0);
}

el.changed = true;
}

// schedule autoJavaScript() at the end of adjustColumns() -- DQ Qin
if (adjustColumnsFirstTime) {
self.autoJavaScript();
adjustColumnsFirstTime = false;
}
adjustColumnsDone = true;
}, 0);
};

var dropEl = null;

el.handleDragDrop=function(action, object, event, sourceId, mimeType) {
if (dropEl) {
dropEl.className = dropEl.classNameOrig;
dropEl = null;
}

if (action=='end')
return;

var item = getItem(event);

if (!item.selected && item.drop && item.columnId != -1) {
if (action=='drop') {
APP.emit(el, { name: 'itemEvent', eventObject: object, event: event },
item.nodeId, item.columnId, 'drop', sourceId, mimeType);
} else {
object.className = 'Wt-valid-drop';
dropEl = item.el;
dropEl.classNameOrig = dropEl.className;
dropEl.className = dropEl.className + ' Wt-drop-site';
}
} else {
object.className = '';
}
};

/*
* This adjusts invariants that depend on the size of the whole
* treeview:
*
* - changes to the total width (tw inc. affected by scrollbar)
* - when column1 is fixed:
* * .row width
* * table parent width
*/

this.autoJavaScript = function() {
if (el.parentNode == null) {
el = contentsContainer = headerContainer = contents = headers = null;
this.autoJavaScript = function() { };
return;
}

if (WT.isHidden(el))
return;

if (!adjustColumnsDone) //adjustColumns() has never run. --DQ Qin
return;

var $el=$(el),
c0id, c0r, c0w = null;

var tw = WT.pxself(el, 'width');

if (tw == 0)
tw = el.clientWidth;
else if (WT.boxSizing(el)) {
tw -= WT.px(el, 'borderLeftWidth');
tw -= WT.px(el, 'borderRightWidth');
}

var scrollwidth = contentsContainer.offsetWidth
- contentsContainer.clientWidth;

tw -= scrollwidth;

if ($el.hasClass('column1')) {
c0id = $el.find('.Wt-headerdiv').get(0)
.lastChild.className.split(' ')[0];
c0r = WT.getCssRule('#' + el.id + ' .' + c0id);
c0w = WT.pxself(c0r, 'width');

}

// XXX: IE's incremental rendering foobars completely
if ((!WT.isIE || tw > 100)
&& (tw != contentsContainer.tw ||
c0w != contentsContainer.c0w ||
el.changed)) {
var adjustColumns = !el.changed;

contentsContainer.tw = tw;
contentsContainer.c0w = c0w;

c0id = $el.find('.Wt-headerdiv').get(0)
.lastChild.className.split(' ')[0];
c0r = WT.getCssRule('#' + el.id + ' .' + c0id);

var table = contents.firstChild,
r = WT.getCssRule('#' + el.id + ' .cwidth'),
contentstoo = (r.style.width == table.offsetWidth + 'px'),
hc = headers.firstChild;

r.style.width = tw + 'px';

contentsContainer.style.width = (tw + scrollwidth) + 'px';

// IE moves the scrollbar left in rtl mode.
if (!WT.isIE)
headerContainer.style.marginRight = scrollwidth + 'px';

if (c0w != null) {
var w = tw - c0w - (WT.isIE6 ? 10 : 8);

if (w > 0) {
var w2
= Math.min(w, WT.pxself
(WT.getCssRule('#' + el.id + ' .Wt-tv-row'),'width'));
tw -= (w - w2);

headers.style.width=tw + 'px';
table.style.width=tw + 'px';

/* This is really slow in FF, slower than the jquery equivalent */
WT.getCssRule('#' + el.id + ' .Wt-tv-row').style.width = w2 + 'px';

if (WT.isIE)
setTimeout(function() {
$el.find(' .Wt-tv-row')
.css('width', w2 + 'px')
.css('width', '');
}, 0);
}
} else {
if (contentstoo) {
headers.style.width=r.style.width;
table.style.width=r.style.width;
} else
headers.style.width = table.offsetWidth + 'px';
}

if (!rowHeaderCount && (table.offsetWidth - hc.offsetWidth >= 8))
c0r.style.width = (table.offsetWidth - hc.offsetWidth - 8) + 'px';

el.changed = false;

if (adjustColumns && !adjustColumnsFirstTime /* && WT.isIE */)
self.adjustColumns();
}
};

this.scrollTo = function(x, y, rowHeight, hint) {
if (y != -1) {
y *= rowHeight;
var top = contentsContainer.scrollTop,
height = contentsContainer.clientHeight;
if (hint == EnsureVisible) {
if (top + height < y)
hint = PositionAtTop;
else if (y < top)
hint = PositionAtBottom;
}

switch (hint) {
case PositionAtTop:
contentsContainer.scrollTop = y; break;
case PositionAtBottom:
contentsContainer.scrollTop = y - (height - rowHeight); break;
case PositionAtCenter:
contentsContainer.scrollTop = y - (height - rowHeight)/2; break;
}

window.fakeEvent = {object: contentsContainer};
contentsContainer.onscroll(window.fakeEvent);
window.fakeEvent = null;
}
};

self.adjustColumns();

});
(4-4/4)