Javascript 用于替换文本的 Angularjs 指令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14692640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angularjs directive to replace text
提问by NimmoNet
How would I create a directive in angularjs that for example takes this element:
我将如何在 angularjs 中创建一个指令,例如采用这个元素:
<div>Example text http://example.com</div>
And convert it in to this
并将其转换为这个
<div>Example text <a href="http://example.com">http://example.com</a></div>
I already have the functionality written to auto link the text in a function and return the html (let's call the function "autoLink" ) but i'm not up to scratch on my directives.
我已经编写了自动链接函数中的文本并返回 html 的功能(让我们将函数称为 "autoLink" ),但我不符合我的指令。
I would also like to add a attribute to the element to pass a object in to the directive. e.g.
我还想向元素添加一个属性以将对象传递给指令。例如
<div linkprops="link.props" >Example text http://example.com</div>
Where link.props is object like {a: 'bla bla', b: 'waa waa'} which is to be passed to the autoLink function as a second param (the first been the text).
其中 link.props 是像 {a: 'bla bla', b: 'waa waa'} 这样的对象,它将作为第二个参数(第一个是文本)传递给 autoLink 函数。
回答by bmleite
Two ways of doing it:
两种做法:
Directive
指示
app.directive('parseUrl', function () {
var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/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:
HTML:
<p parse-url="props" ng-model="text"></p>
Filter
筛选
app.filter('parseUrlFilter', function () {
var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/gi;
return function (text, target, otherProp) {
return text.replace(urlPattern, '<a target="' + target + '" href="$&">$&</a>') + " | " + otherProp;
};
});
HTML:
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.
注意:这'otherProperty'只是举例,以防您想将更多属性传递到过滤器中。
Update:Improved replacing algorithm.
更新:改进的替换算法。
回答by exclsr
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
要回答这个问题的前半部分,没有额外的属性要求,可以使用 Angular 的链接过滤器:https://docs.angularjs.org/api/ngSanitize/filter/linky
回答by Neal
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.
如果有多个链接,最高投票的答案不起作用。Linky 已经为我们完成了 90% 的工作,唯一的问题是它清理了 html,从而删除了 html/换行符。我的解决方案是只编辑链接过滤器(以下是 Angular 1.2.19)而不是清理输入。
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>');
}
};
}]);
回答by konsumer
I wanted a pause button that swaps text. here is how I did it:
我想要一个可以交换文本的暂停按钮。这是我如何做到的:
in CSS:
在 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>
回答by Shai Reznik - HiRez.io
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...
}
}
});
回答by Jette
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.comand www.google.comwill be linkyfied.
受@Neal 的启发,我从较新的 Angular 1.5.8 中制作了这个“无消毒”过滤器。它还可以识别没有 ftp|http(s) 但以 www 开头的地址。这意味着,https://google.com和www.google.com将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, '"'),
'">');
addText(text);
html.push('</a>');
}
};
}

