/*
Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
dojo.provide("dojo.html.metrics");
dojo.require("dojo.html.layout");
/* dojo.html.metrics
* Methods to help determine font metrics, including things like
* how much of a string will fit inside a certain width, what size
* something might be if you were to place it in a certain node, etc.
*
* Based partially on a submitted patch by Morris Johns, and work
* done with 13th Parallel and f( m ) (the 13th columns and the
* unreleased f( m ) layout manager.
*/
// derived from Morris John's scrollbar measurer.
dojo.html.getScrollbar=function(){
// summary
// returns the width of a scrollbar.
// set up the test nodes.
var scroll = document.createElement("div");
scroll.style.width="100px";
scroll.style.height="100px";
scroll.style.overflow="scroll";
scroll.style.position="absolute";
scroll.style.top="-300px";
scroll.style.left="0px"
var test = document.createElement("div");
test.style.width="400px";
test.style.height="400px";
scroll.appendChild(test);
dojo.body().appendChild(scroll);
var width=scroll.offsetWidth - scroll.clientWidth;
dojo.body().removeChild(scroll);
scroll.removeChild(test);
scroll=test=null;
// we return an object because we may add additional info in the future.
return { width: width }; // object
};
// derived from Morris John's emResized measurer
dojo.html.getFontMeasurements = function(){
// summary
// Returns an object that has pixel equivilents of standard font size values.
var heights = {
'1em':0, '1ex':0, '100%':0, '12pt':0, '16px':0, 'xx-small':0, 'x-small':0,
'small':0, 'medium':0, 'large':0, 'x-large':0, 'xx-large':0
};
if(dojo.render.html.ie){
// we do a font-size fix if and only if one isn't applied already.
// NOTE: If someone set the fontSize on the HTML Element, this will kill it.
document.documentElement.style.fontSize="100%";
}
// set up the measuring node.
var div=document.createElement("div");
div.style.position="absolute";
div.style.left="-100px";
div.style.top="0";
div.style.width="30px";
div.style.height="1000em";
div.style.border="0";
div.style.margin="0";
div.style.padding="0";
div.style.outline="0";
div.style.lineHeight="1";
div.style.overflow="hidden";
dojo.body().appendChild(div);
// do the measurements.
for(var p in heights){
div.style.fontSize = p;
heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
}
dojo.body().removeChild(div);
div = null;
return heights; // object
};
dojo.html._fontMeasurements = null;
dojo.html.getCachedFontMeasurements = function(recalculate){
if(recalculate || !dojo.html._fontMeasurements){
dojo.html._fontMeasurements = dojo.html.getFontMeasurements();
}
return dojo.html._fontMeasurements;
};
dojo.html.measureFragment = function(/* HTMLElement */node, /* string */html, /* string? */boxType){
// summary
// get the dimensions of passed node if it were populated with passed html.
var clone = node.cloneNode(true);
clone.innerHTML = html;
node.parentNode.appendChild(clone);
var ret = dojo.html.getElementBox(clone, boxType);
node.parentNode.removeChild(clone);
clone=null;
return ret; // object
};
// the following are derived from the 13th Parallel Column script, as
// reinterpreted by trt. http://www.13thparallel.org/archive/column-script
// Original by Dan Pupius and Michael van Ouwerkerk.
dojo.html.getFittedFragment = function(/* HTMLElement */node, /* string */html){
// summary
// Given html, return the fragment that will fit on one line of passed node.
function cl(node){
var element = document.createElement(node.tagName);
element.id = node.id + "-clone";
element.className = node.className;
for (var j = 0; j < node.attributes.length; j++) {
if (node.attributes[j].specified) {
if (node.attributes[j].nodeName.toLowerCase() != "style"
&& node.attributes[j].nodeName.toLowerCase() != "edited"
&& node.attributes[j].nodeName.toLowerCase() != "contenteditable"
&& node.attributes[j].nodeName.toLowerCase() != "id"
&& node.attributes[j].nodeName.toLowerCase() != "class"
){
element.setAttribute(node.attributes[j].nodeName.toLowerCase(), node.attributes[j].nodeValue);
}
}
}
return element;
}
var height = dojo.html.getFontMeasurements()["16px"];
var n=cl(node);
n.style.width=dojo.html.getBorderBox(node).width+"px";
n.style.height=(height+4)+"px";
node.parentNode.appendChild(n);
var rem = dojo.html.fitToElement(n, html);
var ret = n.innerHTML;
n.parentNode.removeChild(n);
return ret;
};
dojo.html.fitToElement = function(/* HTMLElement */node, /* string */html){
// summary
// will fit as much html as possible into node, and return the unused
// portion, with tag corrections.
function cl(node){
var element = document.createElement(node.tagName);
element.id = node.id + "-clone";
element.className = node.className;
for (var j = 0; j < node.attributes.length; j++) {
if (node.attributes[j].specified) {
if (node.attributes[j].nodeName.toLowerCase() != "style"
&& node.attributes[j].nodeName.toLowerCase() != "edited"
&& node.attributes[j].nodeName.toLowerCase() != "contenteditable"
&& node.attributes[j].nodeName.toLowerCase() != "id"
&& node.attributes[j].nodeName.toLowerCase() != "class"
){
element.setAttribute(node.attributes[j].nodeName.toLowerCase(), node.attributes[j].nodeValue);
}
}
}
return element;
}
var clone = cl(node);
node.parentNode.appendChild(clone);
var t=dojo.html.getBorderBox(node);
clone.style.width = t.width+"px";
var singletons = ["br","img", "hr", "input", "!--"];
var chop = ["
","
","
","
","