如何获得dijit ComboBox或FilteringSelect所需的最小宽度?

时间:2011-02-05 01:16:40

标签: combobox width dojo

我在对话框中使用ComboBox和FilteringSelect,但却无法使控件只具有最小的所需宽度,即仅足以显示下拉列表中最长的文本。此外,控件不能设置为固定宽度,因为下拉列表的实际内容会从翻译数据库中填充。

在简单输入文本类型的普通html中,默认情况下它的工作流畅。但是,即使dojotoolkit.org上的所有示例都显示了相同的行为,在我看来dojo为所有这些输入控件引入了最小宽度。因此我想知道它是否可以完成......

提前致谢!

2 个答案:

答案 0 :(得分:0)

我有同样的问题;经过一番努力,我决定让this适应我的问题。

在我的情况下,我被迫使用旧版本的dojo,而FilteringSelect是声明性的,所以我必须使用hack(下面代码的最后三行)来确保我的功能将在合适的时间执行。

因此,下面的函数获取所有dijit小部件,查找那些存储元素是selectgetAllDropdowns),并为每个它选择它,将内容复制到外面移动的新元素可见屏幕并获取该元素的宽度,使用填充调整(这可能不是你的情况,所以检查getWidth);然后它取这些宽度的最大值并将其与输入元素的当前长度进行比较,如果最长的选项更大,则调整输入和最外面的div宽度。

这个答案很晚,但由于我不容易找到这个解决方案,我认为值得分享。

// change dropdowns width to fit the largest option
function fixDropdownWidth() {
  var getAllDropdowns = function() {
    var dropdowns = [];
    dijit.registry.forEach(function(widget, idx, hash) {
      if (widget.store) {
        var root = widget.store.root;
        if (root && root.nodeName.toLowerCase() == 'select') {
          dropdowns.push(widget);
        }
      }
    });
    return dropdowns;
  };

  var getTesterElement = function() {
    var ret = dojo.query('tester');
    if (ret.length) {
      return ret;
    }
    else {
      document.body.appendChild(document.createElement('tester'));
      return dojo.query('tester');
    }
  };

  var getWidth = function(el) {
    var style = dojo.getComputedStyle(el);
    return el.clientWidth + parseInt(style.paddingLeft) + parseInt(style.paddingRight);
  };

  var getOptionWidth = function(option) {
    var testEl = getTesterElement();
    testEl[0].innerHTML = option.innerHTML;
    return getWidth(testEl[0]);
  };

  var dropdowns = getAllDropdowns();
  var testEl = getTesterElement();
  dojo.style(testEl[0], {
    position: 'absolute',
    top: -9999,
    left: -9999,
    width: 'auto',
    whiteSpace: 'nowrap'
  });
  for (var i = 0; i < dropdowns.length; i++) {
    var input = dropdowns[i].textbox;
    dojo.style(testEl[0], {
      fontSize: dojo.style(input, 'fontSize'),
      fontFamily: dojo.style(input, 'fontFamily'),
      fontWeight: dojo.style(input, 'fontWeight'),
      letterSpacing: dojo.style(input, 'letterSpacing')
    });
    var max = 0;
    var treshold = 5;
    dojo.query('option', dropdowns[i].store.root).forEach(function(el, idx, list) {
      max = Math.max(max, getOptionWidth(el) + treshold);
    });
    if (max > getWidth(dropdowns[i].textbox)) {
      var icon = dojo.query('.dijitValidationIcon', dropdowns[i].domNode)[0];
      dojo.style(dropdowns[i].textbox, {width: max + 'px'});
      var width = max + getWidth(icon) + getWidth(dropdowns[i].downArrowNode) + treshold;
      dojo.style(dropdowns[i].domNode, {
        width: width + 'px'
      });
    }
  }
}


dojo.addOnLoad(function() {
  dojo._loaders.push(fixDropdownWidth);
});

答案 1 :(得分:0)

var dropDowns = [];
var getAllDropdowns = function (dropDowns) {
    array.forEach(dijit.registry.toArray(), function (widget) {
        if (widget.store) {
            if (widget.domNode.classList.contains("dijitComboBox")) { 
                dropDowns.push(widget);
            }
        }
    });
};

getAllDropdowns(dropDowns);

var maxLength = 0;
array.forEach(dropDowns, function (dropDown) {
    var opts = dropDown.get("store").data;
    array.forEach(opts, function (option) {
    var optionValue = option[dropDown.get("searchAttr")];
    var dropDownCurrentStyle = window.getComputedStyle(dropDown.domNode);
    var currentOptionWidth = getTextWidth(optionValue, dropDownCurrentStyle.fontStyle, dropDownCurrentStyle.fontVariant, dropDownCurrentStyle.fontWeight, dropDownCurrentStyle.fontSize, dropDownCurrentStyle.fontFamily);
    if (currentOptionWidth > maxLength) {
        maxLength = currentOptionWidth;
    }
});

dropDown.domNode.style.width = maxLength + "px";
    maxLength = 0;
});

function getTextWidth(text, fontStyle, fontVariant, fontWeight, fontSize, fontFamily) {
    // re-use canvas object for better performance
    var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    var font = fontStyle + " " + fontVariant + " " + fontWeight + " " + fontSize + " " + fontFamily;
    context.font = font;
    canvas.innerText = text;
    var metrics = context.measureText(text);

    return metrics.width + 25; //change this to what you need it to be
}