I'd like to truncate DrawLabel contents when it overflows a specified width.
I've experimented a bit with measuring text size on a hidden DIV.
Follows a snippet that works on current SmartClient showcase: it shows a red label that overflows the green rectangle, while the black label (having the same contents) is truncated with an ellipsis.
Is there any smarter way to obtain the same or even better results? My concerns are almost about performances.
Also: is there any chance to have a similar feature integrated into smartclient/smartgwt? It could be enabled only on demand, just to avoid performance issues.
I've experimented a bit with measuring text size on a hidden DIV.
Follows a snippet that works on current SmartClient showcase: it shows a red label that overflows the green rectangle, while the black label (having the same contents) is truncated with an ellipsis.
Is there any smarter way to obtain the same or even better results? My concerns are almost about performances.
Also: is there any chance to have a similar feature integrated into smartclient/smartgwt? It could be enabled only on demand, just to avoid performance issues.
Code:
var lbl1; var lbl2; var fontSize = 15; var fontFamily = 'Sans'; var fontStyle = 'italic'; var fontWeight = 'bold'; var mainPane = isc.VLayout.create({ autoDraw: true, height: 200, width: 600, members: [ isc.DrawPane.create({ autoDraw: false, cursor: "default", height: "100%", drawItems: [ lbl1 = isc.DrawLabel.create({ left: 60, top: 40, lineColor: 'red', fontSize: fontSize, fontFamily: fontFamily, fontStyle: fontStyle, fontWeight: fontWeight, contents: 'The quick brown fox jumps over the lazy dog' }), lbl2 = isc.DrawLabel.create({ left: 60, top: 70, width: 200, lineColor: 'black', fontSize: fontSize, fontFamily: fontFamily, fontStyle: fontStyle, fontWeight: fontWeight }), isc.DrawRect.create({ id: "lblContainer", width: 200, height: 100, left: 60, top: 30, lineColor: 'green' }) ] }) ] }); isc.VStack.create({ height: "100%", members: [mainPane] }); /* returns the actual width of a label */ var getLabelWidth = function (contents, dirty) { dirty.innerHTML = contents; return dirty.clientWidth + 1; } /* truncates the label contents in order to keep its size less than the specified width */ var truncateLabel = function (theLabel, width, dirty) { var originalContents = theLabel.contents; var contents = originalContents; console.log ('analyzing "'+originalContents+'" for target width: '+width); dirty.style.fontSize = theLabel.fontSize+'px'; dirty.style.fontFamily = theLabel.fontFamily; dirty.style.fontStyle = theLabel.fontStyle; dirty.style.fontWeight = theLabel.fontWeight; var maxSteps = 3; for (var i=0;i<maxSteps;i++) { var currentWidth = getLabelWidth (i==0?contents:(contents+'...'), dirty); console.log ('currentWidth: '+currentWidth); if (currentWidth<=width) { break; } else {// shrink needed var ratio = width/currentWidth; contents = contents.substring (0, contents.length * ratio); console.log ('i: '+i+', contents: '+contents+', ratio: '+ratio); } theLabel.contents = contents+'...'; } } var dirty = document.createElement('div'); dirty.id = 'dirty'; dirty.style.position = 'absolute'; dirty.style.visibility = 'hidden'; dirty.style.height = 'auto'; dirty.style.width = 'auto'; document.body.appendChild(dirty); lbl2.contents = lbl1.contents; truncateLabel (lbl2, lbl2.width, dirty);