Angularjs directive to replace text

前端 未结 6 660
陌清茗
陌清茗 2020-12-04 18:05

How would I create a directive in angularjs that for example takes this element:

Example text http://example.com

And

相关标签:
6条回答
  • 2020-12-04 18:48

    I wanted a pause button that swaps text. here is how I did it:

    in CSS:

    .playpause.paused .pause, .playpause .play { display:none; }
    .playpause.paused .play { display:inline; }
    

    in template:

    <button class="playpause" ng-class="{paused:paused}" ng-click="paused = !paused">
      <span class="play">play</span><span class="pause">pause</span>
    </button>
    
    0 讨论(0)
  • 2020-12-04 18:49

    Inspired by @Neal I made this "no sanitize" filter from the newer Angular 1.5.8. It also recognizes addresses without ftp|http(s) but starting with www. This means that both https://google.com and www.google.com will be linkyfied.

    angular.module('filter.parselinks',[])
    
    .filter('parseLinks', ParseLinks);
    
    function ParseLinks() {
      var LINKY_URL_REGEXP =
            /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
          MAILTO_REGEXP = /^mailto:/i;
    
      var isDefined = angular.isDefined;
      var isFunction = angular.isFunction;
      var isObject = angular.isObject;
      var isString = angular.isString;
    
      return function(text, target, attributes) {
        if (text == null || text === '') return text;
        if (typeof text !== 'string') return text;
    
        var attributesFn =
          isFunction(attributes) ? attributes :
          isObject(attributes) ? function getAttributesObject() {return attributes;} :
          function getEmptyAttributesObject() {return {};};
    
        var match;
        var raw = text;
        var html = [];
        var url;
        var i;
        while ((match = raw.match(LINKY_URL_REGEXP))) {
          // We can not end in these as they are sometimes found at the end of the sentence
          url = match[0];
          // if we did not match ftp/http/www/mailto then assume mailto
          if (!match[2] && !match[4]) {
            url = (match[3] ? 'http://' : 'mailto:') + url;
          }
          i = match.index;
          addText(raw.substr(0, i));
          addLink(url, match[0].replace(MAILTO_REGEXP, ''));
          raw = raw.substring(i + match[0].length);
        }
        addText(raw);
        return html.join('');
    
        function addText(text) {
          if (!text) {
            return;
          }
          html.push(text);
        }
    
        function addLink(url, text) {
          var key, linkAttributes = attributesFn(url);
          html.push('<a ');
    
          for (key in linkAttributes) {
            html.push(key + '="' + linkAttributes[key] + '" ');
          }
    
          if (isDefined(target) && !('target' in linkAttributes)) {
            html.push('target="',
                      target,
                      '" ');
          }
          html.push('href="',
                    url.replace(/"/g, '&quot;'),
                    '">');
          addText(text);
          html.push('</a>');
        }
      };
    }
    
    0 讨论(0)
  • 2020-12-04 18:51

    I would analyze the text in the link function on the directive:

    directive("myDirective", function(){
    
      return {
            restrict: "A",
            link: function(scope, element, attrs){
              // use the 'element' to manipulate it's contents...
            }
          }
      });
    
    0 讨论(0)
  • 2020-12-04 19:01

    Two ways of doing it:

    Directive

    app.directive('parseUrl', function () {
        var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/gi;
        return {
            restrict: 'A',
            require: 'ngModel',
            replace: true,
            scope: {
                props: '=parseUrl',
                ngModel: '=ngModel'
            },
            link: function compile(scope, element, attrs, controller) {
                scope.$watch('ngModel', function (value) {
                    var html = value.replace(urlPattern, '<a target="' + scope.props.target + '" href="$&">$&</a>') + " | " + scope.props.otherProp;
                    element.html(html);
                });
            }
        };
    });
    

    HTML:

    <p parse-url="props" ng-model="text"></p>
    

    Filter

    app.filter('parseUrlFilter', function () {
        var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/gi;
        return function (text, target, otherProp) {
            return text.replace(urlPattern, '<a target="' + target + '" href="$&">$&</a>') + " | " + otherProp;
        };
    });
    

    HTML:

    <p ng-bind-html-unsafe="text | parseUrlFilter:'_blank':'otherProperty'"></p>
    

    Note: The 'otherProperty' is just for example, in case you want to pass more properties into the filter.

    jsFiddle

    Update: Improved replacing algorithm.

    0 讨论(0)
  • 2020-12-04 19:03

    To answer the first half of this question, without the additional property requirement, one can use Angular's linky filter: https://docs.angularjs.org/api/ngSanitize/filter/linky

    0 讨论(0)
  • 2020-12-04 19:08

    The top voted answer does not work if there are multiple links. Linky already does 90% of the work for us, the only problem is that it sanitizes the html thus removing html/newlines. My solution was to just edit the linky filter (below is Angular 1.2.19) to not sanitize the input.

    app.filter('linkyUnsanitized', ['$sanitize', function($sanitize) {
      var LINKY_URL_REGEXP =
            /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/,
          MAILTO_REGEXP = /^mailto:/;
    
      return function(text, target) {
        if (!text) return text;
        var match;
        var raw = text;
        var html = [];
        var url;
        var i;
        while ((match = raw.match(LINKY_URL_REGEXP))) {
          // We can not end in these as they are sometimes found at the end of the sentence
          url = match[0];
          // if we did not match ftp/http/mailto then assume mailto
          if (match[2] == match[3]) url = 'mailto:' + url;
          i = match.index;
          addText(raw.substr(0, i));
          addLink(url, match[0].replace(MAILTO_REGEXP, ''));
          raw = raw.substring(i + match[0].length);
        }
        addText(raw);
        return html.join('');
    
        function addText(text) {
          if (!text) {
            return;
          }
          html.push(text);
        }
    
        function addLink(url, text) {
          html.push('<a ');
          if (angular.isDefined(target)) {
            html.push('target="');
            html.push(target);
            html.push('" ');
          }
          html.push('href="');
          html.push(url);
          html.push('">');
          addText(text);
          html.push('</a>');
        }
      };
    }]);
    
    0 讨论(0)
提交回复
热议问题