1

私が尋ねた前の質問(http://stackoverflow.com/q/13383552/740318)から、私は不十分に設計されたフィルターを作成することから、(まだ不十分に開発されているが効果的な)ディレクティブに完全に一周しました、そしてそうすることで、私は適切に実装された場合、フィルターとして実行されるべきであることに気づきました。ここで興味深いのは、(私の理解は限られていますが)フィルターを変換するときにフィルターを機能させるために、元々実装されていた「ハック」手法のいくつかを再確立する必要があるということです。

ディレクティブは次のとおりです。

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プロパティなど)に応じて、文字列を切り捨てて可能な限り表示し、3つのピリオド( "...")で終了します。要素がディレクティブに渡されることを考えると、これは単純であり、$(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を介してアクセスしたい場合は、次のようなハックを実行して、上記のディレクティブの機能を複製する必要があります。

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に問い合わせ続けています。フィルタを使用する場合、jQueryを悪用することなく、親要素の幅やフォントサイズなどのDOMプロパティにアクセスし、フィルタ内のDOMにアクセスするためだけに構文をまとめる適切な方法はありますか? ?

4

1 に答える 1

3

AFAIK、角度を介して$elementをフィルターに渡す方法はありません。ディレクティブは、DOM操作を目的としています。スコープ内の文字列を短くしようとしているように感じるかもしれませんが、実際にはDOMに追加されているものを操作しようとしているので、ディレクティブは正しい選択です、IMO。

そうは言っても、CSSのテキストオーバーフローを調べましたか?JavaScriptなしであなたが探していることをするかもしれません。

于 2012-11-19T14:07:37.940 に答える