我有这样的HTML:
<div>
<h3>How are you? Fine?</h3>
</div>
我想在不同的东西中使用两个数字n和m来转换它,例如: 如果n = 5且m = 12
<div>
<h3>How
<span class="yellow">are you?</span>
Fine?</h3>
</div>
换句话说,我想使用两个数字“突出显示”字符串的一部分,这两个数字指定“突出显示”的开头和结尾(以字符为单位)。
我尝试了这个,但它不起作用:
//in the previous example it will be a xpath selector for div/h3
var selection=$(document.body).xpath(selector).text();
//it will be "are you?"
var substring=selection.substring(n,m);
//it would make that i want, but it doesn't
$(document.body).xpath(selector).contents().filter(function() {
return substring;
}).wrap("<span class=\"yellow\"></span>");
}
答案 0 :(得分:1)
一种方法是 - 而不是换行,用切片操作版本替换h3的内容。
请参阅此JSFiddle http://jsfiddle.net/9LeL3f3n/21/
<div>
<h3>How are you? Fine?</h3>
</div>
$(document).ready(function() {
var highlight = function(str, start, end) {
return str.slice(0,start-1) +
'<span style="color:#ffff00">' +
str.substring(start-1, end) +
'</span>' +
str.slice(-1 * (str.length - end));
};
var n = 5;
var m = 12;
$('h3').html(highlight($('h3').html(),n,m));
});
答案 1 :(得分:0)
我建议编写自己的插件来实现这一点,只是因为它似乎对重复使用有用。也就是说,我提供了以下方法,它有效地分割textNode节点,使用textNode.splitText()
并在重新插入该节点之前将相关部分附加到创建的元素,并将textNodes包围回父元素: / p>
// a simple plugin approach, taken from:
// https://learn.jquery.com/plugins/basic-plugin-creation/
(function ($) {
// defining the name of the plugin ('highlight'):
$.fn.highlight = function (opts) {
// the default settings, used if no arguments are
// passed into the plugin via the 'opts' Object:
var settings = {
'start' : 0,
'end' : 1,
'wrapper' : 'span',
'class' : 'highlight',
'css' : {
'color' : 'yellow'
}
},
// 'empty' declared variables for later use:
node, textMiddle, textEnd;
// iterating over the 'opts' Object using
// a for...in loop:
for (var prop in opts) {
// if the 'opts' Object has an own property 'prop'
// (not one inherited from its prototype chain):
if (opts.hasOwnProperty(prop)) {
// we update the 'settings' Object to
// be equal to the 'opts' Object property-value:
settings[prop] = opts[prop];
}
}
// using parseInt() to ensure that we're working
// with numbers, rather than strings, and that those
// numbers are in base-10:
settings.start = parseInt(settings.start, 10);
settings.end = parseInt(settings.end, 10);
// normalising the settings.wrapper string, ensuring that
// if the user passes in '<span>' (or '<<<<<span>', etc)
// we remove those (this could be made even safer by only
// allowing the first consecutive string of alphabetical
// characters):
settings.wrapper = settings.wrapper.replace(/<|>/g,'');
// here we iterate over, and return, the jQuery collection
// to allow for chaining to continue (here 'this' is the
// jQuery collection of nodes/elements):
return this.each(function () {
// here this is the DOM node from the collection.
// and here we iterate over the childNodes of each
// DOM node from that collection:
$(this).contents().each(function () {
// if the current childNode is nodeType 3 (a textNode)
// AND the length of the nodeValue (the text itself)
// is greater than, or equal to, the settings.end:
if (this.nodeType === 3 && this.nodeValue.length >= settings.end) {
// we create a new element equal to the
// settings.wrapper argument passed in by
// the user (or the default):
node = document.createElement(settings.wrapper);
// if we have a settings.css Object:
if (settings.css) {
// we iterate over that Object with a
// for...in loop (as above):
for (var prop in settings.css){
if (settings.css.hasOwnProperty(prop)) {
// setting the node's style property
// to be equal to the property-value
// of the settings.css Object:
node.style[prop] = settings.css[prop];
}
}
}
// if we have a settings.class:
if (settings.class) {
// we use Array.prototype.forEach
Array.prototype.forEach
// with Function.prototype.call()
// to iterate over the resulting array
// of splitting the settings.class
// String on white-space characters:
.call(settings.class.split(/\s+/),
// the 'classname' argument is the
// class-name from the string, now
// in the Array over which we're iterating:
function (classname) {
// here we add the trimmed classname
// string (removing the leading and
// trailing white=space) to the
// list of classes of the node:
node.classList.add(classname.trim());
});
}
// here we split the textNode (this) using
// Text.splitText(offset); which converts
// one textNode into two separate textNodes
// and returns the second (newly-created)
// textNode ('this' remains 'this' but with
// shortened text):
textMiddle = this.splitText(settings.start);
// and again, but this time we have to compensate
// for already shortening the textNode, and
// and so subtract the offset from the settings.end:
textEnd = textMiddle.splitText(settings.end - settings.start);
// appending the textNode to the created
// element:
node.appendChild(textMiddle);
// inserting the created node after the original
// textNode:
this.parentNode.insertBefore(node, this.nextSibling);
}
});
});
};
// passing jQuery into the plugin in order to allow us to use
// the $ alias within the plugin:
})(jQuery);
// using the plugin:
$('div h3').highlight({
// setting the 'start' offset:
'start' : 4,
// the end index/offset:
'end' : 12,
// specifying classes to add to the created element(s):
'class' : 'highlight classes',
// setting the CSS properties of the created element(s):
'css' : {
'color' : '#f89',
'text-decoration' : 'underline'
}
});
(function($) {
$.fn.highlight = function(opts) {
var settings = {
'start': 0,
'end': 1,
'wrapper': 'span',
'class': 'highlight',
'css': {
'color': 'yellow'
}
},
node, textMiddle, textEnd;
for (var prop in opts) {
if (opts.hasOwnProperty(prop)) {
settings[prop] = opts[prop];
}
}
settings.wrapper = settings.wrapper.replace(/<|>/g, '');
return this.each(function() {
$(this).contents().each(function() {
if (this.nodeType === 3 && this.nodeValue.length >= settings.end) {
node = document.createElement(settings.wrapper);
if (settings.css) {
for (var prop in settings.css) {
if (settings.css.hasOwnProperty(prop)) {
node.style[prop] = settings.css[prop];
}
}
}
if (settings.class) {
Array.prototype.forEach.call(settings.class.split(/\s+/), function(classname) {
node.classList.add(classname.trim());
});
}
textMiddle = this.splitText(settings.start);
textEnd = textMiddle.splitText(settings.end - settings.start);
node.appendChild(textMiddle);
this.parentNode.insertBefore(node, this.nextSibling);
}
});
});
};
})(jQuery);
$('div h3').highlight({
'start': 4,
'end': 12,
'class': 'highlight classes',
'css': {
'color': '#f89',
'text-decoration': 'underline'
}
});
.highlight {
font-style: italic;
}
.classes {
font-variant: small-caps;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h3>How are you? Fine?</h3>
</div>
参考文献:
Array.prototype.forEach()
。document.createElement()
。Element.classList
。For...in
loop。Function.prototype.call()
。Node.appendChild()
。Node.insertBefore()
。Node.nodeType
。Node.nodeValue
。Node.parentNode
。Object.prototype.hasOwnProperty()
。parseInt()
。String.prototype.replace()
。String.prototype.split()
。Text.splitText()
。