Error in Firefox while replace string using regexp in JavaScript - javascript

try{
var hdnPassenger = $("#ctl00_ContentPlaceHolder1_hdnPassenger").val();
var newTr = $("#hdnCtl").html();
newTr = newTr.replace(/_ID/g, hdnPassenger);
}
catch(ex){
alert(ex);
}
Above code is working fine in the internet explorer, but displayed the following error in the mozilla firefox
InternalError: regular expression too complex

Having done some research into this problem, there are two possible reasons for this error:
The actual regex too complex (not in your case, as you only have /_ID/)
The length of the string you're trying to do the substitution on (I don't know what it is, but probably quite long). It seems that there's some hard-coded limit in some versions of firefox, but I can't vouch for that.
I suggest you do two this: add the values of your hdnPassenger and newTr variables - and at the same time google firefox regular expression too complex - there are plenty of hits.

Related

CSS - returning different values from different browsers

When I am using jQuery to grab CSS values for objects, each of the browsers (IE, Mozilla, Chrome, etc) returns different values.
For example, in Chrome, a background image (.css("background-image")) returns:
url(http://i41.tinypic.com/f01zsy.jpg)
Where in Mozilla, it returns:
url("http://i41.tinypic.com/f01zsy.jpg")
I am having the same problem on other aspects, such as background-size.
In chrome it returns:
50% 50%
But Mozilla returns:
50%+50%
My problem with this is, I have functions that split the CSS (background-size), for example based on a space .split(" "), but this could not work on Mozilla because it uses a + instead.
Is there any way that I can fix this problem and make the browsers to use one standard?
Is there any function that I could write which grabs and splits values, based on the type of browser the user is using?
My problem with this is, I have functions that split the CSS
(background-size), for example based on a space .split(" "), but this
could not work on Mozilla because it uses a + instead.
Try adding \+ to RegExp passed to .split
.split(/\s|\+/)
var res = ["50%+50%", "50% 50%"];
var re = /\s+|\+/;
console.log(res[0].split(re), res[1].split(re));
Different browsers use different CSS standards and you may have to write a full-blown parser to make them one standard.
Workaround is that you should split or use CSS values taking into account the different browsers standards. Like the CSS(background-size) problem can be solved using this:
space.split("\\s|\\+"); //split my string where it either has a space 'or' a plus sign
For CSS(background-image), the solution may be to replace the inverted commas before using it:
space.replace("\"", "");
Try to make the splits generallized for all browsers. Hope that helps.
This probably isn't the cleanest method, but you could run a string parser for the background image source and delete any quotation marks. This would be the most efficient method for parsing the background image URL. It should work without harming the data because URL's typically can't contain quotation marks, as they are encoded as %22
As for the background-size, you could parse the results for + signs and change those to spaces, as + signs typically aren't present as the values for any CSS properties, so you should be relatively safe in taking those out.
In addition, you could check the browser type to see if you'd even have to run these parsings in the first place. As a precaution, you should also see how Opera and Safari return results, and if those are any different, you could create branch statements for the parsers that handle the different types of CSS values returned by the different browsers.
Note: The parsing methods I have described attempt the goal of converting the Firefox results to the Chrome-style results.
Thanks for all the help.
I'll share the code I have ended up using!
cssCommas: function(text)
{
return text.replace(new RegExp("\"", "g"),"");
},
cssPlus: function(text)
{
return text.replace(new RegExp("\\+", "g"),"");
},
cssSplit: function(text,removePercent)
{
var removeParent = removeParent || false;
if(removePercent == true)
{
text = text.replace(new RegExp("%", "g"),"");
}
return text.split(new RegExp("\\s|\\+","g"));
},
css: function(text)
{
return this.cssCommas(this.cssPlus(text));
}
Works perfectly on all browsers now. Thanks a lot.

XPath queries in IE use zero-based indexes but the W3C spec is one-based. How should I handle the difference?

The Problem
I am converting a relatively large piece of Javascript that currently only works on Internet Explorer in order to make it work on the other browsers as well. Since the code uses XPath extensively we made a little compatibility function to make things easier
function selectNodes(xmlDoc, xpath){
if('selectNodes' in xmlDoc){
//use IE logic
}else{
//use W3C's document.evaluate
}
}
This is mostly working fine but we just came across the limitation that positions in IE are zero-based but in the W3C model used by the other browsers they are one-based. This means that to get the first element we need to do //books[0] in IE and //books[1] in the other browsers.
My proposed solution
The first thought was using a regex to add one to all indexes that appear in the queries if we are using the document.evaluate version:
function addOne(n){ return 1 + parseInt(nStr, 10); }
xpath = xpath.replace(
/\[\s*(\d+)\s*\]/g,
function(_, nStr){ return '[' + addOne(nStr) + ']'; }
);
My question
Is this regex based solution reasonably safe?
Are there any places it will convert something it should not?
Are there any places where it will not convert something it should?
For example, it would fail to replace the index in //books[position()=1] but since IE doesn't appear to support position() and our code is not using that I think this particular case would not be a problem.
Considerations
I downloaded Sarissa to see if they have a way to solve this but after looking at the source code apparently they don't?
I want to add one to the W3C version instead of subtracting one in the IE version to ease my conversion effort.
In the end
We decided to rewrite the code to use proper XPath in IE too by setting the selection language
xmlDoc.setProperty("SelectionLanguage", "XPath");
we just came across the limitation that positions in IE are zero-based
but in the W3C model used by the other browsers they are one-based.
This means that to get the first element we need to do //books[0] in
IE and //books[1] in the other browsers.
Before doing any XPath selection, specify:
xmlDoc.setProperty("SelectionLanguage", "XPath");
MSXML3 uses a dialect of XSLT/XPath that was in use before XSLT and XPath became W3C Recommendations. The default is "XSLPattern" and this is what you see as behavior.
Read more on this topic here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms754679(v=vs.85).aspx
Why not modify the original expressions, so that this:
var expr = "books[1]";
...becomes:
var expr = "books[" + index(1) + "]";
...where index is defined as (pseudocode):
function index(i) {
return isIE ? (i - 1) : i;
}

How to remove linebreaks in IE with Javascript?

I am trying to remove linebreaks with JavaScript. It works in all browsers except Internet Explorer (tested in ie7, ie8). I have read a lot of posts but couldn't find a solution to the problem.
Var someText = "Here’s your text.\n It has line breaks that need to be removed.\rUsing Javascript.\r\n";
someText = someText.replace(/(\r\n|\n|\r)/gm,"");
What else can I try?
* EDITED *****
Here's more code and a better explanation of my problem:
function checkLength(fn) {
var fn = document.getElementById(fn);
var fnb = fn.value;
var fnb = fnb.replace(/(\r\n|\n|\r)/gm,"");
var len = fnb.length;
...
What I am trying to do is calculate the number of chars in a textarea. I had to calculate with both Javascript and PHP and because of the linebreaks, PHP and Javascript never came to the same number. When removing the linebreaks, it is all good except in Internet Explorer (when I calculate it with Javascript). fnb.replace doesn't change anything in Internet Explorer for the character count so that is why I am sure it does not remove the linebreaks correctly. In all other browsers it is fine, I can see the difference in the counter after removing the linebreaks in javascript. Only in ie it doesn't change a thing. I have tried a couple of things as well as your suggestions below and the char count before removing the linebreaks and after is the same in ie.
///////// MY ANSWER /////////////////////////////////////
function checkLength(fn) {
var fn = document.getElementById(fn);
var fnb = fn.value;
var fnb = fnb.replace(/(\r\n|\n|\r)/gm,"");
var len = fnb.length;
...
Like Tomalak said, my logic could be improved - Sorry for being new to JavaScript & programming. Maybe Tomalak doesn't make any mistakes but I'm sure everyone else does. We have to make mistakes to learn.
Internet Explorer didn't like
var fn = document.getElementById(fn);
var fnb = fn.value;
I had to change it to:
var fnb = document.getElementById(fn).value;
Even if it wasn't logical, it should have worked. It did work in all browsers except ie. It's a bug.
That was the answer I was looking for.
Try this:
someText = someText.replace(/[\r\n]+/gm,"");
In fact, the regular expression works just fine in at least IE8.0.
The real problem is that you wrote Var instead of var; Firefox lets you get away with it, but IE doesn't.
You don't need the m flag, but you ought to replace with a space instead of nothing.
someText = someText.replace(/[\r\n]+/g,' ');

A weird regex problem

The following code results in "undefined" for lastIndex:
var a = /cat/g;
var l = "A test sentence containing cat and dog.";
var r = a.exec(l);
document.write(r.lastIndex);
However, it works perfectly for r.index (and r.input).
I am using Firefox. Does anybody have a clue?
EDIT: OK, the above code works perfectly in IE! Further, in Firefox, it works perfectly if instead of calling r.lastIndex on line 5, a.lastIndex is called. It appears that Firefox does not return lastIndex property in the result - rather sets the property for the pattern invoking the exec() only. Interesting that IE sets both.
This is one of those places where Microsoft decided to add some stuff to the language and act as if it was supposed to be there. Thankfully, they are now cleaning up their act and documenting such nonsense.
To be clear: Firefox is correct according to the ECMAScript Language Specification 3rd Edition (PDF, 705KB).
IE is not correct; its behaviour is a proprietary extension. There is no reason to believe that this IE-specific behaviour will ever be supported by any other browser. It certainly isn't at the moment. See JScript Deviations from ES3 (PDF, 580KB, by Pratap Lakshman of Microsoft Corporation) Section 4.6 for more on this particular deviation from the spec, including tests showing no support on other browsers.
Note also that this may not even be supported in the future by IE: a number of proprietary IE CSS-related mechanisms are disabled by default on IE8-in-IE8-mode, and future implementations of JScript may find a reason to similarly disable this extension to the language.
lastIndex is a property of a RegExp object. So try this:
a.lastIndex
To avoid all the weird, try this
var a = /cat/g;
var l = "A test sentence containing cat and dog.";
var r = a.exec(l);
var lastIndex = (r!=null) ? l.indexOf(r[0])+r[0].length : 0;
It is used here: http://www.pagecolumn.com/tool/regtest.htm

Regex to match contents of HTML body

EDIT: OOPS, sorry I wasn't clear. I have a string that I get from AJAX that is an xhtml document, I need to get the body tag of it, unless I can generate a dom tree from the string?
I need to get everything from a body tag in a string, including markup, with a javascript regex.
I know that this is a duplicate, but the regexes I found in other questions were for different flavours of regex, and gave me errors.
Thank in advance.
document.getElementsByTagName('body')[0].innerHTML will return a string of everything in the body tag. It's not a regex, but I'm not sure why you need one...?
POST QUESTION EDIT:
Your XHR object that you performed your AJAX with has responseText and responseXML properties. As long as the response is valid xml, which is probably should be, you can get any tag you want using getElementsByTagName on the xml object that I mentioned. But if you just want the inner parts of the body, I would do it this way:
var inner = myXHR.responseText.split(/(<body>|</body>)/ig)[2]);
Regex isn't the ideal tool for parsing the DOM as you will see mentioned throughout this site and others. The most ideal way, as suggested by George IV is to use the JavaScript tools that are more suited to this and that is getElementsByTagName and grab the innerHTML:
var bodyText = document.getElementsByTagName("body")[0].innerHTML;
Edit1: I've not checked it out yet, but Rudisimo suggested a tool that shows a lot of promise - the XRegExp Library which is an open sources and extensible library out of MIT. This could potentially be a viable option - I still think the DOM is the better way, but this looks far superior to the standard JavaScript implementation of regex.
Edit2: I recant my previous statements about the Regex engine [for reasons of accuracy] due to the example provided by Gumbo - however absurd the expression might be. I do, however, stand by my opinion that using regex in this instance is an inherently bad way to go and you should reference the DOM using the aforementioned example.
In general regular expressions are not suitable for parsing. But if you really want to use a regular expression, try this:
/^\s*(?:<(?:!(?:(?:--(?:[^-]+|-[^-])*--)+|\[CDATA\[(?:[^\]]+|](?:[^\]]|][^>]))*\]\]|[^<>]+)|(?!body[\s>])[a-z]+(?:\s*(?:[^<>"']+|"[^"]*"|'[^']*'))*|\/[a-z]+)\s*>|[^<]+)*\s*<body(?:\s*(?:[^<>"']+|"[^"]*"|'[^']*'))*\s*>([\s\S]+)<\/body\s*>/i
As you see, there is no easy way to do that. And I wouldn’t even claim that this is a correct regular expression. But it should take comment tags (<!-- … -->), CDATA tags (<![CDATA[ … ]]>) and normal HTML tags into account.
Good luck while trying to read it.
Everybody seems dead set on using regular expressions so I figured I'd go the other way and answer the second query you had.
It is theoretically possible to parse the result of your AJAX as an xmlDocument.
There are a few steps you'll likely want to take if you want this to work.
Use a library. I recommend jQuery
If you're using a library you must make sure that the mimetype of the response is an xml mimetype!
Make sure you test thoroughly in all your target browsers. You will get tripped up.
That being said, I created a quick example on jsbin.
It works in both IE and Firefox, unfortunately in order to get it to work I had to roll my own XMLHttpRequest object.
View the example source code here
(Seriously though, this code is ugly. It's worth using a library and setting the mime type properly...)
function getXHR() {
var xmlhttp;
//Build the request
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
} else if (window.ActiveXObject) {
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
} else {
alert("Your browser does not support XMLHTTP!");
}
//Override the mime type for firefox so that it returns the
//result as an XMLDocument.
if( xmlhttp.overrideMimeType ) {
xmlhttp.overrideMimeType('application/xhtml+xml; charset=x-user-defined');
}
return xmlhttp;
}
function runVanillaAjax(url,functor)
{
var xmlhttp = getXHR();
xmlhttp.onreadystatechange=function() { functor(xmlhttp); };
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
function vanillaAjaxDone( response ) {
if(response.readyState==4) {
//Get the xml document element for IE or firefox
var xml;
if ($.browser.msie) {
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = false;
xml.loadXML(response.responseText);
} else {
xml = response.responseXML.documentElement;
}
var textarea = document.getElementById('textarea');
var bodyTag = xml.getElementsByTagName('body')[0];
if( $.browser.msie ) {
textarea.value = bodyTag.text;
} else {
textarea.value = bodyTag.textContent;
}
}
}
function vanillaAjax() {
runVanillaAjax('http://jsbin.com/ulevu',vanillaAjaxDone);
}
There is an alternative fix to the dot matches newline limitation of the RegExp library in JavaScript. XRegExp is a powerful and open source library with an almost limitless license "MIT License" (for commercial projects), which is very compact (2.7KB gzipped) and powerful.
If you go to the New Flags section, you can see how there's a flag (s), in which dot matches all characters; including newlines.

Categories