$scope
IE8 で奇妙な問題が発生しました。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;
}
});
次に、このフィルターを with で使用しますng-repeat
。
<a class="entity-name" href="{{child.url}}" title="{{child.name}}" ng-cloak>{{child.name|truncate}}</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()
2 回チェーンして値を識別します (基本的に、ウィンドウではなく親 (x2) 要素の幅を取得する場合は、より正確な値になります)。 child
と呼ばれる追加のキーを追加しましたdisplay
。これは、child.name
jQuery.text()
を使用して切り捨てられchild.name
た .truncPnt
になりますcharacterCount
(変数を省略しないように覚えようとしています)
問題は、(プロンプトが表示された場合) javascript を強制終了するまで、jQuery がブラウザーをフリーズさせることです。Firefox はそれを表示するかもしれませんし、Chrome はまだハングしていません。私はまだ IE でテストしていませんが、前者より悪いと思います。
問題のメイン要素の上にある 2 つの親の値を適切に取得しchild.display
、親の div を超えてラップ/拡張しないように切り捨てるにはどうすればよいですか?
更新 2:
親 div の幅、フォント サイズ、および神のみぞ知る比率を考慮して、主に DOM ベースの計算の考えを捨てることにしました。フォントサイズに関係なく、一貫して同様の結果が得られるものを得るまで、私は真剣に数式に取り組みました. メディア クエリは問題の文字列のフォント サイズ 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 + '...';
}
});
}
}
});
興味深いことに、DOM の変更とスコープ内のプロパティの変更に関する Brandon Tilley のコメントに完全に戻ったと思います。プロパティを変更するように変更したので、おそらくフィルターでより適切に機能するでしょうか? この種の操作をフィルターとディレクティブで処理する必要があるかどうかを決定する一般的な要因は何ですか?