javascript regular expression does not work in IE8 - javascript

Trying to replace the contents of a td using regular expressions in my javascript function. I'm using this...
var re = /<td id="idreplaceme">.+?<\/td>/gi;
oldDivContent = oldDivContent.replace(re,'<td id="idreplaceme"></td>');
This works in FF and Chrome but not IE8. How do I make this work in IE8?
EDIT:
OldDivContent is a string

Why not document.getElementById('idreplaceme').innerHTML = ''

Try a slightly different regex:
var re = /<td id="idreplaceme">[^<]+<\/td>/gi;
oldDivContent = oldDivContent.replace(re,'<td id="idreplaceme"></td>');
or assuming the lawyers don't want you posting any part of oldDivContent, here's a JavaScript function that should work in lieu of a regex:
function removeContentOfIdentifiedTDs(content, id) {
var d = document.createElement('div'),
tr = {},
td = {},
i = 0;
d.innerHTML = content; //add content to div
td = d.getElementsByTagName('td');
for (i = 0; i < td.length; i += 1) {
if (td[i].id === id) { //if id matches
td[i].innerHTML = ''; //remove content
}
}
return d.innerHTML; //return original html minus removed content
}
removeContentOfIdentifiedTDs(oldDivContent, 'idreplaceme');

Related

Error while selecting allElementsByID and adding a class to them

Hello I'm trying to add a class to all of my elements on a webpage. The overall goal is to grab all the elements on a webpage and add in a class. The class containing a font size will be changed to hide a message.
I'm getting this error
Uncaught TypeError: Cannot set property 'innerHTML' of null
I've tried moving my script outside the body tag of my index.html but its still not working.
Another problem is I can't add a class to all of the IDs I'm selecting. I can add classes manually like
$("#iconLog").addClass("style"); //this works
but when I try to add a class like this
empTwo = "#" + temp; //where empTwo is a string that equals "#iconLog"
$("empTwo").addClass("style") //this does not work
I'll post my entire script below for reference
$(function() {
var hideMsg = "f";
var n = hideMsg.length;
var i;
var j;
var holder;
var hideHolder;
// on button click - hide msg
$('#btnHide').on('click', function() {
//grab all IDS ON WEBPAGE
var allElements = document.getElementsByTagName("*");
var allIds = [];
for (var i = 0, n = allElements.length; i < n; ++i) {
var el = allElements[i];
if (el.id) {
allIds.push(el.id);
}
}
//ERRORS HAPPENING IN THIS LOOP
for(var i = 0; i < allElements.length; ++i)
{
console.log(allIds[i]);
try{
var temp = document.getElementById(allIds[i]).id;
}
catch(err){
document.getElementById("*").innerHTML = err.message;
}
tempTwo = "#" + temp;
console.log(tempTwo);
//$("#iconLog").addClass("style") //this works
$("tempTwo").addClass("style"); //this does not work
}
for(i = 0; i < n; i++) {
//set var holder to first value of the message to hide
holder = hideMsg.charCodeAt(i);
for(j = 7; -1 < j; j--) {
//set hideHolder to holders value
hideHolder = holder;
//mask hideHolder to grab the first bit to hide
hideHolder = hideHolder & (1<<j);
//grab the first element ID
if(hideHolder === 0) {
// embed the bit
// bitwise &=
} else {
//embed the bit
// bitwise ^=
}
}
}
});
});
To add a class to all elements you don't need a for loop. Try this:
$("*").addClass("style");
Same for setting the inner html of all elements. Try this:
$("*").html("Html here");
Remove the double quotes from empTwo .You don't need quotes when you are passing a varible as a selector. The variable itself contains a string so you don't need the quotes.
empTwo = "#" + temp;
$(empTwo).addClass("style") //this will work
Try this:
$(empTwo).addClass("style")
Note: You used string instead of variable:
well,
try this...
You were passing the varibale in the quotos because of that instead of getting value to empTwo it was searching directly for "empTwo".
$(empTwo).addClass("style");
to get all element try this-
var allElements = = document.body.getElementsByTagName("*");
Hoping this will help you :)
empTwo = "#" + temp; //where empTwo is a string that equals "#iconLog"
$("empTwo").addClass("style") //this does not work
You made mistake in the second Line.
The variable empTwo already is in string format.
So all you need to do is
$(empTwo).addClass("style") //this works because empTwo returns "#iconLog"

Replacing all urls in a div

I am trying to write javascript code to find all the urls inside a div. Now this would be pretty easy if all the urls within the div were separated by spaces in which case I can just do a regex on what's inside the div to find them. However, the urls within this outer div may be in sub divs (or any other html tag) and I want to consider the subdivs as separators as well (and I don't want to get rid of these subdivs). To give an example, in the following I want to find www.foo.com and www.bar.com within the div with id "outer":
<div id="outer"><div>www.foo.com</div>www.bar.com</div>
What would be a good way of doing this?
You can apply a recursive call to all non-text child nodes.
function replaceWwwInNodes(node) {
//text node
if (node.nodeType === 3) {
node.textContent = node.textContent.replace(/* ??? */)
}
else {
Array.prototype.forEach.call(node.childNodes, function (elem) {
replaceWwwInNodes(elem);
});
}
}
replaceWwwInNodes(document.getElementById('outer'));
http://jsfiddle.net/UDX5V/
Try to use this sample http://jsfiddle.net/iklementiev/TaCx9/1/
var data = document.getElementById("outer").innerText;
var myRe = /www\.[0-9a-z-]+\.[a-z]{2,4}/igm;
var matches= data.match(myRe)
for (var i = 0; i < matches.length; i++) {
alert('match: ' + matches[i]);
}
this help to find all urls.
try this
var expression = /[-a-zA-Z0-9#:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9#:%_\+.~#?&//=]*)?/gi;
var regex = new RegExp(expression);
var regContent = $("#outer").html();
var newContent = regContent;
if(regContent.match(regex))
{
var textContent = regContent.match(regex);
for(var i=0;i<regContent.match(regex).length;i++)
{
newContent = newContent.replace(new RegExp(regContent.match(regex)[i], "g"), "test");
}
$("#outer").html(newContent);
}
this will get all url content and replace it as "test".

innerText is undefined in Greasemonkey script

I've made code to query a document for matching strings and make a URL from the strings obtained. It looks through the tag elements looking for matches, makes the URL string, then it appends the link to the designated parentNode object. This code works fine in plain javascript, but it breaks when I stick it in Greasemonkey. I can't figure out why.
Here is a fully working version when I stick it in the chrome console:
//loop through elements by classname and find string matches
regexQueryEmail = "(AccountEmailAddress\\s)(.+?)(\\n)"
regexQueryContact = "(Contact with ID: )(.+?)(\\D)"
var Tags = document.getElementsByClassName('msg-body-div')
for (i = 0; i < Tags.length; i++) {
matchEmail = Tags[i].innerText.match(regexQueryEmail)
matchContact = Tags[i].innerText.match(regexQueryContact)
if (matchEmail != null) {
var emailString = matchEmail[2]
var placeHolder = Tags[i]
}
if (matchContact != null) {
var idString = matchContact[2]
}
}
var urlFirst = "https://cscentral.foo.com/gp/stores/www.foo.com/gp/communications/manager/main/191- 4559276-8054240?ie=UTF8&customerEmailAddress="
var urlSecond = "%3E&initialCommId="
var cscURL = urlFirst + emailString + urlSecond + idString
var cscLink = document.createElement('a')
cscLink.innerText = 'Communication History'
cscLink.href = cscURL
placeHolder.parentNode.appendChild(cscLink)
When I stick it in Greasemonkey, it gives me this error from the Greasemonkey "Edit" screen:
/*
Exception: Tags[i].innerText is undefined
#Scratchpad:18
*/
It has also told me that "placeHolder" is undefined, but I am unable to replicate this right now. I have a feeling that it has something to do with how the variables are scoped. I've added "var Tags;" and "var placeHolder;" to the top of the script and it didn't help.
Firefox uses the element.textContent property.
https://developer.mozilla.org/en-US/docs/Web/API/Node.textContent?redirectlocale=en-US&redirectslug=DOM%2FNode.textContent
The variable placeholder in never declared in the scope you try to use it in. Instead it's declared somewhere in your for loop. Make sure you declare it within the same scope.
E.g.
var Tags = document.getElementsByClassName('msg-body-div')
var placeholder; // declare in same scope
for (var i = 0; i < Tags.length; i++) {
// lookup the tag once
var tag = Tags[i];
// get the text only once
var text = tag.textContent;
matchEmail = text.match(regexQueryEmail)
matchContact = text.match(regexQueryContact)
if (matchEmail != null) {
var emailString = matchEmail[2]
placeHolder = tag // deleted var statement
}
if (matchContact != null) {
var idString = matchContact[2]
}
}
...
// now you can use it.
if (placeHolder) {
placeHolder.parentNode.appendChild(cscLink);
}

Make a text Highlight using javascript

I want to make a word bold in given paragraph. Here is a javascript code.
var hlWord = "idm";
var nregex = new RegExp(hlWord,"gi");
var div = document.getElementById("SR").innerHTML;
var rword = div.replace(nregex,"<b>"+hlWord+"</b>");
document.getElementById("SR").innerHTML = rword;
Here is a HTML code.
<div id="SR">
Download here free idm.
click here to download
</div>
This is work well and make all idm bold but here is a problem that it also change
url to like this
click here to download
This is not a valid url.This is the problem that this code make the url damaged.
Please tell me how can I avoid this.
Thanks...
You can iterate through all the text nodes with the methods in this thread, change them and replace them with new bold ones.
var hlWord = "idm";
var nregex = new RegExp(hlWord,"gi");
var sr = document.getElementById('SR');
function escape_html(html) {
return html.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
}
(function findTextNodes(current) {
// make a shadow copy of the child nodes.
var current_children = Array.prototype.slice.call(current.childNodes);
for(var i = 0; i < current_children.length; i++) {
var child = current.childNodes[i];
// text node
if(child.nodeType == 3) {
var value = escape_html(child.nodeValue);
var html = value.replace(nregex, '<b>' + hlWord + '</b>');
if (html != value) {
var node = document.createElement('div');
node.innerHTML = html;
// make a shadow copy of the child nodes.
var childNodes = Array.prototype.slice.call(node.childNodes);
// replace the plain text node with the bold segments
for (var j = 0; j < childNodes.length; j++) {
var c = childNodes[j];
current.insertBefore(c, child);
}
current.removeChild(child);
}
}
else {
findTextNodes(child);
}
}
})(sr);
Check the code example at jsFiddle.
UPDATE:
Passerby pointed out that innerHTML should be used carefully. Escape text nodeValue before processing.
After some try-and-fail, I made a working demo that may be more complicated than you might have think:
http://jsfiddle.net/4VKNk/
var cache=[];
var reg=/idm/gi;
var id=function(ID){return document.getElementById(ID);}
function walkElement(ele){
if(ele.childNodes.length>0){
for(var i=0;i<ele.childNodes.length;i++){
walkElement(ele.childNodes[i]);
}
}else if(ele.nodeType==3){//text node
if(reg.test(ele.nodeValue)){
cache.push(ele);
}
}
}
id("test").onclick=function(){
cache=[];
walkElement(id("SR"));
while(cache.length>0){
var ele=cache.shift();
var val=ele.nodeValue;
var pnt=ele.parentNode;
var nextSibling=ele.nextSibling;
var i=0;
var r,tmp;
pnt.removeChild(ele);
while(r=reg.exec(val)){
tmp=document.createTextNode(val.substring(i,r.index));
if(nextSibling){
pnt.insertBefore(tmp,nextSibling);
tmp=document.createElement("strong");
tmp.appendChild(document.createTextNode("idm"));
pnt.insertBefore(tmp,nextSibling);
}else{
pnt.appendChild(tmp);
tmp=document.createElement("strong");
tmp.appendChild(document.createTextNode("idm"));
pnt.appendChild(tmp);
}
i=reg.lastIndex;
}
if(i<val.length-1){
tmp=document.createTextNode(val.substring(i,val.length));
if(nextSibling){
pnt.insertBefore(tmp,nextSibling);
}else{
pnt.appendChild(tmp);
}
}
}
};
I took the approach of DOM manipulation.
Explanation:
Walk through the whole DOM tree under target element, and cache all TEXT_NODE (nodeType==3);
Use RegExp.exec() method to get the index of each match;
While you find a match, add back the text that come before it, and then add a highlight element (<strong>) that contains the match; continue this step;
If we still have text left, add it back.
The reason I need to cache the TEXT_NODEs first, is that if we directly modify it in walkElement, it will change childNodes.length of its parent, and break the process.

Using innerHTML.replace to replace text to create link

I'm using Sharepoint (WSS 3.0), which is unfortunately very limited in its ability to format survey questions (i.e., it strips any HTML you enter). I saw a solution elsewhere that suggested we add some JS to our master page file in order to allow line breaks. This works beautifully, but I'd like to see if we can allow links as well.
In our WSS surveys, I can now use {{br}} anywhere I want a line break (this works). I have tried extending the code to allow the use of link tags (e.g., {{link1}}url{{link2}}URL Title{{link3}}; but, this doesn't work, presumably because the updates aren't happening as a whole, and the browser then tries to render it piece by piece, confusing it. (FF and IE show different results, but both fail. If I mix up the order of the JS below -- i.e., do link3, 2 and then 1 -- the output changes as well, but still fails.) Is there a better way to do this?
<script language="JavaScript">
var className;
className = 'ms-formlabel';
var elements = new Array();
var elements = document.getElementsByTagName('td');
for (var e = 0; e < elements.length; e++)
{
if (elements[e].className == className){
elements[e].innerHTML = elements[e].innerHTML.replace(/{{br}}/g,'<br/>');
elements[e].innerHTML = elements[e].innerHTML.replace(/{{link1}}/g,'<a href="');
elements[e].innerHTML = elements[e].innerHTML.replace(/{{link2}}/g,'">');
elements[e].innerHTML = elements[e].innerHTML.replace(/{{link3}}/g,'</a>');}
}
</script>
Instead of modifying the innerHTML property in chunks (the browser tries to update the DOM each time you change innerHTML, which if you provide incomplete/broken markup, will obviously mess things up), do all your modifications against your own string variable, and then overwrite the entire innerHTML with your completed string:
<script language="JavaScript">
var className;
className = 'ms-formlabel';
var elements = new Array();
var elements = document.getElementsByTagName('td');
for (var e = 0; e < elements.length; e++)
{
if (elements[e].className == className) {
var newHTML = elements[e].innerHTML;
newHTML = newHTML.replace(/{{br}}/g,'<br/>');
newHTML = newHTML.replace(/{{link1}}/g,'<a href="');
newHTML = newHTML.replace(/{{link2}}/g,'">');
newHTML = newHTML.replace(/{{link3}}/g,'</a>');}
elements[e].innerHTML = newHTML;
}
</script>
The simple answer would be to build up the innerHTML and replace it all at once:
for (var e = 0; e < elements.length; e++)
{
if (elements[e].className == className) {
var newHTML = elements[e].innerHTML;
newHTML = newHTML.replace(/{{br}}/g,'<br/>');
newHTML = newHTML.replace(/{{link1}}/g,'<a href="');
newHTML = newHTML.replace(/{{link2}}/g,'">');
newHTML = newHTML.replace(/{{link3}}/g,'</a>');
elements[e].innerHTML = newHTML;
}
}
The more complex answer would be to use capturing groups in your regex and pass a function as the 2nd parameter to replace(), so as to use a single call to replace() for the HTML. For example,
elements[e].innerHTML = elements[e].innerHTML.replace(/({{link1}})|({{link2}})|({{link3}})/g,
function (match) {
var map = {
'{{link1}}' : '<a href="',
'{{link2}}' : '>',
'{{link3}}' : '</a>', }
return map[match];
});
The second solution is more complex and leads to some ugly regexes, but is more efficient than calling replace() over and over again.

Categories

Resources