[483] | 1 | define(["dojo/_base/array"], function(arr){ |
---|
| 2 | var utils = { |
---|
| 3 | group: function(/*Array*/items, /*Array*/groupingFunctions, /*Function*/measureFunction){ |
---|
| 4 | var response = { |
---|
| 5 | children: [] |
---|
| 6 | }; |
---|
| 7 | var merge = function(obj, entry){ |
---|
| 8 | if(!obj.__treeValue){ |
---|
| 9 | obj.__treeValue = 0; |
---|
| 10 | } |
---|
| 11 | obj.__treeValue += measureFunction(entry); |
---|
| 12 | return obj; |
---|
| 13 | }; |
---|
| 14 | // we go over each entry in the array |
---|
| 15 | arr.forEach(items, function(entry){ |
---|
| 16 | var r = response; |
---|
| 17 | // for this entry, for each rowField we |
---|
| 18 | // look at the actual value for this rowField |
---|
| 19 | // and create a holding object for this |
---|
| 20 | // value in response if it does not exist |
---|
| 21 | arr.forEach(groupingFunctions, function(groupingFunction, j){ |
---|
| 22 | // actual value for the rowField |
---|
| 23 | var data = groupingFunction(entry); |
---|
| 24 | // create child if undefined |
---|
| 25 | var child = utils.find(r.children, function(item){ |
---|
| 26 | return (item.__treeName == data); |
---|
| 27 | }); |
---|
| 28 | if(!child){ |
---|
| 29 | r.children.push(child = { |
---|
| 30 | __treeName: data, |
---|
| 31 | __treeID: data+Math.random(), |
---|
| 32 | children: [] |
---|
| 33 | }); |
---|
| 34 | } |
---|
| 35 | child = merge(child, entry); |
---|
| 36 | if(j != groupingFunctions.length - 1){ |
---|
| 37 | // branch & prepare response for |
---|
| 38 | // next call |
---|
| 39 | r = child; |
---|
| 40 | }else{ |
---|
| 41 | // add the entry to the leaf! |
---|
| 42 | child.children.push(entry); |
---|
| 43 | } |
---|
| 44 | }); |
---|
| 45 | r = merge(r, entry); |
---|
| 46 | }); |
---|
| 47 | return response; |
---|
| 48 | }, |
---|
| 49 | find: function(/*Array*/array, /*Function*/callback){ |
---|
| 50 | var l = array.length; |
---|
| 51 | for (var i = 0; i < l; ++i) { |
---|
| 52 | if (callback.call(null, array[i])){ |
---|
| 53 | return array[i]; |
---|
| 54 | } |
---|
| 55 | } |
---|
| 56 | return null; |
---|
| 57 | }, |
---|
| 58 | solve: function(items, width, height, areaFunc, rtl){ |
---|
| 59 | // |
---|
| 60 | // Create temporary TreeMap elements |
---|
| 61 | // |
---|
| 62 | var treeMapElements = utils.initElements(items, areaFunc); |
---|
| 63 | var dataTotal = treeMapElements.total; |
---|
| 64 | var elements = treeMapElements.elements; |
---|
| 65 | |
---|
| 66 | var realSize = dataTotal; |
---|
| 67 | |
---|
| 68 | if(dataTotal == 0){ |
---|
| 69 | if(elements.length == 0){ |
---|
| 70 | return { |
---|
| 71 | items: items, rects: [], total: 0 |
---|
| 72 | }; |
---|
| 73 | } |
---|
| 74 | arr.forEach(elements, function(element){ |
---|
| 75 | element.size = element.sizeTmp = 100; |
---|
| 76 | }); |
---|
| 77 | dataTotal = elements.length * 100; |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | // |
---|
| 81 | // Sort the TreeMap elements |
---|
| 82 | // |
---|
| 83 | elements.sort(function(b, a){ |
---|
| 84 | return a.size - b.size; |
---|
| 85 | }); |
---|
| 86 | |
---|
| 87 | utils._compute(width, height, elements, dataTotal); |
---|
| 88 | |
---|
| 89 | // |
---|
| 90 | // Restore initial Sort order |
---|
| 91 | // |
---|
| 92 | elements.sort(function(a, b){ |
---|
| 93 | return a.index - b.index; |
---|
| 94 | }); |
---|
| 95 | |
---|
| 96 | var result = {}; |
---|
| 97 | result.elements = elements; |
---|
| 98 | result.size = realSize; |
---|
| 99 | |
---|
| 100 | rects = arr.map(elements, function(element){ |
---|
| 101 | return { |
---|
| 102 | x: rtl?width - element.x - element.width:element.x, y: element.y, w: element.width, h: element.height |
---|
| 103 | }; |
---|
| 104 | }); |
---|
| 105 | |
---|
| 106 | result.rectangles = rects; |
---|
| 107 | |
---|
| 108 | return result; |
---|
| 109 | }, |
---|
| 110 | initElements: function(items, areaFunc){ |
---|
| 111 | var total = 0; |
---|
| 112 | var elements = arr.map(items, function(item, index){ |
---|
| 113 | var size = areaFunc != null ? areaFunc(item) : 0; |
---|
| 114 | if(size < 0){ |
---|
| 115 | throw new Error("item size dimension must be positive"); |
---|
| 116 | } |
---|
| 117 | total += size; |
---|
| 118 | return { |
---|
| 119 | index: index, size: size, sizeTmp: size |
---|
| 120 | }; |
---|
| 121 | }); |
---|
| 122 | return { |
---|
| 123 | elements: elements, total: total |
---|
| 124 | }; |
---|
| 125 | }, |
---|
| 126 | _compute: function(width, height, elements, total){ |
---|
| 127 | var valueScale = ((width * height) / total) / 100; |
---|
| 128 | |
---|
| 129 | arr.forEach(elements, function(element){ |
---|
| 130 | element.sizeTmp *= valueScale; |
---|
| 131 | }); |
---|
| 132 | |
---|
| 133 | var start = 0; |
---|
| 134 | var end = 0; |
---|
| 135 | var aspectCurr = -1 >>> 1; // int.MaxValue; |
---|
| 136 | var aspectLast; |
---|
| 137 | var offsetX = 0; |
---|
| 138 | var offsetY = 0; |
---|
| 139 | var tmp_width = width; |
---|
| 140 | var tmp_height = height; |
---|
| 141 | |
---|
| 142 | var vert = tmp_width > tmp_height; |
---|
| 143 | |
---|
| 144 | while(end != elements.length){ |
---|
| 145 | aspectLast = utils._trySolution(elements, start, end, vert, tmp_width, tmp_height); |
---|
| 146 | |
---|
| 147 | if((aspectLast > aspectCurr) || (aspectLast < 1)){ |
---|
| 148 | var currX = 0; |
---|
| 149 | var currY = 0; |
---|
| 150 | |
---|
| 151 | for(var n = start; n < end; n++){ |
---|
| 152 | elements[n].x = offsetX + currX; |
---|
| 153 | elements[n].y = offsetY + currY; |
---|
| 154 | if(vert){ |
---|
| 155 | currY += elements[n].height; |
---|
| 156 | }else{ |
---|
| 157 | currX += elements[n].width; |
---|
| 158 | } |
---|
| 159 | } |
---|
| 160 | |
---|
| 161 | if(vert){ |
---|
| 162 | offsetX += elements[start].width; |
---|
| 163 | }else{ |
---|
| 164 | offsetY += elements[start].height; |
---|
| 165 | } |
---|
| 166 | |
---|
| 167 | tmp_width = width - offsetX; |
---|
| 168 | tmp_height = height - offsetY; |
---|
| 169 | |
---|
| 170 | vert = tmp_width > tmp_height; |
---|
| 171 | |
---|
| 172 | start = end; |
---|
| 173 | end = start; |
---|
| 174 | |
---|
| 175 | aspectCurr = -1 >>> 1; // int.MaxValue; |
---|
| 176 | continue; |
---|
| 177 | }else{ |
---|
| 178 | for(var n = start; n <= end; n++){ |
---|
| 179 | elements[n].width = elements[n].widthTmp; |
---|
| 180 | elements[n].height = elements[n].heightTmp; |
---|
| 181 | } |
---|
| 182 | aspectCurr = aspectLast; |
---|
| 183 | } |
---|
| 184 | end++; |
---|
| 185 | } |
---|
| 186 | |
---|
| 187 | var currX1 = 0; |
---|
| 188 | var currY1 = 0; |
---|
| 189 | |
---|
| 190 | for(var n = start; n < end; n++){ |
---|
| 191 | elements[n].x = offsetX + currX1; |
---|
| 192 | elements[n].y = offsetY + currY1; |
---|
| 193 | if(vert){ |
---|
| 194 | currY1 += elements[n].height; |
---|
| 195 | }else{ |
---|
| 196 | currX1 += elements[n].width; |
---|
| 197 | } |
---|
| 198 | } |
---|
| 199 | |
---|
| 200 | }, |
---|
| 201 | _trySolution: function(elements, start, end, vert, tmp_width, tmp_height){ |
---|
| 202 | var total = 0; |
---|
| 203 | var aspect = 0; |
---|
| 204 | var localWidth = 0; |
---|
| 205 | var localHeight = 0; |
---|
| 206 | |
---|
| 207 | for(var n = start; n <= end; n++){ |
---|
| 208 | total += elements[n].sizeTmp; |
---|
| 209 | } |
---|
| 210 | |
---|
| 211 | if(vert){ |
---|
| 212 | if(tmp_height == 0){ |
---|
| 213 | localWidth = localHeight = 0; |
---|
| 214 | }else{ |
---|
| 215 | localWidth = total / tmp_height * 100; |
---|
| 216 | localHeight = tmp_height; |
---|
| 217 | } |
---|
| 218 | }else{ |
---|
| 219 | if(tmp_width == 0){ |
---|
| 220 | localWidth = localHeight = 0; |
---|
| 221 | }else{ |
---|
| 222 | localHeight = total / tmp_width * 100; |
---|
| 223 | localWidth = tmp_width; |
---|
| 224 | } |
---|
| 225 | } |
---|
| 226 | |
---|
| 227 | for(var n = start; n <= end; n++){ |
---|
| 228 | if(vert){ |
---|
| 229 | elements[n].widthTmp = localWidth; |
---|
| 230 | if(total == 0){ |
---|
| 231 | elements[n].heightTmp = 0; |
---|
| 232 | }else{ |
---|
| 233 | elements[n].heightTmp = localHeight * elements[n].sizeTmp / total; |
---|
| 234 | } |
---|
| 235 | }else{ |
---|
| 236 | if(total == 0){ |
---|
| 237 | elements[n].widthTmp = 0; |
---|
| 238 | }else{ |
---|
| 239 | elements[n].widthTmp = localWidth * elements[n].sizeTmp / total; |
---|
| 240 | } |
---|
| 241 | elements[n].heightTmp = localHeight; |
---|
| 242 | } |
---|
| 243 | } |
---|
| 244 | aspect = Math.max(elements[end].heightTmp / elements[end].widthTmp, elements[end].widthTmp |
---|
| 245 | / elements[end].heightTmp); |
---|
| 246 | if(aspect == undefined){ |
---|
| 247 | return 1; |
---|
| 248 | } |
---|
| 249 | return aspect; |
---|
| 250 | } |
---|
| 251 | }; |
---|
| 252 | return utils; |
---|
| 253 | }); |
---|