You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
6.0 KiB
253 lines
6.0 KiB
define(["dojo/_base/array"], function(arr){ |
|
var utils = { |
|
group: function(/*Array*/items, /*Array*/groupingFunctions, /*Function*/measureFunction){ |
|
var response = { |
|
children: [] |
|
}; |
|
var merge = function(obj, entry){ |
|
if(!obj.__treeValue){ |
|
obj.__treeValue = 0; |
|
} |
|
obj.__treeValue += measureFunction(entry); |
|
return obj; |
|
}; |
|
// we go over each entry in the array |
|
arr.forEach(items, function(entry){ |
|
var r = response; |
|
// for this entry, for each rowField we |
|
// look at the actual value for this rowField |
|
// and create a holding object for this |
|
// value in response if it does not exist |
|
arr.forEach(groupingFunctions, function(groupingFunction, j){ |
|
// actual value for the rowField |
|
var data = groupingFunction(entry); |
|
// create child if undefined |
|
var child = utils.find(r.children, function(item){ |
|
return (item.__treeName == data); |
|
}); |
|
if(!child){ |
|
r.children.push(child = { |
|
__treeName: data, |
|
__treeID: data+Math.random(), |
|
children: [] |
|
}); |
|
} |
|
child = merge(child, entry); |
|
if(j != groupingFunctions.length - 1){ |
|
// branch & prepare response for |
|
// next call |
|
r = child; |
|
}else{ |
|
// add the entry to the leaf! |
|
child.children.push(entry); |
|
} |
|
}); |
|
r = merge(r, entry); |
|
}); |
|
return response; |
|
}, |
|
find: function(/*Array*/array, /*Function*/callback){ |
|
var l = array.length; |
|
for (var i = 0; i < l; ++i) { |
|
if (callback.call(null, array[i])){ |
|
return array[i]; |
|
} |
|
} |
|
return null; |
|
}, |
|
solve: function(items, width, height, areaFunc, rtl){ |
|
// |
|
// Create temporary TreeMap elements |
|
// |
|
var treeMapElements = utils.initElements(items, areaFunc); |
|
var dataTotal = treeMapElements.total; |
|
var elements = treeMapElements.elements; |
|
|
|
var realSize = dataTotal; |
|
|
|
if(dataTotal == 0){ |
|
if(elements.length == 0){ |
|
return { |
|
items: items, rects: [], total: 0 |
|
}; |
|
} |
|
arr.forEach(elements, function(element){ |
|
element.size = element.sizeTmp = 100; |
|
}); |
|
dataTotal = elements.length * 100; |
|
} |
|
|
|
// |
|
// Sort the TreeMap elements |
|
// |
|
elements.sort(function(b, a){ |
|
return a.size - b.size; |
|
}); |
|
|
|
utils._compute(width, height, elements, dataTotal); |
|
|
|
// |
|
// Restore initial Sort order |
|
// |
|
elements.sort(function(a, b){ |
|
return a.index - b.index; |
|
}); |
|
|
|
var result = {}; |
|
result.elements = elements; |
|
result.size = realSize; |
|
|
|
rects = arr.map(elements, function(element){ |
|
return { |
|
x: rtl?width - element.x - element.width:element.x, y: element.y, w: element.width, h: element.height |
|
}; |
|
}); |
|
|
|
result.rectangles = rects; |
|
|
|
return result; |
|
}, |
|
initElements: function(items, areaFunc){ |
|
var total = 0; |
|
var elements = arr.map(items, function(item, index){ |
|
var size = areaFunc != null ? areaFunc(item) : 0; |
|
if(size < 0){ |
|
throw new Error("item size dimension must be positive"); |
|
} |
|
total += size; |
|
return { |
|
index: index, size: size, sizeTmp: size |
|
}; |
|
}); |
|
return { |
|
elements: elements, total: total |
|
}; |
|
}, |
|
_compute: function(width, height, elements, total){ |
|
var valueScale = ((width * height) / total) / 100; |
|
|
|
arr.forEach(elements, function(element){ |
|
element.sizeTmp *= valueScale; |
|
}); |
|
|
|
var start = 0; |
|
var end = 0; |
|
var aspectCurr = -1 >>> 1; // int.MaxValue; |
|
var aspectLast; |
|
var offsetX = 0; |
|
var offsetY = 0; |
|
var tmp_width = width; |
|
var tmp_height = height; |
|
|
|
var vert = tmp_width > tmp_height; |
|
|
|
while(end != elements.length){ |
|
aspectLast = utils._trySolution(elements, start, end, vert, tmp_width, tmp_height); |
|
|
|
if((aspectLast > aspectCurr) || (aspectLast < 1)){ |
|
var currX = 0; |
|
var currY = 0; |
|
|
|
for(var n = start; n < end; n++){ |
|
elements[n].x = offsetX + currX; |
|
elements[n].y = offsetY + currY; |
|
if(vert){ |
|
currY += elements[n].height; |
|
}else{ |
|
currX += elements[n].width; |
|
} |
|
} |
|
|
|
if(vert){ |
|
offsetX += elements[start].width; |
|
}else{ |
|
offsetY += elements[start].height; |
|
} |
|
|
|
tmp_width = width - offsetX; |
|
tmp_height = height - offsetY; |
|
|
|
vert = tmp_width > tmp_height; |
|
|
|
start = end; |
|
end = start; |
|
|
|
aspectCurr = -1 >>> 1; // int.MaxValue; |
|
continue; |
|
}else{ |
|
for(var n = start; n <= end; n++){ |
|
elements[n].width = elements[n].widthTmp; |
|
elements[n].height = elements[n].heightTmp; |
|
} |
|
aspectCurr = aspectLast; |
|
} |
|
end++; |
|
} |
|
|
|
var currX1 = 0; |
|
var currY1 = 0; |
|
|
|
for(var n = start; n < end; n++){ |
|
elements[n].x = offsetX + currX1; |
|
elements[n].y = offsetY + currY1; |
|
if(vert){ |
|
currY1 += elements[n].height; |
|
}else{ |
|
currX1 += elements[n].width; |
|
} |
|
} |
|
|
|
}, |
|
_trySolution: function(elements, start, end, vert, tmp_width, tmp_height){ |
|
var total = 0; |
|
var aspect = 0; |
|
var localWidth = 0; |
|
var localHeight = 0; |
|
|
|
for(var n = start; n <= end; n++){ |
|
total += elements[n].sizeTmp; |
|
} |
|
|
|
if(vert){ |
|
if(tmp_height == 0){ |
|
localWidth = localHeight = 0; |
|
}else{ |
|
localWidth = total / tmp_height * 100; |
|
localHeight = tmp_height; |
|
} |
|
}else{ |
|
if(tmp_width == 0){ |
|
localWidth = localHeight = 0; |
|
}else{ |
|
localHeight = total / tmp_width * 100; |
|
localWidth = tmp_width; |
|
} |
|
} |
|
|
|
for(var n = start; n <= end; n++){ |
|
if(vert){ |
|
elements[n].widthTmp = localWidth; |
|
if(total == 0){ |
|
elements[n].heightTmp = 0; |
|
}else{ |
|
elements[n].heightTmp = localHeight * elements[n].sizeTmp / total; |
|
} |
|
}else{ |
|
if(total == 0){ |
|
elements[n].widthTmp = 0; |
|
}else{ |
|
elements[n].widthTmp = localWidth * elements[n].sizeTmp / total; |
|
} |
|
elements[n].heightTmp = localHeight; |
|
} |
|
} |
|
aspect = Math.max(elements[end].heightTmp / elements[end].widthTmp, elements[end].widthTmp |
|
/ elements[end].heightTmp); |
|
if(aspect == undefined){ |
|
return 1; |
|
} |
|
return aspect; |
|
} |
|
}; |
|
return utils; |
|
});
|
|
|