I have this sample code for replacing text with emoticons when message is submitted. However, I want to add title on emoticons when mouse hover to it to identify what kind of emoticon user used, how can I achieved that in my current code? thanks
<html>
<head>
<title>Testing Emoticon</title>
</head>
<body>
<input type="text" name="message" id="message">
<br><br>
<div class="results"></div>
<script language="javascript" src="./assets/js/jquery-1.11.3.min.js"></script>
<script>
function replaceEmoticons(text) {
var emoticons = {
':-)' : 'smile.png',
':)' : 'smile.png',
';)' : 'wink.png',
';-)' : 'wink.png',
':P' : 'tongue.png'
}, url = "http://localhost/cb/2/assets/img/smileys/", patterns = [],
metachars = /[[\]{}()*+?.\\|^$\-,&#\s]/g;
// build a regex pattern for each defined property
for (var i in emoticons) {
if (emoticons.hasOwnProperty(i)){ // escape metacharacters
patterns.push('('+i.replace(metachars, "\\$&")+')');
}
}
// build the regular expression and replace
return text.replace(new RegExp(patterns.join('|'),'g'), function(match) {
return typeof emoticons[match] != 'undefined' ?
'<img src="'+url+emoticons[match]+'"/>' :
match;
});
}
</script>
<script>
$('#message').keypress(function(e){
if(e.which == 13){//Enter key pressed
e.preventDefault();
var emoticon = $('#message').val();
$('.results').html(replaceEmoticons(emoticon));
}
});
</script>
</body>
</html>
Main purpose is solved, when you type :) the output title on hover is smile that came from smile.png thanks to #PraveenKumar
Additional question is can I customize the title, like if I type :P the output of title might be Stick Out Tongue instead of tongue that came from tongue.png ?
For my additional question, I came up with a solution base on my research and trial error tests.
I've got an idea when I see this link javascript emotify by Ben Alman.
So I reconstruct my codes and came up to this:
I modified my json array to add more data.
var emoticons = {
':-)' : ['smile.png', 'Smile'],
':)' : ['smile.png', 'Smile'],
';)' : ['wink.png', 'Wink'],
';-)' : ['wink.png', 'Wink'],
':P' : ['tongue.png', 'Stick Out Tongue']
}, url = "http://localhost/cb/2/assets/img/smileys/", patterns = [],
metachars = /[[\]{}()*+?.\\|^$\-,&#\s]/g;
And also this part of the function to match my new json array:
// build the regular expression and replace
return text.replace(new RegExp(patterns.join('|'),'g'), function (match) {
return typeof emoticons[match][0] != 'undefined' ?
'<img src="'+url+emoticons[match][0]+'" title="' + emoticons[match][1] + '" />' :
match;
});
Now its really working according to my needs. Hooray!
Add it while replacing:
return text.replace(new RegExp(patterns.join('|'),'g'), function(match) {
return typeof emoticons[match] != 'undefined' ?
'<img src="'+url+emoticons[match]+'" title="' + emoticons[match].substr(0, emoticons[match].length-4) + '" />' :
match;
});
Working Bin: http://jsbin.com/cotefuwate/edit?output
Related
Trying to wrap specific keywords in hyperlinks, but replacements take place inifitely many times:
var replacements = [
{ txt: 'magicFunction', link: 'https://www.example.com/doc/api/magicFunction.htm' },
];
$(function() {
$.each(replacements,
function() {
var searchWord = this.txt;
var link = this.link;
$('body:contains("' + searchWord + '")').each(function() {
var newHtml = $(this).html().replace(searchWord,
'' + searchWord + '');
$(this).html(newHtml);
});
}
);
});
I'd need a condition around the matching part to say that if is already wrapped in a hyperlink then don't do anything, or some other workaround.
How can it be fixed?
https://jsfiddle.net/m4j28s13/
You can select all nodes in the body but exclude all <a> elements:
$('body *:not(a):contains("' + searchWord + '")').each(...)
See proof-of-concept example:
var replacements = [{
txt: 'magicFunction',
link: 'https://www.example.com/doc/api/magicFunction.htm'
}, ];
$.each(replacements,
function() {
var searchWord = this.txt;
var link = this.link;
$('body *:not(a):contains("' + searchWord + '")').each(function() {
var newHtml = $(this).html().replace(searchWord,
'' + searchWord + '');
$(this).html(newHtml);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>This sentence mentions magicFunction() in a paragraph.</p>
<p>The following code block (from API reference) mentions it too:</p>
<code class="code-block hljs lua">if a==0 then
h=magicFunction('foo')
end</code>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/highlight.min.js"></script>
Update: to handle cases where an <a> element may contain nested tags that contain the replacement word, another solution will be to actually replace :contains with a custom guard clause in the callback, which will check if the child textNodes contain the keyword. If it does, then perform the replacement:
var replacements = [{
txt: 'magicFunction',
link: 'https://www.example.com/doc/api/magicFunction.htm'
}, ];
$.each(replacements,
function() {
var searchWord = this.txt;
var link = this.link;
$('*:not(a, script)').each(function() {
const textContent = $(this).contents().filter(function() {
return this.nodeType === Node.TEXT_NODE;
}).text();
if (textContent.match(searchWord)) {
var newHtml = $(this).html().replace(searchWord,
'' + searchWord + '');
$(this).html(newHtml);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>This sentence mentions magicFunction() in a paragraph.</p>
<p>The following code block (from API reference) mentions it too:</p>
<code class="code-block hljs lua">if a==0 then
h=magicFunction('foo')
end</code>
<p>This mention is already linked (should not be linked again): <a class="postlink" href="//www.example2.com/doc/api/magicFunction"><code style="display:inline">magicFunction</code></a></p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/highlight.min.js"></script>
I know there are many similar questions posted, and have tried a couple solutions, but would really appreciate some guidance with my specific issue.
I would like to remove the following HTML markup from my string for each item in my array:
<SPAN CLASS="KEYWORDSEARCHTERM"> </SPAN>
I have an array of json objects (printArray) with a printArray.header that might contain the HTML markup.
The header text is not always the same.
Below are 2 examples of what the printArray.header might look like:
<SPAN CLASS="KEYWORDSEARCHTERM">MOST EMPOWERED</SPAN> COMPANIES 2016
RECORD WINE PRICES AT <SPAN CLASS="KEYWORDSEARCHTERM">NEDBANK</SPAN> AUCTION
I would like the strip the HTML markup, leaving me with the following results:
MOST EMPOWERED COMPANIES 2016
RECORD WINE PRICES AT NEDBANK AUCTION
Here is my function:
var newHeaderString;
var printArrayWithExtract;
var summaryText;
this.setPrintItems = function(printArray) {
angular.forEach(printArray, function(printItem){
if (printItem.ArticleText === null) {
summaryText = '';
}
else {
summaryText = '... ' + printItem.ArticleText.substring(50, 210) + '...';
}
// Code to replace the HTML markup in printItem.header
// and return newHeaderString
printArrayWithExtract.push(
{
ArticleText: printItem.ArticleText,
Summary: summaryText,
Circulation: printItem.Circulation,
Headline: newHeaderString,
}
);
});
return printArrayWithExtract;
};
Try this function. It will remove all markup tags...
function strip(html)
{
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || "";
}
Call this function sending the html as a string. For example,
var str = '<SPAN CLASS="KEYWORDSEARCHTERM">MOST EMPOWERED</SPAN> COMPANIES 2016';
var expectedText = strip(str);
Here you find your expected text.
It can be done using regular expressions, see below:
var s1 = '<SPAN CLASS="KEYWORDSEARCHTERM">MOST EMPOWERED</SPAN> COMPANIES 2016';
var s2 = 'RECORD WINE PRICES AT <SPAN CLASS="KEYWORDSEARCHTERM">NEDBANK</SPAN> AUCTION';
function removeSpanInText(s) {
return s.replace(/<\/?SPAN[^>]*>/gi, "");
}
$("#x1").text(removeSpanInText(s1));
$("#x2").text(removeSpanInText(s2));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
1 ->
<span id="x1"></span>
<br/>2 ->
<span id="x2"></span>
For more info, see e.g. Javascript Regex Replace HTML Tags.
And jQuery is not needed, just used here to show the output.
I used this little replace function:
if (printItem.Headline === null) {
headlineText = '';
}
else {
var str = printItem.Headline;
var rem1 = str.replace('<SPAN CLASS="KEYWORDSEARCHTERM">', '');
var rem2 = rem1.replace('</SPAN>', '');
var newHeaderString = rem2;
}
I'm using the Twitter API to get top 5 tweets for my app. I need to highlight, or link parts of the tweets differently. Ex, #'s will be orange, #'s will be red and clickable, etc...
From their API, they offer user_timeline endpoint:
https://dev.twitter.com/rest/reference/get/statuses/user_timeline
But the tweets object's text returns with those special characters embedded within it. I don't see options to pull out those #, # and href from the object:
Tweets object:
{
...
text: "This is some text #tagName that I'd like to #parse here https://t.co/m9Addr4IlS",
...
}
While I can write my own string parser to look for those things, is there something the Twitter API offers to handle this?
EDIT: <tweets> is an Angular directive that ng-repeats over my tweets from ModulesService. replace doesn't seem to be appending the DOM tags
scope.getTweets = function() {
ModulesService.getTweets().success(function(res) {
if (res && Array.isArray(res)) {
scope.tweets = parseTweets(res);
}
});
};
scope.getTweets();
var parseTweets = function (tweets) {
tweets.forEach(function (tweet) {
tweet.text.replace(/(#[^ ]+)/g, '<a class="user">$1</a>').
replace(/(#[^ ]+)/g, '<span class="hash">$1</span>').
replace(/(https?:\/\/[^ ]+)/g, '$1');
console.log('tweet!', tweet.text); //does not contain altered HTML
});
return tweets;
};
HTML:
<div ng-repeat="tweet in tweets" class="post-body clearfix">
{{tweet.text}}
</div>
recommended solution
The library twitter-text does the work for you.
As per their examples:
autolink
var twitter = require('twitter-text')
twitter.autoLink(twitter.htmlEscape('#hello < #world >'))
extract entities
var usernames = twttr.txt.extractMentions("Mentioning #twitter and #jack")
// usernames == ["twitter", "jack"]
Using that solution will save you from re-inventing the wheel and will provide you with a stable working code :)
alternative
Inside the tweet object that you receive from the user_timeline API endpoint, the entities property stores the list of urls, hashtags and mentions included inside the tweet. These contain the text content as well as the position (start / end character indices) of each entity.
Example hashtag entity:
"entities": {
"hashtags": [
"text": "pleaseRT"
"indices": [
6,
13
]
]
cf Entities documentation for more info.
Try:
var text = "This is some text #tagName that I'd like to #parse here https://t.co/m9Addr4IlS";
var div = document.getElementsByTagName('div')[0];
div.innerHTML = text.replace(/(#[^ ]+)/g, '<a class="user">$1</a>').
replace(/(#[^ ]+)/g, '<span class="hash">$1</span>').
replace(/(https?:\/\/[^ ]+)/g, '$1');
.hash { color: orange; }
.user { color: red; }
<div></div>
Loop over the returned tweets and modify the tweet text according to some conditions:
returnValues.forEach(function (tweet) {
if (tweet.text.search(/#|#/ig) > -1) {
var words = obj.text.split(' ');
var parsedTweetText = words.map(function (word) {
if (word.indexOf('#') === 0)
return '<span class="hashtag">' + word + '</span>';
else if (word.indexOf('#') === 0)
return '<span class="at-user">' + word + '</span>';
else
return word;
}).join(' ');
tweet.text = parsedTweetText;
}
});
I have a number of pages that contain phone number in this format xxx-xxx-xxxx.
These phone numbers are not links, what I need to do it write some script that first finds these phone numbers. This is what I have got for that:
$(document).ready(function(){
var content = $(".main").text();
var phoneNumber = content.match(/\d{3}-\d{3}-\d{4}/)
alert(phoneNumber);
});
This works in so much that is captures the number, what I need to do now is replace that phone number on the page with
'' + 'originalPhoneNumber' + ''
However I am totally lost at this point. Can I use .replaceWith() in jQuery?
EDIT:
Okay I tried to modify the code to include the second attribute i wanted:
$(document).ready(function () {
var content = $(".main").html();
content = content.replace(/\d{3}-\d{3}-\d{4}/g, function(v){
return $('<a>').attr({
href: "tel:"+v,
onclick: "ga('send', 'event', 'lead', 'phone call', 'call');"
}).html(v)[0].outerHTML;
});
$('.main').html(content);
});
It is still adding the href but it is ignoring the onclick.
This will replace all matching strings in an element with a tel: link
<div class = "main">333-333-3333 444-444-4444</div>
<script type="text/javascript">
var content = $(".main").text();
content = content.replace(/\d{3}-\d{3}-\d{4}/g, function(v){
return $('<a>').attr('class', set.classname).attr('href', 'tel:'+v).html(v).wrap('<a>').parent().html();
});
$('.main').html(content);
</script>
Or more neatly implemented as :
$.fn.extend({
tel : function(def) {
var set = {
regex : /\d{3}-\d{3}-\d{4}/g,
classname : ""
}
$.extend(true, set, def);
var c = $(this).html();
c = c.replace(set.regex, function(v){
return $('<a>').attr('class', set.classname).attr('href', 'tel:'+v).html(v).wrap('<a>').parent().html();
});
$(this).html(c);
return this;
}
});
// default regex: 000-000-0000
$('.main').tel();
// default regex: 000-000-0000 <a> class of tel-link applied
$('.main').tel({ classname : "tel-link" });
// override regex: 0000-0000-000
$('.main').tel({ regex: /\d{4}-\d{4}-\d{3}/g });
I am working on a new masterpage withing sharepoint 2010. One of the placeholders produces the sitename - the page name in a string. When the page is ready the sources shows this for exampe.
<h1 class="ribbonmc">
Devness Squared - Mark Jensen
</h1>
Devenss Squared is the site name and Mark Jensen is the page name. I am trying to remove the sitename from being displayed and show the page name only using jQuery. This is what I have so far.
$(document).ready(function() {
$('#ribbonmc').text(function(i, oldText) {
return oldText === 'Devness Squared - ' ? '' : oldText;
});
});
Regex solution:
$(".ribbonmc").text(function(i, oldText) {
return oldText.replace(/^Devness Squared - /, "");
});
Non-regex solution:
$(".ribbonmc").text(function(i, oldText) {
var r = "Devness Squared - ";
return oldText.indexOf(r) === 0 ? oldText.substring(r.length) : oldText;
});
$(document).ready(function() {
var sitename = 'Devness Squared - ';
$(".ribbonmc").text(function(i, oldText) {
return oldText.indexOf(sitename) === 0 // if it starts with `sitename`
? oldText.substring(sitename.length) // t: return everything after it
: oldText; // f: return existing
});
});