I want to manipulate the DOM a bit and need some help.
That's my HTML-Markup:
<span class=“content“> This is my content: {#eeeeee}grey text{/#eeeeee} {#f00000}red text{/#f00000}</span>
That's how it should be:
<span class="content">This is my content: <span style="color:#eeeeee;">grey text</span><span style="color:#f00000;">red text</span></span>
The script should replace the brackets with span tags to change the font-color.
The color should the same that is in the bracket.
My approach:
function regcolor(element) {
var text = element.innerText;
var matches = text.match(/\{(#[0-9A-Fa-f]{6})\}([\s\S]*)\{\/\1\}/gim);
if (matches != null) {
var arr = $(matches).map(function (i, val) {
var input = [];
var color = val.slice(1, 8);
var textf = val.slice(9, val.length - 10);
var html = "<span style=\"color: " + color + ";\">" + textf + "</span>";
input.push(html);
return input;
});
var input = $.makeArray(arr);
$(element).html(input.join(''));
};
But it's not working very well and i'm not feeling good with the code, it looks messy.
And the script looses the content that's not in the brackets("This is my content:").
Anyone a idea?
I've used just a touch of jQuery, but it could easily do without. It's just a regular expression string replacement.
$('.content').each(function() {
var re = /\{(#[a-z0-9]{3,6})\}(.*?)\{\/\1\}/g;
// ^ ^
// $1 $2
this.innerHTML = this.innerHTML.replace(re, function($0, $1, $2) {
return '<span style="color: ' + $1 + '">' + $2 + '</span>';
});
});
I'm using a back-reference to properly match the opening and closing braces.
Update
Could be even shorter:
$('.content').each(function() {
var re = /\{(#[a-z0-9]{3,6})\}(.*?)\{\/\1\}/g,
repl = '<span style="color: $1">$2</span>';
this.innerHTML = this.innerHTML.replace(re, repl);
});
Look mum, no jQuery
var nodes = document.getElementsByClassName('content');
for (var i = 0, n = nodes.length; i < n; ++i) {
var re = /\{(#[a-z0-9]{3,6})\}(.*?)\{\/\1\}/g,
repl = '<span style="color: $1">$2</span>';
nodes[i].innerHTML = nodes[i].innerHTML.replace(re, repl);
}
Use the regex to replace the matches directly:
function regcolor2(element) {
var text = element.html();
var i = 0;
var places = text.replace(/\{(#[0-9A-Fa-f]{6})\}([\s\S]*)\{\/\1\}/gim, function( match ) {
var color = match.slice(1, 8);
var textf = match.slice(9, match.length - 10);
var html = "<span style=\"color: " + color + ";\">" + textf + "</span>";
return html;
});
$(element).html(places);
}
it can be shorter with jquery and this method or syntax
$(function() {
$('.content').html($('.content').text().replace( new RegExp('{(.*?)}(.*?){\/.*?}','g'), '<span style="color:$1">$2</span>'));
});
Related
The code is used in a HTML document, where when you press a button the first word in every sentence gets marked in bold
This is my code:
var i = 0;
while(i < restOftext.length) {
if (text[i] === ".") {
var space = text.indexOf(" ", i + 2);
var tekststykke = text.slice(i + 2, space);
var text = text.slice(0, i) + "<b>" + tekststykke + "</b>" + text.slice(i + (tekststykke.length + 2));
var period = text.replace(/<b>/g, ". <b>");
var text2 = "<b>" + firstWord + "</b>" + period.slice(space1);
i++
}
}
document.getElementById("firstWordBold").innerHTML = text2;
}
It's in the first part of the code under function firstWordBold(); where it says there is an error with
var space1 = text.indexOf(" ");
Looks like you're missing a closing quote on your string, at least in the example you provided in the question.
Your problem is the scope of the text variable. In firstWordBold change every text to this.text, except the last two where you re-define text
Also, if you want to apply bold to the first word this is easier...
document.getElementById('test-div-2').innerHTML = '<b>' + firstWord + '</b>' + restOftext;
It now works for me, with no errors and it applies bold to the first word.
Here's how the function ended up,
function firstWordBold() {
console.log('bolding!');
var space1 = this.text.indexOf(' ');
var firstWord = this.text.slice(0, space1);
var restOftext = this.text.slice(space1);
document.getElementById('test-div-2').innerHTML = '<b>' + firstWord + '</b>' + restOftext;
}
To make every first word bold, try this...
function firstWordBold() {
let newHTML = '';
const sentences = this.text.split('.');
for (let sentence of sentences) {
sentence = sentence.trim();
var space1 = sentence.indexOf(' ');
var firstWord = sentence.slice(0, space1);
var restOftext = sentence.slice(space1);
newHTML += '<b>' + firstWord + '</b>' + restOftext + ' ';
}
document.getElementById('test-div-2').innerHTML = newHTML;
}
One last edit, I didn't notice you had sentences ending with anything other that a period before. To split on multiple delimiters use a regex, like so,
const sentences = this.text.split(/(?<=[.?!])\s/);
my highlight filter
app.filter('highlightWord', function () {
return function (isSectionData, selectedWord) {
if (!isSectionData) return '';
// var items = selectedWord.split(" ");
var items = selectedWord.trim().replace(/ OR /g, ' ').replace(/ AND /g, ' ').replace(/ - /g, '').replace(/-/g, '').replace(/"/g, '').split(' ');
for (var i = 0, len = items.length; i < len; i++) {
var pattern = new RegExp(items[i], "gi");
if (isSectionData && items[i] != "") {
isSectionData = isSectionData.replace(pattern, '<span class="highlighted">' + items[i] + '</span>');
}
}
return isSectionData;
};});
in this highlighter is working fine
but in some case, it changes my HTML paragraph
like I search for 'MI' word in highlight search world like 'similar' and highlight and change this to 'siMIlar'
Is there any something I need to change for correct my result
Some changes on code
app.filter('highlightWord', function () {
return function (isSectionData, selectedWord) {
if (!isSectionData) return '';
// var items = selectedWord.split(" ");
var items = selectedWord.trim().replace(/ OR /g, ' ').replace(/ AND /g, ' ').replace(/ - /g, '').replace(/-/g, '').replace(/"/g, '').split(' ');
for (var i = 0, len = items.length; i < len; i++) {
var pattern = new RegExp(' (' + items[i] + ')', "ig");
if (isSectionData && items[i] != "") {
isSectionData = isSectionData.replace(pattern, function (match) {
return ' <span class="highlighted">' + match + '</span> ';
});
}
}
return isSectionData;
};
});
changes are
pattern search text with space in RegExp with ig reg expression
I'd like to extract hex colors from a string and generate a colored html code. Example: I have this string :
#ff0000He#ffccccllo
it'd convert it to
<span style="color:#ff0000">He</span><span style="color:#ffcccc">llo</span>
Single-liner with regex replace:
"#ff0000He#ffccccllo#ffccccooo".replace(/(#.{6})([^#]*)/g, '<span style="color: $1">$2</span>')
Fiddle
You could make it using 'split' with a RegExp
Something like:
var str = '#ff0000He#ffccccllo#123123sdfsdfsdfsdf#AA6456asdasdasd';
var expR = /(#[0-9|a-f]{6})/gi
var a = str.split(expR);
a.shift();
var output = ''
for (var i = 0; i < a.length; i++) {
var color = a[i];
var text = a[++i];
output += '<span style="color: ' + color + '">' + text + '</span>';
};
document.getElementById("result").innerHTML = output;
<div id="result">
</div>
This will do the trick:
var input = '#ff0000He#ffccccllo'.split('#');
var output = '';
input.filter(function (str) {
return !!str;
}).forEach(function (str) {
output += '<span style="#' + str.slice(0, 6) + '">' + str.slice(6) + '</span>';
})
console.log(output) // --> <span style="...
Or as a function:
function convert(input) {
input = input.split('#');
var output = '';
input.filter(function (str) {
return !!str;
}).forEach(function (str) {
output += '<span style="#' + str.slice(0, 6) + '">' + str.slice(6) + '</span>';
})
return output;
}
UPDATE: fixed error in the function dfn. Works now.
There are similar posts but I can't find a solution for my unique case.
I have a script which highlights a keyword when a user clicks the highlight button. Currently it is only highlighting the word "fox", but I need it to highlight additional words, in this case "fence" and "jumped".
Here is HTML:
<div id="inputText">
The fox quickly jumped over the fence.
</div>
<button onclick="highlight('fox')">Highlight</button>
I tried changing 'fox' to '+fox+','+fence+','+jumped+' but no luck.
The javascript is:
function highlight(text)
{
inputText = document.getElementById("inputText")
var innerHTML = inputText.innerHTML
var index = innerHTML.indexOf(text);
if ( index >= 0 )
{
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
inputText.innerHTML = innerHTML
}
}
and CSS:
.highlight
{
background-color:yellow;}
<button onclick="highlight('fox')+highlight('jumped')+highlight('fence')">Highlight</button>
Instead of using onclick in your markup, you should try to utilize best practice and bind events through javascript only since it's the most unobtrusive way to attach handlers to DOM elements.
Furthermore you can define the words you want to highlight in an array that you iterate the highlighting code over, like the fiddle below.
(function() {
function highlight() {
var wordsToHighlight = ["fox", "fence", "jumped"];
wordsToHighlight.forEach(function(text) {
inputText = document.getElementById("inputText")
var innerHTML = inputText.innerHTML
var index = innerHTML.indexOf(text);
if (index >= 0) {
innerHTML = innerHTML.substring(0, index) + "<span class='highlight'>" + innerHTML.substring(index, index + text.length) + "</span>" + innerHTML.substring(index + text.length);
inputText.innerHTML = innerHTML
}
});
}
button = document.getElementById('btn-highlight');
button.onclick = highlight;
})();
.highlight {
background-color: yellow;
}
<div id="inputText">The fox quickly jumped over the fence.</div>
<br/>
<button id="btn-highlight">Highlight</button>
Notice the id="btn-highlight" in the markup, and the binding of the highlight function to the click event.
We can pass a delimited string and then split that into an array. You can use any delimiter you want, but I chose a comma. You can then loop through this array to highlight the words.
jsfiddle
<div id="inputText">
The fox quickly jumped over the fence.
</div>
<button onclick="highlight('fox,fence,jumped')">Highlight</button>
<script>
function highlight(text){
var i, index, words = text.split(",");
var inputText = document.getElementById("inputText");
var innerHTML = inputText.innerHTML;
for(i=0;i<words.length;i++){
index = innerHTML.indexOf(words[i]);
if (index >= 0) {
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+words[i].length) + "</span>" + innerHTML.substring(index + words[i].length);
inputText.innerHTML = innerHTML;
}
}
}
</script>
Better approach will be to use a pre-made dictionary like object:
DEMO and source : JSnippet DEMO
JS:
var dic = {
fox:['fox','jumped','fence'],
cat:['cat','happy']
};
function parse(target) {
var inputText = document.getElementById("inputText");
inputText.innerHTML = inputText.innerHTML.replace(/(<([^>]+)>)/ig,"");
if (typeof dic[target] === 'object')
for (var i=0; i<dic[target].length; i++)
tokenize(dic[target][i]);
}
function tokenize(text) {
var inputText = document.getElementById("inputText");
var inner = inputText.innerHTML;
var index = inner.indexOf(text);
if ( index >= 0 ) {
inner = inner.substring(0,index) +
"<span class='highlight'>" + inner.substring(index, index + text.length) + "</span>" +
inner.substring(index + text.length);
inputText.innerHTML = inner;
}
}
I'm having a small problem with a regexp pattern. I don't have regexp knowledge, so I couldn't solve it.
I have this text:
var text = "this (is) some (ran)dom text";
and I want to capture anything between (). So after following this tutorial I came up with this pattern:
var re = /(\(\w*\))/g;
which works fine. But what I want to do now is replace the found matches, or rather modify. I want to wrap the found matches with a span tag. So I used this code:
var spanOpen = '<span style="color: silver;">';
var spanClose = '</span>';
text.replace(re, spanOpen + text.match(re) + spanClose);
even though the code works, I don't get the result I want. It outputs:
as HTML
this <span style="color: silver;">(is),(ran)</span> some <span style="color: silver;">(is),(ran)</span>dom text
as text
this (is),(ran) some (is),(ran)dom text
You can check the example in fiddle. How can I fix this?
The code in fiddle:
var text = "this (is) some (ran)dom text";
var re = /(\(\w*\))/g;
var spanOpen = '<span style="color: silver;">';
var spanClose = '</span>';
var original = "original: " + text + "<br>";
var desired = "desired: this " +spanOpen+"(is)"+spanClose+ " some " +spanOpen+"(ran)"+spanClose+ "dom text<br>";
var output = "output: " + text.replace(re, spanOpen + text.match(re) + spanClose);
var result = original + desired + output;
document.body.innerHTML = result;
If the title is wrong or misleading, I'll change it.
The .replace() method can take a function as the 2nd parameter. That will come in handy here.
var output = "output: " + text.replace(re, function(match){
return spanOpen + match + spanClose
});
The function will be called for each individual match.
You can also use '$&' in your replace string to reference each match
var output = "output: " + text.replace(re, spanOpen + '$&' + spanClose);
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
text.match(re) is returning an array of the result, so what you can do is loop this array and replace your string with each items, like this:
var matches = text.match(re);
var output = "output: " + text;
for (var i = 0; i < matches.length; i++)
{
output = output.replace(matches[i], spanOpen + matches[i] + spanClose);
}
See this FIDDLE