Add URL to specific word across entire website - javascript

I want to be able to link any word of my choice to a specific URL for example:
I want the word "goat" to link to "http://goat.com" across the entire website. So all "goat"/s will link to that URL right across the website.
I am using wordpress and I have not yet found a plugin to do this. If I can get a solution to this I would most likely create a plugin for this functionality.
I know how to target one word on a single page. But I would like it to be across all the pages and all the words in those pages( I used JavaScript for this).

Something like this may work for you.
function replaceWithUri(textToReplace, element){
element.innerHTML = element.innerHTML.replace(textToReplace, '<a href="http://www.' + textToReplace + '.com" >' + textToReplace + '</a>');
}
replaceWithUri('goat', document.getElementsByTagName('body')[0]);

Here's a crappy solution but it's better than nothing:
I found some code here which searches for a world across the whole page so I copy pasted that and modified it.
The replaceWord variable cannot contain the same string as word, otherwise it'll loop infinitely.
var word = " goat",
replaceWord = " <a href = 'http://goat.com'>goat</a>",
queue = [document.body],
curr
;
while (curr = queue.pop()) {
if (!curr.textContent.match(word)) continue;
for (var i = 0; i < curr.childNodes.length; ++i) {
switch (curr.childNodes[i].nodeType) {
case Node.TEXT_NODE : // 3
if (curr.childNodes[i].textContent.match(word)) {
curr.innerHTML = curr.innerHTML.replace(word,replaceWord);
}
break;
case Node.ELEMENT_NODE : // 1
queue.push(curr.childNodes[i]);
break;
}
}
}
Hello goat
<div>Look a goat</div>

This might be a bit resource intensive and replaceWord cannot contain the same string as word, otherwise it'll loop forever.
document.onload = function() {
var word = " goat",
replaceWord = " <a href = 'http://goat.com'>goat</a>";
while(document.body.innerHTML.indexOf(word) !== -1) {
document.body.innerHTML = document.body.innerHTML.replace(word,replaceWord);
}
}
Hello goat
<div>Look a goat</div>

Related

How to get all the text separately from the bracket using javascript regular expression

I have a sentence stored in a variable.That sentence I need to extract into 4 parts depends on sentence which I have put into variables in my code,I can able to extract here and get into console but I am not getting the whole text of inside the bracket,only I am getting first words.Here is the code below.Can anyone please help me.
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="messages">
SCRIPT
$(document).ready(function() {
regex = /.+\(|\d. \w+/g;
maintext = "Welcome to project, are you a here(1. new user , 2. test user , 3. minor Accident or 4. Major Accident)";
matches = maintext.match(regex);
text_split0 = matches[0].slice(0, -1);
text_split1 = matches[1];
text_split2 = matches[2];
text_split3 = matches[3];
text_split4 = matches[4];
console.log(text_split0);
console.log(text_split1);
console.log(text_split2);
console.log(text_split3);
console.log(text_split4);
$(".messages").append('<li>'+text_split0+'</li><li>'+text_split1+'</li><li>'+text_split2+'</li><li>'+text_split3+'</li><li>'+text_split4+'</li>');
// $("li:contains('undefined')").remove()
});
function buildMessages(text) {
let messages = text.split(/\d\.\s/);
messages.shift();
messages.forEach((v)=>{
let msg = v.replace(/\,/,'').replace(/\sor\s/,'').trim();
$('.messages').append(`<li>${msg}</li>`);
// console.log(`<li>${msg}</li>`);
});
}
let sentenceToParse = "Welcome to project, are you a here(1. new user , 2. test user , 3. minor Accident or 4. Major Accident)";
buildMessages(sentenceToParse);
Use the split function on the String, keying on the digits (e.g. 1.), you will get the preface and each of the steps into an array.
Use the shift function on the Array removes the unneeded preface.
Use forEach to iterate over the values in the array, clean up the text.
Using replace to first remove commas, then remove or with spaces on either side.
Use trim to remove leading and training whitespace.
At this point, your array will have sanitized copy for use in your <li> elements.
If you're only concerned with working through a regex and not re-factoring, the easiest way may be to use an online regex tool where you provide a few different string samples. Look at https://www.regextester.com/
Ok, Try another approach, cause regex for this isn't the best way. Try this:
$(document).ready(function() {
// First part of sentence.
var mainText = "Welcome to project, are you a here(";
// Users array.
var USERS = ['new user', 'test user', 'minor Accident', 'Major Accident'];
var uSize = USERS.length;
// Construct string & user list dynamically.
for(var i = 0; i < uSize; i++) {
var li = $('<li/>').text(USERS[i]);
if(i === uSize - 1)
mainText += (i+1) + ". " + USERS[i] + ")";
else if(i === uSize - 2)
mainText += (i+1) + ". " + USERS[i] + " or ";
else
mainText += (i+1) + ". " + USERS[i] + " , ";
$(".messages").append(li);
}
console.log(mainText); // You will have you complete sentence.
}
Why that way is better? Simple, you can add or remove users inside the user array. String together with your user list will be updated automatically. I hope that help you.

Searching for most performant way for string replacing with javascript

I'm programming my own autocomplete textbox control using C# and javascript on clientside. On client side i want to replace the characters in string which matching the characters the user was searching for to highlight it. For example if the user was searching for the characters 'bue' i want to replace this letters in the word 'marbuel' like so:
mar<span style="color:#81BEF7;font-weight:bold">bue</span>l
in order to give the matching part another color. This works pretty fine if i have 100-200 items in my autocomplete, but when it comes to 500 or more, it takes too mutch time.
The following code shows my method which does the logic for this:
HighlightTextPart: function (text, part) {
var currentPartIndex = 0;
var partLength = part.length;
var finalString = '';
var highlightPart = '';
var bFoundPart = false;
var bFoundPartHandled = false;
var charToAdd;
for (var i = 0; i < text.length; i++) {
var myChar = text[i];
charToAdd = null;
if (!bFoundPart) {
var myCharLower = myChar.toLowerCase();
var charToCompare = part[currentPartIndex].toLowerCase();
if (charToCompare == myCharLower) {
highlightPart += myChar;
if (currentPartIndex == partLength - 1)
bFoundPart = true;
currentPartIndex++;
}
else {
currentPartIndex = 0;
highlightPart = '';
charToAdd = myChar;
}
}
else
charToAdd = myChar;
if (bFoundPart && !bFoundPartHandled) {
finalString += '<span style="color:#81BEF7;font-weight:bold">' + highlightPart + '</span>';
bFoundPartHandled = true;
}
if (charToAdd != null)
finalString += charToAdd;
}
return finalString;
},
This method only highlight the first occurence of the matching part.
I use it as follows. Once the request is coming back from server i build an html UL list with the matching items by looping over each item and in each loop i call this method in order to highlight the matching part.
As i told for up to 100 items it woks pretty nice but it is too mutch for 500 or more.
Is there any way to make it faster? Maybe by using regex or some other technique?
I also thought about using "setTimeOut" to do it in a extra function or maybe do it only for the items, which currently are visible, because only a couple of items are visible while for the others you have to scroll.
Try limiting visible list size, so you are only showing 100 items at maximum for example. From a usability standpoint, perhaps even go down to only 20 items, so it would be even faster than that. Also consider using classes - see if it improves performance. So instead of
mar<span style="color:#81BEF7;font-weight:bold">bue</span>l
You will have this:
mar<span class="highlight">bue</span>l
String replacement in JavaScript is pretty easy with String.replace():
function linkify(s, part)
{
return s.replace(part, function(m) {
return '<span style="color:#81BEF7;font-weight:bold">' + htmlspecialchars(m) + '</span>';
});
}
function htmlspecialchars(txt)
{
return txt.replace('<', '<')
.replace('>', '>')
.replace('"', '"')
.replace('&', '&');
}
console.log(linkify('marbuel', 'bue'));
I fixed this problem by using regex instead of my method posted previous. I replace the string now with the following code:
return text.replace(new RegExp('(' + part + ')', 'gi'), "<span>$1</span>");
This is pretty fast. Much faster as the code above. 500 items in the autocomplete seems to be no problem. But can anybody explain, why this is so mutch faster as my method or doing it with string.replace without regex? I have no idea.
Thx!

Replace only once body text, with some html, by an Iframe

What I need to do
I display an iframe with javascript in the body of an HTML page.
With something like that document.write('<iframe ...></iframe'>);
In this iframe there is my javascript function witch search a keyword in the body of the parent document, and replace it with an html link keyword in the parent document.
What I've tried
Javascript Bookmarklet to replace text with a link : complex script, but I need the skipTags
and Javascript .replace command replace page text? : very short and nice script, but there is not the skipTags function...
Those worked like a charm when the script is in the document but not in an iframe to work with the parent document.
My problems/questions
The problem is that the 'keyword' is replaced with a
'non-interpreted' html as text. (Browser displays keyword).
My second question is how to do the replace just once, and not for
all the matching expressions ?
Usualy I use some jQuery but in this project I need to use only some javascript without any library.
Any idea to help me ? (I don't want anyone to "write my code", I just want some advices to make it by myself)
P.S. 1 : I use Chrome, but I would like to make it work in every browser.
P.S. 2 : English is not my first language, so if you don't understand something, don't hesitate to ask it to me, I'll try to explain it better.
Edit 2
First script now works for the HTML, so question 1 is solved, but how to do the replace only once, even if the keyword is repeated several times ? (question 2)
With the help of xiaoyi, I've found some solutions :
Stop the loop and replace only the first match
Globalize the functions to search/replace multiple keywords
I think that it could be optimized, but for me it works like a charm, and I share it with you, if it can help anyone (don't forget to change the target of the document, here "parent") :
(function(){
// don't replace text within these tags
var skipTags = { 'a': 1, 'style': 1, 'script': 1, 'iframe': 1, 'meta':1, 'title':1, 'img':1, 'h':1 };
// find text nodes to apply replFn to
function findKW( el, term, replFn )
{
var child, tag,found=false;
for (var i = 0;i<=el.childNodes.length - 1 && !found; i++)
{
child = el.childNodes[i];
if (child.nodeType == 1)
{ // ELEMENT_NODE
tag = child.nodeName.toLowerCase();
if (!(tag in skipTags))
{
findKW(child, term, replFn);
}
}
else if (child.nodeType == 3)
{ // TEXT_NODE
found=replaceKW(child, term, replFn); // if found=true, we stop the loop
}
}
};
// replace terms in text according to replFn
function replaceKW( text, term, replFn)
{
var match,
matches = [],found=false;
while (match = term.exec(text.data))
{
matches.push(match);
}
for (var i = 0;i<=matches.length - 1 && !found; i++)
{
match = matches[i];
// cut out the text node to replace
text.splitText(match.index);
text.nextSibling.splitText(match[1].length);
text.parentNode.replaceChild(replFn(match[1]), text.nextSibling);
if(matches[i])found=true;// To stop the loop
}
return found;
};
// First search/replace
var replTerm = 'keyword';
findKW(
parent.document.body,
new RegExp('\\b(' + replTerm + ')\\b', 'gi'),
function (match)
{
var link = parent.document.createElement('a');
link.href = 'http://www.okisurf.com/#q=' + replTerm;
link.target = '_blank';
link.innerHTML = match;
return link;
}
);
// A second search/replace
var replTerm = 'word';
findKW(
parent.document.body,
new RegExp('\\b(' + replTerm + ')\\b', 'gi'),
function (match)
{
var link = parent.document.createElement('a');
link.href = 'http://www.okisurf.com/#q=' + replTerm;
link.target = '_blank';
link.innerHTML = match;
return link;
}
);
// Other search/replace
// ...
}());
I've also discovered that the second solution doesn't works with Internet Explorer witch doesn't accept the createTreeWalker() DOM function

Url parsing in javascript and DOM

I am writing a support chat application where I want text to be parsed for urls. I have found answers for similar questions but nothing for the following.
what i have
function ReplaceUrlToAnchors(text) {
var exp = /(\b(https?:\/\/|ftp:\/\/|file:\/\/|www.)
[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig;
return text.replace(exp,"<a href='$1' target='_blank'>$1</a>");
}
that pattern is a modified version of one i found on the internet. It includes www. in the first token, because not all urls start with protocol:// However, when www.google.com is replaced with
<a href='www.google.com' target='_blank'>www.google.com</a>
which pulls up MySite.com/webchat/wwww.google.com and I get a 404
that is my first problem, my second is...
in my script for generating messages to the log, I am forced to do it a hacky way:
var last = 0;
function UpdateChatWindow(msgArray) {
var chat = $get("MessageLog");
for (var i = 0; i < msgArray.length; i++) {
var element = document.createElement("div");
var linkified = ReplaceUrlToAnchors(msgArray[i]);
element.setAttribute("id", last.toString());
element.innerHTML = linkified;
chat.appendChild(element);
last = last + 1;
}
}
To get the "linkified" string to render HTML out correctly I have to use the non-standard .innerHTML attribute of element. I would prefer a way were i could parse the string as tokens - text tokens and anchor tokens - and call either createTextNode or createElement("a") and stitch them together with DOM.
so question 1 is how should I go about www.site.com parsing, or even site.com?
and question 2 is how would could I do this using only DOM?
Another thing you could do is this:
function ReplaceUrlToAnchors(text) {
var exp = /(\b(https?:\/\/|ftp:\/\/|file:\/\/|www.)
[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig;
return text.replace(exp, function(_, url) {
return '<a href="' +
(/^www\./.test(url) ? "http://" + url : url) +
'target="_blank">' +
url +
'</a>';
});
}
That is kind-of like your solution, but it does the check for "www" URLs in that callback passed in to ".replace()".
Note that you won't be picking up "stackoverflow.com" or "newegg.com" or anything like that, which I understand may be unavoidable (and even desirable, given the false positives you'd pick up).
Here is what I came up with, perhaps someone has something better?
function replaceUrlToAnchors(text) {
var naked = /(\b(www.)[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|](.com|.net|.org|.co.uk|.ca|.))/ig;
text = text.replace(naked, "http://$1");
var exp = /(\b(https?:\/\/|ftp:\/\/|file:\/\/)([-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|]))/ig;
return text.replace(exp,"<a href='$1' target='_blank'>$3</a>");
}
the first regex will replace www.google.com with http://www.google.com and is good enough for what I am doing. However, I will hold off marking this as the answer because I would also like to make (www.) optional but when I do (www.)? it replaces every word with http://word/

Manage firefox tabs in emacs with org-mode

I recently find a way to manage firefox tab in emacs. This sounds a little crazy. I use tree style tabs(firefox addon), Moz Repl, emacs, org-mode to do it.
For 10-15 tabs, my plan works fine. But 20+ tabs, My firefox hangs randomly. Maybe javascript stack overflow or something else? I don't know what's wrong with my code. I post the most import code here. Somesone help me to find some bugs?
It's a basic firefox chrome code below, you can run it in firefox without emacs and MozPepl.
I use tree style tabs api to get tabs and set each tab a cetain level. The output will be used in emacs with org-mode.
tree style tabs api: http://piro.sakura.ne.jp/xul/_treestyletab.html.en#api
The Code can run in many ways. I recommend "workspace addon". Copy My code, choose chrome context to run it.
https://addons.mozilla.org/en-US/firefox/addon/workspace/
// two helper function to get title and url of tab
function getTitle(tab)
{
var brower = gBrowser.getBrowserForTab(tab)
var url = brower.currentURI.spec
var title = brower.contentTitle
return title
}
function getUrl(tab)
{
var brower = gBrowser.getBrowserForTab(tab)
var url = brower.currentURI.spec
var title = brower.contentTitle
return ":PROPERTIES:\n:URL:"+url+"\n:END:\n"
}
var L = gBrowser.tabContainer.childNodes.length //firefox tabs length
var str = "" //global string for output
//parse tabs. If tab has child, parse it. It tab has no child, just output.
for(i = 0; i < L; i++){
level = "*"
tab = gBrowser.tabContainer.childNodes[i]
if ('TreeStyleTabService' in window){
if(TreeStyleTabService.hasChildTabs(tab))
{
str = [str, level, " [+] ", getTitle(tab), "\n", getUrl(tab)].join("") //output title and url. level used in org-mode
treeparse(TreeStyleTabService.getChildTabs(tab), "**") //if a tab has child tabs. parse it and level up
}
str = [str, level, " ", getTitle(tab), "\n", getUrl(tab)].join("")
}
function treeparse(tablist,level) //parse a list of tabs. If tab has not a child, output. If it has childs, parse again
{
for(i=0 ; i < tablist.length;i++) {
tab = tablist[i]
if ('TreeStyleTabService' in window){
if(TreeStyleTabService.hasChildTabs(tab))
{
str = [str, level, " [+] ", getTitle(tab), "\n", getUrl(tab)].join("")
newlevel = level + "*"
treeparse(TreeStyleTabService.getChildTabs(tab),newlevel)
}
} }
str = [str, level, " ", getTitle(tab), "\n", getUrl(tab)].join("")
}
}
alert(str) //alert to view result. You can also write the result into a file.
I'm not sure what's specifically causing the problem, as I couldn't reproduce it, but I see loads of issues with this code. I can't remember how MozRepl works, but this improved code should give you a nice org-mode friendly tab output. I hope this helps you, or whoever stumbles across this thread.
var bullet = "*"; // Org-mode bullet
// two helper function to get title and url of tab
function getTitle(tab) {
var brower = gBrowser.getBrowserForTab(tab);
var url = brower.currentURI.spec;
var title = brower.contentTitle;
return title;
}
function getUrl(tab) {
var brower = gBrowser.getBrowserForTab(tab);
var url = brower.currentURI.spec;
var title = brower.contentTitle;
return ":PROPERTIES:\n:URL:"+url+"\n:END:\n";
}
// NOTE: we factor these string-generation functions out,
// to make things a bit more clear
function makeParentNodeOutput(tab, level) {
return (Array(level+1).join(bullet) +
" [+] " +
getTitle(tab) +
"\n" +
getUrl(tab));
}
function makeLeafNodeOutput(tab, level) {
return (Array(level+1).join(bullet) +
" " +
getTitle(tab) +
"\n" +
getUrl(tab));
}
// NOTE: we only need to handle parsing a collection of tabs
// in once place, and we have a function for it here.
function parseTabCollection(tabs, level) {
var currentTab;
var outputString = "";
for(var i = 0; i < tabs.length; i++){
currentTab = tabs[i];
// For a parent node, we output the node and its children
if(TreeStyleTabService.hasChildTabs(currentTab)){
outputString += makeParentNodeOutput(currentTab, level);
outputString += parseTabCollection(
TreeStyleTabService.getChildTabs(currentTab),
level + 1
);
} else {
outputString += makeLeafNodeOutput(currentTab, level);
}
}
return outputString;
}
if ('TreeStyleTabService' in window){
//NOTE: Start with the rootTabs only. The old version started with
// *all* tabs, which isn't what we want
var orgModeOutput = parseTabCollection(TreeStyleTabService.rootTabs, 1);
alert(orgModeOutput);
}
I hope this helps somehow.

Categories