我对 IE8 有一个奇怪的问题,如果我尝试$scope
通过 AngularJS 的双向数据绑定在模板中呈现变量,它不会替换{{child.name}}
为正确的值。这肯定与以下过滤器的低效率有关:
filter('truncate', function() {
return function(name) {
// It's just easier to use jQuery here
var windowWidth = $(window).width(),
nameElement = $('a:contains("' + name + '")'),
truncPnt = Math.floor(name.length * 0.9);
while (nameElement.width() > windowWidth * 0.75 && truncPnt > 6) {
truncPnt = Math.floor(truncPnt * 0.9);
name = name.substring(0, truncPnt);
nameElement.text(name + ' ...');
}
return name;
}
});
然后,我将此过滤器与 withng-repeat
一起使用:
<a class="entity-name" href="{{child.url}}" title="{{child.name}}" ng-cloak>{{child.name|truncate}}</a>
总体目标是根据屏幕宽度将传递到过滤器的变量截断,用“...”替换任何截断的字符。我相当有信心这个过滤器是原因,因为我有一个类似的函数在处理程序的 a 上被调用.resize()
,$(window)
如果我使用 IE8 并调整浏览器窗口的大小,它会导致{{child.name}}
渲染为正确的值,但是仅当我调整浏览器大小时。
更新:
所以我已经摆脱了上面的过滤器,并用一个非常相似的指令代替了它。这是我第一次尝试创建自定义指令,所以我相当肯定它可以做得更好,减去我目前似乎无法解决的明显缺陷。该指令如下:
.directive('truncate', function() {
return {
restrict: 'A',
replace: true,
template: '<a class="entity-name" href="{{child.url}}" title="{{child.name}}">{{child.display}}</a>',
link: function(scope, element, attr) {
var widthThreshold = $(element[0]).parent().parent().width() * 0.85;
scope.$watch('child', function(val) {
var elementWidth = $(element[0]).width(),
characterCount = scope.child.name.length;
while ($(element[0]).width() > widthThreshold || characterCount > 5) {
characterCount--;
scope.child.display = scope.child.name.substring(0, characterCount) + ' ...';
}
});
}
}
});
我将部分替换为简单的:
<a truncate="child"></a>
这与过滤器的区别如下(减去明显的过滤器与指令):
- 替换
windowWidth
为widthThreshold
, 通过链接 jQuery.parent()
两次来识别值(本质上,当获取父 (x2) 元素而不是窗口的宽度时,它是一个更准确的值)。 child
为被调用添加了一个附加键display
。这将child.name
是用于显示的截断版本,而不是使用 jQuery.text()
并仅使用截断的child.name
.truncPnt
变成characterCount
(尽量记住不要缩写变量)
现在的问题是 jQuery 冻结了浏览器,直到我终止了 javascript(如果出现提示)。Firefox 可能会显示它,Chrome 还没有挂起,虽然我还没有在 IE 中进行测试,但我想比前者更糟。
可以做些什么来正确获取相关主元素上方的两个父元素的值,并截断child.display
以使其不会包裹/延伸到父 div 之外?
更新 2:
我决定放弃主要基于 DOM 的计算的想法,转而使用数学,考虑父 div 的宽度、字体大小和天知道的比例。我认真地插入了一个公式,直到我得到了无论字体大小都始终给出相似结果的东西。媒体查询确实会影响相关字符串的字体大小 CSS,因此我需要考虑这一点,否则不同字体大小的截断字符串的长度会有一些巨大差异:
.directive('truncate', function() {
return {
restrict: 'A',
replace: true,
// {{child.display}} will be a truncated copy of child.name
template: '<a class="entity-name" href="{{child.url}}" title="{{child.name}}">{{child.display}}</a>',
link: function(scope, element, attr) {
var widthThreshold = $(element).parent().parent().width() * 0.85,
// get the font-size without the 'px' at the end, what with media queries effecting font
fontSize = $(element).css('font-size').substring(0, $(element).css('font-size').lastIndexOf('px')),
// ... Don't ask...
sizeRatio = 29760/20621,
characterCount = Math.floor((widthThreshold / fontSize) * sizeRatio);
scope.$watch('child', function(val) {
// Truncate it and trim any possible trailing white-space
var truncatedName = scope.child.name.substring(0, characterCount).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
// Make sure characterCount isn't > the current length when accounting for the '...'
if (characterCount < scope.child.name.length + 3) {
scope.child.display = truncatedName + '...';
}
});
}
}
});
有趣的是,我相信我又回到了 Brandon Tilley 关于修改 DOM 与修改范围内的属性的评论。现在我已将其更改为修改属性,它可能会更好地用于过滤器?对于这种操作是否应该在过滤器和指令中处理,通常决定因素是什么?