从我问过的上一个问题(http://stackoverflow.com/q/13383552/740318)我从创建一个设计不佳的过滤器到一个(仍然很糟糕但有效的)指令,这样做,我意识到它应该在正确实施时作为过滤器完成。现在奇怪的部分是(以我有限的理解)我将不得不重新建立一些最初实现的“hackish”技术,以使过滤器在转换时工作。
该指令是这样的:
widget.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')),
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 = $.trim(scope.child.name.substring(0, characterCount));
// Make sure characterCount isn't > the current length when accounting for the ...
if (characterCount < scope.child.name.length + 3) {
scope.child.display = truncatedName + '...';
}
});
}
}
});
为简单起见,我使用 jQuery 来获取.width()
元素父级的父级。这给了我必须使用的总屏幕宽度。根据上述值(以及诸如 font-size CSS 属性之类的东西),我截断字符串以尽可能合理地显示,然后以三个句点(“...”)结束。这很简单,因为元素被传递给指令,我可以简单地使用$(element)
jQuery 来获取标识符并解决它。
现在使用过滤器,我仅限于传入的字符串,并且没有像使用指令那样的元素。以我有限的知识,在过滤器中完成此操作的唯一方法是$('a:contains("' + name + '")')
使用之前实现的原始(并且可能是过程密集型)方法(在上面提到的上一个问题中),或者可以动态地为每个方法分配一个 id<a>
并传递它进入过滤器。也许类似于(未经测试的伪代码,希望它能够理解这一点):
<script>
function entityController($scope, $http) {
$http.get('/path/to/json').success(function(res) {
/* Sample return JSON ("uuid" is a unique database stored identifier):
* {
* children: [
* { uuid:"123", url:"path/to/file", name:"File Name", display:"File Name" },
* { uuid:"234", url:"path/to/file2", name:"Second File Name", display:"Second File Name" },
* ...
* ]
* }
*/
$scope.children = res.children
});
}
</script>
<body class="ng-controller:entityController" ng-controller="entityController">
<div ng-repeat="child in children">
<!-- Not sure if {{child.name | truncate:uuid}} would work, hopefully it conveys the point -->
<a id="{{child.uuid}}" href="{{child.url}}" title="{{child.name | truncate:uuid}}">{{child.display}}</a>
</div>
</body>
现在,如果我想通过 jQuery 访问它,我将不得不通过一些 hackish 来复制上述指令的功能,例如:
var app = angular.module('app', []);
app.filter('truncate', function() {
return function(str, uuid) {
var widthThreshold = $('#' + uuid).parent().parent().width() * 0.85,
fontSize = $('#' + uuid).css('font-size').substring(0, $('#' + uuid).lastIndexOf('px')),
...
});
它似乎从那里螺旋式下降,在那里我继续查询 DOM 以获取越来越多的信息,这些信息让我思考指令是否是不正确的(但“更干净”,如果它曾经是这样的话)方法。使用过滤器时,是否有适当的方法来访问 DOM 属性,例如父元素的宽度或字体大小,而不必滥用 jQuery,并增加我的语法只是为了访问过滤器中的 DOM ?