| @@ -7,10 +7,25 @@ | ||
| 7 | 7 | return ptr.apply(context); |
| 8 | 8 | return typeof ptr == "string" ? context.find(ptr) : ptr; |
| 9 | 9 | }; |
| 10 | 10 | |
| 11 | + // Writes text into box, wrapping the first match of re in the highlight element. | |
| 12 | + // Text is only ever inserted as text nodes so names are never parsed as HTML. | |
| 13 | + var highlight = function (box, text, re, opts) { | |
| 14 | + var m = re ? text.match(re) : null; | |
| 15 | + if (!m || !m[0].length) { | |
| 16 | + box.text(text); | |
| 17 | + return; | |
| 18 | + } | |
| 19 | + box.empty().append( | |
| 20 | + document.createTextNode(text.slice(0, m.index)), | |
| 21 | + $(opts.highlight).text(m[0]), | |
| 22 | + document.createTextNode(text.slice(m.index + m[0].length)) | |
| 23 | + ); | |
| 24 | + }; | |
| 25 | + | |
| 11 | 26 | var filter = function (obj, search, opts) { |
| 12 | - var re = new RegExp(search.replace(/[.\\\\+*?\[\]\{\}\(\)-]/g, "\\$&"), | |
| 27 | + var re = new RegExp(search.replace(/[.*+?^${}()|[\]\\-]/g, "\\$&"), | |
| 13 | 28 | opts.caseSensitive ? "" : "i"); |
| 14 | 29 | var ctx = sel(opts.element, obj); |
| 15 | 30 | var n = 0; |
| 16 | 31 | var size = opts.stepSize || 100; |
| @@ -32,14 +47,14 @@ | ||
| 32 | 47 | if (!e.hasClass('hidden')) { |
| 33 | 48 | if (!search.length) { |
| 34 | 49 | e.show(); |
| 35 | 50 | if (opts.highlight) { |
| 36 | - box.html(val); | |
| 51 | + highlight(box, val, null, opts); | |
| 37 | 52 | } |
| 38 | 53 | } else if (val.match(re)) { |
| 39 | 54 | e.show(); |
| 40 | 55 | if (opts.highlight) { |
| 41 | - box.html(val.replace(re, opts.highlightRe)); | |
| 56 | + highlight(box, val, re, opts); | |
| 42 | 57 | } |
| 43 | 58 | } else { |
| 44 | 59 | e.hide(); |
| 45 | 60 | } |
| @@ -53,11 +68,8 @@ | ||
| 53 | 68 | |
| 54 | 69 | }; |
| 55 | 70 | |
| 56 | 71 | $.fn.searchFilter = function (opts) { |
| 57 | - if (opts.highlight) { | |
| 58 | - opts.highlightRe = $("<div>@</div>").wrapInner(opts.highlight).html().replace(/@/g, "$$&"); | |
| 59 | - } | |
| 60 | 72 | $(this).on("keyup", function () { |
| 61 | 73 | filter(this, this.value, opts) |
| 62 | 74 | }); |
| 63 | 75 | $(this).on("change", function () { |