表格单元格中的动态可折叠文本

时间:2014-03-17 23:43:55

标签: javascript css angularjs angularjs-directive collapsable

我有一张例如正则表达式包含名称,正则表达式,时间等。除了正则表达式之外的所有列都有固定宽度,表格的宽度设置为100%,表格在页面布局中为div。

我需要按照以下规则显示每个正则表达式:

  1. 如果正则表达式比列宽短 - 显示完整正则表达式
  2. 如果正则表达式长于列宽
    一个。显示完整正则表达式的显示图标,适用于列和省略号的正则表达式的一部分(...)

    湾显示短显正则表达式和完整正则表达式的显示图标

  3. 如果调整窗口大小或更改列宽,则必须动态评估所有规则。

    实施例

    --------------------------------------------------------------------------------
    | Name    | Regex                                          | Time       | Rule |
    --------------------------------------------------------------------------------
    | Full    | (^) \b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b | 2012-10-01 | 2b   |
    | Short   | [0-9a-f]{64}                                   | 2012-11-23 | 1    |
    | To long | (>) ^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}...| 2012-11-27 | 2a   |
    --------------------------------------------------------------------------------
    

    我拥有(更新)

    没有省略号的解决方案

    指令

    angular.module('ui.directives').directive('collapsibleText', function ($window, $compile, $timeout) {
        return {
            restrict: 'A',
            require: '^collapsibleText',
            scope: { collapsibleText: '@' },
            template: '<div style="display: inline-block;height: 20px;white-space: nowrap;">'
                        + '<i style="cursor:pointer" ng-hide="textSize < parentSize && !collapsed" ng-class="collapsed && \'icon-collapse\' || \'icon-expand\'" ng-click="changeCollapsed()"></i>'
                        + '<div ng-class="collapsed && \'no-collapsible\' || \'collapsible-text\'">{{collapsibleText}}</div>'
                    + '</div>',
            controller: ['$scope', function ($scope) {
                $scope.collapsed = false;
    
                $scope.getTextSize = function () {
                    var paddingLeft = $scope.element.css('paddingLeft'),
                        paddingRight = $scope.element.css('paddingRight');
    
                    var $shadow = angular.element('<span></span>').css({
                        position: 'absolute',
                        paddingLeft: paddingLeft,
                        paddingRight: paddingRight,
                        fontSize: $scope.element.css('fontSize'),
                        fontFamily: $scope.element.css('fontFamily'),
                        lineHeight: $scope.element.css('lineHeight'),
                        resize: 'none',
                        visibility: 'hidden'
                    });
                    angular.element(document.body).append($shadow);
                    $shadow.html($scope.collapsibleText);
    
                    $scope.textSize = $shadow[0].offsetWidth + 20;
                    return $scope.textSize;
                };
    
                $scope.getParentSize = function() {
                    $scope.parentSize = $scope.parent[0].offsetWidth;
                    return $scope.parentSize;
                };
    
                $scope.changeCollapsed = function () {
                    $scope.collapsed = !$scope.collapsed;
                };
            }],
            link: function (scope, element, attrs, ctrl) {
                scope.element = $(element);
                scope.parent = scope.element.parent();
    
                scope.getTextSize();
    
                var w = angular.element($window);
                scope.getWindowDimensions = function () {
                    return { 'h': w.height(), 'w': w.width() };
                };
                scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) {
                    scope.getParentSize();
                }, true);
    
                w.bind('resize', function () {
                    scope.$apply();
                });
    
                $timeout(function () { scope.getParentSize(); }, 0);
            }
        };
    });
    

    HTML

    ...
    <td><span collapsible-text="regex"></span></td>
    ...
    

    问题在哪里

    • 如果我展开一个正则表达式,其他长正则表达式以省略号结束,尽管比列宽更短
    • 一开始,所有正则表达式都已折叠图标,直到有人点击图标

    这是一个更好的解决方案吗?

1 个答案:

答案 0 :(得分:0)

我的最终解决方案

angular.module('ui.directives').directive('collapsibleText', function ($window, $timeout) {
    return {
        restrict: 'A',
        require: '^collapsibleText',
        scope: { collapsibleText: '@' },
        template: '<div style="display: inline-block;height: 20px;white-space: nowrap;position: relative;padding-right: 30px;">'
                    + '<i style="cursor:pointer" ng-hide="textSize < parentSize && !collapsed" ng-class="collapsed && \'icon-collapse\' || \'icon-expand\'" ng-click="changeCollapsed()"></i>'
                    + '<div ng-class="collapsed && \'no-collapsible\' || \'collapsible-text\'">{{collapsibleText}}</div>'
                    + '<span ng-hide="textSize < parentSize">...</span>'
                + '</div>',
        controller: ['$scope', function ($scope) {
            $scope.collapsed = false;

            $scope.getTextSize = function () {
                var paddingLeft = $scope.element.css('paddingLeft'),
                    paddingRight = $scope.element.css('paddingRight');

                var $shadow = angular.element('<span></span>').css({
                    position: 'absolute',
                    paddingLeft: paddingLeft,
                    paddingRight: paddingRight,
                    fontSize: $scope.element.css('fontSize'),
                    fontFamily: $scope.element.css('fontFamily'),
                    lineHeight: $scope.element.css('lineHeight'),
                    resize: 'none',
                    visibility: 'hidden'
                });
                angular.element(document.body).append($shadow);
                $shadow.html($scope.collapsibleText);

                $scope.textSize = $shadow[0].offsetWidth + 40;
                return $scope.textSize;
            };

            $scope.getParentSize = function() {
                $scope.parentSize = $scope.parent[0].offsetWidth;
                return $scope.parentSize;
            };

            $scope.changeCollapsed = function () {
                $scope.collapsed = !$scope.collapsed;
                $timeout(function() {
                     angular.element($window).triggerHandler('collapseChanged');
                }, 100);
            };
        }],
        link: function (scope, element) {
            scope.element = $(element);
            scope.parent = scope.element.parent();

            scope.getTextSize();

            var w = angular.element($window);
            w.bind('resize shown collapseChanged', function () {
                scope.getParentSize();
                scope.$apply();
            });
        }
    };
});