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/
Related
var url = window.location.href.toString();
the above line gives me the url of my current page correctly and my url is:
http://localhost/xyzCart/products.php?cat_id=35
However, using javascript how can i get only a portion of the url i.e. from the above url i just want
products.php?cat_id=35
How to accomplish this plz help.I have looked at similar questions in this forum but none were any help for me..
You can sliply use this:
var url = window.location.href.toString();
var newString = url.substr(url.lastIndexOf(".") + 1));
This will result in: php?cat_id=35
Good luck /Zorken17
You can use the location of the final /:
var page = url.substr(url.substr(0, (url + "?").indexOf("?")).lastIndexOf("/") + 1);
(This allows for / in a query string)
You can get your desired result by using javascript split() method.check this link for further detail
https://jsfiddle.net/x06ywtvo/
var urls = [
"http://localhost/xyzCart/products.php?cat_id=35",
"http://localhost/xyzCart/products.php",
"http://www.google.com/xyzCart/products.php?cat_id=37"
];
var target = $('#target');
for(var i=0;i<urls.length;i++){
var index = urls[i].indexOf("xyzCart");
var sub = urls[i].substring(index, urls[i].length);
target.append("<div>" + sub + "</div>");
}
Try the folowing javacript code to get the part you need. It splits up your url by the "/"s and takes the fourth part. This is superior to substr solutions in terms of descriptive clarity.
url.split("/")[4]
Or if url can contain more "/" path parts, then simply take the last split part.
var parts = url.split("/");
console.log( parts[parts.length-1] );
You will get all necessary values in window.location object.
Kindly check on following CodePen Link for proper output.
I have added parameter test=1
Link: http://codepen.io/rajesh_dixit/pen/EVebJe?test=1
Code
(function() {
var url = window.location.pathname.split('/');
var index = 1;
document.write("URL: ");
document.write(window.location.href);
document.write("<br/> Full Path: ");
document.write(window.location.pathname);
document.write("<br/> Last Value:")
// For cases where '/' comes at the end
if(!url[url.length - index])
index++;
document.write(url[url.length-index])
document.write("<br/> Query Parameter: ");
document.write(window.location.search.substring(1));
})()
I have a page of database results where users occasionally type in a reference to another post. (The database is day event tracker for a scheduling office).
The reference to the other post is always the posts ID (format of 001234). We uses these to match events with dockets and other paperwork from truck drivers. It is always a 6 digit number on its own.
<div class="eventsWrapper">
Data from DB is output here using PHP in a foreach loop.
Presents data in similar fashion to facebook for example.
</div>
What I need to do is once the data in the above DIV is loaded, then go through and replace every whole 6 digit number (not part of a number) with the number as a hyperlink.
It is important it only looks for number with a space either side:
EG: Ref 001122 <- like this - not like this -> ignore AB001122
Once I have the hyperlink tag I can make the reference number clickable to take users directly to that post.
I am not that good with regex but think it is something like:
\b(![0-9])?\d{6}\b
I have no idea how to search the DIV and then replace that regex with the hyperlink. Appreciate any help.
(?:^| )\d{6}(?= |$)
You can use this and replace by <space><whateveryouwant>.See demo.
https://regex101.com/r/bW3aR1/7
\b wont works cos A1 is not a word boundary which you want.
Something like this? Make an array of the individual posts and loop through. If there is only ever one ID in a post, you can do without the second loop.
var str = ['Ref 001122 <- like this - not like this -> ignore AB001122', 'Ref 001123 <- like this - not like this -> ignore AB001122', 'Ref 001124 <- like this - not like this -> ignore AB001122'];
var regex = /\b\d{6}\b/g;
for (var j = 0; j < str.length; j++) {
var urls = str[j].match(regex);
for (var i = 0; i < urls.length; i++) {
var url = urls[i];
newString = str[j].replace('' + urls[i] + '', '<a href = ' + url + '>' + urls[i] + '</a>')
}
$('#output').append(newString);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="output"></div>
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>
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!
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