/*!
* jQuery highlightTextarea 3.1.0
* Copyright 2014 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
* Licensed under MIT (http://opensource.org/licenses/MIT)
*/
/*!
* jQuery highlightTextarea 3.1.0
* Copyright 2014 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
* Licensed under MIT (http://opensource.org/licenses/MIT)
*/! function(a) {
"use strict";
var b = function(d, e) {
this.settings = a.extend({}, b.DEFAULTS), this.scrollbarWidth = c.getScrollbarWidth(), this.isInput = "input" == d[0].tagName.toLowerCase(), this.active = !1, this.$el = d, this.$el.wrap("<div class=highlightTextarea></div>"), this.$main = this.$el.parent(), this.$main.prepend("<div class=container><div class=highlighter></div></div>"), this.$container = this.$main.children().first(), this.$highlighter = this.$container.children(), this.setOptions(e), this.settings.id && (this.$main[0].id = this.settings.id), this.settings.resizable && this.applyResizable(), this.updateCss(), this.bindEvents(), this.highlight()
};
b.DEFAULTS = {
words: {},
ranges: {},
color: "#ffff00",
caseSensitive: !0,
resizable: !1,
id: "",
debug: !1
}, b.prototype.highlight = function() {
var b = c.htmlEntities(this.$el.val()),
d = this;
a.each(this.settings.words, function(a, c) {
b = b.replace(new RegExp("(" + c.join("|") + ")", d.regParam), '<mark style="background-color:' + a + ';">$1</mark>')
}), a.each(this.settings.ranges, function(a, d) {
d.start < b.length && (b = c.strInsert(b, d.end, "</mark>"), b = c.strInsert(b, d.start, '<mark style="background-color:' + d.color + ';">'))
}), this.$highlighter.html(b), this.updateSizePosition()
}, b.prototype.setWords = function(a) {
this.setOptions({
words: a,
ranges: {}
})
}, b.prototype.setRanges = function(a) {
this.setOptions({
words: {},
ranges: a
})
}, b.prototype.enable = function() {
this.bindEvents(), this.highlight()
}, b.prototype.disable = function() {
this.unbindEvents(), this.$highlighter.empty()
}, b.prototype.destroy = function() {
this.disable(), c.cloneCss(this.$container, this.$el, ["background-image", "background-color", "background-position", "background-repeat", "background-origin", "background-clip", "background-size", "background-attachment"]), this.$main.replaceWith(this.$el), this.$el.removeData("highlighter")
}, b.prototype.setOptions = function(b) {
"object" != typeof b || a.isEmptyObject(b) || (a.extend(this.settings, b), this.regParam = this.settings.caseSensitive ? "gm" : "gim", a.isEmptyObject(this.settings.words) ? a.isEmptyObject(this.settings.ranges) || (this.settings.words = {}, this.settings.ranges = c.cleanRanges(this.settings.ranges, this.settings.color)) : (this.settings.words = c.cleanWords(this.settings.words, this.settings.color), this.settings.ranges = {}), this.settings.debug ? this.$main.addClass("debug") : this.$main.removeClass("debug"), this.active && this.highlight())
}, b.prototype.bindEvents = function() {
if (!this.active) {
this.active = !0;
var b = this;
this.$highlighter.on({
"this.highlighter": function() {
b.$el.focus()
}
}), this.$el.on({
"input.highlighter": c.throttle(function() {
this.highlight()
}, 100, this),
"resize.highlighter": c.throttle(function() {
this.updateSizePosition(!0)
}, 50, this),
"scroll.highlighter select.highlighter": c.throttle(function() {
this.updateSizePosition()
}, 50, this)
}), this.isInput && this.$el.on({
"keydown.highlighter keypress.highlighter keyup.highlighter": function() {
setTimeout(a.proxy(b.updateSizePosition, b), 1)
},
"blur.highlighter": function() {
this.value = this.value, this.scrollLeft = 0, b.updateSizePosition.call(b)
}
})
}
}, b.prototype.unbindEvents = function() {
this.active && (this.active = !1, this.$highlighter.off("click.highlighter"), this.$el.off("input.highlighter resize.highlighter scroll.highlighter keydown.highlighter keypress.highlighter keyup.highlighter select.highlighter blur.highlighter"))
}, b.prototype.updateCss = function() {
c.cloneCss(this.$el, this.$main, ["float", "vertical-align"]), this.$main.css({
width: this.$el.outerWidth(!0),
height: this.$el.outerHeight(!0)
}), c.cloneCss(this.$el, this.$container, ["background-image", "background-color", "background-position", "background-repeat", "background-origin", "background-clip", "background-size", "background-attachment", "padding-top", "padding-right", "padding-bottom", "padding-left"]), this.$container.css({
top: c.toPx(this.$el.css("margin-top")) + c.toPx(this.$el.css("border-top-width")),
left: c.toPx(this.$el.css("margin-left")) + c.toPx(this.$el.css("border-left-width")),
width: this.$el.width(),
height: this.$el.height()
}), c.cloneCss(this.$el, this.$highlighter, ["font-size", "font-family", "font-style", "font-weight", "font-variant", "font-stretch", "line-height", "vertical-align", "word-spacing", "text-align", "letter-spacing", "text-rendering"]), this.$el.css({
background: "none"
})
}, b.prototype.applyResizable = function() {
jQuery.ui && this.$el.resizable({
handles: "se",
resize: c.throttle(function() {
this.updateSizePosition(!0)
}, 50, this)
})
}, b.prototype.updateSizePosition = function(a) {
a && (this.$main.css({
width: this.$el.outerWidth(!0),
height: this.$el.outerHeight(!0)
}), this.$container.css({
width: this.$el.width(),
height: this.$el.height()
}));
var b, c = 0;
this.isInput ? b = 99999 : (("scroll" == this.$el.css("overflow") || "scroll" == this.$el.css("overflow-y") || "hidden" != this.$el.css("overflow") && "hidden" != this.$el.css("overflow-y") && this.$el[0].clientHeight < this.$el[0].scrollHeight) && (c = this.scrollbarWidth), b = this.$el.width() - c), this.$highlighter.css({
width: b,
height: this.$el.height() + this.$el.scrollTop(),
top: -this.$el.scrollTop(),
left: -this.$el.scrollLeft()
})
};
var c = function() {};
c.getScrollbarWidth = function() {
var b = a('<div style="width:50px;height:50px;overflow:auto"><div> </div></div>').appendTo("body"),
c = b.children(),
d = c.innerWidth() - c.height(100).innerWidth();
return b.remove(), d
}, c.cloneCss = function(a, b, c) {
for (var d = 0, e = c.length; e > d; d++) b.css(c[d], a.css(c[d]))
}, c.toPx = function(b) {
if (b != b.replace("em", "")) {
var c = a('<div style="font-size:1em;margin:0;padding:0;height:auto;line-height:1;border:0;"> </div>').appendTo("body");
return b = Math.round(parseFloat(b.replace("em", "")) * c.height()), c.remove(), b
}
return parseInt(b != b.replace("px", "") ? b.replace("px", "") : b)
}, c.htmlEntities = function(b) {
return b ? a("<div></div>").text(b).html() : ""
}, c.strInsert = function(a, b, c) {
return a.slice(0, b) + c + a.slice(b)
}, c.throttle = function(a, b, c) {
var d = {
pid: null,
last: 0
};
return function() {
function e() {
return d.last = (new Date).getTime(), c ? a.apply(c, Array.prototype.slice.call(g)) : a.apply(h, Array.prototype.slice.call(g))
}
var f = (new Date).getTime() - d.last,
g = arguments,
h = this;
return f > b ? e() : (clearTimeout(d.pid), void(d.pid = setTimeout(e, b - f)))
}
}, c.cleanWords = function(b, d) {
var e = {};
a.isArray(b) || (b = [b]);
for (var f = 0, g = b.length; g > f; f++) {
var h = b[f];
if (a.isPlainObject(h)) {
e[h.color] || (e[h.color] = []), a.isArray(h.words) || (h.words = [h.words]);
for (var i = 0, j = h.words.length; j > i; i++) e[h.color].push(c.htmlEntities(h.words[i]))
} else e[d] || (e[d] = []), e[d].push(c.htmlEntities(h))
}
return e
}, c.cleanRanges = function(b, c) {
var d = [];
(a.isPlainObject(b) || a.isNumeric(b[0])) && (b = [b]);
for (var e = 0, f = b.length; f > e; e++) {
var g = b[e];
if (a.isArray(g)) d.push({
color: c,
start: g[0],
end: g[1]
});
else if (g.ranges) {
(a.isPlainObject(g.ranges) || a.isNumeric(g.ranges[0])) && (g.ranges = [g.ranges]);
for (var h = 0, i = g.ranges.length; i > h; h++) a.isArray(g.ranges[h]) ? d.push({
color: g.color,
start: g.ranges[h][0],
end: g.ranges[h][1]
}) : (g.ranges[h].length && (g.ranges[h].end = g.ranges[h].start + g.ranges[h].length), d.push(g.ranges[h]))
} else g.length && (g.end = g.start + g.length), d.push(g)
}
d.sort(function(a, b) {
return a.start == b.start ? a.end - b.end : a.start - b.start
});
var j = -1;
return a.each(d, function(b, c) {
c.start >= c.end && a.error("Invalid range end/start"), c.start < j && a.error("Ranges overlap"), j = c.end
}), d.reverse(), d
}, a.fn.highlightTextarea = function(c) {
var d = arguments;
return this.each(function() {
var e = a(this),
f = e.data("highlighter"),
g = "object" == typeof c && c;
(f || "destroy" != c) && (f || (f = new b(e, g), e.data("highlighter", f)), "string" == typeof c && f[c].apply(f, Array.prototype.slice.call(d, 1)))
})
}
}(jQuery);
$('textarea').highlightTextarea({
words: [{
color: '#ADF0FF',
words: ['東京']
}, {
color: '#FFFF00',
words: ['江戸']
}]
});
.highlightTextarea {
position: relative;
overflow: hidden
}
.highlightTextarea .container {
position: absolute;
margin: 0;
overflow: hidden
}
.highlightTextarea .highlighter {
position: relative;
border: none;
padding: 0;
margin: 0;
color: transparent;
cursor: text;
overflow: hidden;
white-space: pre-wrap;
word-wrap: break-word
}
.highlightTextarea.debug .highlighter {
color: red;
border: 1px solid red;
margin: -1px
}
.highlightTextarea mark {
line-height: inherit;
color: transparent;
margin: 0;
padding: 0
}
.highlightTextarea input,.highlightTextarea textarea {
position: absolute;
left: 0;
top: 0;
resize: none;
white-space: pre-wrap;
word-wrap: break-word
}
.highlightTextarea .ui-wrapper {
margin: 0!important
}
.highlightTextarea .ui-resizable-se {
bottom: 15px;
right: 0
}
textarea{
width:300px;
height:200px;
}
<textarea>東京は、江戸幕府の所在地の江戸を1868年9月に改称したものであり[1]、1869年2月11日(明治2年1月1日)に遷都、1878年(明治11年)に府制を施行[1]、「東京府」となった。</textarea>